Merge pull request #240 from josusky/master
Add basic support for delivery status notifications (DSN).
This commit is contained in:
commit
84294f6543
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
65
src/vmime/net/dsnAttributes.cpp
Normal file
65
src/vmime/net/dsnAttributes.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2020 Jan Osusky <jan@osusky.name>
|
||||
//
|
||||
// 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(const string& dsnNotify, const string& dsnRet, const string& dsnEnvelopId)
|
||||
: m_notifications(dsnNotify), m_returnFormat(dsnRet), m_envelopId(dsnEnvelopId) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
string dsnAttributes::getNotificationConditions() const {
|
||||
|
||||
return m_notifications;
|
||||
}
|
||||
|
||||
|
||||
string dsnAttributes::getReturnFormat() const {
|
||||
|
||||
return m_returnFormat;
|
||||
}
|
||||
|
||||
|
||||
string dsnAttributes::getEnvelopId() const {
|
||||
|
||||
return m_envelopId;
|
||||
}
|
||||
|
||||
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
108
src/vmime/net/dsnAttributes.hpp
Normal file
108
src/vmime/net/dsnAttributes.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2020 Jan Osusky <jan@osusky.name>
|
||||
//
|
||||
// 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 <vector>
|
||||
|
||||
#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(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 getNotificationConditions() const;
|
||||
|
||||
/** Returns requested format of the notification (RET parameter of the ESMTP MAIL command).
|
||||
*
|
||||
* @return requested format of the notification.
|
||||
*/
|
||||
string getReturnFormat() const;
|
||||
|
||||
/** Returns envelop ID used to pair the DSN with the original message.
|
||||
*
|
||||
* @return envelop ID used to pair the DSN with the original message.
|
||||
*/
|
||||
string getEnvelopId() const;
|
||||
|
||||
private:
|
||||
|
||||
string m_notifications;
|
||||
string m_returnFormat;
|
||||
string m_envelopId;
|
||||
};
|
||||
|
||||
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
|
||||
#endif // VMIME_NET_DSNATTRIBUTES_HPP_INCLUDED
|
@ -148,7 +148,8 @@ void sendmailTransport::send(
|
||||
utility::inputStream& is,
|
||||
const size_t size,
|
||||
utility::progressListener* progress,
|
||||
const mailbox& sender
|
||||
const mailbox& sender,
|
||||
const dsnAttributes& /*dsnAttrs*/
|
||||
) {
|
||||
|
||||
// If no recipient/expeditor was found, throw an exception
|
||||
|
@ -73,7 +73,8 @@ public:
|
||||
utility::inputStream& is,
|
||||
const size_t size,
|
||||
utility::progressListener* progress = NULL,
|
||||
const mailbox& sender = mailbox()
|
||||
const mailbox& sender = mailbox(),
|
||||
const dsnAttributes& dsnAttrs
|
||||
);
|
||||
|
||||
bool isSecuredConnection() const;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -183,7 +183,8 @@ void SMTPTransport::sendEnvelope(
|
||||
const mailboxList& recipients,
|
||||
const mailbox& sender,
|
||||
bool sendDATACommand,
|
||||
const size_t size
|
||||
const size_t size,
|
||||
const dsnAttributes& dsnAttrs
|
||||
) {
|
||||
// If no recipient/expeditor was found, throw an exception
|
||||
if (recipients.isEmpty()) {
|
||||
@ -229,7 +230,9 @@ void SMTPTransport::sendEnvelope(
|
||||
|
||||
commands->addCommand(
|
||||
SMTPCommand::MAIL(
|
||||
sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0
|
||||
sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0,
|
||||
dsnAttrs.getNotificationConditions(),
|
||||
dsnAttrs.getEnvelopId()
|
||||
)
|
||||
);
|
||||
|
||||
@ -237,7 +240,9 @@ void SMTPTransport::sendEnvelope(
|
||||
|
||||
commands->addCommand(
|
||||
SMTPCommand::MAIL(
|
||||
expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0
|
||||
expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0,
|
||||
dsnAttrs.getNotificationConditions(),
|
||||
dsnAttrs.getEnvelopId()
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -249,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));
|
||||
commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8,
|
||||
dsnAttrs.getNotificationConditions()));
|
||||
}
|
||||
|
||||
// Prepare sending of message data
|
||||
@ -375,7 +381,8 @@ void SMTPTransport::send(
|
||||
utility::inputStream& is,
|
||||
const size_t size,
|
||||
utility::progressListener* progress,
|
||||
const mailbox& sender
|
||||
const mailbox& sender,
|
||||
const dsnAttributes& dsnAttrs
|
||||
) {
|
||||
|
||||
if (!isConnected()) {
|
||||
@ -383,7 +390,8 @@ void SMTPTransport::send(
|
||||
}
|
||||
|
||||
// Send message envelope
|
||||
sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size);
|
||||
sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size,
|
||||
dsnAttrs);
|
||||
|
||||
// Send the message data
|
||||
// Stream copy with "\n." to "\n.." transformation
|
||||
@ -415,7 +423,8 @@ void SMTPTransport::send(
|
||||
const mailbox& expeditor,
|
||||
const mailboxList& recipients,
|
||||
utility::progressListener* progress,
|
||||
const mailbox& sender
|
||||
const mailbox& sender,
|
||||
const dsnAttributes& dsnAttrs
|
||||
) {
|
||||
|
||||
if (!isConnected()) {
|
||||
@ -442,14 +451,14 @@ void SMTPTransport::send(
|
||||
|
||||
utility::inputStreamStringAdapter isAdapter(str);
|
||||
|
||||
send(expeditor, recipients, isAdapter, str.length(), progress, sender);
|
||||
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);
|
||||
sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize, dsnAttrs);
|
||||
|
||||
// Send the message by chunks
|
||||
SMTPChunkingOutputStreamAdapter chunkStream(m_connection, msgSize, progress);
|
||||
|
@ -78,7 +78,8 @@ public:
|
||||
utility::inputStream& is,
|
||||
const size_t size,
|
||||
utility::progressListener* progress = NULL,
|
||||
const mailbox& sender = mailbox()
|
||||
const mailbox& sender = mailbox(),
|
||||
const dsnAttributes& dsnAttrs = dsnAttributes()
|
||||
);
|
||||
|
||||
void send(
|
||||
@ -86,7 +87,8 @@ public:
|
||||
const mailbox& expeditor,
|
||||
const mailboxList& recipients,
|
||||
utility::progressListener* progress = NULL,
|
||||
const mailbox& sender = mailbox()
|
||||
const mailbox& sender = mailbox(),
|
||||
const dsnAttributes& dsnAttrs = dsnAttributes()
|
||||
);
|
||||
|
||||
bool isSecuredConnection() const;
|
||||
@ -108,13 +110,15 @@ 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 dsnAttributes attributes for Delivery Status Notification (if needed)
|
||||
*/
|
||||
void sendEnvelope(
|
||||
const mailbox& expeditor,
|
||||
const mailboxList& recipients,
|
||||
const mailbox& sender,
|
||||
bool sendDATACommand,
|
||||
const size_t size
|
||||
const size_t size,
|
||||
const dsnAttributes& dsnAttrs = dsnAttributes()
|
||||
);
|
||||
|
||||
|
||||
|
@ -136,7 +136,8 @@ static void extractMailboxes(
|
||||
|
||||
void transport::send(
|
||||
const shared_ptr <vmime::message>& msg,
|
||||
utility::progressListener* progress
|
||||
utility::progressListener* progress,
|
||||
const dsnAttributes& dsnAttrs
|
||||
) {
|
||||
|
||||
// Extract expeditor
|
||||
@ -221,7 +222,7 @@ void transport::send(
|
||||
|
||||
} headerExchanger(msg, hdr);
|
||||
|
||||
send(msg, expeditor, recipients, progress, sender);
|
||||
send(msg, expeditor, recipients, progress, sender, dsnAttrs);
|
||||
}
|
||||
|
||||
|
||||
@ -230,7 +231,8 @@ void transport::send(
|
||||
const mailbox& expeditor,
|
||||
const mailboxList& recipients,
|
||||
utility::progressListener* progress,
|
||||
const mailbox& sender
|
||||
const mailbox& sender,
|
||||
const dsnAttributes& dsnAttrs
|
||||
) {
|
||||
|
||||
// Generate the message, "stream" it and delegate the sending
|
||||
@ -244,7 +246,8 @@ void transport::send(
|
||||
|
||||
utility::inputStreamStringAdapter isAdapter(str);
|
||||
|
||||
send(expeditor, recipients, isAdapter, str.length(), progress, sender);
|
||||
send(expeditor, recipients, isAdapter, str.length(), progress, sender,
|
||||
dsnAttrs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,10 +70,12 @@ public:
|
||||
*
|
||||
* @param msg message to send
|
||||
* @param progress progress listener, or NULL if not used
|
||||
* @param dsnAttributes attributes for Delivery Status Notification (if needed)
|
||||
*/
|
||||
virtual void send(
|
||||
const shared_ptr <vmime::message>& msg,
|
||||
utility::progressListener* progress = NULL
|
||||
utility::progressListener* progress = NULL,
|
||||
const dsnAttributes& dsnAttrs = dsnAttributes()
|
||||
);
|
||||
|
||||
/** Send a message over this transport service.
|
||||
@ -83,6 +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 dsnAttributes attributes for Delivery Status Notification (if needed)
|
||||
*/
|
||||
virtual void send(
|
||||
const mailbox& expeditor,
|
||||
@ -90,7 +94,8 @@ public:
|
||||
utility::inputStream& is,
|
||||
const size_t size,
|
||||
utility::progressListener* progress = NULL,
|
||||
const mailbox& sender = mailbox()
|
||||
const mailbox& sender = mailbox(),
|
||||
const dsnAttributes& dsnAttrs = dsnAttributes()
|
||||
) = 0;
|
||||
|
||||
/** Send a message over this transport service.
|
||||
@ -102,13 +107,15 @@ 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 <vmime::message>& msg,
|
||||
const mailbox& expeditor,
|
||||
const mailboxList& recipients,
|
||||
utility::progressListener* progress = NULL,
|
||||
const mailbox& sender = mailbox()
|
||||
const mailbox& sender = mailbox(),
|
||||
const dsnAttributes& dsnAttrs = dsnAttributes()
|
||||
);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user