From ad1b75b30e445be213f23a9df57aade64ab50d29 Mon Sep 17 00:00:00 2001 From: Alex Fabijanic Date: Tue, 10 Oct 2017 18:06:02 -0500 Subject: [PATCH] POP3 client fails to retrieve message if content-type is absent #806; add multi-part attachment name retrieval --- Net/src/MailMessage.cpp | 32 +++++++++++++++++---------- Net/src/MultipartReader.cpp | 6 ++--- Net/testsuite/src/MailMessageTest.cpp | 28 +++++++++++++++++++++-- Net/testsuite/src/MailMessageTest.h | 1 + 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/Net/src/MailMessage.cpp b/Net/src/MailMessage.cpp index c478082a3..e9776b897 100644 --- a/Net/src/MailMessage.cpp +++ b/Net/src/MailMessage.cpp @@ -65,12 +65,12 @@ namespace /// in its entirety, including attachments. { } - + ~MultiPartHandler() /// Destroys string part handler. { } - + void handlePart(const MessageHeader& header, std::istream& stream) /// Handles a part. If message pointer was provided at construction time, /// the message pointed to will be properly populated so it could be written @@ -92,7 +92,7 @@ namespace cte = MailMessage::ENCODING_BASE64; } - std::string contentType = header.get(MailMessage::HEADER_CONTENT_TYPE, ""); + std::string contentType = header.get(MailMessage::HEADER_CONTENT_TYPE, "text/plain; charset=us-ascii"); std::string contentDisp = header.get(MailMessage::HEADER_CONTENT_DISPOSITION, ""); std::string filename; if (!contentDisp.empty()) @@ -110,8 +110,8 @@ namespace { if (it->second == "inline") _pMsg->addContent(pPS, cte); - else - _pMsg->addAttachment("", pPS, cte); + else + _pMsg->addAttachment(getPartName(header), pPS, cte); added = true; } @@ -134,7 +134,7 @@ namespace StringTokenizer st(header, ";=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); StringTokenizer::Iterator it = st.begin(); StringTokenizer::Iterator end = st.end(); - for (; it != end; ++it) { if (*it == param) break; } + for (; it != end; ++it) { if (icompare(*it, param) == 0) break; } if (it != end) { ++it; @@ -144,6 +144,14 @@ namespace return ""; } + std::string getPartName(const MessageHeader& header) + { + std::string ct = MailMessage::HEADER_CONTENT_TYPE; + if (header.has(ct)) + return getParamFromHeader(header[ct], "name"); + return ""; + } + MailMessage* _pMsg; }; @@ -216,7 +224,7 @@ MailMessage::~MailMessage() } } - + void MailMessage::addRecipient(const MailRecipient& recipient) { _recipients.push_back(recipient); @@ -272,13 +280,13 @@ void MailMessage::setContentType(const std::string& mediaType) set(HEADER_CONTENT_TYPE, mediaType); } - + void MailMessage::setContentType(const MediaType& mediaType) { setContentType(mediaType.toString()); } - + const std::string& MailMessage::getContentType() const { if (has(HEADER_CONTENT_TYPE)) @@ -293,7 +301,7 @@ void MailMessage::setDate(const Poco::Timestamp& dateTime) set(HEADER_DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::RFC1123_FORMAT)); } - + Poco::Timestamp MailMessage::getDate() const { const std::string& dateTime = get(HEADER_DATE); @@ -301,7 +309,7 @@ Poco::Timestamp MailMessage::getDate() const return DateTimeParser::parse(dateTime, tzd).timestamp(); } - + bool MailMessage::isMultipart() const { MediaType mediaType = getContentType(); @@ -328,7 +336,7 @@ void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encodi addPart("", pSource, CONTENT_INLINE, encoding); } - + void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding) { addPart(name, pSource, CONTENT_ATTACHMENT, encoding); diff --git a/Net/src/MultipartReader.cpp b/Net/src/MultipartReader.cpp index 29408cd08..579d67aea 100644 --- a/Net/src/MultipartReader.cpp +++ b/Net/src/MultipartReader.cpp @@ -88,7 +88,7 @@ int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length) { buf.sbumpc(); // '\n' } - return 0; + return 0; } else if (ch == '-' && buf.sgetc() == '-') { @@ -218,11 +218,11 @@ bool MultipartReader::hasNextPart() return (!_pMPI || !_pMPI->lastPart()) && _istr.good(); } - + std::istream& MultipartReader::stream() const { poco_check_ptr (_pMPI); - + return *_pMPI; } diff --git a/Net/testsuite/src/MailMessageTest.cpp b/Net/testsuite/src/MailMessageTest.cpp index 26b5d387a..30a104f92 100644 --- a/Net/testsuite/src/MailMessageTest.cpp +++ b/Net/testsuite/src/MailMessageTest.cpp @@ -374,6 +374,28 @@ void MailMessageTest::testReadDefaultTransferEncoding() } +void MailMessageTest::testReadDefaultContentType() +{ + std::istringstream istr("Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + ); + + MailMessage message; + message.read(istr); + + assert (message.getSender() == "poco@appinf.com"); + assert (message.getContentType() == "text/plain"); + assert (message.getContent() == "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + ); +} + + void MailMessageTest::testRead8Bit() { std::istringstream istr( @@ -468,10 +490,10 @@ void MailMessageTest::testReadMultiPartWithAttachmentNames() "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n" "--MIME_boundary_01234567--\r\n" ); - + MailMessage message; message.read(istr); - + assert (message.parts().size() == 2); assert (message.parts()[1].name == "sample"); assert (message.parts()[1].pSource->filename() == "sample.dat"); @@ -667,8 +689,10 @@ CppUnit::Test* MailMessageTest::suite() CppUnit_addTest(pSuite, MailMessageTest, testWriteMultiPart); CppUnit_addTest(pSuite, MailMessageTest, testReadQP); CppUnit_addTest(pSuite, MailMessageTest, testReadDefaultTransferEncoding); + CppUnit_addTest(pSuite, MailMessageTest, testReadDefaultContentType); CppUnit_addTest(pSuite, MailMessageTest, testRead8Bit); CppUnit_addTest(pSuite, MailMessageTest, testReadMultiPart); + CppUnit_addTest(pSuite, MailMessageTest, testReadMultiPartWithAttachmentNames); CppUnit_addTest(pSuite, MailMessageTest, testReadMultiPartDefaultTransferEncoding); CppUnit_addTest(pSuite, MailMessageTest, testReadWriteMultiPart); CppUnit_addTest(pSuite, MailMessageTest, testReadWriteMultiPartStore); diff --git a/Net/testsuite/src/MailMessageTest.h b/Net/testsuite/src/MailMessageTest.h index b46aa6dc4..603a5bf60 100644 --- a/Net/testsuite/src/MailMessageTest.h +++ b/Net/testsuite/src/MailMessageTest.h @@ -32,6 +32,7 @@ public: void testReadWriteMultiPart(); void testReadWriteMultiPartStore(); void testReadDefaultTransferEncoding(); + void testReadDefaultContentType(); void testReadQP(); void testRead8Bit(); void testReadMultiPart();