diff options
Diffstat (limited to 'smtp')
-rw-r--r-- | smtp/src/error.rs | 21 | ||||
-rw-r--r-- | smtp/src/lib.rs | 25 | ||||
-rw-r--r-- | smtp/src/request.rs | 176 | ||||
-rw-r--r-- | smtp/src/resolve_all.rs | 40 | ||||
-rw-r--r-- | smtp/src/send_mail.rs | 100 |
5 files changed, 180 insertions, 182 deletions
diff --git a/smtp/src/error.rs b/smtp/src/error.rs index 17f76e5..0d637a8 100644 --- a/smtp/src/error.rs +++ b/smtp/src/error.rs @@ -1,13 +1,10 @@ //! Module containing all custom errors. -use std::{io as std_io}; +use std::io as std_io; -use new_tokio_smtp::error::{ - ConnectingFailed, - LogicError, GeneralError -}; +use new_tokio_smtp::error::{ConnectingFailed, GeneralError, LogicError}; -use mail::error::MailError; use headers::error::HeaderValidationError; +use mail::error::MailError; /// Error used when sending a mail fails. /// @@ -16,7 +13,6 @@ use headers::error::HeaderValidationError; /// it's done "on the fly" when sending a mail. #[derive(Debug, Fail)] pub enum MailSendError { - /// Something is wrong with the mail instance (e.g. it can't be encoded). /// /// This can happen for a number of reasons including: @@ -56,7 +52,7 @@ pub enum MailSendError { /// was successful, which normally includes sending Ehlo and Auth /// commands. #[fail(display = "{}", _0)] - Io(std_io::Error) + Io(std_io::Error), } impl From<MailError> for MailSendError { @@ -89,21 +85,18 @@ impl From<GeneralError> for MailSendError { match err { Connecting(err) => Self::from(err), Cmd(err) => Self::from(err), - Io(err) => Self::from(err) + Io(err) => Self::from(err), } } } - #[derive(Debug, Fail)] pub enum OtherValidationError { - #[fail(display = "no To header was present")] - NoTo + NoTo, } impl From<OtherValidationError> for HeaderValidationError { - fn from(ove: OtherValidationError) -> Self { HeaderValidationError::Custom(ove.into()) } @@ -113,4 +106,4 @@ impl From<OtherValidationError> for MailError { fn from(ove: OtherValidationError) -> Self { MailError::from(HeaderValidationError::from(ove)) } -}
\ No newline at end of file +} diff --git a/smtp/src/lib.rs b/smtp/src/lib.rs index 911c0a9..b37b2cc 100644 --- a/smtp/src/lib.rs +++ b/smtp/src/lib.rs @@ -59,11 +59,11 @@ //! //! extern crate futures; -extern crate new_tokio_smtp; extern crate mail_core as mail; -extern crate mail_internals; #[cfg_attr(test, macro_use)] extern crate mail_headers as headers; +extern crate mail_internals; +extern crate new_tokio_smtp; #[macro_use] extern crate failure; @@ -73,15 +73,15 @@ pub mod error; mod request; mod send_mail; -pub use self::request::MailRequest; -#[cfg(feature="extended-api")] +#[cfg(feature = "extended-api")] pub use self::request::derive_envelop_data_from_mail; +pub use self::request::MailRequest; -pub use self::send_mail::{send, send_batch}; -#[cfg(feature="extended-api")] +#[cfg(feature = "extended-api")] pub use self::send_mail::encode; +pub use self::send_mail::{send, send_batch}; -pub use new_tokio_smtp::{ConnectionConfig, ConnectionBuilder}; +pub use new_tokio_smtp::{ConnectionBuilder, ConnectionConfig}; pub mod auth { //! Module containing authentification commands/methods. @@ -99,12 +99,5 @@ pub mod auth { pub mod misc { //! A small collection of usefull types re-exported from `new-tokio-smtp`. - pub use new_tokio_smtp::{ - ClientId, - Domain, - AddressLiteral, - SetupTls, - DefaultTlsSetup, - Cmd - }; -}
\ No newline at end of file + pub use new_tokio_smtp::{AddressLiteral, ClientId, Cmd, DefaultTlsSetup, Domain, SetupTls}; +} diff --git a/smtp/src/request.rs b/smtp/src/request.rs index 2737836..0a4c094 100644 --- a/smtp/src/request.rs +++ b/smtp/src/request.rs @@ -1,27 +1,23 @@ use std::mem; -use new_tokio_smtp::send_mail::{ - self as smtp, - MailAddress, - EnvelopData -}; +use new_tokio_smtp::send_mail::{self as smtp, EnvelopData, MailAddress}; -use mail_internals::{ - MailType, - encoder::{EncodingBuffer, EncodableInHeader}, - error::EncodingError -}; use headers::{ - headers::{Sender, _From, _To}, + error::BuildInValidationError, header_components::Mailbox, - error::{BuildInValidationError} + headers::{Sender, _From, _To}, }; use mail::{ + error::{MailError, OtherValidationError}, Mail, - error::{MailError, OtherValidationError} +}; +use mail_internals::{ + encoder::{EncodableInHeader, EncodingBuffer}, + error::EncodingError, + MailType, }; -use ::error::{ OtherValidationError as AnotherOtherValidationError }; +use error::OtherValidationError as AnotherOtherValidationError; /// This type contains a mail and potentially some envelop data. /// @@ -35,7 +31,7 @@ use ::error::{ OtherValidationError as AnotherOtherValidationError }; #[derive(Clone, Debug)] pub struct MailRequest { mail: Mail, - envelop_data: Option<EnvelopData> + envelop_data: Option<EnvelopData>, } impl From<Mail> for MailRequest { @@ -44,13 +40,13 @@ impl From<Mail> for MailRequest { } } - - impl MailRequest { - /// creates a new `MailRequest` from a `Mail` instance pub fn new(mail: Mail) -> Self { - MailRequest { mail, envelop_data: None } + MailRequest { + mail, + envelop_data: None, + } } /// create a new `MailRequest` and use custom smtp `EnvelopData` @@ -60,7 +56,10 @@ impl MailRequest { /// cases where you need to set it manually just import it from /// `new-tokio-smtp`. pub fn new_with_envelop(mail: Mail, envelop: EnvelopData) -> Self { - MailRequest { mail, envelop_data: Some(envelop) } + MailRequest { + mail, + envelop_data: Some(envelop), + } } /// replace the smtp `EnvelopData` @@ -69,14 +68,16 @@ impl MailRequest { } pub fn _into_mail_with_envelop(self) -> Result<(Mail, EnvelopData), MailError> { - let envelop = - if let Some(envelop) = self.envelop_data { envelop } - else { derive_envelop_data_from_mail(&self.mail)? }; + let envelop = if let Some(envelop) = self.envelop_data { + envelop + } else { + derive_envelop_data_from_mail(&self.mail)? + }; Ok((self.mail, envelop)) } - #[cfg(not(feature="extended-api"))] + #[cfg(not(feature = "extended-api"))] #[inline(always)] pub(crate) fn into_mail_with_envelop(self) -> Result<(Mail, EnvelopData), MailError> { self._into_mail_with_envelop() @@ -87,7 +88,7 @@ impl MailRequest { /// If envelop data was explicitly set it is returned. /// If no envelop data was explicitly given it is derived from the /// Mail header fields using `derive_envelop_data_from_mail`. - #[cfg(feature="extended-api")] + #[cfg(feature = "extended-api")] #[inline(always)] pub fn into_mail_with_envelop(self) -> Result<(Mail, EnvelopData), MailError> { self._into_mail_with_envelop() @@ -97,9 +98,13 @@ impl MailRequest { fn mailaddress_from_mailbox(mailbox: &Mailbox) -> Result<MailAddress, EncodingError> { let email = &mailbox.email; let needs_smtputf8 = email.check_if_internationalized(); - let mt = if needs_smtputf8 { MailType::Internationalized } else { MailType::Ascii }; + let mt = if needs_smtputf8 { + MailType::Internationalized + } else { + MailType::Ascii + }; let mut buffer = EncodingBuffer::new(mt); - { + { let mut writer = buffer.writer(); email.encode(&mut writer)?; writer.commit_partial_header(); @@ -128,39 +133,36 @@ fn mailaddress_from_mailbox(mailbox: &Mailbox) -> Result<MailAddress, EncodingEr /// - No To header /// - A From header with multiple addresses but no Sender header /// -pub fn derive_envelop_data_from_mail(mail: &Mail) - -> Result<smtp::EnvelopData, MailError> -{ +pub fn derive_envelop_data_from_mail(mail: &Mail) -> Result<smtp::EnvelopData, MailError> { let headers = mail.headers(); - let smtp_from = - if let Some(sender) = headers.get_single(Sender) { - let sender = sender?; - //TODO double check with from field - mailaddress_from_mailbox(sender)? - } else { - let from = headers.get_single(_From) - .ok_or(OtherValidationError::NoFrom)??; - - if from.len() > 1 { - return Err(BuildInValidationError::MultiMailboxFromWithoutSender.into()); - } + let smtp_from = if let Some(sender) = headers.get_single(Sender) { + let sender = sender?; + //TODO double check with from field + mailaddress_from_mailbox(sender)? + } else { + let from = headers + .get_single(_From) + .ok_or(OtherValidationError::NoFrom)??; + + if from.len() > 1 { + return Err(BuildInValidationError::MultiMailboxFromWithoutSender.into()); + } - mailaddress_from_mailbox(from.first())? - }; + mailaddress_from_mailbox(from.first())? + }; - let smtp_to = - if let Some(to) = headers.get_single(_To) { - let to = to?; - to.try_mapped_ref(mailaddress_from_mailbox)? - } else { - return Err(AnotherOtherValidationError::NoTo.into()); - }; + let smtp_to = if let Some(to) = headers.get_single(_To) { + let to = to?; + to.try_mapped_ref(mailaddress_from_mailbox)? + } else { + return Err(AnotherOtherValidationError::NoTo.into()); + }; //TODO Cc, Bcc Ok(EnvelopData { from: Some(smtp_from), - to: smtp_to + to: smtp_to, }) } @@ -169,15 +171,8 @@ mod test { mod derive_envelop_data_from_mail { use super::super::derive_envelop_data_from_mail; - use mail::{ - Mail, - Resource, - test_utils::CTX - }; - use headers::{ - headers::{_From, _To, Sender}, - }; - + use headers::headers::{Sender, _From, _To}; + use mail::{test_utils::CTX, Mail, Resource}; fn mock_resource() -> Resource { Resource::plain_text("abcd↓efg", CTX.unwrap()) @@ -187,11 +182,14 @@ mod test { fn use_sender_if_given() { let mut mail = Mail::new_singlepart_mail(mock_resource()); - mail.insert_headers(headers! { - Sender: "strange@caffe.test", - _From: ["ape@caffe.test", "epa@caffe.test"], - _To: ["das@ding.test"] - }.unwrap()); + mail.insert_headers( + headers! { + Sender: "strange@caffe.test", + _From: ["ape@caffe.test", "epa@caffe.test"], + _To: ["das@ding.test"] + } + .unwrap(), + ); let envelop_data = derive_envelop_data_from_mail(&mail).unwrap(); @@ -204,10 +202,13 @@ mod test { #[test] fn use_from_if_no_sender_given() { let mut mail = Mail::new_singlepart_mail(mock_resource()); - mail.insert_headers(headers! { - _From: ["ape@caffe.test"], - _To: ["das@ding.test"] - }.unwrap()); + mail.insert_headers( + headers! { + _From: ["ape@caffe.test"], + _To: ["das@ding.test"] + } + .unwrap(), + ); let envelop_data = derive_envelop_data_from_mail(&mail).unwrap(); @@ -220,10 +221,13 @@ mod test { #[test] fn fail_if_no_sender_but_multi_mailbox_from() { let mut mail = Mail::new_singlepart_mail(mock_resource()); - mail.insert_headers(headers! { - _From: ["ape@caffe.test", "a@b.test"], - _To: ["das@ding.test"] - }.unwrap()); + mail.insert_headers( + headers! { + _From: ["ape@caffe.test", "a@b.test"], + _To: ["das@ding.test"] + } + .unwrap(), + ); let envelop_data = derive_envelop_data_from_mail(&mail); @@ -234,29 +238,29 @@ mod test { #[test] fn use_to() { let mut mail = Mail::new_singlepart_mail(mock_resource()); - mail.insert_headers(headers! { - _From: ["ape@caffe.test"], - _To: ["das@ding.test"] - }.unwrap()); + mail.insert_headers( + headers! { + _From: ["ape@caffe.test"], + _To: ["das@ding.test"] + } + .unwrap(), + ); let envelop_data = derive_envelop_data_from_mail(&mail).unwrap(); - assert_eq!( - envelop_data.to.first().as_str(), - "das@ding.test" - ); + assert_eq!(envelop_data.to.first().as_str(), "das@ding.test"); } } mod mailaddress_from_mailbox { + use super::super::mailaddress_from_mailbox; use headers::{ + header_components::{Email, Mailbox}, HeaderTryFrom, - header_components::{Mailbox, Email} }; - use super::super::mailaddress_from_mailbox; #[test] - #[cfg_attr(not(feature="test-with-traceing"), ignore)] + #[cfg_attr(not(feature = "test-with-traceing"), ignore)] fn does_not_panic_with_tracing_enabled() { let mb = Mailbox::try_from("hy@b").unwrap(); mailaddress_from_mailbox(&mb).unwrap(); @@ -294,4 +298,4 @@ mod test { assert_eq!(address.needs_smtputf8(), true); } } -}
\ No newline at end of file +} diff --git a/smtp/src/resolve_all.rs b/smtp/src/resolve_all.rs index 69d3c8b..c0a01d7 100644 --- a/smtp/src/resolve_all.rs +++ b/smtp/src/resolve_all.rs @@ -1,15 +1,16 @@ -use std::mem; use std::iter::FromIterator; +use std::mem; -use futures::{Future, Async, Poll}; +use futures::{Async, Future, Poll}; pub enum AltFuse<F: Future> { Future(F), - Resolved(Result<F::Item, F::Error>) + Resolved(Result<F::Item, F::Error>), } impl<F> Future for AltFuse<F> - where F: Future +where + F: Future, { type Item = (); //TODO[futures/v>=0.2 |rust/! type]: use Never or ! @@ -21,8 +22,8 @@ impl<F> Future for AltFuse<F> AltFuse::Future(ref mut fut) => match fut.poll() { Ok(Async::NotReady) => return Ok(Async::NotReady), Ok(Async::Ready(val)) => Ok(val), - Err(err) => Err(err) - } + Err(err) => Err(err), + }, }; *self = AltFuse::Resolved(result); @@ -30,15 +31,16 @@ impl<F> Future for AltFuse<F> } } - pub struct ResolveAll<F> - where F: Future +where + F: Future, { - all: Vec<AltFuse<F>> + all: Vec<AltFuse<F>>, } impl<F> Future for ResolveAll<F> - where F: Future +where + F: Future, { type Item = Vec<Result<F::Item, F::Error>>; //TODO[futures >= 0.2/rust ! type]: use Never or ! @@ -55,9 +57,10 @@ impl<F> Future for ResolveAll<F> Ok(Async::NotReady) } else { let results = mem::replace(&mut self.all, Vec::new()) - .into_iter().map(|alt_fuse_fut| match alt_fuse_fut { + .into_iter() + .map(|alt_fuse_fut| match alt_fuse_fut { AltFuse::Resolved(res) => res, - AltFuse::Future(_) => unreachable!() + AltFuse::Future(_) => unreachable!(), }) .collect(); Ok(Async::Ready(results)) @@ -66,16 +69,15 @@ impl<F> Future for ResolveAll<F> } impl<I> FromIterator<I> for ResolveAll<I> - where I: Future +where + I: Future, { fn from_iter<T>(all: T) -> Self - where T: IntoIterator<Item = I> + where + T: IntoIterator<Item = I>, { - let all = all - .into_iter() - .map(|fut| AltFuse::Future(fut)) - .collect(); + let all = all.into_iter().map(|fut| AltFuse::Future(fut)).collect(); ResolveAll { all } } -}
\ No newline at end of file +} diff --git a/smtp/src/send_mail.rs b/smtp/src/send_mail.rs index 2e211f5..10fe432 100644 --- a/smtp/src/send_mail.rs +++ b/smtp/src/send_mail.rs @@ -1,31 +1,20 @@ //! Module implementing mail sending using `new-tokio-smtp::send_mail`. -use std::iter::{once as one}; +use std::iter::once as one; use futures::{ + future::{self, Either, Future}, stream::{self, Stream}, - future::{self, Future, Either} }; -use mail_internals::{ - MailType, - encoder::EncodingBuffer -}; use mail::Context; +use mail_internals::{encoder::EncodingBuffer, MailType}; use new_tokio_smtp::{ - ConnectionConfig, - Cmd, - SetupTls, - send_mail::MailEnvelop, - Connection, - send_mail as smtp + send_mail as smtp, send_mail::MailEnvelop, Cmd, Connection, ConnectionConfig, SetupTls, }; -use ::{ - error::MailSendError, - request::MailRequest -}; +use {error::MailSendError, request::MailRequest}; /// Sends a given mail (request). /// @@ -38,15 +27,22 @@ use ::{ /// You can use `MailRequest: From<Mail>` (i.e. `mail.into()`) to pass in /// a mail and derive the envelop data (from, to) from it or create your own /// mail request if different smtp envelop data is needed. -pub fn send<A, S>(mail: MailRequest, conconf: ConnectionConfig<A, S>, ctx: impl Context) - -> impl Future<Item=(), Error=MailSendError> - where A: Cmd, S: SetupTls +pub fn send<A, S>( + mail: MailRequest, + conconf: ConnectionConfig<A, S>, + ctx: impl Context, +) -> impl Future<Item = (), Error = MailSendError> +where + A: Cmd, + S: SetupTls, { let fut = encode(mail, ctx) - .then(move |envelop_res| Connection - ::connect_send_quit(conconf, one(envelop_res)) - .collect()) - .map(|mut results| results.pop().expect("[BUG] sending one mail expects one result")); + .then(move |envelop_res| Connection::connect_send_quit(conconf, one(envelop_res)).collect()) + .map(|mut results| { + results + .pop() + .expect("[BUG] sending one mail expects one result") + }); fut } @@ -74,9 +70,12 @@ pub fn send<A, S>(mail: MailRequest, conconf: ConnectionConfig<A, S>, ctx: impl pub fn send_batch<A, S, C>( mails: Vec<MailRequest>, conconf: ConnectionConfig<A, S>, - ctx: C -) -> impl Stream<Item=(), Error=MailSendError> - where A: Cmd, S: SetupTls, C: Context + ctx: C, +) -> impl Stream<Item = (), Error = MailSendError> +where + A: Cmd, + S: SetupTls, + C: Context, { let iter = mails.into_iter().map(move |mail| encode(mail, ctx.clone())); @@ -88,8 +87,9 @@ pub fn send_batch<A, S, C>( } //FIXME[futures/v>=0.2] use Error=Never -fn collect_res<S, E>(stream: S) -> impl Future<Item=Vec<Result<S::Item, S::Error>>, Error=E> - where S: Stream +fn collect_res<S, E>(stream: S) -> impl Future<Item = Vec<Result<S::Item, S::Error>>, Error = E> +where + S: Stream, { stream.then(|res| Ok(res)).collect() } @@ -105,35 +105,41 @@ fn collect_res<S, E>(stream: S) -> impl Future<Item=Vec<Result<S::Item, S::Error /// then take a connection, test it, use the mail envelops with `new-tokio-smtp`'s /// `SendAllMails` stream with a `on_completion` handler which places it /// back in the pool. -pub fn encode<C>(request: MailRequest, ctx: C) - -> impl Future<Item=MailEnvelop, Error=MailSendError> - where C: Context +pub fn encode<C>( + request: MailRequest, + ctx: C, +) -> impl Future<Item = MailEnvelop, Error = MailSendError> +where + C: Context, { - let (mail, envelop_data) = - match request.into_mail_with_envelop() { - Ok(pair) => pair, - Err(e) => return Either::A(future::err(e.into())) - }; + let (mail, envelop_data) = match request.into_mail_with_envelop() { + Ok(pair) => pair, + Err(e) => return Either::A(future::err(e.into())), + }; let fut = mail .into_encodable_mail(ctx.clone()) - .and_then(move |enc_mail| ctx.offload_fn(move || { - let (mail_type, requirement) = - if envelop_data.needs_smtputf8() { - (MailType::Internationalized, smtp::EncodingRequirement::Smtputf8) + .and_then(move |enc_mail| { + ctx.offload_fn(move || { + let (mail_type, requirement) = if envelop_data.needs_smtputf8() { + ( + MailType::Internationalized, + smtp::EncodingRequirement::Smtputf8, + ) } else { (MailType::Ascii, smtp::EncodingRequirement::None) }; - let mut buffer = EncodingBuffer::new(mail_type); - enc_mail.encode(&mut buffer)?; + let mut buffer = EncodingBuffer::new(mail_type); + enc_mail.encode(&mut buffer)?; - let vec_buffer: Vec<_> = buffer.into(); - let smtp_mail = smtp::Mail::new(requirement, vec_buffer); + let vec_buffer: Vec<_> = buffer.into(); + let smtp_mail = smtp::Mail::new(requirement, vec_buffer); - Ok(smtp::MailEnvelop::from((smtp_mail, envelop_data))) - })) + Ok(smtp::MailEnvelop::from((smtp_mail, envelop_data))) + }) + }) .map_err(MailSendError::from); Either::B(fut) -}
\ No newline at end of file +} |