void transport::send(ref <vmime::message> msg, utility::progressListener* progress)
{
	// Extract expeditor
	mailbox expeditor;

	try
	{
		const mailbox& mbox = *msg->getHeader()->findField(fields::FROM)->
			getValue().dynamicCast <const mailbox>();

		expeditor = mbox;
	}
	catch (exceptions::no_such_field&)
	{
		throw exceptions::no_expeditor();
	}

	// Extract sender
	mailbox sender;

	try
	{
		const mailbox& mbox = *msg->getHeader()->findField(fields::SENDER)->
			getValue().dynamicCast <const mailbox>();

		sender = mbox;
	}
	catch (exceptions::no_such_field&)
	{
		sender = expeditor;
	}

	// Extract recipients
	mailboxList recipients;

	try
	{
		const addressList& to = *msg->getHeader()->findField(fields::TO)->
			getValue().dynamicCast <const addressList>();

		extractMailboxes(recipients, to);
	}
	catch (exceptions::no_such_field&) { }

	try
	{
		const addressList& cc = *msg->getHeader()->findField(fields::CC)->
			getValue().dynamicCast <const addressList>();

		extractMailboxes(recipients, cc);
	}
	catch (exceptions::no_such_field&) { }

	try
	{
		const addressList& bcc = *msg->getHeader()->findField(fields::BCC)->
			getValue().dynamicCast <const addressList>();

		extractMailboxes(recipients, bcc);
	}
	catch (exceptions::no_such_field&) { }

	// 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
	{
		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);

	send(msg, expeditor, recipients, progress, sender);
}
Exemplo n.º 2
0
void transport::send(shared_ptr <vmime::message> msg, utility::progressListener* progress)
{
	// Extract expeditor
	shared_ptr <mailbox> fromMbox =
		msg->getHeader()->findFieldValue <mailbox>(fields::FROM);

	if (!fromMbox)
		throw exceptions::no_expeditor();

	mailbox expeditor = *fromMbox;

	// Extract sender
	shared_ptr <mailbox> senderMbox =
		msg->getHeader()->findFieldValue <mailbox>(fields::SENDER);

	mailbox sender;

	if (!senderMbox)
		sender = expeditor;
	else
		sender = *senderMbox;

	// Extract recipients
	mailboxList recipients;

	// -- "To" field
	shared_ptr <addressList> addresses =
		msg->getHeader()->findFieldValue <addressList>(fields::TO);

	if (addresses)
		extractMailboxes(recipients, *addresses);

	// -- "Cc" field
	addresses =
		msg->getHeader()->findFieldValue <addressList>(fields::CC);

	if (addresses)
		extractMailboxes(recipients, *addresses);

	// -- "Bcc" field
	addresses =
		msg->getHeader()->findFieldValue <addressList>(fields::BCC);

	if (addresses)
		extractMailboxes(recipients, *addresses);

	// 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.
	shared_ptr <header> hdr = vmime::clone(msg->getHeader());
	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
	{
		XChangeMsgHeader(shared_ptr <vmime::message> _msg,
		                 shared_ptr <vmime::header> _hdr)
			: msg(_msg), hdr(msg->getHeader())
		{
			// Set new header
			msg->setHeader(_hdr);
		}

		~XChangeMsgHeader()
		{
			// Revert original header
			msg->setHeader(hdr);
		}

	private:

		shared_ptr <vmime::message> msg;
		shared_ptr <vmime::header> hdr;
	} headerExchanger(msg, hdr);

	send(msg, expeditor, recipients, progress, sender);
}
Exemplo n.º 3
0
void transport::send(ref <vmime::message> msg, utility::progressListener* progress)
{
	// Extract expeditor
	mailbox expeditor;

	try
	{
		const mailbox& mbox = *msg->getHeader()->findField(fields::FROM)->
			getValue().dynamicCast <const mailbox>();

		expeditor = mbox;
	}
	catch (exceptions::no_such_field&)
	{
		throw exceptions::no_expeditor();
	}

	// Extract recipients
	mailboxList recipients;

	try
	{
		const addressList& to = *msg->getHeader()->findField(fields::TO)->
			getValue().dynamicCast <const addressList>();

		extractMailboxes(recipients, to);
	}
	catch (exceptions::no_such_field&) { }

	try
	{
		const addressList& cc = *msg->getHeader()->findField(fields::CC)->
			getValue().dynamicCast <const addressList>();

		extractMailboxes(recipients, cc);
	}
	catch (exceptions::no_such_field&) { }

	try
	{
		const addressList& bcc = *msg->getHeader()->findField(fields::BCC)->
			getValue().dynamicCast <const addressList>();

		extractMailboxes(recipients, bcc);
	}
	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
	{
		ref <headerField> bcc = msg->getHeader()->findField(fields::BCC);
		msg->getHeader()->removeField(bcc);
	}
	catch (exceptions::no_such_field&) { }

	// Generate the message, "stream" it and delegate the sending
	// to the generic send() function.
	std::ostringstream oss;
	utility::outputStreamAdapter ossAdapter(oss);

	msg->generate(ossAdapter);

	const string& str(oss.str());

	utility::inputStreamStringAdapter isAdapter(str);

	send(expeditor, recipients, isAdapter, str.length(), progress);
}