From 55482f880cfa67e68e52e5937f36251e886c137c Mon Sep 17 00:00:00 2001 From: Philipp Korber Date: Thu, 22 Nov 2018 20:22:23 +0100 Subject: fix(examples) made template example usable again --- mail/Cargo.toml | 3 - .../templates/template_a/template.toml | 2 +- mail/examples/mail_from_template/error.rs | 56 --------- mail/examples/mail_from_template/main.rs | 129 ++++++++------------- mail/src/lib.rs | 13 ++- 5 files changed, 59 insertions(+), 144 deletions(-) delete mode 100644 mail/examples/mail_from_template/error.rs (limited to 'mail') diff --git a/mail/Cargo.toml b/mail/Cargo.toml index 2d55b36..0a5f504 100644 --- a/mail/Cargo.toml +++ b/mail/Cargo.toml @@ -20,18 +20,15 @@ test-utils = ["mail-core/test-utils"] [[example]] name = "mail_by_hand" -crate-type = ["bin"] path = "examples/mail_by_hand.rs" [[example]] name = "mail_from_template" -crate-type = ["bin"] path = "examples/mail_from_template/main.rs" required-features = ["handlebars"] [[example]] name = "send_mail" -create-type = ["bind"] path = "examples/send_mail/main.rs" required-features = ["smtp"] diff --git a/mail/example_resources/templates/template_a/template.toml b/mail/example_resources/templates/template_a/template.toml index 4da0f10..25ff85a 100644 --- a/mail/example_resources/templates/template_a/template.toml +++ b/mail/example_resources/templates/template_a/template.toml @@ -11,6 +11,6 @@ path = "mail.html" logo = "logo.png" [[attachments]] -iri = "path:./portfolio.pdf" +iri = "path:portfolio.pdf" media_type = "application/pdf" diff --git a/mail/examples/mail_from_template/error.rs b/mail/examples/mail_from_template/error.rs deleted file mode 100644 index 21bccfe..0000000 --- a/mail/examples/mail_from_template/error.rs +++ /dev/null @@ -1,56 +0,0 @@ - -use mail::error::{CompositionError, ComponentCreationError}; -use mail::render_template_engine::error::{CreatingSpecError, InsertionError as _InsertionError}; -use mail::tera::error::TeraError; - -type InsertionError = _InsertionError; - -#[derive(Fail, Debug)] -pub enum SetupError { - #[fail(display = "{}", _0)] - Tera(TeraError), - - #[fail(display = "{}", _0)] - CreatingSpecs(CreatingSpecError), - - #[fail(display = "{}", _0)] - UsingSpecs(InsertionError) -} - -impl From for SetupError { - fn from(err: TeraError) -> Self { - SetupError::Tera(err) - } -} -impl From for SetupError { - fn from(err: InsertionError) -> Self { - SetupError::UsingSpecs(err) - } -} - -impl From for SetupError { - fn from(err: CreatingSpecError) -> Self { - SetupError::CreatingSpecs(err) - } -} - -// TODO `Header` should be mergeable into `Composition`. -#[derive(Fail, Debug)] -pub enum Error { - #[fail(display = "{}", _0)] - Composition(CompositionError), - #[fail(display = "{}", _0)] - Header(ComponentCreationError) -} - -impl From> for Error { - fn from(err: CompositionError) -> Self { - Error::Composition(err) - } -} - -impl From for Error { - fn from(err: ComponentCreationError) -> Self { - Error::Header(err) - } -} diff --git a/mail/examples/mail_from_template/main.rs b/mail/examples/mail_from_template/main.rs index 6a43125..deeda80 100644 --- a/mail/examples/mail_from_template/main.rs +++ b/mail/examples/mail_from_template/main.rs @@ -1,99 +1,70 @@ -//! In this example a mail is created using the tempalte engine with tera bindings +//! In this example a mail is created using the template engine with handlebars bindings //! (and then printed) //! -#[cfg(not(all(feature = "render-template-engine", feature = "tera-engine")))] -compile_error!("example `mail_from_template` requires feature `render-template-engine` and `tera-engine`"); -#[macro_use] extern crate mail; -#[macro_use] -extern crate failure; -#[macro_use] -extern crate serde_derive; extern crate futures; extern crate soft_ascii_string; +extern crate serde; +extern crate failure; + +use std::{ + path::Path +}; +use failure::Error; use futures::Future; use soft_ascii_string::SoftAsciiString; -use std::str; -use std::borrow::Cow; - -use mail::error::MailError; -use mail::{Mail, Mailbox, MailType, HeaderTryFrom, Context, Domain}; -use mail::default_impl::simple_context; -use mail::template::{InspectEmbeddedResources, Embedded, MailSendData}; -use mail::render_template_engine::{RenderTemplateEngine, TemplateSpec, DEFAULT_SETTINGS}; -use mail::tera::TeraRenderEngine; - -use self::error::{SetupError, Error}; - -mod error; - -#[derive(Debug, Serialize, InspectEmbeddedResources)] +use serde::Serialize; + +use mail::{ + Domain, + MailType, + default_impl::simple_context, + template::{ + load_toml_template_from_path, + handlebars::Handlebars, + TemplateExt + }, + headers, + HeaderTryFrom, + HeaderKind +}; + +#[derive(Debug, Serialize)] struct UserData { name: &'static str - // TODO: include embedded avatar. } fn main() { + //TODO[workspace] check if [dir mail and has sub-dir mail]/[dir mail and has parent mail] + // depending on this switch the CWD to the subdir-mail + eprintln!(concat!( + "Warning: This example currently only works if mail/mail is the cwd\n", + " i.e. it fails when run from the workspace!" + )); let msg_id_domain = Domain::try_from("company_a.test").unwrap(); let unique_part = SoftAsciiString::from_string("c207n521cec").unwrap(); let ctx = simple_context::new(msg_id_domain, unique_part).unwrap(); - let engine = setup_template_engine().unwrap(); - - let mail = create_mail(&engine, &ctx).unwrap(); - let string_mail = encode_mail_to_string(mail, ctx.clone()).unwrap(); - println!("{}", string_mail); -} - -fn create_mail(engine: &RenderTemplateEngine, ctx: &impl Context) - -> Result -{ - let from = Mailbox::try_from("a@b.c")?; - let to = Mailbox::try_from("d@e.f")?; - let subject = "Live might not be a roller coaster"; - // Use template_a. - let template_id = Cow::Borrowed("template_a"); - // This can be basically a type implementing `Serialize`, - // in the tera template we use it with `{{data.name}}`. - let data = UserData { name: "Mr. Slow Coaster" }; - - // `MailSendData` contains everything needed to crate (and send) - // a mail based on a template. - let send_data = MailSendData::simple_new( - from, to, subject, - template_id, data - ); - - let mail = send_data.compose(ctx, engine)?; - Ok(mail) -} - -fn setup_template_engine() -> Result, SetupError> { - // Create instance of the tera rte implementation, - // we can reuse/derive from all templates in `tera_base` with - // this (and we do so in the example using `{% extends "base_mail.html" %}`). - let tera = TeraRenderEngine::new("./example_resources/tera_base/**/*")?; - let mut rte = RenderTemplateEngine::new(tera); - // Load all template specs based on the files/folders in `templates` - // using the folder structure as way to define the templates is easy - // but we can do differently if we need to. - let specs = TemplateSpec - ::from_dirs("./example_resources/templates", &*DEFAULT_SETTINGS)?; - - for (name, spec) in specs { - rte.insert_spec(name, spec)?; - } - Ok(rte) -} - -fn encode_mail_to_string(mail: Mail, ctx: impl Context) -> Result { - let res = mail - .into_encodeable_mail(ctx) - .wait()? - .encode_into_bytes(MailType::Ascii)?; - - Ok(String::from_utf8(res).unwrap()) + let engine = Handlebars::new(); + let template_path = Path::new("example_resources/templates/template_a/template.toml").to_owned(); + let fut = load_toml_template_from_path(engine, template_path, &ctx) + .and_then(|template| -> Result<_, Error> { + // If our "user data" would contain additional inline_emebeddings/attachments + // we would need another "and_then" chain here where we load such parts. + let mut mail = template.render(UserData { name: "Ferris" }.into(), &ctx)?; + // `auto_body` has some nice but failable conversion for **header bodies**. + // Alternatively there is `::body()` which + // is not failable. + mail.insert_header(headers::_From::auto_body(["a@b.example"])?); + mail.insert_header(headers::_To::auto_body(["d@e.example"])?); + Ok(mail) + }).and_then(|mail| mail.into_encodable_mail(ctx.clone()).map_err(Into::into)); + + let enc_mail = fut.wait().unwrap(); + let bytes = enc_mail.encode_into_bytes(MailType::Ascii).unwrap(); + let string = String::from_utf8(bytes).unwrap(); + println!("{}", string); } diff --git a/mail/src/lib.rs b/mail/src/lib.rs index dd0eeb7..39a3c8e 100644 --- a/mail/src/lib.rs +++ b/mail/src/lib.rs @@ -98,7 +98,7 @@ //! which normally doesn't need to be accessed directly. #[doc(hidden)] -pub extern crate mail_internals; +pub extern crate mail_internals as internals; extern crate mail_headers; extern crate mail_core; pub extern crate mail_template as template; @@ -120,7 +120,7 @@ pub use mail_core::*; /// - `mail-template` /// - `mail-smtp` (feature: `smtp`) pub mod error { - pub use mail_internals::error::*; + pub use crate::internals::error::*; pub use mail_headers::error::*; pub use mail_headers::InvalidHeaderName; pub use mail_core::error::*; @@ -129,7 +129,7 @@ pub mod error { pub use smtp::error::*; } -pub use mail_internals::MailType; +pub use self::internals::MailType; /// Re-export of headers from `mail-headers`. pub use mail_headers::{ @@ -154,6 +154,9 @@ pub use mail_headers::{ def_headers, }; +#[doc(hidden)] +pub use mail_headers::data; + pub use self::header_components::{ MediaType, Mailbox, @@ -162,8 +165,8 @@ pub use self::header_components::{ }; -#[doc(hidden)] -pub use mail_headers::data; +// Re-export some parts of mail-internals useful for writing custom header. +pub use crate::internals::{encoder as header_encoding}; /// Re-export of the default_impl parts from `mail-core`. /// -- cgit v1.2.3