From a302df61d49f27875f50c22b1d62eeb8992519cd Mon Sep 17 00:00:00 2001 From: Lars Reichardt Date: Fri, 14 Oct 2016 10:57:26 +0200 Subject: [PATCH 1/2] feat(transport): add sendmail transport --- src/transport/mod.rs | 1 + src/transport/sendmail/error.rs | 54 +++++++++++++++++++++++++++++++++ src/transport/sendmail/mod.rs | 44 +++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 src/transport/sendmail/error.rs create mode 100644 src/transport/sendmail/mod.rs diff --git a/src/transport/mod.rs b/src/transport/mod.rs index e884bb8..bd575d2 100644 --- a/src/transport/mod.rs +++ b/src/transport/mod.rs @@ -1,5 +1,6 @@ //! Represents an Email transport pub mod smtp; +pub mod sendmail; pub mod stub; pub mod file; diff --git a/src/transport/sendmail/error.rs b/src/transport/sendmail/error.rs new file mode 100644 index 0000000..5db1cf7 --- /dev/null +++ b/src/transport/sendmail/error.rs @@ -0,0 +1,54 @@ +//! Error and result type for sendmail transport + + +use self::Error::*; +use std::error::Error as StdError; +use std::fmt; +use std::fmt::{Display, Formatter}; +use std::io; + +/// An enum of all error kinds. +#[derive(Debug)] +pub enum Error { + /// Internal client error + Client(&'static str), + /// IO error + Io(io::Error), +} + +impl Display for Error { + fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { + fmt.write_str(self.description()) + } +} + +impl StdError for Error { + fn description(&self) -> &str { + match *self { + Client(_) => "an unknown error occured", + Io(_) => "an I/O error occured", + } + } + + fn cause(&self) -> Option<&StdError> { + match *self { + Io(ref err) => Some(&*err as &StdError), + _ => None, + } + } +} + +impl From for Error { + fn from(err: io::Error) -> Error { + Io(err) + } +} + +impl From<&'static str> for Error { + fn from(string: &'static str) -> Error { + Client(string) + } +} + +/// SendMail result type +pub type SendmailResult = Result<(), Error>; diff --git a/src/transport/sendmail/mod.rs b/src/transport/sendmail/mod.rs new file mode 100644 index 0000000..6d226d7 --- /dev/null +++ b/src/transport/sendmail/mod.rs @@ -0,0 +1,44 @@ +//! This transport uilizes the sendmail executable for each email. + +use email::SendableEmail; +use std::error::Error; +use std::io::prelude::*; +use std::process::{Command, Stdio}; + +use transport::EmailTransport; +use transport::sendmail::error::SendmailResult; + +pub mod error; + +/// Writes the content and the envelope information to a file +pub struct SendmailTransport; + +impl EmailTransport for SendmailTransport { + fn send(&mut self, email: T) -> SendmailResult { + // Spawn the `wc` command + let process = try!(Command::new("/usr/bin/sendmail") + .args(&email.to_addresses()) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn()); + + match process.stdin.unwrap().write_all(email.message().clone().as_bytes()) { + Err(why) => error!("couldn't write to sendmail stdin: {}", + why.description()), + Ok(_) => info!("sent pangram to sendmail"), + } + + let mut s = String::new(); + match process.stdout.unwrap().read_to_string(&mut s) { + Err(why) => error!("couldn't read sendmail stdout: {}", + why.description()), + Ok(_) => info!("sendmail responded with:\n{}", s), + } + + Ok(()) + } + + fn close(&mut self) { + () + } +} From 13ee61d5cf5506826f88d202b57ae4f59f690f6d Mon Sep 17 00:00:00 2001 From: Lars Reichardt Date: Fri, 21 Oct 2016 14:32:28 +0200 Subject: [PATCH 2/2] test(transport): add sendmail transport test --- src/transport/sendmail/mod.rs | 2 +- tests/lib.rs | 1 + tests/transport_sendmail.rs | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/transport_sendmail.rs diff --git a/src/transport/sendmail/mod.rs b/src/transport/sendmail/mod.rs index 6d226d7..da8ed7c 100644 --- a/src/transport/sendmail/mod.rs +++ b/src/transport/sendmail/mod.rs @@ -16,7 +16,7 @@ pub struct SendmailTransport; impl EmailTransport for SendmailTransport { fn send(&mut self, email: T) -> SendmailResult { // Spawn the `wc` command - let process = try!(Command::new("/usr/bin/sendmail") + let process = try!(Command::new("/usr/sbin/sendmail") .args(&email.to_addresses()) .stdin(Stdio::piped()) .stdout(Stdio::piped()) diff --git a/tests/lib.rs b/tests/lib.rs index 45a6ab9..1e446d5 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,5 +1,6 @@ extern crate lettre; mod transport_smtp; +mod transport_sendmail; mod transport_stub; mod transport_file; diff --git a/tests/transport_sendmail.rs b/tests/transport_sendmail.rs new file mode 100644 index 0000000..39f7dbb --- /dev/null +++ b/tests/transport_sendmail.rs @@ -0,0 +1,19 @@ +extern crate lettre; + +use lettre::transport::sendmail::SendmailTransport; +use lettre::transport::EmailTransport; +use lettre::email::EmailBuilder; + +#[test] +fn sendmail_transport_simple() { + let mut sender = SendmailTransport; + let email = EmailBuilder::new() + .to("root@localhost") + .from("user@localhost") + .body("Hello World!") + .subject("Hello") + .build() + .unwrap(); + let result = sender.send(email); + assert!(result.is_ok()); +}