mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 16:48:06 +02:00
MailMessage: attachments saving and read/write
MailMessage: attachments saving support and consistent read/write
This commit is contained in:
@@ -40,8 +40,10 @@
|
||||
#include "Poco/Net/MultipartWriter.h"
|
||||
#include "Poco/Net/PartSource.h"
|
||||
#include "Poco/Net/PartHandler.h"
|
||||
#include "Poco/Net/StringPartSource.h"
|
||||
#include "Poco/Net/QuotedPrintableEncoder.h"
|
||||
#include "Poco/Net/QuotedPrintableDecoder.h"
|
||||
#include "Poco/Net/NameValueCollection.h"
|
||||
#include "Poco/Base64Encoder.h"
|
||||
#include "Poco/Base64Decoder.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
@@ -49,6 +51,7 @@
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/DateTimeParser.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include <sstream>
|
||||
@@ -60,6 +63,7 @@ using Poco::StreamCopier;
|
||||
using Poco::DateTimeFormat;
|
||||
using Poco::DateTimeFormatter;
|
||||
using Poco::DateTimeParser;
|
||||
using Poco::StringTokenizer;
|
||||
using Poco::icompare;
|
||||
|
||||
|
||||
@@ -69,21 +73,107 @@ namespace Net {
|
||||
|
||||
namespace
|
||||
{
|
||||
class StringPartHandler: public PartHandler
|
||||
class MultiPartHandler: public PartHandler
|
||||
/// This is a default part handler for multipart messages, used when there
|
||||
/// is no external handler provided to he MailMessage. This handler
|
||||
/// will handle all types of message parts, including attachments.
|
||||
{
|
||||
public:
|
||||
StringPartHandler(std::string& content):
|
||||
_str(content)
|
||||
MultiPartHandler(MailMessage* pMsg): _pMsg(pMsg)
|
||||
/// Creates multi part handler.
|
||||
/// The pMsg pointer points to the calling MailMessage
|
||||
/// and will be used to properly populate it, so the
|
||||
/// message content could be written out unmodified
|
||||
/// in its entirety, including attachments.
|
||||
{
|
||||
}
|
||||
|
||||
~StringPartHandler()
|
||||
~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
|
||||
/// back out at a later point in time.
|
||||
{
|
||||
Poco::StreamCopier::copyToString(stream, _str);
|
||||
std::string tmp;
|
||||
Poco::StreamCopier::copyToString(stream, tmp);
|
||||
if (_pMsg)
|
||||
{
|
||||
|
||||
MailMessage::ContentTransferEncoding cte = MailMessage::ENCODING_7BIT;
|
||||
std::string enc = header[MailMessage::HEADER_CONTENT_TRANSFER_ENCODING];
|
||||
if (enc == MailMessage::CTE_8BIT)
|
||||
cte = MailMessage::ENCODING_8BIT;
|
||||
else if (enc == MailMessage::CTE_QUOTED_PRINTABLE)
|
||||
cte = MailMessage::ENCODING_QUOTED_PRINTABLE;
|
||||
else if (enc == MailMessage::CTE_BASE64)
|
||||
cte = MailMessage::ENCODING_BASE64;
|
||||
|
||||
NameValueCollection::ConstIterator it = header.begin();
|
||||
NameValueCollection::ConstIterator end = header.end();
|
||||
PartSource* pPS = _pMsg->getPartStore(tmp,
|
||||
header[MailMessage::HEADER_CONTENT_TYPE],
|
||||
getFileNameFromDisp(it->second));
|
||||
poco_check_ptr (pPS);
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (MailMessage::HEADER_CONTENT_DISPOSITION == it->first)
|
||||
{
|
||||
if (it->second == "inline") _pMsg->addContent(pPS, cte);
|
||||
else _pMsg->addAttachment("", pPS, cte);
|
||||
}
|
||||
|
||||
pPS->headers().set(it->first, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string getFileNameFromDisp(const std::string& str)
|
||||
{
|
||||
StringTokenizer st(str, ";=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
||||
StringTokenizer::Iterator it = st.begin();
|
||||
StringTokenizer::Iterator end = st.end();
|
||||
for (; it != end; ++it) { if (*it == "filename") break; }
|
||||
if (it != end)
|
||||
{
|
||||
++it;
|
||||
if (it == end) return "";
|
||||
return *it;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
MailMessage* _pMsg;
|
||||
};
|
||||
|
||||
|
||||
class StringPartHandler: public PartHandler
|
||||
/// This is a default part handler, used when there is no
|
||||
/// external handler provided to the MailMessage. This handler
|
||||
/// handles only single-part messages.
|
||||
{
|
||||
public:
|
||||
StringPartHandler(std::string& content): _str(content)
|
||||
/// Creates string part handler.
|
||||
/// The content parameter represents the part content.
|
||||
{
|
||||
}
|
||||
|
||||
~StringPartHandler()
|
||||
/// Destroys string part handler.
|
||||
{
|
||||
}
|
||||
|
||||
void handlePart(const MessageHeader& header, std::istream& stream)
|
||||
/// Handles a part.
|
||||
{
|
||||
std::string tmp;
|
||||
Poco::StreamCopier::copyToString(stream, tmp);
|
||||
_str.append(tmp);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -101,6 +191,7 @@ const std::string MailMessage::HEADER_DATE("Date");
|
||||
const std::string MailMessage::HEADER_CONTENT_TYPE("Content-Type");
|
||||
const std::string MailMessage::HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
|
||||
const std::string MailMessage::HEADER_CONTENT_DISPOSITION("Content-Disposition");
|
||||
const std::string MailMessage::HEADER_CONTENT_ID("Content-ID");
|
||||
const std::string MailMessage::HEADER_MIME_VERSION("Mime-Version");
|
||||
const std::string MailMessage::EMPTY_HEADER;
|
||||
const std::string MailMessage::TEXT_PLAIN("text/plain");
|
||||
@@ -110,7 +201,8 @@ const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable");
|
||||
const std::string MailMessage::CTE_BASE64("base64");
|
||||
|
||||
|
||||
MailMessage::MailMessage()
|
||||
MailMessage::MailMessage(PartStoreFactory* pStoreFactory):
|
||||
_pStoreFactory(pStoreFactory)
|
||||
{
|
||||
Poco::Timestamp now;
|
||||
setDate(now);
|
||||
@@ -263,8 +355,16 @@ void MailMessage::read(std::istream& istr, PartHandler& handler)
|
||||
void MailMessage::read(std::istream& istr)
|
||||
{
|
||||
readHeader(istr);
|
||||
StringPartHandler handler(_content);
|
||||
readPart(istr, *this, handler);
|
||||
if (isMultipart())
|
||||
{
|
||||
MultiPartHandler handler(this);
|
||||
readMultipart(istr, handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringPartHandler handler(_content);
|
||||
readPart(istr, *this, handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -304,14 +404,14 @@ void MailMessage::writeHeader(const MessageHeader& header, std::ostream& ostr) c
|
||||
|
||||
void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) const
|
||||
{
|
||||
std::string boundary(MultipartWriter::createBoundary());
|
||||
if (_boundary.empty()) _boundary = MultipartWriter::createBoundary();
|
||||
MediaType mediaType(getContentType());
|
||||
mediaType.setParameter("boundary", boundary);
|
||||
mediaType.setParameter("boundary", _boundary);
|
||||
header.set(HEADER_CONTENT_TYPE, mediaType.toString());
|
||||
header.set(HEADER_MIME_VERSION, "1.0");
|
||||
writeHeader(header, ostr);
|
||||
|
||||
MultipartWriter writer(ostr, boundary);
|
||||
MultipartWriter writer(ostr, _boundary);
|
||||
for (PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it)
|
||||
{
|
||||
writePart(writer, *it);
|
||||
@@ -384,8 +484,8 @@ void MailMessage::readHeader(std::istream& istr)
|
||||
void MailMessage::readMultipart(std::istream& istr, PartHandler& handler)
|
||||
{
|
||||
MediaType contentType(getContentType());
|
||||
std::string boundary = contentType.getParameter("boundary");
|
||||
MultipartReader reader(istr, boundary);
|
||||
_boundary = contentType.getParameter("boundary");
|
||||
MultipartReader reader(istr, _boundary);
|
||||
while (reader.hasNextPart())
|
||||
{
|
||||
MessageHeader partHeader;
|
||||
@@ -580,4 +680,11 @@ std::string MailMessage::encodeWord(const std::string& text, const std::string&
|
||||
}
|
||||
|
||||
|
||||
PartSource* MailMessage::getPartStore(const std::string& content, const std::string& mediaType, const std::string& filename)
|
||||
{
|
||||
if (!_pStoreFactory) return new StringPartSource(content, mediaType, filename);
|
||||
else return _pStoreFactory->createPartStore(content, mediaType, filename);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@@ -64,7 +64,7 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
const std::string& PartSource::filename()
|
||||
const std::string& PartSource::filename() const
|
||||
{
|
||||
return EMPTY;
|
||||
}
|
||||
|
103
Net/src/PartStore.cpp
Normal file
103
Net/src/PartStore.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// PartStore.cpp
|
||||
//
|
||||
// $Id: //poco/1.4/Net/src/PartStore.cpp#1 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Messages
|
||||
// Module: PartStore
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Net/PartStore.h"
|
||||
#include "Poco/TemporaryFile.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
/// PartStore
|
||||
|
||||
PartStore::PartStore(const std::string& mediaType): PartSource(mediaType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PartStore::~PartStore()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// FilePartStore
|
||||
|
||||
FilePartStore::FilePartStore(const std::string& content, const std::string& mediaType, const std::string& filename):
|
||||
PartStore(mediaType),
|
||||
_filename(filename),
|
||||
_path(TemporaryFile::tempName()),
|
||||
_fstr(_path)
|
||||
{
|
||||
_fstr << content << std::flush;
|
||||
_fstr.seekg(0, std::ios::beg);
|
||||
}
|
||||
|
||||
|
||||
FilePartStore::~FilePartStore()
|
||||
{
|
||||
try
|
||||
{
|
||||
_fstr.close();
|
||||
File(_path).remove();
|
||||
}
|
||||
catch (Exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::istream& FilePartStore::stream()
|
||||
{
|
||||
return _fstr;
|
||||
}
|
||||
|
||||
|
||||
const std::string& FilePartStore::filename() const
|
||||
{
|
||||
return _filename;
|
||||
}
|
||||
|
||||
|
||||
const std::string& FilePartStore::path() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
@@ -74,7 +74,7 @@ std::istream& StringPartSource::stream()
|
||||
}
|
||||
|
||||
|
||||
const std::string& StringPartSource::filename()
|
||||
const std::string& StringPartSource::filename() const
|
||||
{
|
||||
return _filename;
|
||||
}
|
||||
|
Reference in New Issue
Block a user