From 73e7aa36390a93367372182b08c5500647f555a2 Mon Sep 17 00:00:00 2001 From: Alexis Mousset Date: Sun, 23 Oct 2016 20:42:13 +0200 Subject: [PATCH] test(transport): add sendmail transport --- src/email/mod.rs | 2 -- src/lib.rs | 22 +++++++++++++++ src/transport/file/mod.rs | 2 +- src/transport/sendmail/mod.rs | 50 +++++++++++++++++++++++------------ tests/transport_file.rs | 20 +++++++------- tests/transport_sendmail.rs | 19 ++++++------- tests/transport_smtp.rs | 16 +++++------ tests/transport_stub.rs | 16 +++++------ 8 files changed, 92 insertions(+), 55 deletions(-) diff --git a/src/email/mod.rs b/src/email/mod.rs index d04dd02..b8d0652 100644 --- a/src/email/mod.rs +++ b/src/email/mod.rs @@ -82,8 +82,6 @@ impl IntoEmail for SimpleEmail { builder.add_cc(cc_address.into_mailbox()); } - // No bcc for now - if self.reply_to.is_some() { builder.add_reply_to(self.reply_to.unwrap().into_mailbox()); } diff --git a/src/lib.rs b/src/lib.rs index 1029c49..f9524b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -180,6 +180,28 @@ //! let _ = email_client.quit(); //! ``` //! +//! ### Sendmail transport +//! +//! The sendmail transport sends the email using the local sendmail command. +//! +//! ```rust +//! use lettre::transport::sendmail::SendmailTransport; +//! use lettre::transport::EmailTransport; +//! use lettre::email::EmailBuilder; +//! +//! let email = EmailBuilder::new() +//! .to("root@localhost") +//! .from("user@localhost") +//! .body("Hello World!") +//! .subject("Hello") +//! .build() +//! .unwrap(); +//! +//! let mut sender = SendmailTransport::new(); +//! let result = sender.send(email); +//! assert!(result.is_ok()); +//! ``` +//! //! ### Stub transport //! //! The stub transport only logs message envelope and drops the content. It can be useful for diff --git a/src/transport/file/mod.rs b/src/transport/file/mod.rs index 61dac35..dd1ce1a 100644 --- a/src/transport/file/mod.rs +++ b/src/transport/file/mod.rs @@ -38,7 +38,7 @@ impl EmailTransport for FileEmailTransport { email.to_addresses().join("> to=<")); try!(f.write_all(log_line.as_bytes())); - try!(f.write_all(email.message().clone().as_bytes())); + try!(f.write_all(email.message().as_bytes())); info!("{} status=", log_line); diff --git a/src/transport/sendmail/mod.rs b/src/transport/sendmail/mod.rs index da8ed7c..cb19b62 100644 --- a/src/transport/sendmail/mod.rs +++ b/src/transport/sendmail/mod.rs @@ -1,7 +1,6 @@ //! 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}; @@ -10,32 +9,49 @@ use transport::sendmail::error::SendmailResult; pub mod error; -/// Writes the content and the envelope information to a file -pub struct SendmailTransport; +/// Sends an email using the `sendmail` command +#[derive(Debug,Default)] +pub struct SendmailTransport { + command: String, +} + +impl SendmailTransport { + /// Creates a new transport with the default `/usr/sbin/sendmail` command + pub fn new() -> SendmailTransport { + SendmailTransport { command: "/usr/sbin/sendmail".to_string() } + } + + /// Creates a new transport to the given sendmail command + pub fn new_with_command>(command: S) -> SendmailTransport { + SendmailTransport { command: command.into() } + } +} impl EmailTransport for SendmailTransport { fn send(&mut self, email: T) -> SendmailResult { - // Spawn the `wc` command - let process = try!(Command::new("/usr/sbin/sendmail") - .args(&email.to_addresses()) + // Spawn the sendmail command + let mut process = try!(Command::new(&self.command) + .args(&["-i", "-f", &email.from_address(), &email.to_addresses().join(" ")]) .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"), + match process.stdin.as_mut().unwrap().write_all(email.message().as_bytes()) { + Ok(_) => (), + Err(error) => return Err(From::from(error)), } - 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), + info!("Wrote message to stdin"); + + if let Ok(output) = process.wait_with_output() { + if output.status.success() { + Ok(()) + } else { + Err(From::from("The message could not be sent")) + } + } else { + Err(From::from("The sendmail process stopped")) } - - Ok(()) } fn close(&mut self) { diff --git a/tests/transport_file.rs b/tests/transport_file.rs index 01ea837..8c0beb5 100644 --- a/tests/transport_file.rs +++ b/tests/transport_file.rs @@ -1,24 +1,24 @@ extern crate lettre; +use lettre::email::{EmailBuilder, SendableEmail}; +use lettre::transport::EmailTransport; + +use lettre::transport::file::FileEmailTransport; use std::env::temp_dir; use std::fs::File; use std::fs::remove_file; use std::io::Read; -use lettre::transport::file::FileEmailTransport; -use lettre::transport::EmailTransport; -use lettre::email::{EmailBuilder, SendableEmail}; - #[test] fn file_transport() { let mut sender = FileEmailTransport::new(temp_dir()); let email = EmailBuilder::new() - .to("root@localhost") - .from("user@localhost") - .body("Hello World!") - .subject("Hello") - .build() - .unwrap(); + .to("root@localhost") + .from("user@localhost") + .body("Hello World!") + .subject("Hello file") + .build() + .unwrap(); let result = sender.send(email.clone()); assert!(result.is_ok()); diff --git a/tests/transport_sendmail.rs b/tests/transport_sendmail.rs index 39f7dbb..3586d34 100644 --- a/tests/transport_sendmail.rs +++ b/tests/transport_sendmail.rs @@ -1,19 +1,20 @@ extern crate lettre; -use lettre::transport::sendmail::SendmailTransport; -use lettre::transport::EmailTransport; use lettre::email::EmailBuilder; +use lettre::transport::EmailTransport; +use lettre::transport::sendmail::SendmailTransport; #[test] fn sendmail_transport_simple() { - let mut sender = SendmailTransport; + let mut sender = SendmailTransport::new(); let email = EmailBuilder::new() - .to("root@localhost") - .from("user@localhost") - .body("Hello World!") - .subject("Hello") - .build() - .unwrap(); + .to("root@localhost") + .from("user@localhost") + .body("Hello World!") + .subject("Hello sendmail") + .build() + .unwrap(); let result = sender.send(email); + println!("{:?}", result); assert!(result.is_ok()); } diff --git a/tests/transport_smtp.rs b/tests/transport_smtp.rs index 9af40d5..44f3d48 100644 --- a/tests/transport_smtp.rs +++ b/tests/transport_smtp.rs @@ -1,19 +1,19 @@ extern crate lettre; -use lettre::transport::smtp::SmtpTransportBuilder; -use lettre::transport::EmailTransport; use lettre::email::EmailBuilder; +use lettre::transport::EmailTransport; +use lettre::transport::smtp::SmtpTransportBuilder; #[test] fn smtp_transport_simple() { let mut sender = SmtpTransportBuilder::localhost().unwrap().build(); let email = EmailBuilder::new() - .to("root@localhost") - .from("user@localhost") - .body("Hello World!") - .subject("Hello") - .build() - .unwrap(); + .to("root@localhost") + .from("user@localhost") + .body("Hello World!") + .subject("Hello smtp") + .build() + .unwrap(); let result = sender.send(email); assert!(result.is_ok()); } diff --git a/tests/transport_stub.rs b/tests/transport_stub.rs index 9e4b18a..468cb80 100644 --- a/tests/transport_stub.rs +++ b/tests/transport_stub.rs @@ -1,19 +1,19 @@ extern crate lettre; -use lettre::transport::stub::StubEmailTransport; -use lettre::transport::EmailTransport; use lettre::email::EmailBuilder; +use lettre::transport::EmailTransport; +use lettre::transport::stub::StubEmailTransport; #[test] fn stub_transport() { let mut sender = StubEmailTransport; let email = EmailBuilder::new() - .to("root@localhost") - .from("user@localhost") - .body("Hello World!") - .subject("Hello") - .build() - .unwrap(); + .to("root@localhost") + .from("user@localhost") + .body("Hello World!") + .subject("Hello stub") + .build() + .unwrap(); let result = sender.send(email); assert!(result.is_ok()); }