backport MultipartSource for MailMessage from develop branch

This commit is contained in:
Günter Obiltschnig 2018-10-29 13:46:59 +01:00
parent 5d77b3f945
commit fd57b3b34c
2 changed files with 101 additions and 4 deletions

View File

@ -22,7 +22,9 @@
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/MailRecipient.h"
#include "Poco/Net/PartStore.h"
#include "Poco/SharedPtr.h"
#include "Poco/Timestamp.h"
#include <sstream>
#include <vector>
@ -34,6 +36,7 @@ class MediaType;
class PartSource;
class PartHandler;
class MultipartWriter;
class MultipartSource;
class Net_API MailMessage: public MessageHeader
@ -263,8 +266,8 @@ protected:
void makeMultipart();
void writeHeader(const MessageHeader& header, std::ostream& ostr) const;
void writeMultipart(MessageHeader& header, std::ostream& ostr) const;
void writePart(MultipartWriter& writer, const Part& part) const;
void writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const;
static void writePart(MultipartWriter& writer, const Part& part);
static void writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding);
void setRecipientHeaders(MessageHeader& headers) const;
void readHeader(std::istream& istr);
void readMultipart(std::istream& istr, PartHandler& handler);
@ -284,6 +287,47 @@ private:
ContentTransferEncoding _encoding;
mutable std::string _boundary;
PartStoreFactory* _pStoreFactory;
friend class MultipartSource;
};
class Net_API MultipartSource: public PartSource
/// This is a PartSource for constructing complex
/// mail messages consisting of multiple nested parts.
{
public:
explicit MultipartSource(const std::string contentType = "multipart/alternative");
/// Creates an empty MultipartSource.
///
/// At least one part must be added with addPart().
~MultipartSource();
/// Destroys the MultipartSource.
void addPart(const std::string& name,
PartSource* pSource,
MailMessage::ContentDisposition disposition,
MailMessage::ContentTransferEncoding encoding);
/// Adds a part/attachment to the MultipartSource.
///
/// The MultipartSource takes ownership of the PartSource and deletes it
/// when it is no longer needed.
///
/// The part name, and the filename specified in the part source
/// must not contain any non-ASCII characters.
/// To include non-ASCII characters in the part name or filename,
/// use RFC 2047 word encoding (see encodeWord()).
// PartSource
std::istream& stream();
protected:
static std::string contentTypeWithBoundary(const std::string& contentType);
private:
std::vector<MailMessage::Part> _parts;
std::stringstream _content;
};

View File

@ -418,7 +418,7 @@ void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) cons
}
void MailMessage::writePart(MultipartWriter& writer, const Part& part) const
void MailMessage::writePart(MultipartWriter& writer, const Part& part)
{
MessageHeader partHeader(part.pSource->headers());
MediaType mediaType(part.pSource->mediaType());
@ -444,7 +444,7 @@ void MailMessage::writePart(MultipartWriter& writer, const Part& part) const
}
void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const
void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding)
{
switch (encoding)
{
@ -692,4 +692,57 @@ PartSource* MailMessage::createPartStore(const std::string& content, const std::
}
MultipartSource::MultipartSource(const std::string contentType):
PartSource(contentTypeWithBoundary(contentType))
{
}
MultipartSource::~MultipartSource()
{
for (MailMessage::PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it)
{
delete it->pSource;
}
}
void MultipartSource::addPart(const std::string& name,
PartSource* pSource,
MailMessage::ContentDisposition disposition,
MailMessage::ContentTransferEncoding encoding)
{
MailMessage::Part part;
part.name = name;
part.pSource = pSource;
part.disposition = disposition;
part.encoding = encoding;
_parts.push_back(part);
}
std::istream& MultipartSource::stream()
{
MediaType mt(mediaType());
std::string boundary = mt.getParameter("boundary");
MultipartWriter writer(_content, boundary);
for (MailMessage::PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it)
{
MailMessage::writePart(writer, *it);
}
writer.close();
return _content;
}
std::string MultipartSource::contentTypeWithBoundary(const std::string& contentType)
{
MediaType mediaType(contentType);
mediaType.setParameter("boundary", MultipartWriter::createBoundary());
return mediaType.toString();
}
} } // namespace Poco::Net