aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2005-03-25 20:49:54 +0000
committerVincent Richard <[email protected]>2005-03-25 20:49:54 +0000
commit433f21263f7f34456be4aeba27f467ca1ad06d1a (patch)
treea3b8fb270fcd608acf36a20481a1ecaee7dbac80
parentAdded a section about warnings at compilation. (diff)
downloadvmime-433f21263f7f34456be4aeba27f467ca1ad06d1a.tar.gz
vmime-433f21263f7f34456be4aeba27f467ca1ad06d1a.zip
Basic support for MDN (RFC-3798).
-rw-r--r--ChangeLog6
-rw-r--r--SConstruct8
-rw-r--r--src/constants.cpp1
-rw-r--r--src/headerFieldFactory.cpp3
-rw-r--r--src/mdn/MDNHelper.cpp279
-rw-r--r--src/mdn/MDNInfos.cpp34
-rw-r--r--src/mdn/receivedMDNInfos.cpp111
-rw-r--r--src/mdn/sendableMDNInfos.cpp67
-rw-r--r--src/path.cpp184
-rw-r--r--tests/parser/pathTest.cpp119
-rw-r--r--vmime/constants.hpp13
-rw-r--r--vmime/header.hpp5
-rw-r--r--vmime/mailbox.hpp4
-rw-r--r--vmime/mdn/MDNHelper.hpp113
-rw-r--r--vmime/mdn/MDNInfos.hpp53
-rw-r--r--vmime/mdn/receivedMDNInfos.hpp79
-rw-r--r--vmime/mdn/sendableMDNInfos.hpp67
-rw-r--r--vmime/path.hpp96
-rw-r--r--vmime/standardFields.hpp4
-rw-r--r--vmime/vmime.hpp3
20 files changed, 1245 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index bc761da8..0baf8f9a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,12 @@
VERSION 0.6.4cvs
================
+2005-03-25 Vincent Richard <[email protected]>
+
+ * mdn/*.{cpp|hpp}: added support for Message Disposition Notifications (MDN),
+ as defined by RFC-3798 and RFC-1892. This is a very first implementation,
+ API is subject to changes...
+
2005-03-24 Vincent Richard <[email protected]>
* Added 'HACKING' file.
diff --git a/SConstruct b/SConstruct
index 6861edde..e378fb86 100644
--- a/SConstruct
+++ b/SConstruct
@@ -124,6 +124,7 @@ libvmime_sources = [
'messageId.cpp', 'messageId.hpp',
'messageParser.cpp', 'messageParser.hpp',
'options.cpp', 'options.hpp',
+ 'path.cpp', 'path.hpp',
'parameter.cpp', 'parameter.hpp',
'parameterFactory.cpp', 'parameterFactory.hpp',
'parameterizedHeaderField.cpp', 'parameterizedHeaderField.hpp',
@@ -151,7 +152,11 @@ libvmime_sources = [
'utility/smartPtr.hpp',
'utility/stream.cpp', 'utility/stream.hpp',
'utility/stringProxy.cpp', 'utility/stringProxy.hpp',
- 'utility/stringUtils.cpp', 'utility/stringUtils.hpp'
+ 'utility/stringUtils.cpp', 'utility/stringUtils.hpp',
+ 'mdn/MDNHelper.cpp', 'mdn/MDNHelper.hpp',
+ 'mdn/MDNInfos.cpp', 'mdn/MDNInfos.hpp',
+ 'mdn/receivedMDNInfos.cpp', 'mdn/receivedMDNInfos.hpp',
+ 'mdn/sendableMDNInfos.cpp', 'mdn/sendableMDNInfos.hpp'
]
libvmime_examples_sources = [
@@ -312,6 +317,7 @@ libvmimetest_sources = [
[ 'tests/parser/headerTest', [ 'tests/parser/headerTest.cpp' ] ],
[ 'tests/parser/mailboxTest', [ 'tests/parser/mailboxTest.cpp' ] ],
[ 'tests/parser/mediaTypeTest', [ 'tests/parser/mediaTypeTest.cpp' ] ],
+ [ 'tests/parser/pathTest', [ 'tests/parser/pathTest.cpp' ] ],
[ 'tests/parser/textTest', [ 'tests/parser/textTest.cpp' ] ],
[ 'tests/utility/md5Test', [ 'tests/utility/md5Test.cpp' ] ],
[ 'tests/utility/stringProxyTest', [ 'tests/utility/stringProxyTest.cpp' ] ],
diff --git a/src/constants.cpp b/src/constants.cpp
index f7c52fbb..5ca08960 100644
--- a/src/constants.cpp
+++ b/src/constants.cpp
@@ -53,6 +53,7 @@ namespace mediaTypes
const string::value_type* const MESSAGE_RFC822 = "rfc822";
const string::value_type* const MESSAGE_PARTIAL = "partial";
const string::value_type* const MESSAGE_EXTERNAL_BODY = "external-body";
+ const string::value_type* const MESSAGE_DISPOSITION_NOTIFICATION = "disposition-notification";
const string::value_type* const APPLICATION_OCTET_STREAM = "octet-stream";
diff --git a/src/headerFieldFactory.cpp b/src/headerFieldFactory.cpp
index 544a2ac2..62eff647 100644
--- a/src/headerFieldFactory.cpp
+++ b/src/headerFieldFactory.cpp
@@ -46,7 +46,7 @@ headerFieldFactory::headerFieldFactory()
registerName <mailboxField>(vmime::fields::DELIVERED_TO);
registerName <textField>(vmime::fields::ORGANIZATION);
registerName <textField>(vmime::fields::USER_AGENT);
- registerName <mailboxField>(vmime::fields::RETURN_PATH);
+ registerName <pathField>(vmime::fields::RETURN_PATH);
registerName <contentTypeField>(vmime::fields::CONTENT_TYPE);
registerName <contentEncodingField>(vmime::fields::CONTENT_TRANSFER_ENCODING);
registerName <textField>(vmime::fields::CONTENT_DESCRIPTION);
@@ -58,6 +58,7 @@ headerFieldFactory::headerFieldFactory()
registerName <messageIdField>(vmime::fields::IN_REPLY_TO);
registerName <messageIdField>(vmime::fields::ORIGINAL_MESSAGE_ID);
+ registerName <dispositionField>(vmime::fields::DISPOSITION);
registerName <mailboxListField>(vmime::fields::DISPOSITION_NOTIFICATION_TO);
}
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
diff --git a/src/mdn/MDNInfos.cpp b/src/mdn/MDNInfos.cpp
new file mode 100644
index 00000000..9490113f
--- /dev/null
+++ b/src/mdn/MDNInfos.cpp
@@ -0,0 +1,34 @@
+//
+// 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/MDNInfos.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+
+MDNInfos::~MDNInfos()
+{
+}
+
+
+} // mdn
+} // vmime
diff --git a/src/mdn/receivedMDNInfos.cpp b/src/mdn/receivedMDNInfos.cpp
new file mode 100644
index 00000000..e9a82198
--- /dev/null
+++ b/src/mdn/receivedMDNInfos.cpp
@@ -0,0 +1,111 @@
+//
+// 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/receivedMDNInfos.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+receivedMDNInfos::receivedMDNInfos(const message* msg)
+ : m_msg(msg)
+{
+ extract();
+}
+
+
+receivedMDNInfos::receivedMDNInfos(const receivedMDNInfos& other)
+ : MDNInfos()
+{
+ copyFrom(other);
+}
+
+
+receivedMDNInfos& receivedMDNInfos::operator=(const receivedMDNInfos& other)
+{
+ copyFrom(other);
+ return (*this);
+}
+
+
+const message* receivedMDNInfos::getMessage() const
+{
+ return (m_msg);
+}
+
+
+const messageId receivedMDNInfos::getOriginalMessageId() const
+{
+ return (m_omid);
+}
+
+
+const disposition receivedMDNInfos::getDisposition() const
+{
+ return (m_disp);
+}
+
+
+void receivedMDNInfos::copyFrom(const receivedMDNInfos& other)
+{
+ m_msg = other.m_msg;
+ m_omid = other.m_omid;
+ m_disp = other.m_disp;
+}
+
+
+void receivedMDNInfos::extract()
+{
+ const body* bdy = m_msg->getBody();
+
+ for (int i = 0 ; i < bdy->getPartCount() ; ++i)
+ {
+ const bodyPart* part = bdy->getPartAt(i);
+
+ if (!part->getHeader()->hasField(fields::CONTENT_TYPE))
+ continue;
+
+ const mediaType& type = part->getHeader()->ContentType().getValue();
+
+ // Extract from second part (message/disposition-notification)
+ if (type.getType() == vmime::mediaTypes::MESSAGE &&
+ type.getSubType() == vmime::mediaTypes::MESSAGE_DISPOSITION_NOTIFICATION)
+ {
+ std::ostringstream oss;
+ utility::outputStreamAdapter vos(oss);
+
+ part->getBody()->getContents().extract(vos);
+
+ // Body actually contains fields
+ header fields;
+ fields.parse(oss.str());
+
+ try { m_omid = fields.OriginalMessageId().getValue(); }
+ catch (exceptions::no_such_field&) { /* Ignore */ }
+
+ try { m_disp = fields.Disposition().getValue(); }
+ catch (exceptions::no_such_field&) { /* Ignore */ }
+ }
+ }
+}
+
+
+} // mdn
+} // vmime
diff --git a/src/mdn/sendableMDNInfos.cpp b/src/mdn/sendableMDNInfos.cpp
new file mode 100644
index 00000000..e8ae8b62
--- /dev/null
+++ b/src/mdn/sendableMDNInfos.cpp
@@ -0,0 +1,67 @@
+//
+// 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/sendableMDNInfos.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+sendableMDNInfos::sendableMDNInfos(const message* msg, const mailbox& mbox)
+ : m_msg(msg), m_mailbox(mbox)
+{
+}
+
+
+sendableMDNInfos::sendableMDNInfos(const sendableMDNInfos& other)
+ : MDNInfos()
+{
+ copyFrom(other);
+}
+
+
+sendableMDNInfos& sendableMDNInfos::operator=(const sendableMDNInfos& other)
+{
+ copyFrom(other);
+ return (*this);
+}
+
+
+const message* sendableMDNInfos::getMessage() const
+{
+ return (m_msg);
+}
+
+
+const mailbox& sendableMDNInfos::getRecipient() const
+{
+ return (m_mailbox);
+}
+
+
+void sendableMDNInfos::copyFrom(const sendableMDNInfos& other)
+{
+ m_msg = other.m_msg;
+ m_mailbox = other.m_mailbox;
+}
+
+
+} // mdn
+} // vmime
diff --git a/src/path.cpp b/src/path.cpp
new file mode 100644
index 00000000..153facd3
--- /dev/null
+++ b/src/path.cpp
@@ -0,0 +1,184 @@
+//
+// 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/path.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime
+{
+
+
+path::path()
+{
+}
+
+
+path::path(const string& localPart, const string& domain)
+ : m_localPart(localPart), m_domain(domain)
+{
+}
+
+
+path::path(const path& p)
+ : component(), m_localPart(p.m_localPart), m_domain(p.m_domain)
+{
+}
+
+
+const string& path::getLocalPart() const
+{
+ return (m_localPart);
+}
+
+
+void path::setLocalPart(const string& localPart)
+{
+ m_localPart = localPart;
+}
+
+
+const string& path::getDomain() const
+{
+ return (m_domain);
+}
+
+
+void path::setDomain(const string& domain)
+{
+ m_domain = domain;
+}
+
+
+const bool path::operator==(const path& p) const
+{
+ return (m_localPart == p.m_localPart &&
+ m_domain == p.m_domain);
+}
+
+
+const bool path::operator!=(const path& p) const
+{
+ return (m_localPart != p.m_localPart ||
+ m_domain != p.m_domain);
+}
+
+
+void path::copyFrom(const component& other)
+{
+ const path& p = dynamic_cast <const path&>(other);
+
+ m_localPart = p.m_localPart;
+ m_domain = p.m_domain;
+}
+
+
+path* path::clone() const
+{
+ return new path(*this);
+}
+
+
+path& path::operator=(const path& other)
+{
+ copyFrom(other);
+ return (*this);
+}
+
+
+const std::vector <const component*> path::getChildComponents() const
+{
+ return std::vector <const component*>();
+}
+
+
+void path::parse(const string& buffer, const string::size_type position,
+ const string::size_type end, string::size_type* newPosition)
+{
+ string::size_type pos = position;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos]))
+ ++pos;
+
+ string addrSpec;
+
+ if (pos < end && buffer[pos] == '<')
+ {
+ // Skip '<'
+ ++pos;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos]))
+ ++pos;
+
+ const string::size_type addrStart = pos;
+
+ while (pos < end && buffer[pos] != '>')
+ ++pos;
+
+ string::size_type addrEnd = pos;
+
+ while (addrEnd > addrStart && parserHelpers::isSpace(buffer[addrEnd - 1]))
+ addrEnd--;
+
+ addrSpec = string(buffer.begin() + addrStart, buffer.begin() + addrEnd);
+ }
+ else
+ {
+ addrSpec = string(buffer.begin() + position, buffer.begin() + end);
+ }
+
+ const string::size_type at = addrSpec.find_first_of('@');
+
+ if (at != string::npos)
+ {
+ m_localPart = string(addrSpec.begin(), addrSpec.begin() + at);
+ m_domain = string(addrSpec.begin() + at + 1, addrSpec.end());
+ }
+ else
+ {
+ m_localPart.clear();
+ m_domain = addrSpec;
+ }
+
+ if (newPosition != NULL)
+ *newPosition = end;
+}
+
+
+void path::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
+ const string::size_type curLinePos, string::size_type* newLinePos) const
+{
+ if (m_localPart.empty() && m_domain.empty())
+ {
+ os << "<>";
+
+ if (newLinePos)
+ *newLinePos = curLinePos + 2;
+ }
+ else
+ {
+ os << "<" << m_localPart << "@" << m_domain << ">";
+
+ if (newLinePos)
+ *newLinePos = curLinePos + m_localPart.length() + m_domain.length() + 3;
+ }
+}
+
+
+} // vmime
diff --git a/tests/parser/pathTest.cpp b/tests/parser/pathTest.cpp
new file mode 100644
index 00000000..a2fc76b8
--- /dev/null
+++ b/tests/parser/pathTest.cpp
@@ -0,0 +1,119 @@
+//
+// 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 "../lib/unit++/unit++.h"
+
+#include <iostream>
+#include <ostream>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#include "tests/parser/testUtils.hpp"
+
+using namespace unitpp;
+
+
+namespace
+{
+ class pathTest : public suite
+ {
+ void testParse()
+ {
+ vmime::path p1;
+ p1.parse("<>");
+
+ assert_eq("1.1", "", p1.getLocalPart());
+ assert_eq("1.2", "", p1.getDomain());
+
+ vmime::path p2;
+ p2.parse("<domain>");
+
+ assert_eq("2.1", "", p2.getLocalPart());
+ assert_eq("2.2", "domain", p2.getDomain());
+
+ vmime::path p3;
+ p3.parse("<local@domain>");
+
+ assert_eq("3.1", "local", p3.getLocalPart());
+ assert_eq("3.2", "domain", p3.getDomain());
+ }
+
+ void testParse2()
+ {
+ // Test some invalid paths (no '<>')
+ vmime::path p1;
+ p1.parse("");
+
+ assert_eq("1.1", "", p1.getLocalPart());
+ assert_eq("1.2", "", p1.getDomain());
+
+ vmime::path p2;
+ p2.parse("domain");
+
+ assert_eq("2.1", "", p2.getLocalPart());
+ assert_eq("2.2", "domain", p2.getDomain());
+
+ vmime::path p3;
+ p3.parse("local@domain");
+
+ assert_eq("3.1", "local", p3.getLocalPart());
+ assert_eq("3.2", "domain", p3.getDomain());
+ }
+
+ void testGenerate()
+ {
+ vmime::path p1;
+
+ assert_eq("1", "<>", p1.generate());
+
+ vmime::path p2;
+ p2.setLocalPart("local");
+
+ assert_eq("2", "<local@>", p2.generate());
+
+ vmime::path p3;
+ p3.setDomain("domain");
+
+ assert_eq("3", "<@domain>", p3.generate());
+
+ vmime::path p4;
+ p4.setLocalPart("local");
+ p4.setDomain("domain");
+
+ assert_eq("4", "<local@domain>", p4.generate());
+ }
+
+ public:
+
+ pathTest() : suite("vmime::path")
+ {
+ vmime::platformDependant::setHandler<vmime::platforms::posix::posixHandler>();
+
+ add("Parse", testcase(this, "Parse", &pathTest::testParse));
+ add("Parse2", testcase(this, "Parse2", &pathTest::testParse2));
+ add("Generate", testcase(this, "Generate", &pathTest::testGenerate));
+
+ suite::main().add("vmime::path", this);
+ }
+
+ };
+
+ pathTest* theTest = new pathTest();
+}
diff --git a/vmime/constants.hpp b/vmime/constants.hpp
index 929796fd..bbb11a9a 100644
--- a/vmime/constants.hpp
+++ b/vmime/constants.hpp
@@ -57,6 +57,7 @@ namespace vmime
extern const string::value_type* const MESSAGE_RFC822;
extern const string::value_type* const MESSAGE_PARTIAL;
extern const string::value_type* const MESSAGE_EXTERNAL_BODY;
+ extern const string::value_type* const MESSAGE_DISPOSITION_NOTIFICATION;
extern const string::value_type* const APPLICATION_OCTET_STREAM;
@@ -199,22 +200,34 @@ namespace vmime
/** Constants for disposition action modes (RFC-3978). */
namespace dispositionActionModes
{
+ /** User implicitely displayed or deleted the message (filter or
+ * any other automatic action). */
extern const string::value_type* const MANUAL;
+
+ /** User explicitely displayed or deleted the message (manual action). */
extern const string::value_type* const AUTOMATIC;
}
/** Constants for disposition sending modes (RFC-3798). */
namespace dispositionSendingModes
{
+ /** The MDN was sent because the MUA had previously been configured
+ * to do so automatically. */
extern const string::value_type* const SENT_MANUALLY;
+
+ /** User explicitly gave permission for this particular MDN to be sent. */
extern const string::value_type* const SENT_AUTOMATICALLY;
}
/** Constants for disposition types (RFC-3798). */
namespace dispositionTypes
{
+ /** Message has been displayed to the user. */
extern const string::value_type* const DISPLAYED;
+ /** Message has been deleted without being displayed. */
extern const string::value_type* const DELETED;
+ /** Message has been denied. */
+ extern const string::value_type* const DENIED;
}
/** Constants for disposition modifiers (RFC-3798). */
diff --git a/vmime/header.hpp b/vmime/header.hpp
index 42b465b2..7050c1dd 100644
--- a/vmime/header.hpp
+++ b/vmime/header.hpp
@@ -68,6 +68,7 @@ public:
FIELD_ACCESS(ReplyTo, REPLY_TO, mailboxField)
FIELD_ACCESS(DeliveredTo, DELIVERED_TO, mailboxField)
FIELD_ACCESS(InReplyTo, IN_REPLY_TO, messageIdField)
+ FIELD_ACCESS(ReturnPath, RETURN_PATH, pathField)
FIELD_ACCESS(To, TO, addressListField)
FIELD_ACCESS(Cc, CC, addressListField)
@@ -86,6 +87,10 @@ public:
FIELD_ACCESS(MessageId, MESSAGE_ID, messageIdField)
FIELD_ACCESS(ContentLocation, CONTENT_LOCATION, defaultField)
+ FIELD_ACCESS(OriginalMessageId, ORIGINAL_MESSAGE_ID, messageIdField)
+ FIELD_ACCESS(Disposition, DISPOSITION, dispositionField)
+ FIELD_ACCESS(DispositionNotificationTo, DISPOSITION_NOTIFICATION_TO, mailboxListField)
+
#undef FIELD_ACCESS
/** Checks whether (at least) one field with this name exists.
diff --git a/vmime/mailbox.hpp b/vmime/mailbox.hpp
index b34300f0..1c30e102 100644
--- a/vmime/mailbox.hpp
+++ b/vmime/mailbox.hpp
@@ -52,7 +52,7 @@ public:
/** Set the full name of the mailbox.
*
- * @return full name of the mailbox
+ * @param name full name of the mailbox
*/
void setName(const text& name);
@@ -64,7 +64,7 @@ public:
/** Set the email of the mailbox.
*
- * @return email of the mailbox
+ * @param email email of the mailbox
*/
void setEmail(const string& email);
diff --git a/vmime/mdn/MDNHelper.hpp b/vmime/mdn/MDNHelper.hpp
new file mode 100644
index 00000000..7eaf64e8
--- /dev/null
+++ b/vmime/mdn/MDNHelper.hpp
@@ -0,0 +1,113 @@
+//
+// 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.
+//
+
+#ifndef VMIME_MDN_MDNHELPER_HPP_INCLUDED
+#define VMIME_MDN_MDNHELPER_HPP_INCLUDED
+
+
+#include "vmime/mdn/receivedMDNInfos.hpp"
+#include "vmime/mdn/sendableMDNInfos.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Helper for creating or extracting Message Disposition
+ * Notifications (MDN), as defined in RFC-3798.
+ */
+
+class MDNHelper
+{
+public:
+
+ /** Return a list of possible MDNs that can be generated
+ * for the specified message.
+ *
+ * @param msg message for which to send a MDN
+ * @return list of possible MDNs
+ */
+ static const std::vector <sendableMDNInfos> getPossibleMDNs(const message* msg);
+
+ /** Test whether the specified message is a MDN.
+ *
+ * @param msg message
+ * @return true if the message is a MDN, false otherwise
+ */
+ static const bool isMDN(const message* msg);
+
+ /** If the specified message is a MDN, return information
+ * about it.
+ *
+ * @param msg message
+ * @throw exceptions::invalid_argument if the message is not a MDN
+ * @return information about the MDN
+ */
+ static receivedMDNInfos getReceivedMDN(const message* msg);
+
+ /** Check whether we need user confirmation for sending a MDN even
+ * if he/she explicitely allowed automatic send of MDNs. This can
+ * happen in some situations, described in RFC-3798.
+ *
+ * @param msg message for which to send a MDN
+ * @return true if user confirmation should be asked, false otherwise
+ */
+ static bool needConfirmation(const message* msg);
+
+ /** Build a new MDN for the message. The resulting MDN can then be
+ * sent over SMTP transport service.
+ *
+ * @param mdnInfos information about the MDN to construct
+ * @param text human readable message. The purpose of this message is
+ * to provide an easily-understood description of the
+ * condition(s) that caused the report to be generated.
+ * @param ch charset of the text
+ * @param dispo disposition information
+ * @param reportingUA name of reporting user-agent (optional)
+ * @param reportingUAProducts list of products in the reporting user-agent (optional)
+ * @return a new message object containing the MDN
+ */
+ static message* buildMDN(const sendableMDNInfos& mdnInfos,
+ const string& text,
+ const charset& ch,
+ const mailbox& expeditor,
+ const disposition& dispo,
+ const string& reportingUA = NULL_STRING,
+ const std::vector <string>& reportingUAProducts
+ = std::vector <string>());
+
+private:
+
+ static bodyPart* createFirstMDNPart(const sendableMDNInfos& mdnInfos,
+ const string& text, const charset& ch);
+
+ static bodyPart* createSecondMDNPart(const sendableMDNInfos& mdnInfos,
+ const disposition& dispo,
+ const string& reportingUA,
+ const std::vector <string>& reportingUAProducts);
+
+ static bodyPart* createThirdMDNPart(const sendableMDNInfos& mdnInfos);
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_MDNHELPER_HPP_INCLUDED
diff --git a/vmime/mdn/MDNInfos.hpp b/vmime/mdn/MDNInfos.hpp
new file mode 100644
index 00000000..13347eed
--- /dev/null
+++ b/vmime/mdn/MDNInfos.hpp
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+
+#ifndef VMIME_MDN_MDNINFOS_HPP_INCLUDED
+#define VMIME_MDN_MDNINFOS_HPP_INCLUDED
+
+
+#include "vmime/message.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Holds information about Message Disposition Notifications (MDN).
+ */
+
+class MDNInfos
+{
+public:
+
+ virtual ~MDNInfos();
+
+
+ /** Return the message related to this MDN.
+ *
+ * @return related message
+ */
+ virtual const message* getMessage() const = 0;
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_MDNINFOS_HPP_INCLUDED
diff --git a/vmime/mdn/receivedMDNInfos.hpp b/vmime/mdn/receivedMDNInfos.hpp
new file mode 100644
index 00000000..1f3d179c
--- /dev/null
+++ b/vmime/mdn/receivedMDNInfos.hpp
@@ -0,0 +1,79 @@
+//
+// 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.
+//
+
+#ifndef VMIME_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED
+#define VMIME_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED
+
+
+#include "vmime/mdn/MDNInfos.hpp"
+#include "vmime/disposition.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Holds information about a Message Disposition Notification (MDN)
+ * that has been received.
+ */
+
+class receivedMDNInfos : public MDNInfos
+{
+public:
+
+ receivedMDNInfos(const message* msg);
+ receivedMDNInfos(const receivedMDNInfos& other);
+
+ receivedMDNInfos& operator=(const receivedMDNInfos& other);
+
+
+ const message* getMessage() const;
+
+ /** Return the identifier of the message for which this MDN
+ * has been generated.
+ *
+ * @return original message-id
+ */
+ const messageId getOriginalMessageId() const;
+
+ /** Return information about the disposition.
+ *
+ * @return disposition information
+ */
+ const disposition getDisposition() const;
+
+private:
+
+ void copyFrom(const receivedMDNInfos& other);
+
+ void extract();
+
+
+ const message* m_msg;
+
+ disposition m_disp;
+ messageId m_omid;
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED
diff --git a/vmime/mdn/sendableMDNInfos.hpp b/vmime/mdn/sendableMDNInfos.hpp
new file mode 100644
index 00000000..6e5a6f0a
--- /dev/null
+++ b/vmime/mdn/sendableMDNInfos.hpp
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+
+#ifndef VMIME_MDN_SENDABLEMDNINFOS_HPP_INCLUDED
+#define VMIME_MDN_SENDABLEMDNINFOS_HPP_INCLUDED
+
+
+#include "vmime/mdn/MDNInfos.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Holds information about a Message Disposition Notifications (MDN)
+ * that is to be sent.
+ */
+
+class sendableMDNInfos : public MDNInfos
+{
+public:
+
+ sendableMDNInfos(const message* msg, const mailbox& mbox);
+ sendableMDNInfos(const sendableMDNInfos& other);
+
+ sendableMDNInfos& operator=(const sendableMDNInfos& other);
+
+ const message* getMessage() const;
+
+ /** Return the recipient of the MDN (the mailbox that will receive
+ * the notification message).
+ *
+ * @return recipient of the MDN
+ */
+ const mailbox& getRecipient() const;
+
+private:
+
+ void copyFrom(const sendableMDNInfos& other);
+
+
+ const message* m_msg;
+ mailbox m_mailbox;
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_SENDABLEMDNINFOS_HPP_INCLUDED
diff --git a/vmime/path.hpp b/vmime/path.hpp
new file mode 100644
index 00000000..5e50feb9
--- /dev/null
+++ b/vmime/path.hpp
@@ -0,0 +1,96 @@
+//
+// 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.
+//
+
+#ifndef VMIME_PATH_HPP_INCLUDED
+#define VMIME_PATH_HPP_INCLUDED
+
+
+#include "vmime/component.hpp"
+
+
+namespace vmime
+{
+
+
+/** A path: a local part + '@' + a domain.
+ */
+
+class path : public component
+{
+public:
+
+ path();
+ path(const string& localPart, const string& domain);
+ path(const path& p);
+
+ /** Return the local part of the address.
+ *
+ * @return local part of the address
+ */
+ const string& getLocalPart() const;
+
+ /** Set the local part of the address.
+ *
+ * @param localPart local part of the address
+ */
+ void setLocalPart(const string& localPart);
+
+ /** Return the domain of the address.
+ *
+ * @return domain of the address
+ */
+ const string& getDomain() const;
+
+ /** Set the domain of the address.
+ *
+ * @param domain domain of the address
+ */
+ void setDomain(const string& domain);
+
+ // Comparison
+ const bool operator==(const path& p) const;
+ const bool operator!=(const path& p) const;
+
+ // Assignment
+ void copyFrom(const component& other);
+ path* clone() const;
+ path& operator=(const path& other);
+
+ const std::vector <const component*> getChildComponents() const;
+
+protected:
+
+ string m_localPart;
+ string m_domain;
+
+public:
+
+ using component::parse;
+ using component::generate;
+
+ // Component parsing & assembling
+ void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
+ void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PATH_HPP_INCLUDED
diff --git a/vmime/standardFields.hpp b/vmime/standardFields.hpp
index f75b77d8..7d0905dd 100644
--- a/vmime/standardFields.hpp
+++ b/vmime/standardFields.hpp
@@ -33,6 +33,8 @@
#include "vmime/messageId.hpp"
#include "vmime/relay.hpp"
#include "vmime/mailboxList.hpp"
+#include "vmime/disposition.hpp"
+#include "vmime/path.hpp"
namespace vmime
@@ -92,6 +94,8 @@ DECLARE_STANDARD_FIELD(messageIdField, messageId);
DECLARE_STANDARD_FIELD(defaultField, string);
DECLARE_STANDARD_FIELD(relayField, relay);
DECLARE_STANDARD_FIELD(mailboxListField, mailboxList);
+DECLARE_STANDARD_FIELD(dispositionField, disposition);
+DECLARE_STANDARD_FIELD(pathField, path);
#undef DECLARE_STANDARD_FIELD
diff --git a/vmime/vmime.hpp b/vmime/vmime.hpp
index 965b2184..694a2ba7 100644
--- a/vmime/vmime.hpp
+++ b/vmime/vmime.hpp
@@ -73,6 +73,9 @@
#include "vmime/plainTextPart.hpp"
#include "vmime/htmlTextPart.hpp"
+// MDN
+#include "vmime/mdn/MDNHelper.hpp"
+
// Property set
#include "vmime/propertySet.hpp"