summaryrefslogtreecommitdiffstats
path: root/smtp
diff options
context:
space:
mode:
Diffstat (limited to 'smtp')
-rw-r--r--smtp/src/error.rs21
-rw-r--r--smtp/src/lib.rs25
-rw-r--r--smtp/src/request.rs176
-rw-r--r--smtp/src/resolve_all.rs40
-rw-r--r--smtp/src/send_mail.rs100
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
+}