|
ferencd@0
|
1 \chapter{Parsing and Building Messages}
|
|
ferencd@0
|
2
|
|
ferencd@0
|
3 % ============================================================================
|
|
ferencd@0
|
4 \section{Parsing messages}
|
|
ferencd@0
|
5
|
|
ferencd@0
|
6 \subsection{Introduction} % --------------------------------------------------
|
|
ferencd@0
|
7
|
|
ferencd@0
|
8 Parsing is the process of creating a structured representation (for example,
|
|
ferencd@0
|
9 a hierarchy of C++ objects) of a message from its ``textual'' representation
|
|
ferencd@0
|
10 (the raw data that is actually sent on the Internet).
|
|
ferencd@0
|
11
|
|
ferencd@0
|
12 For example, say you have the following email in a file called "hello.eml":
|
|
ferencd@0
|
13
|
|
ferencd@0
|
14 \begin{verbatim}
|
|
ferencd@0
|
15 Date: Thu, Oct 13 2005 15:22:46 +0200
|
|
ferencd@0
|
16 From: Vincent <vincent@vmime.org>
|
|
ferencd@0
|
17 To: you@vmime.org
|
|
ferencd@0
|
18 Subject: Hello from VMime!
|
|
ferencd@0
|
19
|
|
ferencd@0
|
20 A simple message to test VMime
|
|
ferencd@0
|
21 \end{verbatim}
|
|
ferencd@0
|
22
|
|
ferencd@0
|
23 The following code snippet shows how you can easily obtain a
|
|
ferencd@0
|
24 {\vcode vmime::message} object from data in this file:
|
|
ferencd@0
|
25
|
|
ferencd@0
|
26 \begin{lstlisting}[caption={Parsing a message from a file}]
|
|
ferencd@0
|
27 // Read data from file
|
|
ferencd@0
|
28 std::ifstream file;
|
|
ferencd@0
|
29 file.open("hello.eml", std::ios::in | std::ios::binary);
|
|
ferencd@0
|
30
|
|
ferencd@0
|
31 vmime::utility::inputStreamAdapter is(file);
|
|
ferencd@0
|
32
|
|
ferencd@0
|
33 vmime::string data;
|
|
ferencd@0
|
34 vmime::utility::outputStreamStringAdapter os(data);
|
|
ferencd@0
|
35
|
|
ferencd@0
|
36 vmime::utility::bufferedStreamCopy(is, os);
|
|
ferencd@0
|
37
|
|
ferencd@0
|
38 // Actually parse the message
|
|
ferencd@0
|
39 vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
|
|
ferencd@0
|
40 msg->parse(data);
|
|
ferencd@0
|
41
|
|
ferencd@0
|
42 vmime::shared_ptr <vmime::header> hdr = msg->getHeader();
|
|
ferencd@0
|
43 vmime::shared_ptr <vmime::body> bdy = msg->getBody();
|
|
ferencd@0
|
44
|
|
ferencd@0
|
45 // Now, you can extract some of its components
|
|
ferencd@0
|
46 vmime::charset ch(vmime::charsets::UTF_8);
|
|
ferencd@0
|
47
|
|
ferencd@0
|
48 std::cout
|
|
ferencd@0
|
49 << "The subject of the message is: "
|
|
ferencd@0
|
50 << hdr->Subject()->getValue <vmime::text>()->getConvertedText(ch)
|
|
ferencd@0
|
51 << std::endl
|
|
ferencd@0
|
52 << "It was sent by: "
|
|
ferencd@0
|
53 << hdr->From()->getValue <vmime::mailbox>()->getName().getConvertedText(ch)
|
|
ferencd@0
|
54 << " (email: " << hdr->From()->getValue <vmime::mailbox>()->getEmail() << ")"
|
|
ferencd@0
|
55 << std::endl;
|
|
ferencd@0
|
56 \end{lstlisting}
|
|
ferencd@0
|
57
|
|
ferencd@0
|
58 The output of this program is:
|
|
ferencd@0
|
59
|
|
ferencd@0
|
60 \begin{verbatim}
|
|
ferencd@0
|
61 The subject of the message is: Hello from VMime!
|
|
ferencd@0
|
62 It was sent by: Vincent (email: vincent@vmime.org)
|
|
ferencd@0
|
63 \end{verbatim}
|
|
ferencd@0
|
64
|
|
ferencd@0
|
65
|
|
ferencd@0
|
66 \subsection{Using the {\vcode vmime::messageParser} object} % ----------------
|
|
ferencd@0
|
67
|
|
ferencd@0
|
68 The {\vcode vmime::messageParser} object allows to parse messages in a more
|
|
ferencd@0
|
69 simple manner. You can obtain all the text parts and attachments as well as
|
|
ferencd@0
|
70 basic fields (expeditor, recipients, subject...), without dealing with
|
|
ferencd@0
|
71 MIME message structure.
|
|
ferencd@0
|
72
|
|
ferencd@0
|
73 \begin{lstlisting}[caption={Using {\vcode vmime::messageParser} to parse
|
|
ferencd@0
|
74 more complex messages}]
|
|
ferencd@0
|
75 // Read data from file
|
|
ferencd@0
|
76 std::ifstream file;
|
|
ferencd@0
|
77 file.open("hello.eml", std::ios::in | std::ios::binary);
|
|
ferencd@0
|
78
|
|
ferencd@0
|
79 vmime::utility::inputStreamAdapter is(file);
|
|
ferencd@0
|
80
|
|
ferencd@0
|
81 vmime::string data;
|
|
ferencd@0
|
82 vmime::utility::outputStreamStringAdapter os(data);
|
|
ferencd@0
|
83
|
|
ferencd@0
|
84 vmime::utility::bufferedStreamCopy(is, os);
|
|
ferencd@0
|
85
|
|
ferencd@0
|
86 // Actually parse the message
|
|
ferencd@0
|
87 vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
|
|
ferencd@0
|
88 msg->parse(data);
|
|
ferencd@0
|
89
|
|
ferencd@0
|
90 // Here start the differences with the previous example
|
|
ferencd@0
|
91 vmime::messageParser mp(msg);
|
|
ferencd@0
|
92
|
|
ferencd@0
|
93 // Output information about attachments
|
|
ferencd@0
|
94 std::cout << "Message has " << mp.getAttachmentCount()
|
|
ferencd@0
|
95 << " attachment(s)" << std::endl;
|
|
ferencd@0
|
96
|
|
ferencd@0
|
97 for (int i = 0 ; i < mp.getAttachmentCount() ; ++i)
|
|
ferencd@0
|
98 {
|
|
ferencd@0
|
99 vmime::shared_ptr <const vmime::attachment> att = mp.getAttachmentAt(i);
|
|
ferencd@0
|
100 std::cout << " - " << att->getType().generate() << std::endl;
|
|
ferencd@0
|
101 }
|
|
ferencd@0
|
102
|
|
ferencd@0
|
103 // Output information about text parts
|
|
ferencd@0
|
104 std::cout << "Message has " << mp.getTextPartCount()
|
|
ferencd@0
|
105 << " text part(s)" << std::endl;
|
|
ferencd@0
|
106
|
|
ferencd@0
|
107 for (int i = 0 ; i < mp.getTextPartCount() ; ++i)
|
|
ferencd@0
|
108 {
|
|
ferencd@0
|
109 vmime::shared_ptr <const vmime::textPart> tp = mp.getTextPartAt(i);
|
|
ferencd@0
|
110
|
|
ferencd@0
|
111 // text/html
|
|
ferencd@0
|
112 if (tp->getType().getSubType() == vmime::mediaTypes::TEXT_HTML)
|
|
ferencd@0
|
113 {
|
|
ferencd@0
|
114 vmime::shared_ptr <const vmime::htmlTextPart> htp =
|
|
ferencd@0
|
115 vmime::dynamicCast <const vmime::htmlTextPart>(tp);
|
|
ferencd@0
|
116
|
|
ferencd@0
|
117 // HTML text is in tp->getText()
|
|
ferencd@0
|
118 // Plain text is in tp->getPlainText()
|
|
ferencd@0
|
119
|
|
ferencd@0
|
120 // Enumerate embedded objects
|
|
ferencd@0
|
121 for (int j = 0 ; j < htp->getObjectCount() ; ++j)
|
|
ferencd@0
|
122 {
|
|
ferencd@0
|
123 vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj =
|
|
ferencd@0
|
124 htp->getObjectAt(j);
|
|
ferencd@0
|
125
|
|
ferencd@0
|
126 // Identifier (Content-Id or Content-Location) is obj->getId()
|
|
ferencd@0
|
127 // Object data is in obj->getData()
|
|
ferencd@0
|
128 }
|
|
ferencd@0
|
129 }
|
|
ferencd@0
|
130 // text/plain or anything else
|
|
ferencd@0
|
131 else
|
|
ferencd@0
|
132 {
|
|
ferencd@0
|
133 // Text is in tp->getText()
|
|
ferencd@0
|
134 }
|
|
ferencd@0
|
135 }
|
|
ferencd@0
|
136 \end{lstlisting}
|
|
ferencd@0
|
137
|
|
ferencd@0
|
138
|
|
ferencd@0
|
139 % ============================================================================
|
|
ferencd@0
|
140 \section{Building messages}
|
|
ferencd@0
|
141
|
|
ferencd@0
|
142 \subsection{A simple message\label{msg-building-simple-message}} % -----------
|
|
ferencd@0
|
143
|
|
ferencd@0
|
144 Of course, you can build a MIME message from scratch by creating the various
|
|
ferencd@0
|
145 objects that compose it (parts, fields, etc.). The following is an example of
|
|
ferencd@0
|
146 how to achieve it:
|
|
ferencd@0
|
147
|
|
ferencd@0
|
148 \begin{lstlisting}[caption={Building a simple message from scratch}]
|
|
ferencd@0
|
149 vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
|
|
ferencd@0
|
150
|
|
ferencd@0
|
151 vmime::shared_ptr <vmime::header> hdr = msg->getHeader();
|
|
ferencd@0
|
152 vmime::shared_ptr <vmime::body> bdy = msg->getBody();
|
|
ferencd@0
|
153
|
|
ferencd@0
|
154 vmime::shared_ptr <vmime::headerFieldFactory> hfFactory =
|
|
ferencd@0
|
155 vmime::headerFieldFactory::getInstance();
|
|
ferencd@0
|
156
|
|
ferencd@0
|
157 // Append a 'Date:' field
|
|
ferencd@0
|
158 vmime::shared_ptr <vmime::headerField> dateField =
|
|
ferencd@0
|
159 hfFactory->create(vmime::fields::DATE);
|
|
ferencd@0
|
160
|
|
ferencd@0
|
161 dateField->setValue(vmime::datetime::now());
|
|
ferencd@0
|
162 hdr->appendField(dateField);
|
|
ferencd@0
|
163
|
|
ferencd@0
|
164 // Append a 'Subject:' field
|
|
ferencd@0
|
165 vmime::shared_ptr <vmime::headerField> subjectField =
|
|
ferencd@0
|
166 hfFactory->create(vmime::fields::SUBJECT);
|
|
ferencd@0
|
167
|
|
ferencd@0
|
168 subjectField->setValue(vmime::text("Message subject"));
|
|
ferencd@0
|
169 hdr->appendField(subjectField);
|
|
ferencd@0
|
170
|
|
ferencd@0
|
171 // Append a 'From:' field
|
|
ferencd@0
|
172 vmime::shared_ptr <vmime::headerField> fromField =
|
|
ferencd@0
|
173 hfFactory->create(vmime::fields::FROM);
|
|
ferencd@0
|
174
|
|
ferencd@0
|
175 fromField->setValue
|
|
ferencd@0
|
176 (vmime::make_shared <vmime::mailbox>("me@vmime.org"));
|
|
ferencd@0
|
177 hdr->appendField(fromField);
|
|
ferencd@0
|
178
|
|
ferencd@0
|
179 // Append a 'To:' field
|
|
ferencd@0
|
180 vmime::shared_ptr <vmime::headerField> toField =
|
|
ferencd@0
|
181 hfFactory->create(vmime::fields::TO);
|
|
ferencd@0
|
182
|
|
ferencd@0
|
183 vmime::shared_ptr <vmime::mailboxList> recipients =
|
|
ferencd@0
|
184 vmime::make_shared <vmime::mailboxList>();
|
|
ferencd@0
|
185
|
|
ferencd@0
|
186 recipients->appendMailbox
|
|
ferencd@0
|
187 (vmime::make_shared <vmime::mailbox>("you@vmime.org"));
|
|
ferencd@0
|
188
|
|
ferencd@0
|
189 toField->setValue(recipients);
|
|
ferencd@0
|
190 hdr->appendField(toField);
|
|
ferencd@0
|
191
|
|
ferencd@0
|
192 // Set the body contents
|
|
ferencd@0
|
193 bdy->setContents(vmime::make_shared <vmime::stringContentHandler>
|
|
ferencd@0
|
194 ("This is the text of your message..."));
|
|
ferencd@0
|
195
|
|
ferencd@0
|
196 // Output raw message data to standard output
|
|
ferencd@0
|
197 vmime::utility::outputStreamAdapter out(std::cout);
|
|
ferencd@0
|
198 msg->generate(out);
|
|
ferencd@0
|
199 \end{lstlisting}
|
|
ferencd@0
|
200
|
|
ferencd@0
|
201 As you can see, this is a little fastidious. Hopefully, VMime also offers a
|
|
ferencd@0
|
202 more simple way for creating messages. The {\vcode vmime::messageBuilder}
|
|
ferencd@0
|
203 object can create basic messages that you can then customize.
|
|
ferencd@0
|
204
|
|
ferencd@0
|
205 The following code can be used to build exactly the same message as in the
|
|
ferencd@0
|
206 previous example, using the {\vcode vmime::messageBuilder} object:
|
|
ferencd@0
|
207
|
|
ferencd@0
|
208 \begin{lstlisting}[caption={Building a simple message
|
|
ferencd@0
|
209 using {\vcode vmime::messageBuilder}}]
|
|
ferencd@0
|
210 try
|
|
ferencd@0
|
211 {
|
|
ferencd@0
|
212 vmime::messageBuilder mb;
|
|
ferencd@0
|
213
|
|
ferencd@0
|
214 // Fill in some header fields and message body
|
|
ferencd@0
|
215 mb.setSubject(vmime::text("Message subject"));
|
|
ferencd@0
|
216 mb.setExpeditor(vmime::mailbox("me@vmime.org"));
|
|
ferencd@0
|
217 mb.getRecipients().appendAddress
|
|
ferencd@0
|
218 (vmime::make_shared <vmime::mailbox>("you@vmime.org"));
|
|
ferencd@0
|
219
|
|
ferencd@0
|
220 mb.getTextPart()->setCharset(vmime::charsets::ISO8859_15);
|
|
ferencd@0
|
221 mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>
|
|
ferencd@0
|
222 ("This is the text of your message..."));
|
|
ferencd@0
|
223
|
|
ferencd@0
|
224 // Message construction
|
|
ferencd@0
|
225 vmime::shared_ptr <vmime::message> msg = mb.construct();
|
|
ferencd@0
|
226
|
|
ferencd@0
|
227 // Output raw message data to standard output
|
|
ferencd@0
|
228 vmime::utility::outputStreamAdapter out(std::cout);
|
|
ferencd@0
|
229 msg->generate(out);
|
|
ferencd@0
|
230 }
|
|
ferencd@0
|
231 // VMime exception
|
|
ferencd@0
|
232 catch (vmime::exception& e)
|
|
ferencd@0
|
233 {
|
|
ferencd@0
|
234 std::cerr << "vmime::exception: " << e.what() << std::endl;
|
|
ferencd@0
|
235 }
|
|
ferencd@0
|
236 // Standard exception
|
|
ferencd@0
|
237 catch (std::exception& e)
|
|
ferencd@0
|
238 {
|
|
ferencd@0
|
239 std::cerr << "std::exception: " << e.what() << std::endl;
|
|
ferencd@0
|
240 }
|
|
ferencd@0
|
241 \end{lstlisting}
|
|
ferencd@0
|
242
|
|
ferencd@0
|
243
|
|
ferencd@0
|
244 \subsection{Adding an attachment} % ------------------------------------------
|
|
ferencd@0
|
245
|
|
ferencd@0
|
246 Dealing with attachments is quite simple. Add the following code to the
|
|
ferencd@0
|
247 previous example to attach a file to the message:
|
|
ferencd@0
|
248
|
|
ferencd@0
|
249 \begin{lstlisting}[caption={Building a message with an attachment using
|
|
ferencd@0
|
250 {\vcode vmime::messageBuilder}}]
|
|
ferencd@0
|
251 // Create an attachment
|
|
ferencd@0
|
252 vmime::shared_ptr <vmime::fileAttachment> att =
|
|
ferencd@0
|
253 vmime::make_shared <vmime::fileAttachment>
|
|
ferencd@0
|
254 (
|
|
ferencd@0
|
255 /* full path to file */ "/home/vincent/paris.jpg",
|
|
ferencd@0
|
256 /* content type */ vmime::mediaType("image/jpeg),
|
|
ferencd@0
|
257 /* description */ vmime::text("My holidays in Paris")
|
|
ferencd@0
|
258 );
|
|
ferencd@0
|
259
|
|
ferencd@0
|
260 // You can also set some infos about the file
|
|
ferencd@0
|
261 att->getFileInfo().setFilename("paris.jpg");
|
|
ferencd@0
|
262 att->getFileInfo().setCreationDate
|
|
ferencd@0
|
263 (vmime::datetime("30 Apr 2003 14:30:00 +0200"));
|
|
ferencd@0
|
264
|
|
ferencd@0
|
265 // Add this attachment to the message
|
|
ferencd@0
|
266 mb.appendAttachment(att);
|
|
ferencd@0
|
267 \end{lstlisting}
|
|
ferencd@0
|
268
|
|
ferencd@0
|
269
|
|
ferencd@0
|
270 \subsection{HTML messages and embedded objects} % ----------------------------
|
|
ferencd@0
|
271
|
|
ferencd@0
|
272 VMime also supports aggregate messages, which permits to build MIME messages
|
|
ferencd@0
|
273 containing HTML text and embedded objects (such as images). For more information
|
|
ferencd@0
|
274 about aggregate messages, please read RFC-2557 (\emph{MIME Encapsulation of
|
|
ferencd@0
|
275 Aggregate Documents, such as HTML}).
|
|
ferencd@0
|
276
|
|
ferencd@0
|
277 Creating such messages is quite easy, using the {\vcode vmime::messageBuilder}
|
|
ferencd@0
|
278 object. The following code constructs a message containing text in both plain
|
|
ferencd@0
|
279 and HTML format, and a JPEG image:
|
|
ferencd@0
|
280
|
|
ferencd@0
|
281 \begin{lstlisting}[caption={Building an HTML message with an embedded image
|
|
ferencd@0
|
282 using the {\vcode vmime::messageBuilder}}]
|
|
ferencd@0
|
283 // Fill in some header fields
|
|
ferencd@0
|
284 mb.setSubject(vmime::text("An HTML message"));
|
|
ferencd@0
|
285 mb.setExpeditor(vmime::mailbox("me@vmime.org"));
|
|
ferencd@0
|
286 mb.getRecipients().appendAddress
|
|
ferencd@0
|
287 (vmime::make_shared <vmime::mailbox>("you@vmime.org"));
|
|
ferencd@0
|
288
|
|
ferencd@0
|
289 // Set the content-type to "text/html": a text part factory must be
|
|
ferencd@0
|
290 // available for the type you are using. The following code will make
|
|
ferencd@0
|
291 // the message builder construct the two text parts.
|
|
ferencd@0
|
292 mb.constructTextPart(vmime::mediaType
|
|
ferencd@0
|
293 (vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML));
|
|
ferencd@0
|
294
|
|
ferencd@0
|
295 // Set contents of the text parts; the message is available in two formats:
|
|
ferencd@0
|
296 // HTML and plain text. The HTML format also includes an embedded image.
|
|
ferencd@0
|
297 vmime::shared_ptr <vmime::htmlTextPart> textPart =
|
|
ferencd@0
|
298 vmime::dynamicCast <vmime::htmlTextPart>(mb.getTextPart());
|
|
ferencd@0
|
299
|
|
ferencd@0
|
300 // -- Add the JPEG image (the returned identifier is used to identify the
|
|
ferencd@0
|
301 // -- embedded object in the HTML text, the famous "CID", or "Content-Id").
|
|
ferencd@0
|
302 // -- Note: you can also read data from a file; see the next example.
|
|
ferencd@0
|
303 const vmime::string id = textPart->addObject("<...image data...>",
|
|
ferencd@0
|
304 vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
|
|
ferencd@0
|
305
|
|
ferencd@0
|
306 // -- Set the text
|
|
ferencd@0
|
307 textPart->setCharset(vmime::charsets::ISO8859_15);
|
|
ferencd@0
|
308
|
|
ferencd@0
|
309 textPart->setText(vmime::make_shared <vmime::stringContentHandler>
|
|
ferencd@0
|
310 ("This is the <b>HTML text</b>, and the image:<br/>"
|
|
ferencd@0
|
311 "<img src=\"") + id + vmime::string("\"/>"));
|
|
ferencd@0
|
312
|
|
ferencd@0
|
313 textPart->setPlainText(vmime::make_shared <vmime::stringContentHandler>
|
|
ferencd@0
|
314 ("This is the plain text."));
|
|
ferencd@0
|
315 \end{lstlisting}
|
|
ferencd@0
|
316
|
|
ferencd@0
|
317 This will create a message having the following structure:
|
|
ferencd@0
|
318
|
|
ferencd@0
|
319 \begin{verbatim}
|
|
ferencd@0
|
320 multipart/alternative
|
|
ferencd@0
|
321 text/plain
|
|
ferencd@0
|
322 multipart/related
|
|
ferencd@0
|
323 text/html
|
|
ferencd@0
|
324 image/jpeg
|
|
ferencd@0
|
325 \end{verbatim}
|
|
ferencd@0
|
326
|
|
ferencd@0
|
327 You can easily tell VMime to read the embedded object data from a file. The
|
|
ferencd@0
|
328 following code opens the file \emph{/path/to/image.jpg}, connects it to an
|
|
ferencd@0
|
329 input stream, then add an embedded object:
|
|
ferencd@0
|
330
|
|
ferencd@0
|
331 \begin{lstlisting}
|
|
ferencd@0
|
332 vmime::utility::fileSystemFactory* fs =
|
|
ferencd@0
|
333 vmime::platform::getHandler()->getFileSystemFactory();
|
|
ferencd@0
|
334
|
|
ferencd@0
|
335 vmime::shared_ptr <vmime::utility::file> imageFile =
|
|
ferencd@0
|
336 fs->create(fs->stringToPath("/path/to/image.jpg"));
|
|
ferencd@0
|
337
|
|
ferencd@0
|
338 vmime::shared_ptr <vmime::contentHandler> imageCts =
|
|
ferencd@0
|
339 vmime::make_shared <vmime::streamContentHandler>
|
|
ferencd@0
|
340 (imageFile->getFileReader()->getInputStream(), imageFile->getLength());
|
|
ferencd@0
|
341
|
|
ferencd@0
|
342 const vmime::string cid = textPart.addObject(imageCts,
|
|
ferencd@0
|
343 vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
|
|
ferencd@0
|
344 \end{lstlisting}
|
|
ferencd@0
|
345
|
|
ferencd@0
|
346
|
|
ferencd@0
|
347 % ============================================================================
|
|
ferencd@0
|
348 \section{Working with attachments: the attachment helper}
|
|
ferencd@0
|
349
|
|
ferencd@0
|
350 The {\vcode attachmentHelper} object allows listing all attachments in a
|
|
ferencd@0
|
351 message, as well as adding new attachments, without using the
|
|
ferencd@0
|
352 {\vcode messageParser} and {\vcode messageBuilders} objects. It can work
|
|
ferencd@0
|
353 directly on messages and body parts.
|
|
ferencd@0
|
354
|
|
ferencd@0
|
355 To use it, you do not need any knowledge about how attachment parts should
|
|
ferencd@0
|
356 be organized in a MIME message.
|
|
ferencd@0
|
357
|
|
ferencd@0
|
358 The following code snippet tests if a body part is an attachment, and if so,
|
|
ferencd@0
|
359 extract its contents to the standard output:
|
|
ferencd@0
|
360
|
|
ferencd@0
|
361 \begin{lstlisting}[caption={Testing if a body part is an attachment}]
|
|
ferencd@0
|
362 vmime::shared_ptr <vmime::bodyPart> part; // suppose we have a body part
|
|
ferencd@0
|
363
|
|
ferencd@0
|
364 if (vmime::attachmentHelper::isBodyPartAnAttachment(part))
|
|
ferencd@0
|
365 {
|
|
ferencd@0
|
366 // The body part contains an attachment, get it
|
|
ferencd@0
|
367 vmime::shared_ptr <const vmime::attachment> attach =
|
|
ferencd@0
|
368 attachmentHelper::getBodyPartAttachment(part);
|
|
ferencd@0
|
369
|
|
ferencd@0
|
370 // Extract attachment data to standard output
|
|
ferencd@0
|
371 vmime::utility::outputStreamAdapter out(std::cout);
|
|
ferencd@0
|
372 attach->getData()->extract(out);
|
|
ferencd@0
|
373 }
|
|
ferencd@0
|
374 \end{lstlisting}
|
|
ferencd@0
|
375
|
|
ferencd@0
|
376 You can also easily extract all attachments from a message:
|
|
ferencd@0
|
377
|
|
ferencd@0
|
378 \begin{lstlisting}[caption={Extracting all attachments from a message}]
|
|
ferencd@0
|
379 vmime::shared_ptr <vmime::message> msg; // suppose we have a message
|
|
ferencd@0
|
380
|
|
ferencd@0
|
381 const std::vector <ref <const attachment> > atts =
|
|
ferencd@0
|
382 attachmentHelper::findAttachmentsInMessage(msg);
|
|
ferencd@0
|
383 \end{lstlisting}
|
|
ferencd@0
|
384
|
|
ferencd@0
|
385 Finally, the {\vcode attachmentHelper} object can be used to add an
|
|
ferencd@0
|
386 attachment to an existing message, whatever it contains (text parts,
|
|
ferencd@0
|
387 attachments, ...). The algorithm can modify the structure of the
|
|
ferencd@0
|
388 message if needed (eg. add a \emph{multipart/mixed} part if no one
|
|
ferencd@0
|
389 exists in the message). Simply call the {\vcode addAttachment}
|
|
ferencd@0
|
390 function:
|
|
ferencd@0
|
391
|
|
ferencd@0
|
392 \begin{lstlisting}[caption={Adding an attachment to an existing message}]
|
|
ferencd@0
|
393 vmime::shared_ptr <vmime::message> msg; // suppose we have a message
|
|
ferencd@0
|
394
|
|
ferencd@0
|
395 // Create an attachment
|
|
ferencd@0
|
396 vmime::shared_ptr <vmime::fileAttachment> att =
|
|
ferencd@0
|
397 vmime::make_shared <vmime::fileAttachment>
|
|
ferencd@0
|
398 (
|
|
ferencd@0
|
399 /* full path to file */ "/home/vincent/paris.jpg",
|
|
ferencd@0
|
400 /* content type */ vmime::mediaType("image/jpeg),
|
|
ferencd@0
|
401 /* description */ vmime::text("My holidays in Paris")
|
|
ferencd@0
|
402 );
|
|
ferencd@0
|
403
|
|
ferencd@0
|
404 // Attach it to the message
|
|
ferencd@0
|
405 vmime::attachmentHelper::addAttachment(msg, att);
|
|
ferencd@0
|
406 \end{lstlisting}
|
|
ferencd@0
|
407
|