aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/body.cpp7
-rw-r--r--src/bodyPart.cpp19
-rw-r--r--src/net/transport.cpp99
3 files changed, 117 insertions, 8 deletions
diff --git a/src/body.cpp b/src/body.cpp
index 1980f261..7cd7d401 100644
--- a/src/body.cpp
+++ b/src/body.cpp
@@ -674,6 +674,13 @@ void body::setParentPart(ref <bodyPart> parent)
{
m_part = parent;
m_header = (parent != NULL ? parent->getHeader() : NULL);
+
+ for (std::vector <ref <bodyPart> >::iterator it = m_parts.begin() ;
+ it != m_parts.end() ; ++it)
+ {
+ ref <bodyPart> childPart = *it;
+ childPart->m_parent = parent;
+ }
}
diff --git a/src/bodyPart.cpp b/src/bodyPart.cpp
index 009a7b8c..fbe9f1ed 100644
--- a/src/bodyPart.cpp
+++ b/src/bodyPart.cpp
@@ -121,6 +121,12 @@ ref <header> bodyPart::getHeader()
}
+void bodyPart::setHeader(ref <header> h)
+{
+ m_header = h;
+}
+
+
const ref <const body> bodyPart::getBody() const
{
return (m_body);
@@ -133,6 +139,19 @@ ref <body> bodyPart::getBody()
}
+void bodyPart::setBody(ref <body> b)
+{
+ ref <bodyPart> oldPart = b->m_part.acquire();
+
+ m_body = b;
+ m_body->setParentPart(thisRef().dynamicCast <bodyPart>());
+
+ // A body is associated to one and only one part
+ if (oldPart != NULL)
+ oldPart->setBody(vmime::create <body>());
+}
+
+
ref <bodyPart> bodyPart::getParentPart()
{
return m_parent.acquire();
diff --git a/src/net/transport.cpp b/src/net/transport.cpp
index f54d4dee..9a2db0ae 100644
--- a/src/net/transport.cpp
+++ b/src/net/transport.cpp
@@ -32,6 +32,8 @@
#include "vmime/utility/stream.hpp"
#include "vmime/mailboxList.hpp"
#include "vmime/message.hpp"
+#include "vmime/datetime.hpp"
+#include "vmime/messageId.hpp"
#include "vmime/utility/outputStreamAdapter.hpp"
#include "vmime/utility/inputStreamStringAdapter.hpp"
@@ -47,6 +49,66 @@ transport::transport(ref <session> sess, const serviceInfos& infos, ref <securit
}
+ref <headerField> transport::processHeaderField(ref <headerField> field)
+{
+ if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::BCC))
+ {
+ // Remove Bcc headers from the message, as required by the RFC.
+ // Some SMTP server automatically strip this header (Postfix, qmail),
+ // and others have an option for this (Exim).
+ return NULL;
+ }
+ else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::RETURN_PATH))
+ {
+ // RFC-2821: Return-Path header is added by the final transport system
+ // that delivers the message to its recipient. Then, it should not be
+ // transmitted to MSA.
+ return NULL;
+ }
+ else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::ORIGINAL_RECIPIENT))
+ {
+ // RFC-2298: Delivering MTA may add the Original-Recipient header and
+ // discard existing one; so, no need to send it.
+ return NULL;
+ }
+
+ // Leave the header field as is
+ return field;
+}
+
+
+void transport::processHeader(ref <header> header)
+{
+ if (header->getFieldCount() == 0)
+ return;
+
+ // Remove/replace fields
+ for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx)
+ {
+ ref <headerField> field = header->getFieldAt(idx - 1);
+ ref <headerField> newField = processHeaderField(field);
+
+ if (newField == NULL)
+ header->removeField(field);
+ else if (newField != field)
+ header->replaceField(field, newField);
+ }
+
+ // Add missing header fields
+ // -- Date
+ if (!header->hasField(fields::DATE))
+ header->Date()->setValue(datetime::now());
+
+ // -- Mime-Version
+ if (!header->hasField(fields::MIME_VERSION))
+ header->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION));
+
+ // -- Message-Id
+ if (!header->hasField(fields::MESSAGE_ID))
+ header->MessageId()->setValue(messageId::generateId());
+}
+
+
static void extractMailboxes
(mailboxList& recipients, const addressList& list)
{
@@ -107,15 +169,36 @@ void transport::send(ref <vmime::message> msg, utility::progressListener* progre
}
catch (exceptions::no_such_field&) { }
- // Remove BCC headers from the message we're about to send, as required by the RFC.
- // Some SMTP server automatically strip this header (Postfix, qmail), and others
- // have an option for this (Exim).
- try
+ // Process message header by removing fields that should be removed
+ // before transmitting the message to MSA, and adding missing fields
+ // which are required/recommended by the RFCs.
+ ref <header> hdr = msg->getHeader()->clone().dynamicCast <header>();
+ processHeader(hdr);
+
+ // To avoid cloning message body (too much overhead), use processed
+ // header during the time we are generating the message to a stream.
+ // Revert it back to original header after.
+ struct XChangeMsgHeader
{
- ref <headerField> bcc = msg->getHeader()->findField(fields::BCC);
- msg->getHeader()->removeField(bcc);
- }
- catch (exceptions::no_such_field&) { }
+ XChangeMsgHeader(vmime::ref <vmime::message> _msg,
+ vmime::ref <vmime::header> _hdr)
+ : msg(_msg), hdr(msg->getHeader())
+ {
+ // Set new header
+ msg->setHeader(_hdr);
+ }
+
+ ~XChangeMsgHeader()
+ {
+ // Revert original header
+ msg->setHeader(hdr);
+ }
+
+ private:
+
+ vmime::ref <vmime::message> msg;
+ vmime::ref <vmime::header> hdr;
+ } headerExchanger(msg, hdr);
// Generate the message, "stream" it and delegate the sending
// to the generic send() function.