From 4677fe8a34329bd0bb124d130b32ac79f33450c6 Mon Sep 17 00:00:00 2001 From: randomdan Date: Fri, 15 Jul 2011 16:06:37 +0000 Subject: Automatically sort the order of the MailParts to make life carefree and fix the order of HTML/plain text alternatives --- project2/sendmailTask.cpp | 71 +++++++++++++++++++++++++++++++++++------------ project2/sendmailTask.h | 10 ++++++- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp index ba2f3b0..073022f 100644 --- a/project2/sendmailTask.cpp +++ b/project2/sendmailTask.cpp @@ -12,6 +12,8 @@ DECLARE_LOADER("sendmail", SendMailTask); +uint8_t SendMailTask::MailPart::mimeIdx; + class SendEmailFailed : public std::runtime_error { public: SendEmailFailed(const std::string & what) : std::runtime_error(what) { } @@ -45,9 +47,29 @@ SendMailTask::writeMailWrapper(void ** buf, int * len, void * arg) return static_cast(arg)->writeMail(buf, len); } +SendMailTask::MailPart::MailPart(uint8_t s, uint8_t i, uint8_t p) : + sec(s), + ind(i), + prt(p) +{ +} + +SendMailTask::MailPart::~MailPart() +{ +} + +bool +SendMailTask::SortMailParts::operator()(const MailPartPtr & a, const MailPartPtr & b) const +{ + return (a->sec < b->sec) || ((a->sec == b->sec) && (a->ind < b->ind)) + || ((a->sec == b->sec) && (a->ind == b->ind) && (a->prt < b->prt)); +} + class BoundaryBegin : public SendMailTask::MailPart { public: - BoundaryBegin(const std::string & ct) : contentType(ct) { + BoundaryBegin(const std::string & ct, uint8_t m) : + MailPart(m, MailPart::mimeIdx, 0), + contentType(ct) { } const char * write(char ** buf, int * len) { *len = asprintf(buf, "\r\n--<>\r\nContent-Type: %s\r\n\r\n", contentType.c_str()); @@ -59,6 +81,9 @@ class BoundaryBegin : public SendMailTask::MailPart { class BoundaryEnd : public SendMailTask::MailPart { public: + BoundaryEnd() : + MailPart(255, 0, 0) { + } const char * write(char **, int * len) { *len = 19; return "\r\n--<>--\r\n"; @@ -68,10 +93,14 @@ class BoundaryEnd : public SendMailTask::MailPart { class Header : public SendMailTask::MailPart { public: Header(const std::string & h, const VariableType & v) : - header(h), value(v) { + MailPart(0, 0, 0), + header(h), + value(v) { } Header(const std::string & h, const char * v) : - header(h), value(v) { + MailPart(0, 0, 0), + header(h), + value(v) { } const char * write(char ** buf, int * len) { writeText(buf, len, value); @@ -87,7 +116,10 @@ class Header : public SendMailTask::MailPart { class MimeContent : public SendMailTask::MailPart { public: - MimeContent(const char * s, int l) : str(s), length(l) { + MimeContent(const char * s, int l, uint8_t m) : + MailPart(m, MailPart::mimeIdx, 1), + str(s), + length(l) { } const char * write(char ** buf, int * len) { *buf = NULL; @@ -119,23 +151,25 @@ class TransformHtmlToEmail : public TransformImpl(cdoc->doc); int len = 0; xmlDocDumpFormatMemoryEnc(doc, &buf, &len, "utf-8", 1); - parts->parts.push_back(new BoundaryBegin("text/html; utf-8")); - parts->parts.push_back(new MimeContent(reinterpret_cast(buf), len)); + parts->parts.insert(new BoundaryBegin("text/html; utf-8", 2)); + parts->parts.insert(new MimeContent(reinterpret_cast(buf), len, 2)); + SendMailTask::MailPart::mimeIdx += 1; } private: mutable xmlChar * buf; }; -DECLARE_TRANSFORM(TransformHtmlToEmail) +DECLARE_TRANSFORM(TransformHtmlToEmail); class TransformTextToEmail : public TransformImpl { public: void transform(const TextDocument * str, SendMailTask::Parts * parts) const { - parts->parts.push_back(new BoundaryBegin("text/plain; utf-8")); - parts->parts.push_back(new MimeContent(str->doc.c_str(), str->doc.length())); + parts->parts.insert(new BoundaryBegin("text/plain; utf-8", 1)); + parts->parts.insert(new MimeContent(str->doc.c_str(), str->doc.length(), 1)); + SendMailTask::MailPart::mimeIdx += 1; } }; -DECLARE_TRANSFORM(TransformTextToEmail) +DECLARE_TRANSFORM(TransformTextToEmail); PresenterPtr SendMailTask::createDefaultPresenter(const xmlpp::Element * n) const @@ -155,17 +189,18 @@ void SendMailTask::execute() const { parts = new Parts(); - parts->parts.push_back(new Header("To", to)); - parts->parts.push_back(new Header("From", from)); - parts->parts.push_back(new Header("Subject", subject)); - parts->parts.push_back(new Header("Content-Type", "multipart/alternative; boundary=\"<>\"")); - parts->parts.push_back(new Header("MIME-Version", "1.0")); - parts->parts.push_back(new Header("Content-Transfer-Encoding", "binary")); + MailPart::mimeIdx = 0; + parts->parts.insert(new Header("To", to)); + parts->parts.insert(new Header("From", from)); + parts->parts.insert(new Header("Subject", subject)); + parts->parts.insert(new Header("Content-Type", "multipart/alternative; boundary=\"<>\"")); + parts->parts.insert(new Header("MIME-Version", "1.0")); + parts->parts.insert(new Header("Content-Transfer-Encoding", "binary")); + parts->parts.insert(new BoundaryEnd()); ViewHostPtr vsp = new ViewHost("emails", present); vsp->executeViews(boost::bind(&SendMailTask::createDefaultPresenter, this, _1)); vsp->doTransforms(); - parts->parts.push_back(new BoundaryEnd()); part = parts->parts.begin(); // Write email @@ -180,7 +215,7 @@ SendMailTask::execute() const smtp_strerror(smtp_errno(), buf, sizeof buf); throw SendEmailFailed(buf); } - parts->parts.clear(); + parts.reset(); } const char * diff --git a/project2/sendmailTask.h b/project2/sendmailTask.h index e57a309..f871574 100644 --- a/project2/sendmailTask.h +++ b/project2/sendmailTask.h @@ -14,10 +14,18 @@ class SendMailTask : public Task { public: class MailPart : public IntrusivePtrBase { public: + MailPart(uint8_t, uint8_t, uint8_t); + ~MailPart(); virtual const char * write(char ** buf, int * len) = 0; + const uint8_t sec, ind, prt; + static uint8_t mimeIdx; }; typedef boost::intrusive_ptr MailPartPtr; - typedef std::list PartList; + class SortMailParts { + public: + bool operator()(const MailPartPtr &, const MailPartPtr &) const; + }; + typedef std::multiset PartList; class Parts : public TransformChainLink { public: PartList parts; -- cgit v1.2.3