summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Korber <philippkorber@gmail.com>2018-04-25 18:08:24 +0200
committerPhilipp Korber <philippkorber@gmail.com>2018-04-25 18:08:24 +0200
commit457ad72c4a68a15681e25ca3f12508dba2f6c75d (patch)
tree9d9586cd950abc13c4a5b3b00011e97f8f50fa3c
parentf8619f7246fda41a25c8a9499c5d7cda77324894 (diff)
chore(deps + error): apply changes from deps and moved to failure
-rw-r--r--Cargo.toml39
-rw-r--r--README.md4
-rw-r--r--__examples/composition.rs (renamed from examples/composition.rs)4
-rw-r--r--src/builder_extension.rs93
-rw-r--r--src/compositor/_impl.rs60
-rw-r--r--src/compositor/mail_send_data.rs80
-rw-r--r--src/compositor/mod.rs13
-rw-r--r--src/context.rs11
-rw-r--r--src/default_impl/component_id.rs14
-rw-r--r--src/default_impl/name_composer.rs12
-rw-r--r--src/default_impl/simple_context.rs10
-rw-r--r--src/error.rs253
-rw-r--r--src/lib.rs140
-rw-r--r--src/macros.rs42
-rw-r--r--src/render_template_engine/error.rs372
-rw-r--r--src/render_template_engine/from_dir.rs43
-rw-r--r--src/render_template_engine/mod.rs62
-rw-r--r--src/render_template_engine/settings.rs42
-rw-r--r--src/render_template_engine/utils.rs52
-rw-r--r--src/resource.rs128
-rw-r--r--src/template.rs15
-rw-r--r--src/tera/error.rs44
-rw-r--r--src/tera/mod.rs30
-rw-r--r--tests/rte/main.rs4
-rw-r--r--tests/tera/main.rs29
25 files changed, 968 insertions, 628 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 6e224b7..5c822e7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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
diff --git a/README.md b/README.md
index 6467894..c866805 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-# mail-codec-composition &emsp; [![Build Status](https://travis-ci.org/1aim/mail_codec.svg?branch=master)](https://travis-ci.org/1aim/mail_codec)
+# mail-template &emsp; [![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 @