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); }
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); }
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); }