diff --git a/src/lib.rs b/src/lib.rs index e193e2b..e9ab0ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,12 +25,11 @@ pub mod error; pub mod message; pub mod transport; -pub use crate::address::Address; use crate::error::Error; #[cfg(feature = "builder")] pub use crate::message::{ header::{self, Headers}, - EmailFormat, Mailboxes, Message, + EmailFormat, Mailbox, Mailboxes, Message, }; #[cfg(feature = "file-transport")] pub use crate::transport::file::FileTransport; @@ -42,11 +41,10 @@ pub use crate::transport::smtp::client::net::TlsParameters; pub use crate::transport::smtp::r2d2::SmtpConnectionManager; #[cfg(feature = "smtp-transport")] pub use crate::transport::smtp::{SmtpTransport, Tls}; -pub use crate::transport::stub::StubTransport; +pub use crate::{address::Address, transport::stub::StubTransport}; #[cfg(feature = "builder")] use std::convert::TryFrom; -use std::error::Error as StdError; -use std::fmt; +use std::{error::Error as StdError, fmt}; /// Simple email envelope representation /// @@ -92,9 +90,15 @@ impl TryFrom<&Headers> for Envelope { let from = match headers.get::() { // If there is a Sender, use it Some(header::Sender(a)) => Some(a.email.clone()), - // ... else use the first From address + // ... else try From None => match headers.get::() { - Some(header::From(ref a)) => Some(a.iter().next().unwrap().email.clone()), + Some(header::From(a)) => { + let from: Vec = a.clone().into(); + if from.len() > 1 { + return Err(Error::TooManyFrom); + } + Some(from[0].email.clone()) + } None => None, }, }; diff --git a/src/message/mod.rs b/src/message/mod.rs index 062dc5b..cfc8d50 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -364,25 +364,32 @@ impl MessageBuilder { self } - fn insert_missing_headers(self) -> Self { - let mut new = self; - - // Insert Date if missing - new = if new.headers.get::().is_none() { - new.date_now() - } else { - new - }; - - // TODO insert sender if needed? - new - } - // TODO: High-level methods for attachments and embedded files /// Create message from body fn build(self, body: Body) -> Result { - let res = self.insert_missing_headers(); + // Check for missing required headers + // https://tools.ietf.org/html/rfc5322#section-3.6 + + // Insert Date if missing + let res = if self.headers.get::().is_none() { + self.date_now() + } else { + self + }; + + // Fail is missing correct originator (Sender or From) + match res.headers.get::() { + Some(header::From(f)) => { + let from: Vec = f.clone().into(); + if from.len() > 1 && res.headers.get::().is_none() { + return Err(EmailError::TooManyFrom); + } + } + None => { + return Err(EmailError::MissingFrom); + } + } let envelope = match res.envelope { Some(e) => e, @@ -485,6 +492,29 @@ impl Default for MessageBuilder { mod test { use crate::message::{header, mailbox::Mailbox, Message}; + #[test] + fn email_missing_originator() { + assert!(Message::builder().body("Happy new year!").is_err()); + } + + #[test] + fn email_miminal_message() { + assert!(Message::builder() + .from("NoBody ".parse().unwrap()) + .to("NoBody ".parse().unwrap()) + .body("Happy new year!") + .is_ok()); + } + + #[test] + fn email_missing_sender() { + assert!(Message::builder() + .from("NoBody ".parse().unwrap()) + .from("AnyBody ".parse().unwrap()) + .body("Happy new year!") + .is_err()); + } + #[test] fn email_message() { let date = "Tue, 15 Nov 1994 08:12:31 GMT".parse().unwrap(); diff --git a/src/transport/stub/mod.rs b/src/transport/stub/mod.rs index 0fbd7e8..3419b5d 100644 --- a/src/transport/stub/mod.rs +++ b/src/transport/stub/mod.rs @@ -23,8 +23,7 @@ //! ``` use crate::{Envelope, Transport}; -use std::error::Error as StdError; -use std::fmt; +use std::{error::Error as StdError, fmt}; #[derive(Debug, Copy, Clone)] pub struct Error;