aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Osusky <[email protected]>2017-10-20 12:02:33 +0000
committerJan Osusky <[email protected]>2020-07-22 06:26:04 +0000
commite30766cf2aa0cbfee3848c518193caa982356d11 (patch)
tree6d445c851ca45cd9c8e5007616f9c42d6c492dee
parentMerge pull request #239 from kisli/laurent-richard-fix-message-flag-set (diff)
downloadvmime-e30766cf2aa0cbfee3848c518193caa982356d11.tar.gz
vmime-e30766cf2aa0cbfee3848c518193caa982356d11.zip
Add basic support for delivery status notifications (DSN)
Added possibility to send e-mails with explicit request for delivery status notification and its content.
-rw-r--r--src/vmime/constants.cpp15
-rw-r--r--src/vmime/constants.hpp16
-rw-r--r--src/vmime/net/sendmail/sendmailTransport.cpp4
-rw-r--r--src/vmime/net/sendmail/sendmailTransport.hpp5
-rw-r--r--src/vmime/net/smtp/SMTPCommand.cpp22
-rw-r--r--src/vmime/net/smtp/SMTPCommand.hpp9
-rw-r--r--src/vmime/net/smtp/SMTPTransport.cpp22
-rw-r--r--src/vmime/net/smtp/SMTPTransport.hpp18
-rw-r--r--src/vmime/net/transport.cpp13
-rw-r--r--src/vmime/net/transport.hpp22
10 files changed, 118 insertions, 28 deletions
diff --git a/src/vmime/constants.cpp b/src/vmime/constants.cpp
index 2b242885..6a7ddcb2 100644
--- a/src/vmime/constants.cpp
+++ b/src/vmime/constants.cpp
@@ -58,6 +58,7 @@ namespace mediaTypes {
const char* const MESSAGE_PARTIAL = "partial";
const char* const MESSAGE_EXTERNAL_BODY = "external-body";
const char* const MESSAGE_DISPOSITION_NOTIFICATION = "disposition-notification";
+ const char* const MESSAGE_DELIVERY_STATUS = "delivery-status";
const char* const APPLICATION_OCTET_STREAM = "octet-stream";
@@ -232,5 +233,19 @@ namespace dispositionModifiers {
const char* const ERROR = "error";
}
+// Constants for DSN (delivery status notification)
+namespace dsn
+{
+ const char* const NOTIFY = "NOTIFY";
+ const char* const NEVER = "NEVER";
+ const char* const SUCCESS = "SUCCESS";
+ const char* const FAILURE = "FAILURE";
+ const char* const DELAY = "DELAY";
+ const char* const ORCPT = "ORCPT";
+ const char* const RET = "RET";
+ const char* const FULL = "FULL";
+ const char* const HDRS = "HDRS";
+ const char* const ENVID = "ENVID";
+}
} // vmime
diff --git a/src/vmime/constants.hpp b/src/vmime/constants.hpp
index 17fbd3ad..d15aea1d 100644
--- a/src/vmime/constants.hpp
+++ b/src/vmime/constants.hpp
@@ -70,6 +70,7 @@ namespace vmime {
extern VMIME_EXPORT const char* const MESSAGE_PARTIAL;
extern VMIME_EXPORT const char* const MESSAGE_EXTERNAL_BODY;
extern VMIME_EXPORT const char* const MESSAGE_DISPOSITION_NOTIFICATION;
+ extern VMIME_EXPORT const char* const MESSAGE_DELIVERY_STATUS;
extern VMIME_EXPORT const char* const APPLICATION_OCTET_STREAM;
@@ -250,6 +251,21 @@ namespace vmime {
extern VMIME_EXPORT const char* const ERROR;
}
+
+ /** Constants for DSN (delivery status notification) */
+ namespace dsn
+ {
+ extern VMIME_EXPORT const char* const NOTIFY;
+ extern VMIME_EXPORT const char* const NEVER;
+ extern VMIME_EXPORT const char* const SUCCESS;
+ extern VMIME_EXPORT const char* const FAILURE;
+ extern VMIME_EXPORT const char* const DELAY;
+ extern VMIME_EXPORT const char* const ORCPT;
+ extern VMIME_EXPORT const char* const RET;
+ extern VMIME_EXPORT const char* const FULL;
+ extern VMIME_EXPORT const char* const HDRS;
+ extern VMIME_EXPORT const char* const ENVID;
+ }
}
diff --git a/src/vmime/net/sendmail/sendmailTransport.cpp b/src/vmime/net/sendmail/sendmailTransport.cpp
index e39cdd36..f7817bd7 100644
--- a/src/vmime/net/sendmail/sendmailTransport.cpp
+++ b/src/vmime/net/sendmail/sendmailTransport.cpp
@@ -148,7 +148,9 @@ void sendmailTransport::send(
utility::inputStream& is,
const size_t size,
utility::progressListener* progress,
- const mailbox& sender
+ const mailbox& sender,
+ const std::string& /*dsnNotify*/, const std::string& /*dsnRet*/,
+ const std::string& /*dsnEnvelopId*/
) {
// If no recipient/expeditor was found, throw an exception
diff --git a/src/vmime/net/sendmail/sendmailTransport.hpp b/src/vmime/net/sendmail/sendmailTransport.hpp
index 76e95726..467f9c0d 100644
--- a/src/vmime/net/sendmail/sendmailTransport.hpp
+++ b/src/vmime/net/sendmail/sendmailTransport.hpp
@@ -73,7 +73,10 @@ public:
utility::inputStream& is,
const size_t size,
utility::progressListener* progress = NULL,
- const mailbox& sender = mailbox()
+ const mailbox& sender = mailbox(),
+ const std::string& dsnNotify = std::string(),
+ const std::string& dsnRet = std::string(),
+ const std::string& dsnEnvelopId = std::string()
);
bool isSecuredConnection() const;
diff --git a/src/vmime/net/smtp/SMTPCommand.cpp b/src/vmime/net/smtp/SMTPCommand.cpp
index 8581a994..5e533d16 100644
--- a/src/vmime/net/smtp/SMTPCommand.cpp
+++ b/src/vmime/net/smtp/SMTPCommand.cpp
@@ -100,14 +100,16 @@ shared_ptr <SMTPCommand> SMTPCommand::STARTTLS() {
// static
-shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) {
+shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8,
+ const std::string& dsnRet, const std::string& dsnEnvelopId) {
- return MAIL(mbox, utf8, 0);
+ return MAIL(mbox, utf8, 0, dsnRet, dsnEnvelopId);
}
// static
-shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size) {
+shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size,
+ const std::string& dsnRet, const std::string& dsnEnvelopId) {
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
@@ -125,6 +127,13 @@ shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8,
cmd << ">";
+ if (!dsnRet.empty()) {
+ cmd << " " << dsn::RET << "=" << dsnRet;
+ }
+ if (!dsnEnvelopId.empty()) {
+ cmd << " " << dsn::ENVID << "=<" << dsnEnvelopId << ">";
+ }
+
if (utf8) {
cmd << " SMTPUTF8";
}
@@ -138,7 +147,8 @@ shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8,
// static
-shared_ptr <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) {
+shared_ptr <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox, const bool utf8,
+ const string& dsnNotify) {
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
@@ -156,6 +166,10 @@ shared_ptr <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox, const bool utf8)
cmd << ">";
+ if (!dsnNotify.empty()) {
+ cmd << " " << dsn::NOTIFY << "=" << dsnNotify;
+ }
+
return createCommand(cmd.str());
}
diff --git a/src/vmime/net/smtp/SMTPCommand.hpp b/src/vmime/net/smtp/SMTPCommand.hpp
index 137993c4..9a32d1e7 100644
--- a/src/vmime/net/smtp/SMTPCommand.hpp
+++ b/src/vmime/net/smtp/SMTPCommand.hpp
@@ -63,9 +63,12 @@ public:
static shared_ptr <SMTPCommand> AUTH(const string& mechName);
static shared_ptr <SMTPCommand> AUTH(const string& mechName, const std::string& initialResponse);
static shared_ptr <SMTPCommand> STARTTLS();
- static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8);
- static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8, const size_t size);
- static shared_ptr <SMTPCommand> RCPT(const mailbox& mbox, const bool utf8);
+ static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8,
+ const std::string& dsnRet, const std::string& dsnEnvelopId);
+ static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8, const size_t size,
+ const std::string& dsnRet, const std::string& dsnEnvelopId);
+ static shared_ptr <SMTPCommand> RCPT(const mailbox& mbox, const bool utf8,
+ const std::string& dsnNotify);
static shared_ptr <SMTPCommand> RSET();
static shared_ptr <SMTPCommand> DATA();
static shared_ptr <SMTPCommand> BDAT(const size_t chunkSize, const bool last);
diff --git a/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp
index 72cba7c7..0af3046a 100644
--- a/src/vmime/net/smtp/SMTPTransport.cpp
+++ b/src/vmime/net/smtp/SMTPTransport.cpp
@@ -183,7 +183,8 @@ void SMTPTransport::sendEnvelope(
const mailboxList& recipients,
const mailbox& sender,
bool sendDATACommand,
- const size_t size
+ const size_t size,
+ const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId
) {
// If no recipient/expeditor was found, throw an exception
if (recipients.isEmpty()) {
@@ -229,7 +230,7 @@ void SMTPTransport::sendEnvelope(
commands->addCommand(
SMTPCommand::MAIL(
- sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0
+ sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, dsnRet, dsnEnvelopId
)
);
@@ -237,7 +238,7 @@ void SMTPTransport::sendEnvelope(
commands->addCommand(
SMTPCommand::MAIL(
- expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0
+ expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, dsnRet, dsnEnvelopId
)
);
}
@@ -249,7 +250,7 @@ void SMTPTransport::sendEnvelope(
for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) {
const mailbox& mbox = *recipients.getMailboxAt(i);
- commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8));
+ commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8, dsnNotify));
}
// Prepare sending of message data
@@ -375,7 +376,8 @@ void SMTPTransport::send(
utility::inputStream& is,
const size_t size,
utility::progressListener* progress,
- const mailbox& sender
+ const mailbox& sender,
+ const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId
) {
if (!isConnected()) {
@@ -383,7 +385,8 @@ void SMTPTransport::send(
}
// Send message envelope
- sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size);
+ sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size,
+ dsnNotify, dsnRet, dsnEnvelopId);
// Send the message data
// Stream copy with "\n." to "\n.." transformation
@@ -415,7 +418,8 @@ void SMTPTransport::send(
const mailbox& expeditor,
const mailboxList& recipients,
utility::progressListener* progress,
- const mailbox& sender
+ const mailbox& sender,
+ const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId
) {
if (!isConnected()) {
@@ -442,14 +446,14 @@ void SMTPTransport::send(
utility::inputStreamStringAdapter isAdapter(str);
- send(expeditor, recipients, isAdapter, str.length(), progress, sender);
+ send(expeditor, recipients, isAdapter, str.length(), progress, sender, dsnNotify, dsnRet, dsnEnvelopId);
return;
}
// Send message envelope
const size_t msgSize = msg->getGeneratedSize(ctx);
- sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize);
+ sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize, dsnNotify, dsnRet, dsnEnvelopId);
// Send the message by chunks
SMTPChunkingOutputStreamAdapter chunkStream(m_connection, msgSize, progress);
diff --git a/src/vmime/net/smtp/SMTPTransport.hpp b/src/vmime/net/smtp/SMTPTransport.hpp
index 67c63a55..26d86ea1 100644
--- a/src/vmime/net/smtp/SMTPTransport.hpp
+++ b/src/vmime/net/smtp/SMTPTransport.hpp
@@ -78,7 +78,10 @@ public:
utility::inputStream& is,
const size_t size,
utility::progressListener* progress = NULL,
- const mailbox& sender = mailbox()
+ const mailbox& sender = mailbox(),
+ const std::string& dsnNotify = std::string(),
+ const std::string& dsnRet = std::string(),
+ const std::string& dsnEnvelopId = std::string()
);
void send(
@@ -86,7 +89,10 @@ public:
const mailbox& expeditor,
const mailboxList& recipients,
utility::progressListener* progress = NULL,
- const mailbox& sender = mailbox()
+ const mailbox& sender = mailbox(),
+ const std::string& dsnNotify = std::string(),
+ const std::string& dsnRet = std::string(),
+ const std::string& dsnEnvelopId = std::string()
);
bool isSecuredConnection() const;
@@ -108,13 +114,19 @@ private:
* @param sender envelope sender (if empty, expeditor will be used)
* @param sendDATACommand if true, the DATA command will be sent
* @param size message size, in bytes (or 0, if not known)
+ * @param dsnNotify comma separated list of notification conditions as specified in RFC 1891
+ * @param dsnRet content of DSN - full message or headers only ("FULL" or "HDRS")
+ * @param dsnEnvelopId envelop ID to be able to pair the DSN with the original message
*/
void sendEnvelope(
const mailbox& expeditor,
const mailboxList& recipients,
const mailbox& sender,
bool sendDATACommand,
- const size_t size
+ const size_t size,
+ const std::string& dsnNotify,
+ const std::string& dsnRet,
+ const std::string& dsnEnvelopId
);
diff --git a/src/vmime/net/transport.cpp b/src/vmime/net/transport.cpp
index f87648a3..218ab7f6 100644
--- a/src/vmime/net/transport.cpp
+++ b/src/vmime/net/transport.cpp
@@ -136,7 +136,9 @@ static void extractMailboxes(
void transport::send(
const shared_ptr <vmime::message>& msg,
- utility::progressListener* progress
+ utility::progressListener* progress,
+ const std::string& dsnNotify, const std::string& dsnRet,
+ const std::string& dsnEnvelopId
) {
// Extract expeditor
@@ -221,7 +223,8 @@ void transport::send(
} headerExchanger(msg, hdr);
- send(msg, expeditor, recipients, progress, sender);
+ send(msg, expeditor, recipients, progress, sender,
+ dsnNotify, dsnRet, dsnEnvelopId);
}
@@ -230,7 +233,8 @@ void transport::send(
const mailbox& expeditor,
const mailboxList& recipients,
utility::progressListener* progress,
- const mailbox& sender
+ const mailbox& sender,
+ const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId
) {
// Generate the message, "stream" it and delegate the sending
@@ -244,7 +248,8 @@ void transport::send(
utility::inputStreamStringAdapter isAdapter(str);
- send(expeditor, recipients, isAdapter, str.length(), progress, sender);
+ send(expeditor, recipients, isAdapter, str.length(), progress, sender,
+ dsnNotify, dsnRet, dsnEnvelopId);
}
diff --git a/src/vmime/net/transport.hpp b/src/vmime/net/transport.hpp
index 2f9878d0..089399c8 100644
--- a/src/vmime/net/transport.hpp
+++ b/src/vmime/net/transport.hpp
@@ -69,10 +69,16 @@ public:
*
* @param msg message to send
* @param progress progress listener, or NULL if not used
+ * @param dsnNotify comma separated list of notification conditions as specified in RFC 1891
+ * @param dsnRet content of DSN - full message or headers only ("FULL" or "HDRS")
+ * @param dsnEnvelopId envelop ID to be able to pair the DSN with original message
*/
virtual void send(
const shared_ptr <vmime::message>& msg,
- utility::progressListener* progress = NULL
+ utility::progressListener* progress = NULL,
+ const std::string& dsnNotify = std::string(),
+ const std::string& dsnRet = std::string(),
+ const std::string& dsnEnvelopId = std::string()
);
/** Send a message over this transport service.
@@ -83,6 +89,10 @@ public:
* @param size size of the message data
* @param progress progress listener, or NULL if not used
* @param sender envelope sender (if empty, expeditor will be used)
+ * @param dsnNotify comma separated list of notification conditions as specified in RFC 1891
+ * @param dsnRet content of DSN - full message or headers only ("FULL" or "HDRS")
+ * @param dsnEnvelopId envelope identifier to be transmitted along with the message
+ * to be able to pair the DSN with original message (plain text not in "<" ">")
*/
virtual void send(
const mailbox& expeditor,
@@ -90,7 +100,10 @@ public:
utility::inputStream& is,
const size_t size,
utility::progressListener* progress = NULL,
- const mailbox& sender = mailbox()
+ const mailbox& sender = mailbox(),
+ const std::string& dsnNotify = std::string(),
+ const std::string& dsnRet = std::string(),
+ const std::string& dsnEnvelopId = std::string()
) = 0;
/** Send a message over this transport service.
@@ -108,7 +121,10 @@ public:
const mailbox& expeditor,
const mailboxList& recipients,
utility::progressListener* progress = NULL,
- const mailbox& sender = mailbox()
+ const mailbox& sender = mailbox(),
+ const std::string& dsnNotify = std::string(),
+ const std::string& dsnRet = std::string(),
+ const std::string& dsnEnvelopId = std::string()
);