1//
2// MailMessageTest.cpp
3//
4// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "MailMessageTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/Net/MailMessage.h"
15#include "Poco/Net/MailRecipient.h"
16#include "Poco/Net/PartHandler.h"
17#include "Poco/Net/StringPartSource.h"
18#include "Poco/Net/PartStore.h"
19#include "Poco/Net/MediaType.h"
20#include "Poco/Timestamp.h"
21#include "Poco/FileStream.h"
22#include "Poco/String.h"
23#include <sstream>
24#include <vector>
25
26
27using Poco::Net::MailMessage;
28using Poco::Net::MailRecipient;
29using Poco::Net::MessageHeader;
30using Poco::Net::PartHandler;
31using Poco::Net::MediaType;
32using Poco::Net::StringPartSource;
33using Poco::Net::FilePartStoreFactory;
34using Poco::Net::FilePartStore;
35using Poco::Timestamp;
36using Poco::FileInputStream;
37using Poco::replaceInPlace;
38using Poco::icompare;
39
40
41namespace
42{
43 class StringPartHandler: public PartHandler
44 {
45 public:
46 StringPartHandler()
47 {
48 }
49
50 void handlePart(const MessageHeader& header, std::istream& stream)
51 {
52 _disp.push_back(header["Content-Disposition"]);
53 _type.push_back(header["Content-Type"]);
54 std::string data;
55 int ch = stream.get();
56 while (ch > 0)
57 {
58 data += (char) ch;
59 ch = stream.get();
60 }
61 _data.push_back(data);
62 }
63
64 const std::vector<std::string>& data() const
65 {
66 return _data;
67 }
68
69 const std::vector<std::string>& disp() const
70 {
71 return _disp;
72 }
73
74 const std::vector<std::string>& type() const
75 {
76 return _type;
77 }
78
79 private:
80 std::vector<std::string> _data;
81 std::vector<std::string> _disp;
82 std::vector<std::string> _type;
83 };
84}
85
86
87MailMessageTest::MailMessageTest(const std::string& name): CppUnit::TestCase(name)
88{
89}
90
91
92MailMessageTest::~MailMessageTest()
93{
94}
95
96
97void MailMessageTest::testWriteQP()
98{
99 MailMessage message;
100 MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe");
101 MailRecipient r2(MailRecipient::CC_RECIPIENT, "jane.doe@no.where", "Jane Doe");
102 MailRecipient r3(MailRecipient::BCC_RECIPIENT, "walter.foo@no.where", "Frank Foo");
103 MailRecipient r4(MailRecipient::BCC_RECIPIENT, "bernie.bar@no.where", "Bernie Bar");
104 message.addRecipient(r1);
105 message.addRecipient(r2);
106 message.addRecipient(r3);
107 message.addRecipient(r4);
108 message.setSubject("Test Message");
109 message.setSender("poco@appinf.com");
110 message.setContent(
111 "Hello, world!\r\n"
112 "This is a test for the MailMessage class.\r\n"
113 "To test the quoted-printable encoding, we'll put an extra long line here. This should be enough.\r\n"
114 "And here is some more =fe.\r\n"
115 );
116 Timestamp ts(0);
117 message.setDate(ts);
118
119 assertTrue (!message.isMultipart());
120
121 std::ostringstream str;
122 message.write(str);
123 std::string s = str.str();
124
125 assertTrue (s ==
126 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
127 "Content-Type: text/plain\r\n"
128 "Subject: Test Message\r\n"
129 "From: poco@appinf.com\r\n"
130 "Content-Transfer-Encoding: quoted-printable\r\n"
131 "To: John Doe <john.doe@no.where>\r\n"
132 "CC: Jane Doe <jane.doe@no.where>\r\n"
133 "\r\n"
134 "Hello, world!\r\n"
135 "This is a test for the MailMessage class.\r\n"
136 "To test the quoted-printable encoding, we'll put an extra long line here. T=\r\n"
137 "his should be enough.\r\n"
138 "And here is some more =3Dfe.\r\n"
139 );
140}
141
142
143void MailMessageTest::testWrite8Bit()
144{
145 MailMessage message;
146 MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe");
147 message.addRecipient(r1);
148 message.setSubject("Test Message");
149 message.setSender("poco@appinf.com");
150 message.setContent(
151 "Hello, world!\r\n"
152 "This is a test for the MailMessage class.\r\n",
153 MailMessage::ENCODING_8BIT
154 );
155 Timestamp ts(0);
156 message.setDate(ts);
157
158 std::ostringstream str;
159 message.write(str);
160 std::string s = str.str();
161 assertTrue (s ==
162 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
163 "Content-Type: text/plain\r\n"
164 "Subject: Test Message\r\n"
165 "From: poco@appinf.com\r\n"
166 "Content-Transfer-Encoding: 8bit\r\n"
167 "To: John Doe <john.doe@no.where>\r\n"
168 "\r\n"
169 "Hello, world!\r\n"
170 "This is a test for the MailMessage class.\r\n"
171 );
172}
173
174
175void MailMessageTest::testWriteBase64()
176{
177 MailMessage message;
178 MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe");
179 message.addRecipient(r1);
180 message.setSubject("Test Message");
181 message.setSender("poco@appinf.com");
182 message.setContent(
183 "Hello, world!\r\n"
184 "This is a test for the MailMessage class.\r\n",
185 MailMessage::ENCODING_BASE64
186 );
187 Timestamp ts(0);
188 message.setDate(ts);
189
190 std::ostringstream str;
191 message.write(str);
192 std::string s = str.str();
193 assertTrue (s ==
194 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
195 "Content-Type: text/plain\r\n"
196 "Subject: Test Message\r\n"
197 "From: poco@appinf.com\r\n"
198 "Content-Transfer-Encoding: base64\r\n"
199 "To: John Doe <john.doe@no.where>\r\n"
200 "\r\n"
201 "SGVsbG8sIHdvcmxkIQ0KVGhpcyBpcyBhIHRlc3QgZm9yIHRoZSBNYWlsTWVzc2FnZSBjbGFz\r\n"
202 "cy4NCg=="
203 );
204}
205
206
207void MailMessageTest::testWriteManyRecipients()
208{
209 MailMessage message;
210 MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe");
211 MailRecipient r2(MailRecipient::PRIMARY_RECIPIENT, "jane.doe@no.where", "Jane Doe");
212 MailRecipient r3(MailRecipient::PRIMARY_RECIPIENT, "walter.foo@no.where", "Frank Foo");
213 MailRecipient r4(MailRecipient::PRIMARY_RECIPIENT, "bernie.bar@no.where", "Bernie Bar");
214 MailRecipient r5(MailRecipient::PRIMARY_RECIPIENT, "joe.spammer@no.where", "Joe Spammer");
215 message.addRecipient(r1);
216 message.addRecipient(r2);
217 message.addRecipient(r3);
218 message.addRecipient(r4);
219 message.addRecipient(r5);
220 message.setSubject("Test Message");
221 message.setSender("poco@appinf.com");
222 message.setContent(
223 "Hello, world!\r\n"
224 "This is a test for the MailMessage class.\r\n",
225 MailMessage::ENCODING_8BIT
226 );
227 Timestamp ts(0);
228 message.setDate(ts);
229
230 std::ostringstream str;
231 message.write(str);
232 std::string s = str.str();
233 assertTrue (s ==
234 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
235 "Content-Type: text/plain\r\n"
236 "Subject: Test Message\r\n"
237 "From: poco@appinf.com\r\n"
238 "Content-Transfer-Encoding: 8bit\r\n"
239 "To: John Doe <john.doe@no.where>, Jane Doe <jane.doe@no.where>, \r\n"
240 "\tFrank Foo <walter.foo@no.where>, Bernie Bar <bernie.bar@no.where>, \r\n"
241 "\tJoe Spammer <joe.spammer@no.where>\r\n"
242 "\r\n"
243 "Hello, world!\r\n"
244 "This is a test for the MailMessage class.\r\n"
245 );
246
247 const Poco::Net::MailMessage::Recipients& recipients = message.recipients();
248 assertTrue (recipients.size() == 5);
249 assertTrue (recipients[0].getAddress() == "john.doe@no.where");
250 assertTrue (recipients[0].getRealName() == "John Doe");
251 assertTrue (recipients[1].getAddress() == "jane.doe@no.where");
252 assertTrue (recipients[1].getRealName() == "Jane Doe");
253 assertTrue (recipients[2].getAddress() == "walter.foo@no.where");
254 assertTrue (recipients[2].getRealName() == "Frank Foo");
255 assertTrue (recipients[3].getAddress() == "bernie.bar@no.where");
256 assertTrue (recipients[3].getRealName() == "Bernie Bar");
257 assertTrue (recipients[4].getAddress() == "joe.spammer@no.where");
258 assertTrue (recipients[4].getRealName() == "Joe Spammer");
259}
260
261
262void MailMessageTest::testWriteMultiPart()
263{
264 MailMessage message;
265 MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe");
266 message.addRecipient(r1);
267 message.setSubject("Test Message");
268 message.setSender("poco@appinf.com");
269 Timestamp ts(0);
270 message.setDate(ts);
271 message.addContent(new StringPartSource("Hello World!\r\n", "text/plain"), MailMessage::ENCODING_8BIT);
272 StringPartSource* pSPS = new StringPartSource("This is some binary data. Really.", "application/octet-stream", "sample.dat");
273 pSPS->headers().set("Content-ID", "abcd1234");
274 message.addAttachment("sample", pSPS);
275
276 assertTrue (message.isMultipart());
277
278 std::ostringstream str;
279 message.write(str);
280 std::string s = str.str();
281 std::string rawMsg(
282 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
283 "Content-Type: multipart/mixed; boundary=$\r\n"
284 "Subject: Test Message\r\n"
285 "From: poco@appinf.com\r\n"
286 "To: John Doe <john.doe@no.where>\r\n"
287 "Mime-Version: 1.0\r\n"
288 "\r\n"
289 "--$\r\n"
290 "Content-Type: text/plain\r\n"
291 "Content-Transfer-Encoding: 8bit\r\n"
292 "Content-Disposition: inline\r\n"
293 "\r\n"
294 "Hello World!\r\n"
295 "\r\n"
296 "--$\r\n"
297 "Content-ID: abcd1234\r\n"
298 "Content-Type: application/octet-stream; name=sample\r\n"
299 "Content-Transfer-Encoding: base64\r\n"
300 "Content-Disposition: attachment; filename=sample.dat\r\n"
301 "\r\n"
302 "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n"
303 "--$--\r\n"
304 );
305 std::string::size_type p1 = s.find('=') + 1;
306 std::string::size_type p2 = s.find('\r', p1);
307 std::string boundary(s, p1, p2 - p1);
308 std::string msg;
309 for (std::string::const_iterator it = rawMsg.begin(); it != rawMsg.end(); ++it)
310 {
311 if (*it == '$')
312 msg += boundary;
313 else
314 msg += *it;
315 }
316
317 assertTrue (s == msg);
318}
319
320
321void MailMessageTest::testReadQP()
322{
323 std::istringstream istr(
324 "Content-Transfer-Encoding: quoted-printable\r\n"
325 "Content-Type: text/plain\r\n"
326 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
327 "From: poco@appinf.com\r\n"
328 "Subject: Test Message\r\n"
329 "To: John Doe <john.doe@no.where>\r\n"
330 "\r\n"
331 "Hello, world!\r\n"
332 "This is a test for the MailMessage class.\r\n"
333 "To test the quoted-printable encoding, we'll put an extra long line here. T=\r\n"
334 "his should be enough.\r\n"
335 "And here is some more =3Dfe.\r\n"
336 );
337
338 MailMessage message;
339 message.read(istr);
340
341 assertTrue (message.getSender() == "poco@appinf.com");
342 assertTrue (message.getContentType() == "text/plain");
343 assertTrue (message.getContent() ==
344 "Hello, world!\r\n"
345 "This is a test for the MailMessage class.\r\n"
346 "To test the quoted-printable encoding, we'll put an extra long line here. This should be enough.\r\n"
347 "And here is some more =fe.\r\n"
348 );
349}
350
351
352void MailMessageTest::testReadDefaultTransferEncoding()
353{
354 std::istringstream istr(
355 "Content-Type: text/plain\r\n"
356 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
357 "From: poco@appinf.com\r\n"
358 "Subject: Test Message\r\n"
359 "To: John Doe <john.doe@no.where>\r\n"
360 "\r\n"
361 "Hello, world!\r\n"
362 "This is a test for the MailMessage class.\r\n"
363 );
364
365 MailMessage message;
366 message.read(istr);
367
368 assertTrue (message.getSender() == "poco@appinf.com");
369 assertTrue (message.getContentType() == "text/plain");
370 assertTrue (message.getContent() ==
371 "Hello, world!\r\n"
372 "This is a test for the MailMessage class.\r\n"
373 );
374}
375
376
377void MailMessageTest::testReadDefaultContentType()
378{
379 std::istringstream istr("Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
380 "From: poco@appinf.com\r\n"
381 "Subject: Test Message\r\n"
382 "To: John Doe <john.doe@no.where>\r\n"
383 "\r\n"
384 "Hello, world!\r\n"
385 "This is a test for the MailMessage class.\r\n"
386 );
387
388 MailMessage message;
389 message.read(istr);
390
391 assertTrue (message.getSender() == "poco@appinf.com");
392 assertTrue (message.getContentType() == "text/plain");
393 assertTrue (message.getContent() == "Hello, world!\r\n"
394 "This is a test for the MailMessage class.\r\n"
395 );
396}
397
398
399void MailMessageTest::testRead8Bit()
400{
401 std::istringstream istr(
402 "Content-Transfer-Encoding: 8bit\r\n"
403 "Content-Type: text/plain\r\n"
404 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
405 "From: poco@appinf.com\r\n"
406 "Subject: Test Message\r\n"
407 "To: John Doe <john.doe@no.where>\r\n"
408 "\r\n"
409 "Hello, world!\r\n"
410 "This is a test for the MailMessage class.\r\n"
411 );
412
413 MailMessage message;
414 message.read(istr);
415
416 assertTrue (message.getSender() == "poco@appinf.com");
417 assertTrue (message.getContentType() == "text/plain");
418 assertTrue (message.getContent() ==
419 "Hello, world!\r\n"
420 "This is a test for the MailMessage class.\r\n"
421 );
422}
423
424
425void MailMessageTest::testReadMultiPart()
426{
427 std::istringstream istr(
428 "Content-Type: multipart/mixed; boundary=MIME_boundary_01234567\r\n"
429 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
430 "From: poco@appinf.com\r\n"
431 "Mime-Version: 1.0\r\n"
432 "Subject: Test Message\r\n"
433 "To: John Doe <john.doe@no.where>\r\n"
434 "\r\n"
435 "\r\n"
436 "--MIME_boundary_01234567\r\n"
437 "Content-Disposition: inline\r\n"
438 "Content-Transfer-Encoding: 8bit\r\n"
439 "Content-Type: text/plain\r\n"
440 "\r\n"
441 "Hello World!\r\n"
442 "\r\n"
443 "--MIME_boundary_01234567\r\n"
444 "Content-Disposition: attachment; filename=sample.dat\r\n"
445 "Content-Transfer-Encoding: base64\r\n"
446 "Content-Type: application/octet-stream; name=sample\r\n"
447 "\r\n"
448 "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n"
449 "--MIME_boundary_01234567--\r\n"
450 );
451
452 StringPartHandler handler;
453 MailMessage message;
454 message.read(istr, handler);
455
456 assertTrue (handler.data().size() == 2);
457 assertTrue (handler.data()[0] == "Hello World!\r\n");
458 assertTrue (handler.type()[0] == "text/plain");
459 assertTrue (handler.disp()[0] == "inline");
460
461 assertTrue (handler.data()[1] == "This is some binary data. Really.");
462 assertTrue (handler.type()[1] == "application/octet-stream; name=sample");
463 assertTrue (handler.disp()[1] == "attachment; filename=sample.dat");
464}
465
466
467void MailMessageTest::testReadMultiPartWithAttachmentNames()
468{
469 std::istringstream istr(
470 "Content-Type: multipart/mixed; boundary=MIME_boundary_01234567\r\n"
471 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
472 "From: poco@appinf.com\r\n"
473 "Mime-Version: 1.0\r\n"
474 "Subject: Test Message\r\n"
475 "To: John Doe <john.doe@no.where>\r\n"
476 "\r\n"
477 "\r\n"
478 "--MIME_boundary_01234567\r\n"
479 "Content-Disposition: inline\r\n"
480 "Content-Transfer-Encoding: 8bit\r\n"
481 "Content-Type: text/plain\r\n"
482 "\r\n"
483 "Hello World!\r\n"
484 "\r\n"
485 "--MIME_boundary_01234567\r\n"
486 "Content-Disposition: attachment; filename=sample.dat\r\n"
487 "Content-Transfer-Encoding: base64\r\n"
488 "Content-Type: application/octet-stream; name=sample\r\n"
489 "\r\n"
490 "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n"
491 "--MIME_boundary_01234567--\r\n"
492 );
493
494 MailMessage message;
495 message.read(istr);
496
497 assertTrue (message.parts().size() == 2);
498 assertTrue (message.parts()[1].name == "sample");
499 assertTrue (message.parts()[1].pSource->filename() == "sample.dat");
500}
501
502
503void MailMessageTest::testReadMultiPartDefaultTransferEncoding()
504{
505 std::istringstream istr(
506 "Content-Type: multipart/mixed; boundary=MIME_boundary_01234567\r\n"
507 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
508 "From: poco@appinf.com\r\n"
509 "Mime-Version: 1.0\r\n"
510 "Subject: Test Message\r\n"
511 "To: John Doe <john.doe@no.where>\r\n"
512 "\r\n"
513 "\r\n"
514 "--MIME_boundary_01234567\r\n"
515 "Content-Disposition: inline\r\n"
516 "Content-Type: text/plain\r\n"
517 "\r\n"
518 "Hello World!\r\n"
519 "\r\n"
520 "--MIME_boundary_01234567\r\n"
521 "Content-Disposition: attachment; filename=sample.dat\r\n"
522 "Content-Transfer-Encoding: base64\r\n"
523 "Content-Type: application/octet-stream; name=sample\r\n"
524 "\r\n"
525 "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n"
526 "--MIME_boundary_01234567--\r\n"
527 );
528
529 StringPartHandler handler;
530 MailMessage message;
531 message.read(istr, handler);
532
533 assertTrue (handler.data().size() == 2);
534 assertTrue (handler.data()[0] == "Hello World!\r\n");
535 assertTrue (handler.type()[0] == "text/plain");
536 assertTrue (handler.disp()[0] == "inline");
537
538 assertTrue (handler.data()[1] == "This is some binary data. Really.");
539 assertTrue (handler.type()[1] == "application/octet-stream; name=sample");
540 assertTrue (handler.disp()[1] == "attachment; filename=sample.dat");
541}
542
543
544void MailMessageTest::testReadWriteMultiPart()
545{
546 std::string msgin(
547 "Content-Type: multipart/mixed; boundary=MIME_boundary_31E8A8D61DF53389\r\n"
548 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
549 "From: poco@appinf.com\r\n"
550 "Mime-Version: 1.0\r\n"
551 "Subject: Test Message\r\n"
552 "To: John Doe <john.doe@no.where>\r\n"
553 "\r\n"
554 "--MIME_boundary_31E8A8D61DF53389\r\n"
555 "Content-Disposition: inline\r\n"
556 "Content-Transfer-Encoding: 8bit\r\n"
557 "Content-Type: text/plain\r\n"
558 "\r\n"
559 "Hello World!\r\n"
560 "\r\n"
561 "--MIME_boundary_31E8A8D61DF53389\r\n"
562 "Content-Disposition: attachment; filename=sample.dat\r\n"
563 "Content-ID: abcd1234\r\n"
564 "Content-Transfer-Encoding: base64\r\n"
565 "Content-Type: application/octet-stream; name=sample\r\n"
566 "\r\n"
567 "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n"
568 "--MIME_boundary_31E8A8D61DF53389--\r\n"
569 );
570
571 std::istringstream istr(msgin);
572 std::ostringstream ostr;
573 MailMessage message;
574
575 message.read(istr);
576 message.write(ostr);
577
578 std::string msgout(ostr.str());
579 assertTrue (msgout == msgin);
580}
581
582
583void MailMessageTest::testReadWriteMultiPartStore()
584{
585 std::string msgin(
586 "Content-Type: multipart/mixed; boundary=MIME_boundary_31E8A8D61DF53389\r\n"
587 "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
588 "From: poco@appinf.com\r\n"
589 "Mime-Version: 1.0\r\n"
590 "Subject: Test Message\r\n"
591 "To: John Doe <john.doe@no.where>\r\n"
592 "\r\n"
593 "--MIME_boundary_31E8A8D61DF53389\r\n"
594 "Content-Disposition: inline\r\n"
595 "Content-Transfer-Encoding: 8bit\r\n"
596 "Content-Type: text/plain\r\n"
597 "\r\n"
598 "Hello World!\r\n"
599 "\r\n"
600 "--MIME_boundary_31E8A8D61DF53389\r\n"
601 "Content-Disposition: attachment; filename=sample.dat\r\n"
602 "Content-ID: abcd1234\r\n"
603 "Content-Transfer-Encoding: base64\r\n"
604 "Content-Type: application/octet-stream; name=sample\r\n"
605 "\r\n"
606 "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n"
607 "--MIME_boundary_31E8A8D61DF53389--\r\n"
608 );
609
610 std::istringstream istr(msgin);
611 std::ostringstream ostr;
612 FilePartStoreFactory pfsf;
613 MailMessage message(&pfsf);
614
615 message.read(istr);
616
617 MailMessage::PartVec::const_iterator it = message.parts().begin();
618 MailMessage::PartVec::const_iterator end = message.parts().end();
619 for (; it != end; ++it)
620 {
621 Poco::SharedPtr<FilePartStore> fps = it->pSource.cast<FilePartStore>();
622 if (fps && fps->filename().size())
623 {
624 std::string filename = fps->filename();
625 assertTrue (filename == "sample.dat");
626 std::string path = fps->path();
627 // for security reasons, the filesystem temporary
628 // filename is not the same as attachment name
629 std::size_t sz = (path.size() > filename.size()) ? filename.size() : path.size();
630 assertTrue (0 != icompare(path, path.size() - sz, sz, path));
631
632 Poco::FileInputStream fis(path);
633 assertTrue (fis.good());
634 std::string read;
635 std::string line;
636 while (std::getline(fis, line)) read += line;
637
638 assertTrue (!read.empty());
639 assertTrue (read == "This is some binary data. Really.");
640 }
641 }
642
643 message.write(ostr);
644 std::string msgout(ostr.str());
645 assertTrue (msgout == msgin);
646}
647
648
649void MailMessageTest::testEncodeWord()
650{
651 std::string plain("this is pure ASCII");
652 std::string encoded = MailMessage::encodeWord(plain, "ISO-8859-1");
653 assertTrue (encoded == plain);
654
655 plain = "This text contains German Umlauts: \xC4\xD6";
656 encoded = MailMessage::encodeWord(plain, "ISO-8859-1");
657 assertTrue (encoded == "=?ISO-8859-1?q?This_text_contains_German_Umlauts=3A_=C4=D6?=");
658
659 plain = "This text contains German Umlauts: \xC4\xD6. "
660 "It is also a very long text. Longer than 75 "
661 "characters. Long enough to become three lines "
662 "after being word-encoded.";
663 encoded = MailMessage::encodeWord(plain, "ISO-8859-1");
664 assertTrue (encoded == "=?ISO-8859-1?q?This_text_contains_German_Umlauts=3A_=C4=D6=2E_It_?=\r\n"
665 " =?ISO-8859-1?q?is_also_a_very_long_text=2E_Longer_than_75_characters=2E_?=\r\n"
666 " =?ISO-8859-1?q?Long_enough_to_become_three_lines_after_being_word-encode?=\r\n"
667 " =?ISO-8859-1?q?d=2E?=");
668
669 plain = "If you can read this yo";
670 encoded = MailMessage::encodeWord(plain, "ISO-8859-1", 'B');
671 assertTrue (encoded == "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=");
672
673 plain = "u understand the example.";
674 encoded = MailMessage::encodeWord(plain, "ISO-8859-2", 'B');
675 assertTrue (encoded == "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=");
676
677 plain = "This text contains German Umlauts: \xC4\xD6. "
678 "It is also a very long text. Longer than 75 "
679 "characters. Long enough to become three lines "
680 "after being word-encoded.";
681 encoded = MailMessage::encodeWord(plain, "ISO-8859-1", 'B');
682 assertTrue (encoded ==
683 "=?ISO-8859-1?B?VGhpcyB0ZXh0IGNvbnRhaW5zIEdlcm1hbiBVbWxhdXRzOiDE1i4gSQ==?=\r\n"
684 "=?ISO-8859-1?B?dCBpcyBhbHNvIGEgdmVyeSBsb25nIHRleHQuIExvbmdlciB0aGFuIA==?=\r\n"
685 "=?ISO-8859-1?B?NzUgY2hhcmFjdGVycy4gTG9uZyBlbm91Z2ggdG8gYmVjb21lIHRocg==?=\r\n"
686 "=?ISO-8859-1?B?ZWUgbGluZXMgYWZ0ZXIgYmVpbmcgd29yZC1lbmNvZGVkLg==?=");
687
688 std::string decoded = MailMessage::decodeWord(encoded);
689 assertTrue (decoded == plain);
690}
691
692
693void MailMessageTest::testDecodeWord()
694{
695 std::string encoded = "=?ISO-8859-1?q?=C4=D6?=";
696 std::string decoded = MailMessage::decodeWord(encoded);
697 assertTrue (decoded == "\xC4\xD6");
698
699 encoded = "=?ISO-8859-1?q?=C4=D6?=abc=?ISO-8859-1?q?=C4=D6?=";
700 decoded = MailMessage::decodeWord(encoded);
701 assertTrue (decoded == "\xC4\xD6" "abc" "\xC4\xD6");
702
703 decoded = MailMessage::decodeWord(encoded, "UTF-8");
704 assertTrue (decoded == "\xC3\x84\xC3\x96" "abc" "\xC3\x84\xC3\x96");
705
706 try
707 {
708 MailMessage::decodeWord("=?ISO-8859-1?q?=C4 =D6?=");
709 fail("must fail");
710 }
711 catch (Poco::InvalidArgumentException&) {}
712
713 try
714 {
715 MailMessage::decodeWord("=?ISO-8859-1?q?=C4?=D6?=\r\n");
716 fail("must fail");
717 }
718 catch (Poco::InvalidArgumentException&) {}
719
720 encoded = "=?ISO-8859-1?q?=C4=D6_It_?=\r\n=?ISO-8859-1?q?is?=";
721 decoded = MailMessage::decodeWord(encoded);
722 assertTrue (decoded == "\xC4\xD6 It is");
723
724 encoded = "=?ISO-8859-1?q?This_text_contains_German_Umlauts=3A_=C4=D6?=";
725 decoded = MailMessage::decodeWord(encoded);
726 assertTrue (decoded == "This text contains German Umlauts: \xC4\xD6");
727
728 decoded = MailMessage::decodeWord(encoded, "UTF-8");
729 assertTrue (decoded == "This text contains German Umlauts: \xC3\x84\xC3\x96");
730
731 encoded = "=?ISO-8859-1?q?This_text_contains_German_Umlauts=3A_=C4=D6=2E_It_?=\r\n"
732 "=?ISO-8859-1?q?is_also_a_very_long_text=2E_Longer_than_75_characters=2E_?=\r\n"
733 "=?ISO-8859-1?q?Long_enough_to_become_three_lines_after_being_word-encode?=\r\n"
734 "=?ISO-8859-1?q?d=2E?=";
735 decoded = MailMessage::decodeWord(encoded);
736 assertTrue (decoded == "This text contains German Umlauts: \xC4\xD6. It "
737 "is also a very long text. Longer than 75 characters. "
738 "Long enough to become three lines after being word-encode"
739 "d.");
740
741 decoded = MailMessage::decodeWord(encoded, "UTF-8");
742 assertTrue (decoded == "This text contains German Umlauts: \xC3\x84\xC3\x96. It "
743 "is also a very long text. Longer than 75 characters. "
744 "Long enough to become three lines after being word-encode"
745 "d.");
746
747 encoded = "=?ISO-8859-1?Q?=F8=E9?=";
748 decoded = MailMessage::decodeWord(encoded);
749 assertTrue (decoded == "\xF8\xE9");
750
751 encoded = "From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>\r\n"
752 "To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>\r\n"
753 "CC: =?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>\r\n"
754 "Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\r\n"
755 "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=";
756 decoded = MailMessage::decodeWord(encoded);
757 assertTrue (decoded == "From: Keith Moore <moore@cs.utk.edu>\r\n"
758 "To: Keld J\xF8rn Simonsen <keld@dkuug.dk>\r\n"
759 "CC: Andr\xE9 Pirard <PIRARD@vm1.ulg.ac.be>\r\n"
760 "Subject: If you can read this you understand the example.");
761
762 encoded = "From: =?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>\r\n"
763 "To: ietf-822@dimacs.rutgers.edu, ojarnef@admin.kth.se\r\n"
764 "Subject: Time for ISO 10646?";
765 decoded = MailMessage::decodeWord(encoded);
766 assertTrue (decoded == "From: Olle J\xE4rnefors <ojarnef@admin.kth.se>\r\n"
767 "To: ietf-822@dimacs.rutgers.edu, ojarnef@admin.kth.se\r\n"
768 "Subject: Time for ISO 10646?");
769
770 encoded = "To: Dave Crocker <dcrocker@mordor.stanford.edu>\r\n"
771 "Cc: ietf-822@dimacs.rutgers.edu, paf@comsol.se\r\n"
772 "From: =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>\r\n"
773 "Subject: Re: RFC-HDR care and feeding";
774 decoded = MailMessage::decodeWord(encoded);
775 assertTrue (decoded == "To: Dave Crocker <dcrocker@mordor.stanford.edu>\r\n"
776 "Cc: ietf-822@dimacs.rutgers.edu, paf@comsol.se\r\n"
777 "From: Patrik F\xE4ltstr\xF6m <paf@nada.kth.se>\r\n"
778 "Subject: Re: RFC-HDR care and feeding");
779
780 // encoded chars cannot be broken between lines
781 try
782 {
783 encoded = "=?ISO-8859-1?Q?=?=\r\n=?ISO-8859-1?Q?AB?=";
784 decoded = MailMessage::decodeWord(encoded);
785 fail("must fail");
786 }
787 catch (Poco::InvalidArgumentException&) {}
788
789 // comments and spaces therein
790 encoded = "(=?ISO-8859-1?Q?a?=)";
791 decoded = MailMessage::decodeWord(encoded);
792 assertTrue (decoded == "(a)");
793
794 encoded = "(=?ISO-8859-1?Q?a?= b =?ISO-8859-1?Q?c?=)";
795 decoded = MailMessage::decodeWord(encoded);
796 assertTrue (decoded == "(a b c)");
797
798 encoded = "(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)";
799 decoded = MailMessage::decodeWord(encoded);
800 assertTrue (decoded == "(ab)");
801
802 encoded = "(=?ISO-8859-1?Q?a?=\r\n\t=?ISO-8859-1?Q?b?=)";
803 decoded = MailMessage::decodeWord(encoded);
804 assertTrue (decoded == "(ab)");
805
806 encoded = "(=?ISO-8859-1?Q?a_b?=)";
807 decoded = MailMessage::decodeWord(encoded);
808 assertTrue (decoded == "(a b)");
809
810 encoded = "(=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=)";
811 decoded = MailMessage::decodeWord(encoded);
812 assertTrue (decoded == "(a b)");
813}
814
815
816void MailMessageTest::setUp()
817{
818}
819
820
821void MailMessageTest::tearDown()
822{
823}
824
825
826CppUnit::Test* MailMessageTest::suite()
827{
828 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MailMessageTest");
829
830 CppUnit_addTest(pSuite, MailMessageTest, testWriteQP);
831 CppUnit_addTest(pSuite, MailMessageTest, testWrite8Bit);
832 CppUnit_addTest(pSuite, MailMessageTest, testWriteBase64);
833 CppUnit_addTest(pSuite, MailMessageTest, testWriteManyRecipients);
834 CppUnit_addTest(pSuite, MailMessageTest, testWriteMultiPart);
835 CppUnit_addTest(pSuite, MailMessageTest, testReadQP);
836 CppUnit_addTest(pSuite, MailMessageTest, testReadDefaultTransferEncoding);
837 CppUnit_addTest(pSuite, MailMessageTest, testReadDefaultContentType);
838 CppUnit_addTest(pSuite, MailMessageTest, testRead8Bit);
839 CppUnit_addTest(pSuite, MailMessageTest, testReadMultiPart);
840 CppUnit_addTest(pSuite, MailMessageTest, testReadMultiPartWithAttachmentNames);
841 CppUnit_addTest(pSuite, MailMessageTest, testReadMultiPartDefaultTransferEncoding);
842 CppUnit_addTest(pSuite, MailMessageTest, testReadWriteMultiPart);
843 CppUnit_addTest(pSuite, MailMessageTest, testReadWriteMultiPartStore);
844 CppUnit_addTest(pSuite, MailMessageTest, testEncodeWord);
845 CppUnit_addTest(pSuite, MailMessageTest, testDecodeWord);
846
847 return pSuite;
848}
849