diff options
author | Philipp Korber <philippkorber@gmail.com> | 2018-04-25 18:08:24 +0200 |
---|---|---|
committer | Philipp Korber <philippkorber@gmail.com> | 2018-04-25 18:08:24 +0200 |
commit | 457ad72c4a68a15681e25ca3f12508dba2f6c75d (patch) | |
tree | 9d9586cd950abc13c4a5b3b00011e97f8f50fa3c | |
parent | f8619f7246fda41a25c8a9499c5d7cda77324894 (diff) |
chore(deps + error): apply changes from deps and moved to failure
-rw-r--r-- | Cargo.toml | 39 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | __examples/composition.rs (renamed from examples/composition.rs) | 4 | ||||
-rw-r--r-- | src/builder_extension.rs | 93 | ||||
-rw-r--r-- | src/compositor/_impl.rs | 60 | ||||
-rw-r--r-- | src/compositor/mail_send_data.rs | 80 | ||||
-rw-r--r-- | src/compositor/mod.rs | 13 | ||||
-rw-r--r-- | src/context.rs | 11 | ||||
-rw-r--r-- | src/default_impl/component_id.rs | 14 | ||||
-rw-r--r-- | src/default_impl/name_composer.rs | 12 | ||||
-rw-r--r-- | src/default_impl/simple_context.rs | 10 | ||||
-rw-r--r-- | src/error.rs | 253 | ||||
-rw-r--r-- | src/lib.rs | 140 | ||||
-rw-r--r-- | src/macros.rs | 42 | ||||
-rw-r--r-- | src/render_template_engine/error.rs | 372 | ||||
-rw-r--r-- | src/render_template_engine/from_dir.rs | 43 | ||||
-rw-r--r-- | src/render_template_engine/mod.rs | 62 | ||||
-rw-r--r-- | src/render_template_engine/settings.rs | 42 | ||||
-rw-r--r-- | src/render_template_engine/utils.rs | 52 | ||||
-rw-r--r-- | src/resource.rs | 128 | ||||
-rw-r--r-- | src/template.rs | 15 | ||||
-rw-r--r-- | src/tera/error.rs | 44 | ||||
-rw-r--r-- | src/tera/mod.rs | 30 | ||||
-rw-r--r-- | tests/rte/main.rs | 4 | ||||
-rw-r--r-- | tests/tera/main.rs | 29 |
25 files changed, 968 insertions, 628 deletions
@@ -1,31 +1,32 @@ [package] +name = "mail-template" +version = "0.2.0" +description = "[internal/mail-api] provides a \"composition through template\" api for the Mail type from the mail-api crates" authors = ["Philipp Korber <p.korber@1aim.com>"] +keywords = ["mail-api", "internal"] categories = [] -description = "TODO" -documentation = "https://docs.rs/mail-codec-composition" -keywords = ["mail", "codec", "mime", "smtp"] license = "MIT OR Apache-2.0" -name = "mail-codec-composition" readme = "./README.md" -repository = "https://github.com/1aim/mail-codec-composition" -version = "0.1.0" +documentation = "https://docs.rs/mail-template" +repository = "https://github.com/1aim/mail-template" [dependencies] +mail-type = { git="https://github.com/1aim/mail-codec" } +mail-common = { git="https://github.com/1aim/mail-common" } +mail-headers = { git="https://github.com/1aim/mail-headers" } + +failure = "0.1.1" futures = "0.1.14" log = "0.3.8" rand = "0.3.15" scoped-tls = "0.1.0" serde = "1.0.10" serde_derive = "1.0.10" -vec1 = { git="https://github.com/1aim/vec1" } -total-order-multi-map = { git="https://github.com/1aim/total-order-multi-map" } -mail-codec = { git="https://github.com/1aim/mail-codec" } -mail-codec-core = { git="https://github.com/1aim/mail-codec-core" } -mail-codec-headers = { git="https://github.com/1aim/mail-codec-headers" } -error-chain = "0.11.0" chrono = "0.4.0" +vec1 = { git="https://github.com/1aim/vec1" } soft-ascii-string = "0.2.0" + futures-cpupool = { version = "0.1.5", optional = true } tera = { version = "0.11.1", optional = true } conduit-mime-types = { version = "0.7.3", optional = true} @@ -45,15 +46,19 @@ regex = "0.2.6" debug_trace_tokens = [] render-template-engine = ["conduit-mime-types", "lazy_static"] tera-bindings = ["tera", "render-template-engine"] -default = ["default_impl"] -default_impl = [ - "default_impl_name_composer", "default_impl_component_id", "default_impl_simple_context" + +default = [ + "default_impl_name_composer", + "default_impl_component_id", + "default_impl_simple_context" ] default_impl_name_composer = [] default_impl_component_id = [] default_impl_simple_context = [ - "default_impl_component_id", "mail-codec/default_impl_fs", "mail-codec/default_impl_cpupool", + "default_impl_component_id", + "mail-type/default_impl_fs", + "mail-type/default_impl_cpupool", "futures-cpupool" ] -traceing = [ "mail-codec/traceing" ] +traceing = [ "mail-type/traceing" ]
\ No newline at end of file @@ -1,5 +1,5 @@ -# mail-codec-composition   [![Build Status](https://travis-ci.org/1aim/mail_codec.svg?branch=master)](https://travis-ci.org/1aim/mail_codec) +# mail-template   [![Build Status](https://travis-ci.org/1aim/mail_type.svg?branch=master)](https://travis-ci.org/1aim/mail_type) **TODO** @@ -8,7 +8,7 @@ TODO -Documentation can be [viewed on docs.rs](https://docs.rs/mail-codec-composition). +Documentation can be [viewed on docs.rs](https://docs.rs/mail-template). ## License diff --git a/examples/composition.rs b/__examples/composition.rs index 1286068..38a7da3 100644 --- a/examples/composition.rs +++ b/__examples/composition.rs @@ -1,8 +1,8 @@ // // !! YOU MIGHT WANT TO TAKE A LOOK AT tests/tera/main.rs WHICH IS A BETTER EXAMPLE !! // -extern crate mail_codec as mail; -extern crate mail_codec_composition as compose; +extern crate mail_type as mail; +extern crate mail_template as compose; extern crate futures; extern crate mime; extern crate serde; diff --git a/src/builder_extension.rs b/src/builder_extension.rs index edf9956..29e5343 100644 --- a/src/builder_extension.rs +++ b/src/builder_extension.rs @@ -1,16 +1,15 @@ use media_type::{MULTIPART, ALTERNATIVE, RELATED, MIXED}; use vec1::Vec1; -use core::error::{Result, ErrorKind}; -use core::header::HeaderMap; -use headers::{ContentId, ContentDisposition}; -use headers::components::Disposition; -use mail::MediaType; +use headers::{HeaderMap, ContentId, ContentDisposition}; +use headers::components::{Disposition, MediaType}; use mail::{Resource, Mail, Builder}; +use mail::error::OtherBuilderErrorKind; -use template::BodyPart; -use resource::{EmbeddingWithCId, Attachment}; +use ::template::BodyPart; +use ::resource::{EmbeddingWithCId, Attachment}; +use ::error::{ExtendedBuilderError, ExtendedBuilderErrorKind}; /// Ext. Trait which adds helper methods to the Builder type. @@ -20,34 +19,34 @@ pub trait BuilderExt { fn create_alternate_bodies<HM>( bodies: Vec1<BodyPart>, header: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>; fn create_mail_body<HM>( body: BodyPart, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>; fn create_with_attachments<HM>( body: Mail, attachments: Vec<Attachment>, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>; fn create_body_from_resource<HM>( resource: Resource, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>; fn create_body_with_embeddings<HM, EMB>( sub_body: Mail, embeddings: EMB, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>, EMB: Iterator<Item=EmbeddingWithCId> + ExactSizeIterator; @@ -55,7 +54,7 @@ pub trait BuilderExt { bodies: Vec1<BodyPart>, embeddings: EMB, header: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>, EMB: Iterator<Item=EmbeddingWithCId> + ExactSizeIterator; } @@ -67,45 +66,45 @@ impl BuilderExt for Builder { fn create_alternate_bodies<HM>( bodies: Vec1<BodyPart>, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>> { let bodies = bodies; match bodies.len() { - 0 => bail!( ErrorKind::NeedAtLastOneBodyInMultipartMail ), - 1 => return Self::create_mail_body(bodies.into_vec().pop().unwrap(), headers ), + 0 => return Err(OtherBuilderErrorKind::EmptyMultipartBody.into()), + 1 => return Self::create_mail_body(bodies.into_vec().pop().unwrap(), headers), _n => {} } let mut builder = Builder::multipart(MediaType::new(MULTIPART, ALTERNATIVE)?)?; if let Some(headers) = headers.into() { - builder = builder.headers( headers )?; + builder = builder.headers(headers)?; } for body in bodies { - builder = builder.body( Self::create_mail_body( body, None )? )?; + builder = builder.body(Self::create_mail_body(body, None)?)?; } - builder.build() + Ok(builder.build()?) } fn create_alternate_bodies_with_embeddings<HM, EMB>( bodies: Vec1<BodyPart>, embeddings: EMB, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>, EMB: Iterator<Item=EmbeddingWithCId> + ExactSizeIterator { match embeddings.len() { 0 => { - Self::create_alternate_bodies( bodies, headers ) + Self::create_alternate_bodies(bodies, headers) }, _n => { Self::create_body_with_embeddings( - Self::create_alternate_bodies( bodies, None )?, + Self::create_alternate_bodies(bodies, None)?, embeddings, headers ) @@ -116,65 +115,65 @@ impl BuilderExt for Builder { fn create_mail_body<HM>( body: BodyPart, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>> { let BodyPart { body_resource, embeddings } = body; if embeddings.len() > 0 { Self::create_body_with_embeddings( - Self::create_body_from_resource( body_resource, None )?, + Self::create_body_from_resource(body_resource, None)?, embeddings.into_iter(), headers ) } else { - Self::create_body_from_resource( body_resource, headers ) + Self::create_body_from_resource(body_resource, headers) } } fn create_body_from_resource<HM>( resource: Resource, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>> { - let mut builder = Builder::singlepart( resource ); - if let Some( headers ) = headers.into() { - builder = builder.headers( headers )?; + let mut builder = Builder::singlepart(resource); + if let Some(headers) = headers.into() { + builder = builder.headers(headers)?; } - builder.build() + Ok(builder.build()?) } fn create_body_with_embeddings<HM, EMB>( sub_body: Mail, embeddings: EMB, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>>, EMB: Iterator<Item=EmbeddingWithCId> + ExactSizeIterator { if embeddings.len() == 0 { - bail!( "this function except at last one embedding" ) + return Err(ExtendedBuilderErrorKind::EmbeddingMissing.into()); } - let mut builder = Builder::multipart( MediaType::new(MULTIPART,RELATED)?)?; + let mut builder = Builder::multipart(MediaType::new(MULTIPART,RELATED)?)?; - if let Some( headers ) = headers.into() { - builder = builder.headers( headers )?; + if let Some(headers) = headers.into() { + builder = builder.headers(headers)?; } - builder = builder.body( sub_body )?; + builder = builder.body(sub_body)?; for embedding in embeddings { - let ( content_id, resource ) = embedding.into(); + let (content_id, resource) = embedding.into(); builder = builder.body( - Self::create_body_from_resource( resource , headers! { + Self::create_body_from_resource(resource , headers! { ContentId: content_id, ContentDisposition: Disposition::inline() - }? )? + }?)? )?; } - builder.build() + Ok(builder.build()?) } @@ -182,28 +181,28 @@ impl BuilderExt for Builder { body: Mail, attachments: Vec<Attachment>, headers: HM - ) -> Result<Mail> + ) -> Result<Mail, ExtendedBuilderError> where HM: Into<Option<HeaderMap>> { let mut builder = Builder::multipart(MediaType::new(MULTIPART, MIXED)?)?; - if let Some( headers ) = headers.into() { - builder = builder.headers( headers )?; + if let Some(headers) = headers.into() { + builder = builder.headers(headers)?; } - builder = builder.body( body )?; + builder = builder.body(body)?; for attachment in attachments { - builder = builder.body( Self::create_body_from_resource( + builder = builder.body(Self::create_body_from_resource( attachment.into(), headers! { ContentDisposition: Disposition::attachment() }? - )? )?; + )?)?; } - builder.build() + Ok(builder.build()?) } } diff --git a/src/compositor/_impl.rs b/src/compositor/_impl.rs index 8bb83bf..9fa803c 100644 --- a/src/compositor/_impl.rs +++ b/src/compositor/_impl.rs @@ -3,22 +3,23 @@ use std::borrow::Cow; use serde::Serialize; use vec1::Vec1; -use core::utils::HeaderTryFrom; -use core::error::{Result, ResultExt}; -use core::header::HeaderMap; -use headers::{From, To, Subject, Sender}; +use headers::{ + HeaderMap, HeaderTryFrom, + _From, _To, Subject, Sender +}; use headers::components::Unstructured; use mail::{Mail, Builder}; -use utils::SerializeOnly; -use resource::{ +use ::utils::SerializeOnly; +use ::resource::{ EmbeddingWithCId, Attachment, with_resource_sidechanel }; -use builder_extension::BuilderExt; -use template::{ +use ::builder_extension::BuilderExt; +use ::template::{ BodyPart, TemplateEngine, MailParts }; +use ::error::CompositionError; use super::mail_send_data::MailSendData; use super::{CompositionBase, EnvelopData}; @@ -27,9 +28,12 @@ pub(crate) trait InnerCompositionBaseExt: CompositionBase { fn _compose_mail<D>( &self, - send_data: - MailSendData<<Self::TemplateEngine as TemplateEngine<Self::Context>>::TemplateId, D> - ) -> Result<(Mail, EnvelopData)> + send_data: MailSendData< + <Self::TemplateEngine as TemplateEngine<Self::Context>>::TemplateId, D> + ) -> Result< + (Mail, EnvelopData), + CompositionError<<Self::TemplateEngine as TemplateEngine<Self::Context>>::Error> + > where D: Serialize { let envelop = EnvelopData::from(&send_data); @@ -39,8 +43,8 @@ pub(crate) trait InnerCompositionBaseExt: CompositionBase { let MailParts { alternative_bodies, shared_embeddings, attachments } = self.use_template_engine(&*template_id, data)?; - let mail = self.build_mail( alternative_bodies, shared_embeddings.into_iter(), - attachments, core_headers )?; + let mail = self.build_mail(alternative_bodies, shared_embeddings.into_iter(), + attachments, core_headers)?; Ok((mail, envelop)) } @@ -53,7 +57,7 @@ pub(crate) trait InnerCompositionBaseExt: CompositionBase { HeaderMap, D, Cow<'a, <Self::TemplateEngine as TemplateEngine<Self::Context>>::TemplateId> - )> + ), CompositionError<<Self::TemplateEngine as TemplateEngine<Self::Context>>::Error>> where D: Serialize { let (sender, from_mailboxes, to_mailboxes, subject, template_id, data) @@ -62,12 +66,12 @@ pub(crate) trait InnerCompositionBaseExt: CompositionBase { // The subject header field let subject = Unstructured::try_from( subject )?; - // createing the header map + // creating the header map let mut core_headers: HeaderMap = headers! { - //NOTE: if we support multiple mailboxes in From we have to + //NOTE: if we support multiple mailboxes in _From we have to // ensure Sender is used _iff_ there is more than one from - From: from_mailboxes, - To: to_mailboxes, + _From: from_mailboxes, + _To: to_mailboxes, Subject: subject }?; @@ -84,22 +88,22 @@ pub(crate) trait InnerCompositionBaseExt: CompositionBase { template_id: &<Self::TemplateEngine as TemplateEngine<Self::Context>>::TemplateId, //TODO change to &D? data: D - ) -> Result<MailParts> + ) -> Result<MailParts, CompositionError<<Self::TemplateEngine as TemplateEngine<Self::Context>>::Error>> where D: Serialize { let id_gen = Box::new(self.context().clone()); let ( mut mail_parts, embeddings, attachments ) = - with_resource_sidechanel(id_gen, || -> Result<_> { + with_resource_sidechanel(id_gen, || -> Result<_, CompositionError<<Self::TemplateEngine as TemplateEngine<Self::Context>>::Error>> { // we just want to make sure that the template engine does // really serialize the data, so we make it so that it can // only do so (if we pass in the data directly it could use - // TypeID+Transmut or TraitObject+downcast to undo the generic + // TypeID+Transmute or TraitObject+downcast to undo the generic // type erasure and then create the template in some other way // but this would break the whole Embedding/Attachment extraction ) let sdata = SerializeOnly::new(data); self.template_engine() .use_templates(self.context(), template_id, &sdata) - .chain_err(|| "failure in template engine") + .map_err(|err| CompositionError::Template(err)) })?; mail_parts.attachments.extend(attachments); @@ -110,25 +114,25 @@ pub(crate) trait InnerCompositionBaseExt: CompositionBase { /// uses the results of preprocessing data and templates, as well as a list of - /// mail headers like `From`,`To`, etc. to create a new mail + /// mail headers like `_From`,`To`, etc. to create a new mail fn build_mail<EMB>(&self, bodies: Vec1<BodyPart>, embeddings: EMB, attachments: Vec<Attachment>, core_headers: HeaderMap - ) -> Result<Mail> + ) -> Result<Mail, CompositionError<<Self::TemplateEngine as TemplateEngine<Self::Context>>::Error>> where EMB: Iterator<Item=EmbeddingWithCId> + ExactSizeIterator { let mail = match attachments.len() { 0 => Builder::create_alternate_bodies_with_embeddings( - bodies, embeddings, Some(core_headers) )?, + bodies, embeddings, Some(core_headers))?, _n => Builder::create_with_attachments( - Builder::create_alternate_bodies_with_embeddings(bodies, embeddings, None )?, + Builder::create_alternate_bodies_with_embeddings(bodies, embeddings, None)?, attachments, - Some( core_headers ) + Some(core_headers) )? }; - Ok( mail ) + Ok(mail) } } diff --git a/src/compositor/mail_send_data.rs b/src/compositor/mail_send_data.rs index 9ff9d04..8a9087e 100644 --- a/src/compositor/mail_send_data.rs +++ b/src/compositor/mail_send_data.rs @@ -6,13 +6,15 @@ use std::fmt::{self, Debug}; use serde::Serialize; use vec1::Vec1; -use error::Error; -use core::HeaderTryFrom; -use mail::headers::components::{ +use headers::HeaderTryFrom; +use headers::error::ComponentCreationError; +use headers::components::{ Mailbox, MailboxList, Phrase, Email }; +use ::error::{MailSendDataError, MailSendDataErrorKind, WithSource, WithSourceExt}; + /// A type containing all per-Mail specific information /// /// The contained information is: @@ -37,13 +39,14 @@ use mail::headers::components::{ /// # Example (Construction) /// /// ``` -/// # extern crate mail_codec as mail; -/// # extern crate mail_codec_composition as compose; -/// # extern crate mail_codec_core as core; +/// # extern crate mail_common as common; +/// # extern crate mail_headers as headers; +/// # extern crate mail_type as mail; +/// # extern crate mail_template as compose; /// # use std::collections::HashMap; +/// # use headers::HeaderTryFrom; +/// # use headers::components::{Mailbox, Email}; /// # use compose::MailSendDataBuilder; -/// # use mail::headers::components::{Mailbox, Email}; -/// # use core::HeaderTryFrom; /// # /// # fn main() { /// # @@ -175,7 +178,7 @@ impl<'a, TId: ?Sized + 'a, D> MailSendData<'a, TId, D> (sender, from, to, subject, template_id, data) } - pub fn auto_gen_display_names<NC>(&mut self, name_composer: NC) -> Result<(), Error> + pub fn auto_gen_display_names<NC>(&mut self, name_composer: NC) -> Result<(), ComponentCreationError> where NC: NameComposer<D> { let data = &mut self.data; @@ -226,7 +229,7 @@ pub trait NameComposer<D> { /// _not_ be returned if there is "just" not enough data to create a display /// name, in which `Ok(None)` should be returned indicating that there is /// no display name. - fn compose_from_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, Error>; + fn compose_from_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, ComponentCreationError>; /// generates a display name used in a To header based on email address and mails data /// The data is passed in as a `&mut` ref so that the generated name can @@ -243,17 +246,17 @@ pub trait NameComposer<D> { /// _not_ be returned if there is "just" not enough data to create a display /// name, in which `Ok(None)` should be returned indicating that there is /// no display name. - fn compose_to_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, Error>; + fn compose_to_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, ComponentCreationError>; } impl<D, T> NameComposer<D> for Arc<T> where T: NameComposer<D>, D: Serialize { - fn compose_from_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, Error> { + fn compose_from_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, ComponentCreationError> { self.deref().compose_from_name(email, data) } - fn compose_to_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, Error> { + fn compose_to_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, ComponentCreationError> { self.deref().compose_to_name(email, data) } } @@ -261,10 +264,10 @@ impl<D, T> NameComposer<D> for Arc<T> impl<D, T> NameComposer<D> for Box<T> where T: NameComposer<D>, D: Serialize { - fn compose_from_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, Error> { + fn compose_from_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, ComponentCreationError> { self.deref().compose_from_name(email, data) } - fn compose_to_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, Error> { + fn compose_to_name( &self, email: &Email, data: &mut D ) -> Result<Option<String>, ComponentCreationError> { self.deref().compose_to_name(email, data) } } @@ -272,7 +275,7 @@ impl<D, T> NameComposer<D> for Box<T> /// Builder to create `MailSendData` pub struct MailSendDataBuilder<'a, TId: ?Sized + 'a, D> - where TId: ToOwned, D: Serialize + where TId: ToOwned + Debug, TId::Owned: Debug, D: Serialize + Debug { sender: Option<Mailbox>, from: Vec<Mailbox>, @@ -283,7 +286,7 @@ pub struct MailSendDataBuilder<'a, TId: ?Sized + 'a, D> } impl<'a, TId: ?Sized + 'a, D> Debug for MailSendDataBuilder<'a, TId, D> - where TId: ToOwned + Debug, <TId as ToOwned>::Owned: Debug, D: Serialize + Debug + where TId: ToOwned + Debug, TId::Owned: Debug, D: Serialize + Debug { fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result { fter.debug_struct("MailSendData") @@ -300,7 +303,7 @@ impl<'a, TId: ?Sized + 'a, D> Debug for MailSendDataBuilder<'a, TId, D> // Sadly I can not used derive(Default) (it want's a bound on TId) // if the deriviate create is stable, I could use them for that impl<'a, TId: ?Sized + 'a, D> Default for MailSendDataBuilder<'a, TId, D> - where TId: ToOwned, D: Serialize + where TId: ToOwned + Debug, TId::Owned: Debug, D: Serialize + Debug { fn default() -> Self { Self::new() @@ -308,7 +311,7 @@ impl<'a, TId: ?Sized + 'a, D> Default for MailSendDataBuilder<'a, TId, D> } impl<'a, TId: ?Sized + 'a, D> MailSendDataBuilder<'a, TId, D> - where TId: ToOwned, D: Serialize + where TId: ToOwned + Debug, TId::Owned: Debug, D: Serialize + Debug { pub fn new() -> Self { MailSendDataBuilder { @@ -398,15 +401,18 @@ impl<'a, TId: ?Sized + 'a, D> MailSendDataBuilder<'a, TId, D> /// /// - no data, template_id, from or to was set /// - more than one from was set, but no sender was set - pub fn build(self) -> Result<MailSendData<'a, TId, D>, Self> { - if self.from.is_empty() || self.to.is_empty() - || self.subject.is_none() || self.template_id.is_none() - || self.data.is_none() - { - return Err(self) + pub fn build(self) + -> Result<MailSendData<'a, TId, D>, WithSource<MailSendDataError, Self>> + { + match self.check_fields_are_set() { + Ok(_) => {}, + Err(err) => return Err(err.with_source(self)) } + if self.from.len() > 1 && self.sender.is_none() { - return Err(self) + return Err(MailSendDataError + ::from(MailSendDataErrorKind::MultiFromButNoSender) + .with_source(self)); } @@ -426,4 +432,24 @@ impl<'a, TId: ?Sized + 'a, D> MailSendDataBuilder<'a, TId, D> data }) } -}
\ No newline at end of file + + fn check_fields_are_set(&self) -> Result<(), MailSendDataError> { + use self::MailSendDataErrorKind::*; + let kind = + if self.from.is_empty() { + MissingFrom + } else if self.to.is_empty() { + MissingTo + } else if self.subject.is_none() { + MissingSubject + } else if self.template_id.is_none() { + MissingTemplateId + } else if self.data.is_none() { + MissingTemplateData + } else { + return Ok(()); + }; + + Err(MailSendDataError::from(kind)) + } +} diff --git a/src/compositor/mod.rs b/src/compositor/mod.rs index 8123f4a..c26101a 100644 --- a/src/compositor/mod.rs +++ b/src/compositor/mod.rs @@ -2,12 +2,12 @@ use std::borrow::ToOwned; use serde::Serialize; -use error::Result; -use context::Context; -use template::TemplateEngine; use mail::Mail; -use mail::headers::components::{MailboxList, Mailbox}; +use headers::components::{MailboxList, Mailbox}; +use ::context::Context; +use ::template::TemplateEngine; +use ::error::CompositionError; //TODO make sure Box/Arc auto wrapping is impl for all parts use self::_impl::InnerCompositionBaseExt; @@ -36,7 +36,10 @@ pub trait CompositionBase { &self, send_data: MailSendData< <Self::TemplateEngine as TemplateEngine<Self::Context>>::TemplateId, D> - ) -> Result<(Mail, EnvelopData)> + ) -> Result< + (Mail, EnvelopData), + CompositionError<<Self::TemplateEngine as TemplateEngine<Self::Context>>::Error> + > where D: Serialize { InnerCompositionBaseExt::_compose_mail(self, send_data) diff --git a/src/context.rs b/src/context.rs index 62daf5d..a637a3a 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,20 +1,19 @@ use futures::{Future, IntoFuture}; use mail::utils::SendBoxFuture; -use core::error::Result; use mail::context::{BuilderContext, Source, LoadResourceFuture}; -use headers::components::MessageID; +use headers::components::ContentID; // TODO extend interface to allow some per mail specifics e.g. gen content id // like `format!(_prefix_{}_{}, mail_cid_count, random)` //NOTE: Sized is just as long as Serialize is used for data pub trait Context: BuilderContext + Send + Sync { - fn new_content_id( &self ) -> Result<MessageID>; + fn new_content_id(&self) -> ContentID; } pub trait ContentIdGenComponent { - fn new_content_id( &self ) -> Result<MessageID>; + fn new_content_id(&self) -> ContentID; } #[derive(Debug, Clone)] @@ -68,7 +67,7 @@ impl<I, B> Context for CompositeContext<I, B> where I: ContentIdGenComponent + Send + Sync + Clone + 'static, B: BuilderContext { - fn new_content_id( &self ) -> Result<MessageID> { + fn new_content_id( &self ) -> ContentID { self.id_gen.new_content_id() } } @@ -76,7 +75,7 @ |