From e30766cf2aa0cbfee3848c518193caa982356d11 Mon Sep 17 00:00:00 2001 From: Jan Osusky Date: Fri, 20 Oct 2017 14:02:33 +0200 Subject: [PATCH 1/8] Add basic support for delivery status notifications (DSN) Added possibility to send e-mails with explicit request for delivery status notification and its content. --- src/vmime/constants.cpp | 15 +++++++++++++ src/vmime/constants.hpp | 16 ++++++++++++++ src/vmime/net/sendmail/sendmailTransport.cpp | 4 +++- src/vmime/net/sendmail/sendmailTransport.hpp | 5 ++++- src/vmime/net/smtp/SMTPCommand.cpp | 22 ++++++++++++++++---- src/vmime/net/smtp/SMTPCommand.hpp | 9 +++++--- src/vmime/net/smtp/SMTPTransport.cpp | 22 ++++++++++++-------- src/vmime/net/smtp/SMTPTransport.hpp | 18 +++++++++++++--- src/vmime/net/transport.cpp | 13 ++++++++---- src/vmime/net/transport.hpp | 22 +++++++++++++++++--- 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::STARTTLS() { // static -shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) { +shared_ptr 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::MAIL(const mailbox& mbox, const bool utf8, const size_t size) { +shared_ptr 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::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::MAIL(const mailbox& mbox, const bool utf8, // static -shared_ptr SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) { +shared_ptr 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::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 AUTH(const string& mechName); static shared_ptr AUTH(const string& mechName, const std::string& initialResponse); static shared_ptr STARTTLS(); - static shared_ptr MAIL(const mailbox& mbox, const bool utf8); - static shared_ptr MAIL(const mailbox& mbox, const bool utf8, const size_t size); - static shared_ptr RCPT(const mailbox& mbox, const bool utf8); + static shared_ptr MAIL(const mailbox& mbox, const bool utf8, + const std::string& dsnRet, const std::string& dsnEnvelopId); + static shared_ptr MAIL(const mailbox& mbox, const bool utf8, const size_t size, + const std::string& dsnRet, const std::string& dsnEnvelopId); + static shared_ptr RCPT(const mailbox& mbox, const bool utf8, + const std::string& dsnNotify); static shared_ptr RSET(); static shared_ptr DATA(); static shared_ptr 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 & 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 & 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() ); From 64ef65e03c21927ecf52c983f0902c4189be5d42 Mon Sep 17 00:00:00 2001 From: Jan Osusky Date: Thu, 23 Jul 2020 10:42:15 +0200 Subject: [PATCH 2/8] Create class for DSN attributes The three attributes needed to request a Delivery Status Notification are now passed as an "dsnAttributes" object to the send methods. Fixed code style at some related palces. --- src/vmime/constants.cpp | 4 +- src/vmime/constants.hpp | 4 +- src/vmime/net/dsnAttributes.cpp | 65 +++++++++++ src/vmime/net/dsnAttributes.hpp | 108 +++++++++++++++++++ src/vmime/net/sendmail/sendmailTransport.cpp | 3 +- src/vmime/net/sendmail/sendmailTransport.hpp | 4 +- src/vmime/net/smtp/SMTPTransport.cpp | 23 ++-- src/vmime/net/smtp/SMTPTransport.hpp | 16 +-- src/vmime/net/transport.cpp | 10 +- src/vmime/net/transport.hpp | 23 ++-- 10 files changed, 208 insertions(+), 52 deletions(-) create mode 100644 src/vmime/net/dsnAttributes.cpp create mode 100644 src/vmime/net/dsnAttributes.hpp diff --git a/src/vmime/constants.cpp b/src/vmime/constants.cpp index 6a7ddcb2..445c0121 100644 --- a/src/vmime/constants.cpp +++ b/src/vmime/constants.cpp @@ -234,8 +234,8 @@ namespace dispositionModifiers { } // Constants for DSN (delivery status notification) -namespace dsn -{ +namespace dsn { + const char* const NOTIFY = "NOTIFY"; const char* const NEVER = "NEVER"; const char* const SUCCESS = "SUCCESS"; diff --git a/src/vmime/constants.hpp b/src/vmime/constants.hpp index d15aea1d..9d253832 100644 --- a/src/vmime/constants.hpp +++ b/src/vmime/constants.hpp @@ -253,8 +253,8 @@ namespace vmime { } /** Constants for DSN (delivery status notification) */ - namespace dsn - { + namespace dsn { + extern VMIME_EXPORT const char* const NOTIFY; extern VMIME_EXPORT const char* const NEVER; extern VMIME_EXPORT const char* const SUCCESS; diff --git a/src/vmime/net/dsnAttributes.cpp b/src/vmime/net/dsnAttributes.cpp new file mode 100644 index 00000000..e76faa00 --- /dev/null +++ b/src/vmime/net/dsnAttributes.cpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2020 Jan Osusky +// +// 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 3 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., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES + + +#include "vmime/net/dsnAttributes.hpp" + + +namespace vmime { +namespace net { + + +dsnAttributes::dsnAttributes(string dsnNotify, string dsnRet, string dsnEnvelopId) + : m_notifications(dsnNotify), m_returnFormat(dsnRet), m_envelopId(dsnEnvelopId) { + +} + + +string dsnAttributes::notificationConditions() const { + + return m_notifications; +} + + +string dsnAttributes::returnFormat() const { + + return m_returnFormat; +} + + +string dsnAttributes::envelopId() const { + + return m_envelopId; +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/vmime/net/dsnAttributes.hpp b/src/vmime/net/dsnAttributes.hpp new file mode 100644 index 00000000..debb9940 --- /dev/null +++ b/src/vmime/net/dsnAttributes.hpp @@ -0,0 +1,108 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2020 Jan Osusky +// +// 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 3 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., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_DSNATTRIBUTES_HPP_INCLUDED +#define VMIME_NET_DSNATTRIBUTES_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES + + +#include + +#include "vmime/types.hpp" + + +namespace vmime { +namespace net { + + +/** Holds a set of attributes for Delivery Status Notifications (DSN). + */ +class VMIME_EXPORT dsnAttributes : public object { + +public: + + /** Constructs an empty dsnAttributes object. + */ + dsnAttributes() = default; + + /** Constructs a new dsnAttributes object by copying an existing object. + * + * @param dsn object to copy + */ + dsnAttributes(const dsnAttributes& dsn) = default; + + /** Constructs a new dsnAttributes object by moving an existing object. + * + * @param dsn object (Rvalue reference) to move from. + */ + dsnAttributes(dsnAttributes&& dsn) = default; + + ~dsnAttributes() = default; + + /** Constructs a new dsnAttributes object by specifying the attributes. + * + * @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 (plain text not in "<" ">") + */ + dsnAttributes(string dsnNotify, string dsnRet, string dsnEnvelopId); + + /** Returns comma separated list of notification conditions as specified in RFC 1891 + * + * @return comma separated list of notification conditions as specified in RFC 1891 + */ + string notificationConditions() const; + + /** Returns requested format of the notification (RET parameter of the ESMTP MAIL command). + * + * @return requested format of the notification. + */ + string returnFormat() const; + + /** Returns envelop ID used pair the DSN with the original message. + * + * @return envelop ID used pair the DSN with the original message. + */ + string envelopId() const; + +private: + + string m_notifications; + string m_returnFormat; + string m_envelopId; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + + +#endif // VMIME_NET_DSNATTRIBUTES_HPP_INCLUDED diff --git a/src/vmime/net/sendmail/sendmailTransport.cpp b/src/vmime/net/sendmail/sendmailTransport.cpp index f7817bd7..7010fd85 100644 --- a/src/vmime/net/sendmail/sendmailTransport.cpp +++ b/src/vmime/net/sendmail/sendmailTransport.cpp @@ -149,8 +149,7 @@ void sendmailTransport::send( const size_t size, utility::progressListener* progress, const mailbox& sender, - const std::string& /*dsnNotify*/, const std::string& /*dsnRet*/, - const std::string& /*dsnEnvelopId*/ + const dsnAttributes& /*dsnAttrs*/ ) { // 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 467f9c0d..56e11d7c 100644 --- a/src/vmime/net/sendmail/sendmailTransport.hpp +++ b/src/vmime/net/sendmail/sendmailTransport.hpp @@ -74,9 +74,7 @@ public: const size_t size, utility::progressListener* progress = NULL, const mailbox& sender = mailbox(), - const std::string& dsnNotify = std::string(), - const std::string& dsnRet = std::string(), - const std::string& dsnEnvelopId = std::string() + const dsnAttributes& dsnAttrs ); bool isSecuredConnection() const; diff --git a/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp index 0af3046a..7ccedd88 100644 --- a/src/vmime/net/smtp/SMTPTransport.cpp +++ b/src/vmime/net/smtp/SMTPTransport.cpp @@ -184,7 +184,7 @@ void SMTPTransport::sendEnvelope( const mailbox& sender, bool sendDATACommand, const size_t size, - const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId + const dsnAttributes& dsnAttrs ) { // If no recipient/expeditor was found, throw an exception if (recipients.isEmpty()) { @@ -230,7 +230,9 @@ void SMTPTransport::sendEnvelope( commands->addCommand( SMTPCommand::MAIL( - sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, dsnRet, dsnEnvelopId + sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, + dsnAttrs.notificationConditions(), + dsnAttrs.envelopId() ) ); @@ -238,7 +240,9 @@ void SMTPTransport::sendEnvelope( commands->addCommand( SMTPCommand::MAIL( - expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, dsnRet, dsnEnvelopId + expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, + dsnAttrs.notificationConditions(), + dsnAttrs.envelopId() ) ); } @@ -250,7 +254,8 @@ 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, dsnNotify)); + commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8, + dsnAttrs.notificationConditions())); } // Prepare sending of message data @@ -377,7 +382,7 @@ void SMTPTransport::send( const size_t size, utility::progressListener* progress, const mailbox& sender, - const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId + const dsnAttributes& dsnAttrs ) { if (!isConnected()) { @@ -386,7 +391,7 @@ void SMTPTransport::send( // Send message envelope sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size, - dsnNotify, dsnRet, dsnEnvelopId); + dsnAttrs); // Send the message data // Stream copy with "\n." to "\n.." transformation @@ -419,7 +424,7 @@ void SMTPTransport::send( const mailboxList& recipients, utility::progressListener* progress, const mailbox& sender, - const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId + const dsnAttributes& dsnAttrs ) { if (!isConnected()) { @@ -446,14 +451,14 @@ void SMTPTransport::send( utility::inputStreamStringAdapter isAdapter(str); - send(expeditor, recipients, isAdapter, str.length(), progress, sender, dsnNotify, dsnRet, dsnEnvelopId); + send(expeditor, recipients, isAdapter, str.length(), progress, sender, dsnAttrs); return; } // Send message envelope const size_t msgSize = msg->getGeneratedSize(ctx); - sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize, dsnNotify, dsnRet, dsnEnvelopId); + sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize, dsnAttrs); // 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 26d86ea1..cd7c712d 100644 --- a/src/vmime/net/smtp/SMTPTransport.hpp +++ b/src/vmime/net/smtp/SMTPTransport.hpp @@ -79,9 +79,7 @@ public: const size_t size, utility::progressListener* progress = NULL, const mailbox& sender = mailbox(), - const std::string& dsnNotify = std::string(), - const std::string& dsnRet = std::string(), - const std::string& dsnEnvelopId = std::string() + const dsnAttributes& dsnAttrs = dsnAttributes() ); void send( @@ -90,9 +88,7 @@ public: const mailboxList& recipients, utility::progressListener* progress = NULL, const mailbox& sender = mailbox(), - const std::string& dsnNotify = std::string(), - const std::string& dsnRet = std::string(), - const std::string& dsnEnvelopId = std::string() + const dsnAttributes& dsnAttrs = dsnAttributes() ); bool isSecuredConnection() const; @@ -114,9 +110,7 @@ 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 + * @param dsnAttributes attributes for Delivery Status Notification (if needed) */ void sendEnvelope( const mailbox& expeditor, @@ -124,9 +118,7 @@ private: const mailbox& sender, bool sendDATACommand, const size_t size, - const std::string& dsnNotify, - const std::string& dsnRet, - const std::string& dsnEnvelopId + const dsnAttributes& dsnAttrs = dsnAttributes() ); diff --git a/src/vmime/net/transport.cpp b/src/vmime/net/transport.cpp index 218ab7f6..0991302b 100644 --- a/src/vmime/net/transport.cpp +++ b/src/vmime/net/transport.cpp @@ -137,8 +137,7 @@ static void extractMailboxes( void transport::send( const shared_ptr & msg, utility::progressListener* progress, - const std::string& dsnNotify, const std::string& dsnRet, - const std::string& dsnEnvelopId + const dsnAttributes& dsnAttrs ) { // Extract expeditor @@ -223,8 +222,7 @@ void transport::send( } headerExchanger(msg, hdr); - send(msg, expeditor, recipients, progress, sender, - dsnNotify, dsnRet, dsnEnvelopId); + send(msg, expeditor, recipients, progress, sender, dsnAttrs); } @@ -234,7 +232,7 @@ void transport::send( const mailboxList& recipients, utility::progressListener* progress, const mailbox& sender, - const std::string& dsnNotify, const std::string& dsnRet, const std::string& dsnEnvelopId + const dsnAttributes& dsnAttrs ) { // Generate the message, "stream" it and delegate the sending @@ -249,7 +247,7 @@ void transport::send( utility::inputStreamStringAdapter isAdapter(str); send(expeditor, recipients, isAdapter, str.length(), progress, sender, - dsnNotify, dsnRet, dsnEnvelopId); + dsnAttrs); } diff --git a/src/vmime/net/transport.hpp b/src/vmime/net/transport.hpp index 089399c8..daa4717f 100644 --- a/src/vmime/net/transport.hpp +++ b/src/vmime/net/transport.hpp @@ -31,6 +31,7 @@ #if VMIME_HAVE_MESSAGING_FEATURES +#include "vmime/net/dsnAttributes.hpp" #include "vmime/net/service.hpp" #include "vmime/utility/stream.hpp" @@ -69,16 +70,12 @@ 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 + * @param dsnAttributes attributes for Delivery Status Notification (if needed) */ virtual void send( const shared_ptr & msg, utility::progressListener* progress = NULL, - const std::string& dsnNotify = std::string(), - const std::string& dsnRet = std::string(), - const std::string& dsnEnvelopId = std::string() + const dsnAttributes& dsnAttrs = dsnAttributes() ); /** Send a message over this transport service. @@ -89,10 +86,7 @@ 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 "<" ">") + * @param dsnAttributes attributes for Delivery Status Notification (if needed) */ virtual void send( const mailbox& expeditor, @@ -101,9 +95,7 @@ public: const size_t size, utility::progressListener* progress = NULL, const mailbox& sender = mailbox(), - const std::string& dsnNotify = std::string(), - const std::string& dsnRet = std::string(), - const std::string& dsnEnvelopId = std::string() + const dsnAttributes& dsnAttrs = dsnAttributes() ) = 0; /** Send a message over this transport service. @@ -115,6 +107,7 @@ public: * @param recipients list of recipient mailboxes * @param progress progress listener, or NULL if not used * @param sender envelope sender (if empty, expeditor will be used) + * @param dsnAttributes attributes for Delivery Status Notification (if needed) */ virtual void send( const shared_ptr & msg, @@ -122,9 +115,7 @@ public: const mailboxList& recipients, utility::progressListener* progress = NULL, const mailbox& sender = mailbox(), - const std::string& dsnNotify = std::string(), - const std::string& dsnRet = std::string(), - const std::string& dsnEnvelopId = std::string() + const dsnAttributes& dsnAttrs = dsnAttributes() ); From d4cc5cfc9b2e9a3a4c260d406453f1fc3215906c Mon Sep 17 00:00:00 2001 From: Jan Osusky Date: Fri, 21 Aug 2020 13:13:55 +0200 Subject: [PATCH 3/8] Editorial changes in DSN attributes --- src/vmime/net/dsnAttributes.cpp | 8 ++++---- src/vmime/net/dsnAttributes.hpp | 8 ++++---- src/vmime/net/smtp/SMTPTransport.cpp | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/vmime/net/dsnAttributes.cpp b/src/vmime/net/dsnAttributes.cpp index e76faa00..122e0c81 100644 --- a/src/vmime/net/dsnAttributes.cpp +++ b/src/vmime/net/dsnAttributes.cpp @@ -34,25 +34,25 @@ namespace vmime { namespace net { -dsnAttributes::dsnAttributes(string dsnNotify, string dsnRet, string dsnEnvelopId) +dsnAttributes::dsnAttributes(const string& dsnNotify, const string& dsnRet, const string& dsnEnvelopId) : m_notifications(dsnNotify), m_returnFormat(dsnRet), m_envelopId(dsnEnvelopId) { } -string dsnAttributes::notificationConditions() const { +string dsnAttributes::getNotificationConditions() const { return m_notifications; } -string dsnAttributes::returnFormat() const { +string dsnAttributes::getReturnFormat() const { return m_returnFormat; } -string dsnAttributes::envelopId() const { +string dsnAttributes::getEnvelopId() const { return m_envelopId; } diff --git a/src/vmime/net/dsnAttributes.hpp b/src/vmime/net/dsnAttributes.hpp index debb9940..9453e858 100644 --- a/src/vmime/net/dsnAttributes.hpp +++ b/src/vmime/net/dsnAttributes.hpp @@ -70,25 +70,25 @@ public: * @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 (plain text not in "<" ">") */ - dsnAttributes(string dsnNotify, string dsnRet, string dsnEnvelopId); + dsnAttributes(const string& dsnNotify, const string& dsnRet, const string& dsnEnvelopId); /** Returns comma separated list of notification conditions as specified in RFC 1891 * * @return comma separated list of notification conditions as specified in RFC 1891 */ - string notificationConditions() const; + string getNotificationConditions() const; /** Returns requested format of the notification (RET parameter of the ESMTP MAIL command). * * @return requested format of the notification. */ - string returnFormat() const; + string getReturnFormat() const; /** Returns envelop ID used pair the DSN with the original message. * * @return envelop ID used pair the DSN with the original message. */ - string envelopId() const; + string getEnvelopId() const; private: diff --git a/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp index 7ccedd88..f5dd3858 100644 --- a/src/vmime/net/smtp/SMTPTransport.cpp +++ b/src/vmime/net/smtp/SMTPTransport.cpp @@ -231,8 +231,8 @@ void SMTPTransport::sendEnvelope( commands->addCommand( SMTPCommand::MAIL( sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, - dsnAttrs.notificationConditions(), - dsnAttrs.envelopId() + dsnAttrs.getNotificationConditions(), + dsnAttrs.getEnvelopId() ) ); @@ -241,8 +241,8 @@ void SMTPTransport::sendEnvelope( commands->addCommand( SMTPCommand::MAIL( expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0, - dsnAttrs.notificationConditions(), - dsnAttrs.envelopId() + dsnAttrs.getNotificationConditions(), + dsnAttrs.getEnvelopId() ) ); } @@ -255,7 +255,7 @@ void SMTPTransport::sendEnvelope( const mailbox& mbox = *recipients.getMailboxAt(i); commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8, - dsnAttrs.notificationConditions())); + dsnAttrs.getNotificationConditions())); } // Prepare sending of message data From 22ae6a91f5adaea5b101965994b62148814e6a96 Mon Sep 17 00:00:00 2001 From: Richard Steele Date: Mon, 18 Nov 2019 11:54:19 +0100 Subject: [PATCH 4/8] Fix #223 --- src/vmime/net/tls/openssl/OpenSSLInitializer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp index 47ad00fd..c7b1013d 100644 --- a/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp +++ b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp @@ -127,8 +127,8 @@ void OpenSSLInitializer::initialize() { g_openSSLMutexes[i] = vmime::platform::getHandler()->createCriticalSection(); } - CRYPTO_set_locking_callback(OpenSSLCallback_lock); - CRYPTO_set_id_callback(OpenSSLCallback_id); + CRYPTO_set_locking_callback(VMime_OpenSSLCallback_lock); + CRYPTO_set_id_callback(VMime_OpenSSLCallback_id); #endif // Seed the RNG, in case /dev/urandom is not available. Explicitely calling From d14038dd669bd8b2bf68d5e6fa1b6f6c45e730ed Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Sat, 8 Aug 2020 12:44:03 -0400 Subject: [PATCH 5/8] Refactor out getPartName() --- src/vmime/net/imap/IMAPMessagePart.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/vmime/net/imap/IMAPMessagePart.cpp b/src/vmime/net/imap/IMAPMessagePart.cpp index 746fe9a4..ddb4dd47 100644 --- a/src/vmime/net/imap/IMAPMessagePart.cpp +++ b/src/vmime/net/imap/IMAPMessagePart.cpp @@ -52,6 +52,21 @@ IMAPMessagePart::IMAPMessagePart( ); } +namespace { + template + vmime::string getPartName(const T& body_type) { + if (const auto* pparam = body_type->body_fields->body_fld_param.get()) { + for (const auto& param : pparam->items) { + if (param->string1->value == "NAME") { + return param->string2->value; + } + } + } + + return {}; + } +} + IMAPMessagePart::IMAPMessagePart( const shared_ptr & parent, @@ -88,13 +103,7 @@ IMAPMessagePart::IMAPMessagePart( m_size = part->body_type_basic->body_fields->body_fld_octets->value; - if (const auto* pparam = part->body_type_basic->body_fields->body_fld_param.get()) { - for (const auto& param : pparam->items) { - if (param->string1->value == "NAME") { - m_name = param->string2->value; - } - } - } + m_name = getPartName(part->body_type_basic); if (part->body_ext_1part && part->body_ext_1part->body_fld_dsp) { auto *cdisp = part->body_ext_1part->body_fld_dsp->str(); From 4edb9ed949583107d770bcd511dfa06d2d99366a Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Sat, 8 Aug 2020 12:50:53 -0400 Subject: [PATCH 6/8] Text body part can also have a name --- src/vmime/net/imap/IMAPMessagePart.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vmime/net/imap/IMAPMessagePart.cpp b/src/vmime/net/imap/IMAPMessagePart.cpp index ddb4dd47..1cf662de 100644 --- a/src/vmime/net/imap/IMAPMessagePart.cpp +++ b/src/vmime/net/imap/IMAPMessagePart.cpp @@ -87,6 +87,8 @@ IMAPMessagePart::IMAPMessagePart( m_size = part->body_type_text->body_fields->body_fld_octets->value; + m_name = getPartName(part->body_type_text); + } else if (part->body_type_msg) { m_mediaType = vmime::mediaType( From 6eb63399a1586f54700eb1783e066a6c26337db4 Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Sat, 8 Aug 2020 14:46:19 -0400 Subject: [PATCH 7/8] Try obtaining content disposition for all body parts types --- src/vmime/net/imap/IMAPMessagePart.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vmime/net/imap/IMAPMessagePart.cpp b/src/vmime/net/imap/IMAPMessagePart.cpp index 1cf662de..ed2c0bd2 100644 --- a/src/vmime/net/imap/IMAPMessagePart.cpp +++ b/src/vmime/net/imap/IMAPMessagePart.cpp @@ -106,12 +106,12 @@ IMAPMessagePart::IMAPMessagePart( m_size = part->body_type_basic->body_fields->body_fld_octets->value; m_name = getPartName(part->body_type_basic); + } - if (part->body_ext_1part && part->body_ext_1part->body_fld_dsp) { - auto *cdisp = part->body_ext_1part->body_fld_dsp->str(); - if (cdisp) { - m_dispType = contentDisposition(cdisp->value); - } + if (part->body_ext_1part && part->body_ext_1part->body_fld_dsp) { + auto *cdisp = part->body_ext_1part->body_fld_dsp->str(); + if (cdisp) { + m_dispType = contentDisposition(cdisp->value); } } From 7000792fa087a871056b9338a688f0f334b3c41d Mon Sep 17 00:00:00 2001 From: Jan Osusky Date: Fri, 21 Aug 2020 13:30:36 +0200 Subject: [PATCH 8/8] Fix wording of DSN attributes documentation --- src/vmime/net/dsnAttributes.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmime/net/dsnAttributes.hpp b/src/vmime/net/dsnAttributes.hpp index 9453e858..6749c721 100644 --- a/src/vmime/net/dsnAttributes.hpp +++ b/src/vmime/net/dsnAttributes.hpp @@ -84,9 +84,9 @@ public: */ string getReturnFormat() const; - /** Returns envelop ID used pair the DSN with the original message. + /** Returns envelop ID used to pair the DSN with the original message. * - * @return envelop ID used pair the DSN with the original message. + * @return envelop ID used to pair the DSN with the original message. */ string getEnvelopId() const;