From c5fe37e82fd96e29c1ee527c3a106c93501c3967 Mon Sep 17 00:00:00 2001 From: randomdan Date: Thu, 18 Nov 2010 16:16:58 +0000 Subject: Tidy up sendmail process ready for sending plain text version too --- project2/sendmailTask.cpp | 112 +++++++++++++++++++++++++++------------------- project2/sendmailTask.h | 17 +++---- 2 files changed, 76 insertions(+), 53 deletions(-) diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp index e4a9af5..3fc0039 100644 --- a/project2/sendmailTask.cpp +++ b/project2/sendmailTask.cpp @@ -10,6 +10,8 @@ ElementLoaderImpl<_SendMailTask> sendmailLoader("sendmail"); +typedef boost::shared_ptr XmlDocumentPtr; + _SendMailTask::_SendMailTask(const xmlpp::Element * p) : _SourceObject(p), _Task(p), @@ -17,16 +19,12 @@ _SendMailTask::_SendMailTask(const xmlpp::Element * p) : subject(p->get_attribute("subject")), from(p->get_attribute("from")), server(p->get_attribute("server")), - present(p->get_attribute_value("present").raw()), - body(NULL) + present(p->get_attribute_value("present").raw()) { } _SendMailTask::~_SendMailTask() { - if (body) { - xmlFree(body); - } } void @@ -40,29 +38,77 @@ _SendMailTask::writeMailWrapper(void ** buf, int * len, void * arg) return static_cast(arg)->writeMail(buf, len); } +class BoundaryBegin : public _SendMailTask::MailPart { + public: + BoundaryBegin(const std::string & ct) : 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()); + return *buf; + } + private: + const std::string contentType; +}; +class BoundaryEnd : public _SendMailTask::MailPart { + public: + const char * write(char ** buf, int * len) { + *len = 19; + return "\r\n--<>--\r\n"; + } +}; +class Header : public _SendMailTask::MailPart { + public: + Header(const std::string & h, const Glib::ustring & v) : + header(h), value(v) { + } + const char * write(char ** buf, int * len) { + *len = asprintf(buf, "%s: %s\r\n", header.c_str(), value.c_str()); + return (const char *)*buf; + } + private: + const std::string header; + const Glib::ustring value; +}; +class HtmlContent : public _SendMailTask::MailPart { + public: + HtmlContent(XmlDocumentPtr d) : doc(d) { + } + const char * write(char ** buf, int * len) { + xmlDocDumpFormatMemoryEnc(doc.get(), (xmlChar**)buf, len, "utf-8", 0); + return *buf; + } + private: + const XmlDocumentPtr doc; +}; + void _SendMailTask::execute() const { PresenterPtr p = ApplicationEngine::getCurrent()->getPresenter("emails", present); Presenter::XmlDocumentPtr data = p->getDataDocument(); typedef boost::shared_ptr XsltStyleSheetPtr; - typedef boost::shared_ptr XmlDocumentPtr; // Do transform - XsltStyleSheetPtr cur = XsltStyleSheetPtr(xsltParseStylesheetFile(BAD_CAST p->responseStyle.c_str()), - xsltFreeStylesheet); - if (!cur) { throw std::runtime_error("Failed to load stylesheet"); } + XsltStyleSheetPtr cur = XsltStyleSheetPtr(xsltParseStylesheetFile(BAD_CAST p->responseStyle.c_str()), xsltFreeStylesheet); + if (!cur) { + throw std::runtime_error("Failed to load stylesheet"); + } XmlDocumentPtr result = XmlDocumentPtr(xsltApplyStylesheet(cur.get(), data->cobj(), NULL), xmlFreeDoc); - if (!result) { throw std::runtime_error("Failed to perform transformation"); } - xmlDocDumpFormatMemoryEnc(result.get(), &body, &bodyLength, "utf-8", 0); + if (!result) { + throw std::runtime_error("Failed to perform transformation"); + } - headers[-1] = HeaderPtr(new Header("To", to)); - headers[-2] = HeaderPtr(new Header("From", from)); - headers[-3] = HeaderPtr(new Header("Subject", subject)); - headers[-4] = HeaderPtr(new Header("Content-Type", "multipart/alternative; boundary=\"<>\"")); - headers[-5] = HeaderPtr(new Header("MIME-Version", "1.0")); - headers[-6] = HeaderPtr(new Header("Content-Transfer-Encoding", "binary")); - position = -1; + parts.clear(); + parts.push_back(new Header("To", to)); + parts.push_back(new Header("From", from)); + parts.push_back(new Header("Subject", subject)); + parts.push_back(new Header("Content-Type", "multipart/alternative; boundary=\"<>\"")); + parts.push_back(new Header("MIME-Version", "1.0")); + parts.push_back(new Header("Content-Transfer-Encoding", "binary")); + parts.push_back(new BoundaryBegin("text/html; utf-8")); + parts.push_back(new HtmlContent(result)); + parts.push_back(new BoundaryEnd()); + part = parts.begin(); // Write email smtp_session_t session = smtp_create_session(); @@ -81,33 +127,9 @@ _SendMailTask::execute() const const char * _SendMailTask::writeMail(void ** buf, int * len) const { - if (!len) { - position = -1; - return NULL; - } - Headers::const_iterator h = headers.find(position); - if (h != headers.end()) { - *len = asprintf((char**)buf, "%s: %s\r\n", h->second->first.c_str(), h->second->second.c_str()); - position -= 1; - return (const char *)*buf; - } - else if (position < 0) { - position = 0; - *len = 51; - return "\r\n--<>\r\nContent-Type: text/html; utf-8\r\n\r\n"; - } - else if (position == bodyLength) { - position = bodyLength + 1; - *len = 17; - return "--<>--\r\n"; - } - else if (position >= 0 && position < bodyLength) { - *buf = NULL; - *len = bodyLength; - position = bodyLength; - return (const char *)body; - } - else { + if (len == NULL || part == parts.end()) { return NULL; } + return (*part++)->write((char**)buf, len); } + diff --git a/project2/sendmailTask.h b/project2/sendmailTask.h index ef66c3f..2193974 100644 --- a/project2/sendmailTask.h +++ b/project2/sendmailTask.h @@ -3,7 +3,6 @@ #include #include -#include #include #include "task.h" #include "variables.h" @@ -14,6 +13,11 @@ typedef unsigned char xmlChar; class _SendMailTask : public _Task { public: + class MailPart : public IntrusivePtrBase { + public: + virtual const char * write(char ** buf, int * len) = 0; + }; + _SendMailTask(const xmlpp::Element * p); virtual ~_SendMailTask(); virtual void loadComplete(); @@ -30,13 +34,10 @@ class _SendMailTask : public _Task { static const char * writeMailWrapper(void ** buf, int * len, void * arg); const char * writeMail(void ** buf, int * len) const; - typedef std::pair Header; - typedef boost::shared_ptr
HeaderPtr; - typedef std::map Headers; - mutable Headers headers; - mutable xmlChar * body; - mutable int bodyLength; - mutable int position; + typedef boost::intrusive_ptr MailPartPtr; + typedef std::list Parts; + mutable Parts parts; + mutable Parts::iterator part; }; typedef boost::intrusive_ptr<_SendMailTask> SendMailTask; typedef std::map SendMailTasks; -- cgit v1.2.3