aboutsummaryrefslogtreecommitdiffstats
path: root/src/mdn/MDNHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mdn/MDNHelper.cpp')
-rw-r--r--src/mdn/MDNHelper.cpp279
1 files changed, 279 insertions, 0 deletions
diff --git a/src/mdn/MDNHelper.cpp b/src/mdn/MDNHelper.cpp
new file mode 100644
index 00000000..72dfeb93
--- /dev/null
+++ b/src/mdn/MDNHelper.cpp
@@ -0,0 +1,279 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "vmime/mdn/MDNHelper.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/stringContentHandler.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+const std::vector <sendableMDNInfos> MDNHelper::getPossibleMDNs(const message* msg)
+{
+ std::vector <sendableMDNInfos> result;
+
+ const header* hdr = msg->getHeader();
+
+ if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO))
+ {
+ const mailboxList& dnto = hdr->DispositionNotificationTo().getValue();
+
+ for (int i = 0 ; i < dnto.getMailboxCount() ; ++i)
+ result.push_back(sendableMDNInfos(msg, *dnto.getMailboxAt(i)));
+ }
+
+ return (result);
+}
+
+
+const bool MDNHelper::isMDN(const message* msg)
+{
+ const header* hdr = msg->getHeader();
+
+ // A MDN message implies the following:
+ // - a Content-Type field is present and its value is "multipart/report"
+ // - a "report-type" parameter is present in the Content-Type field,
+ // and its value is "disposition-notification"
+ if (hdr->hasField(fields::CONTENT_TYPE))
+ {
+ const contentTypeField& ctf = hdr->ContentType();
+
+ if (ctf.getValue().getType() == vmime::mediaTypes::MULTIPART &&
+ ctf.getValue().getSubType() == vmime::mediaTypes::MULTIPART_REPORT)
+ {
+ if (ctf.hasParameter("report-type") &&
+ ctf.getReportType() == "disposition-notification")
+ {
+ return (true);
+ }
+ }
+ }
+
+ return (false);
+}
+
+
+receivedMDNInfos MDNHelper::getReceivedMDN(const message* msg)
+{
+ if (!isMDN(msg))
+ throw exceptions::invalid_argument();
+
+ return receivedMDNInfos(msg);
+}
+
+
+bool MDNHelper::needConfirmation(const message* msg)
+{
+ const header* hdr = msg->getHeader();
+
+ // No "Return-Path" field
+ if (!hdr->hasField(fields::RETURN_PATH))
+ return (true);
+
+ // More than one address in Disposition-Notification-To
+ if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO))
+ {
+ const mailboxList& dnto = hdr->DispositionNotificationTo().getValue();
+
+ if (dnto.getMailboxCount() > 1)
+ return (true);
+
+ // Return-Path != Disposition-Notification-To
+ const mailbox& mbox = *dnto.getMailboxAt(0);
+ const path& rp = hdr->ReturnPath().getValue();
+
+ if (mbox.getEmail() != rp.getLocalPart() + "@" + rp.getDomain())
+ return (true);
+ }
+
+ // User confirmation not needed
+ return (false);
+}
+
+
+message* MDNHelper::buildMDN(const sendableMDNInfos& mdnInfos,
+ const string& text,
+ const charset& ch,
+ const mailbox& expeditor,
+ const disposition& dispo,
+ const string& reportingUA,
+ const std::vector <string>& reportingUAProducts)
+{
+ // Create a new message
+ message* msg = new message;
+
+ // Fill-in header fields
+ header* hdr = msg->getHeader();
+
+ hdr->ContentType().setValue(mediaType(vmime::mediaTypes::MULTIPART,
+ vmime::mediaTypes::MULTIPART_REPORT));
+ hdr->ContentType().setReportType("disosition-notification");
+
+ hdr->Disposition().setValue(dispo);
+
+ hdr->To().getValue().appendAddress(new mailbox(mdnInfos.getRecipient()));
+ hdr->From().getValue() = expeditor;
+ hdr->Subject().getValue().appendWord(new word("Disposition notification"));
+
+ hdr->Date().setValue(datetime::now());
+ hdr->MimeVersion().setValue(string(SUPPORTED_MIME_VERSION));
+
+ msg->getBody()->appendPart(createFirstMDNPart(mdnInfos, text, ch));
+ msg->getBody()->appendPart(createSecondMDNPart(mdnInfos,
+ dispo, reportingUA, reportingUAProducts));
+ msg->getBody()->appendPart(createThirdMDNPart(mdnInfos));
+
+ return (msg);
+}
+
+
+bodyPart* MDNHelper::createFirstMDNPart(const sendableMDNInfos& /* mdnInfos */,
+ const string& text, const charset& ch)
+{
+ bodyPart* part = new bodyPart;
+
+ // Header
+ header* hdr = part->getHeader();
+
+ hdr->ContentType().setValue(mediaType(vmime::mediaTypes::TEXT,
+ vmime::mediaTypes::TEXT_PLAIN));
+
+ hdr->ContentType().setCharset(ch);
+
+ // Body
+ part->getBody()->setContents(stringContentHandler(text));
+
+ return (part);
+}
+
+
+bodyPart* MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdnInfos,
+ const disposition& dispo,
+ const string& reportingUA,
+ const std::vector <string>& reportingUAProducts)
+{
+ bodyPart* part = new bodyPart;
+
+ // Header
+ header* hdr = part->getHeader();
+
+ hdr->ContentDisposition().setValue(vmime::contentDispositionTypes::INLINE);
+ hdr->ContentType().setValue(mediaType(vmime::mediaTypes::MESSAGE,
+ vmime::mediaTypes::MESSAGE_DISPOSITION_NOTIFICATION));
+
+ // Body
+ //
+ // The body of a message/disposition-notification consists of one or
+ // more "fields" formatted according to the ABNF of [RFC-MSGFMT] header
+ // "fields". The syntax of the message/disposition-notification content
+ // is as follows:
+ //
+ // disposition-notification-content = [ reporting-ua-field CRLF ]
+ // [ mdn-gateway-field CRLF ]
+ // [ original-recipient-field CRLF ]
+ // final-recipient-field CRLF
+ // [ original-message-id-field CRLF ]
+ // disposition-field CRLF
+ // *( failure-field CRLF )
+ // *( error-field CRLF )
+ // *( warning-field CRLF )
+ // *( extension-field CRLF )
+ //
+ header fields;
+
+ // -- Reporting-UA (optional)
+ if (!reportingUA.empty())
+ {
+ string ruaText;
+ ruaText = reportingUA;
+
+ for (unsigned int i = 0 ; i < reportingUAProducts.size() ; ++i)
+ {
+ if (i == 0)
+ ruaText += "; ";
+ else
+ ruaText += ", ";
+
+ ruaText += reportingUAProducts[i];
+ }
+
+ defaultField* rua = dynamic_cast <defaultField*>
+ (headerFieldFactory::getInstance()->create(vmime::fields::REPORTING_UA));
+
+ rua->setValue(ruaText);
+
+ fields.appendField(rua);
+ }
+
+ // -- Final-Recipient
+ defaultField* fr = dynamic_cast <defaultField*>
+ (headerFieldFactory::getInstance()->create(vmime::fields::FINAL_RECIPIENT));
+
+ fr->setValue("rfc822; " + mdnInfos.getRecipient().getEmail());
+
+ // -- Original-Message-ID
+ if (mdnInfos.getMessage()->getHeader()->hasField(vmime::fields::MESSAGE_ID))
+ {
+ fields.OriginalMessageId().setValue
+ (mdnInfos.getMessage()->getHeader()->MessageId().getValue());
+ }
+
+ // -- Disposition
+ fields.Disposition().setValue(dispo);
+
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter vos(oss);
+
+ fields.generate(vos);
+
+ part->getBody()->setContents(stringContentHandler(oss.str()));
+
+ return (part);
+}
+
+
+bodyPart* MDNHelper::createThirdMDNPart(const sendableMDNInfos& mdnInfos)
+{
+ bodyPart* part = new bodyPart;
+
+ // Header
+ header* hdr = part->getHeader();
+
+ hdr->ContentDisposition().setValue(vmime::contentDispositionTypes::INLINE);
+ hdr->ContentType().setValue(mediaType(vmime::mediaTypes::TEXT,
+ vmime::mediaTypes::TEXT_RFC822_HEADERS));
+
+ // Body: original message headers
+ std::ostringstream oss;
+ utility::outputStreamAdapter vos(oss);
+
+ mdnInfos.getMessage()->getHeader()->generate(vos);
+
+ part->getBody()->setContents(stringContentHandler(oss.str()));
+
+ return (part);
+}
+
+
+} // mdn
+} // vmime