📄 mailmessage.cpp
字号:
//// MailMessage.cpp//// $Id: //poco/1.2/Net/src/MailMessage.cpp#3 $//// Library: Net// Package: Mail// Module: MailMessage//// 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/MailMessage.h"#include "Poco/Net/MediaType.h"#include "Poco/Net/MultipartReader.h"#include "Poco/Net/MultipartWriter.h"#include "Poco/Net/PartSource.h"#include "Poco/Net/PartHandler.h"#include "Poco/Net/QuotedPrintableEncoder.h"#include "Poco/Net/QuotedPrintableDecoder.h"#include "Poco/Base64Encoder.h"#include "Poco/Base64Decoder.h"#include "Poco/StreamCopier.h"#include "Poco/DateTimeFormat.h"#include "Poco/DateTimeFormatter.h"#include "Poco/DateTimeParser.h"#include "Poco/String.h"#include <sstream>#include <ctype.h>using Poco::Base64Encoder;using Poco::Base64Decoder;using Poco::StreamCopier;using Poco::DateTimeFormat;using Poco::DateTimeFormatter;using Poco::DateTimeParser;using Poco::icompare;namespace Poco {namespace Net {namespace{ class StringPartHandler: public PartHandler { public: StringPartHandler(std::string& content): _str(content) { } ~StringPartHandler() { } void handlePart(const MessageHeader& header, std::istream& stream) { int ch = stream.get(); while (ch >= 0) { _str += (char) ch; ch = stream.get(); } } private: std::string& _str; };}const std::string MailMessage::HEADER_SUBJECT("Subject");const std::string MailMessage::HEADER_FROM("From");const std::string MailMessage::HEADER_TO("To");const std::string MailMessage::HEADER_CC("CC");const std::string MailMessage::HEADER_BCC("BCC");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_MIME_VERSION("Mime-Version");const std::string MailMessage::EMPTY_HEADER;const std::string MailMessage::TEXT_PLAIN("text/plain");const std::string MailMessage::CTE_7BIT("7bit");const std::string MailMessage::CTE_8BIT("8bit");const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable");const std::string MailMessage::CTE_BASE64("base64");MailMessage::MailMessage(){ Poco::Timestamp now; setDate(now); setContentType("text/plain");}MailMessage::~MailMessage(){ for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) { delete it->pSource; }} void MailMessage::addRecipient(const MailRecipient& recipient){ _recipients.push_back(recipient);}void MailMessage::setSender(const std::string& sender){ set(HEADER_FROM, sender);} const std::string& MailMessage::getSender() const{ if (has(HEADER_FROM)) return get(HEADER_FROM); else return EMPTY_HEADER;} void MailMessage::setSubject(const std::string& subject){ set(HEADER_SUBJECT, subject);} const std::string& MailMessage::getSubject() const{ if (has(HEADER_SUBJECT)) return get(HEADER_SUBJECT); else return EMPTY_HEADER;}void MailMessage::setContent(const std::string& content, ContentTransferEncoding encoding){ _content = content; _encoding = encoding; set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(encoding));}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)) return get(HEADER_CONTENT_TYPE); else return TEXT_PLAIN;}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); int tzd; return DateTimeParser::parse(dateTime, tzd).timestamp();} bool MailMessage::isMultipart() const{ MediaType mediaType = getContentType(); return mediaType.matches("multipart");}void MailMessage::addPart(const std::string& name, PartSource* pSource, ContentDisposition disposition, ContentTransferEncoding encoding){ poco_check_ptr (pSource); makeMultipart(); Part part; part.name = name; part.pSource = pSource; part.disposition = disposition; part.encoding = encoding; _parts.push_back(part);}void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encoding){ addPart("", pSource, CONTENT_INLINE, encoding);} void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding){ addPart(name, pSource, CONTENT_ATTACHMENT, encoding);}void MailMessage::read(std::istream& istr, PartHandler& handler){ readHeader(istr); if (isMultipart()) { readMultipart(istr, handler); } else { StringPartHandler handler(_content); readPart(istr, *this, handler); }}void MailMessage::read(std::istream& istr){ readHeader(istr); StringPartHandler handler(_content); readPart(istr, *this, handler);}void MailMessage::write(std::ostream& ostr) const{ MessageHeader header(*this); setRecipientHeaders(header); if (isMultipart()) { writeMultipart(header, ostr); } else { writeHeader(header, ostr); std::istringstream istr(_content); writeEncoded(istr, ostr, _encoding); }}void MailMessage::makeMultipart(){ if (!isMultipart()) { MediaType mediaType("multipart", "mixed"); setContentType(mediaType); }}void MailMessage::writeHeader(const MessageHeader& header, std::ostream& ostr) const{ header.write(ostr); ostr << "\r\n";}void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) const{ std::string boundary(MultipartWriter::createBoundary()); MediaType mediaType(getContentType()); 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); for (PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it) { writePart(writer, *it); } writer.close();}void MailMessage::writePart(MultipartWriter& writer, const Part& part) const{ MessageHeader partHeader; MediaType mediaType(part.pSource->mediaType()); if (!part.name.empty()) mediaType.setParameter("name", part.name); partHeader.set(HEADER_CONTENT_TYPE, mediaType.toString()); partHeader.set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(part.encoding)); std::string disposition; if (part.disposition == CONTENT_ATTACHMENT) { disposition = "attachment"; const std::string& filename = part.pSource->filename(); if (!filename.empty()) { disposition.append("; filename="); quote(filename, disposition); } } else disposition = "inline"; partHeader.set(HEADER_CONTENT_DISPOSITION, disposition); writer.nextPart(partHeader); writeEncoded(part.pSource->stream(), writer.stream(), part.encoding);}void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const{ switch (encoding) { case ENCODING_7BIT: case ENCODING_8BIT: StreamCopier::copyStream(istr, ostr); break; case ENCODING_QUOTED_PRINTABLE: { QuotedPrintableEncoder encoder(ostr); StreamCopier::copyStream(istr, encoder); } break; case ENCODING_BASE64: { Base64Encoder encoder(ostr); StreamCopier::copyStream(istr, encoder); } break; }}void MailMessage::readHeader(std::istream& istr){ clear(); MessageHeader::read(istr); istr.get(); // \r istr.get(); // \n}void MailMessage::readMultipart(std::istream& istr, PartHandler& handler){ MediaType contentType(getContentType()); std::string boundary = contentType.getParameter("boundary"); MultipartReader reader(istr, boundary); while (reader.hasNextPart()) { MessageHeader partHeader; reader.nextPart(partHeader); readPart(reader.stream(), partHeader, handler); }}void MailMessage::readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler){ std::string encoding; if (header.has(HEADER_CONTENT_TRANSFER_ENCODING)) { encoding = header.get(HEADER_CONTENT_TRANSFER_ENCODING); // get rid of a parameter if one is set std::string::size_type pos = encoding.find(';'); if (pos != std::string::npos) encoding.resize(pos); } if (icompare(encoding, CTE_QUOTED_PRINTABLE) == 0) { QuotedPrintableDecoder decoder(istr); handlePart(decoder, header, handler); } else if (icompare(encoding, CTE_BASE64) == 0) { Base64Decoder decoder(istr); handlePart(decoder, header, handler); } else { handlePart(istr, header, handler); }}void MailMessage::handlePart(std::istream& istr, const MessageHeader& header, PartHandler& handler){ handler.handlePart(header, istr); // Read remaining characters from stream in case // the handler failed to read the complete stream. while (istr.good()) istr.get();}void MailMessage::setRecipientHeaders(MessageHeader& headers) const{ std::string to; std::string cc; std::string bcc; for (Recipients::const_iterator it = _recipients.begin(); it != _recipients.end(); ++it) { switch (it->getType()) { case MailRecipient::PRIMARY_RECIPIENT: appendRecipient(*it, to); break; case MailRecipient::CC_RECIPIENT: appendRecipient(*it, cc); break; case MailRecipient::BCC_RECIPIENT: break; } } if (!to.empty()) headers.set(HEADER_TO, to); if (!cc.empty()) headers.set(HEADER_CC, cc);}const std::string& MailMessage::contentTransferEncodingToString(ContentTransferEncoding encoding){ switch (encoding) { case ENCODING_7BIT: return CTE_8BIT; case ENCODING_8BIT: return CTE_8BIT; case ENCODING_QUOTED_PRINTABLE: return CTE_QUOTED_PRINTABLE; case ENCODING_BASE64: return CTE_BASE64; default: poco_bugcheck(); } return CTE_7BIT;}int MailMessage::lineLength(const std::string& str){ int n = 0; std::string::const_reverse_iterator it = str.rbegin(); std::string::const_reverse_iterator end = str.rend(); while (it != end && *it != '\n') { ++n; ++it; } return n;}void MailMessage::appendRecipient(const MailRecipient& recipient, std::string& str){ if (!str.empty()) str.append(", "); const std::string& realName = recipient.getRealName(); const std::string& address = recipient.getAddress(); std::string rec; if (!realName.empty()) { quote(realName, rec, true); rec.append(" "); } rec.append("<"); rec.append(address); rec.append(">"); if (lineLength(str) + rec.length() > 70) str.append("\r\n\t"); str.append(rec);}} } // namespace Poco::Net
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -