From 250ed7bcf4aa1637dbaadf415d9ae548db46b737 Mon Sep 17 00:00:00 2001 From: Alexis Mousset Date: Wed, 21 Oct 2015 23:02:14 +0200 Subject: [PATCH] Add SMTPUTF8 support --- README.md | 2 +- examples/client.rs | 2 +- src/lib.rs | 7 +++---- src/transport/smtp/client/mod.rs | 1 + src/transport/smtp/mod.rs | 36 +++++++++++++++++++++----------- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 7144418..289feb4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -lettre [![Build Status](https://travis-ci.org/lettre/lettre.svg?branch=master)](https://travis-ci.org/lettre/lettre) [![Coverage Status](https://coveralls.io/repos/github/lettre/lettre/badge.svg?branch=master)](https://coveralls.io/github/lettre/lettre?branch=master) [![Crate](https://meritbadge.herokuapp.com/lettre)](https://crates.io/crates/lettre) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) +lettre [![Build Status](https://travis-ci.org/lettre/lettre.svg?branch=master)](https://travis-ci.org/lettre/lettre) [![Coverage Status](https://coveralls.io/repos/lettre/lettre/badge.svg?branch=master&service=github)](https://coveralls.io/github/lettre/lettre?branch=master) [![Crate](https://meritbadge.herokuapp.com/lettre)](https://crates.io/crates/lettre) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) ========= This is an email library written in Rust. diff --git a/examples/client.rs b/examples/client.rs index f6f8b21..b521d8e 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -15,7 +15,7 @@ fn main() { env_logger::init().unwrap(); let sender = SmtpTransportBuilder::localhost().unwrap().hello_name("localhost") - .enable_connection_reuse(true).build(); + .connection_reuse(true).build(); let mailer = Arc::new(Mutex::new(Mailer::new(sender))); let mut threads = Vec::new(); diff --git a/src/lib.rs b/src/lib.rs index 0b45838..e4e9f57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,9 +10,6 @@ //! * 8BITMIME ([RFC 6152](https://tools.ietf.org/html/rfc6152)) //! * AUTH ([RFC 4954](http://tools.ietf.org/html/rfc4954)) with PLAIN and CRAM-MD5 mecanisms //! * STARTTLS ([RFC 2487](http://tools.ietf.org/html/rfc2487)) -//! -//! It will eventually implement the following extensions: -//! //! * SMTPUTF8 ([RFC 6531](http://tools.ietf.org/html/rfc6531)) //! //! ## Architecture @@ -85,10 +82,12 @@ //! // Specify a TLS security level. You can also specify an SslContext with //! // .ssl_context(SslContext::Ssl23) //! .security_level(SecurityLevel::AlwaysEncrypt) +//! // Enable SMTPUTF8 is the server supports it +//! .smtp_utf8(true) //! // Configure accepted authetication mecanisms //! .authentication_mecanisms(vec![Mecanism::CramMd5]) //! // Enable connection reuse -//! .enable_connection_reuse(true).build()); +//! .connection_reuse(true).build()); //! //! let result_1 = mailer.send(email.clone()); //! assert!(result_1.is_ok()); diff --git a/src/transport/smtp/client/mod.rs b/src/transport/smtp/client/mod.rs index fe92293..298ea6f 100644 --- a/src/transport/smtp/client/mod.rs +++ b/src/transport/smtp/client/mod.rs @@ -44,6 +44,7 @@ fn remove_crlf(string: &str) -> String { } /// Structure that implements the SMTP client +#[derive(Debug)] pub struct Client { /// TCP stream between client and server /// Value is None before connection diff --git a/src/transport/smtp/mod.rs b/src/transport/smtp/mod.rs index d1cc8c3..657ec26 100644 --- a/src/transport/smtp/mod.rs +++ b/src/transport/smtp/mod.rs @@ -23,9 +23,6 @@ pub mod client; /// Default smtp port pub static SMTP_PORT: u16 = 25; -/// Default smtps port -pub static SMTPS_PORT: u16 = 465; - /// Default submission port pub static SUBMISSION_PORT: u16 = 587; @@ -47,6 +44,7 @@ pub static MESSAGE_ENDING: &'static str = "\r\n.\r\n"; pub static NUL: &'static str = "\0"; /// TLS security level +#[derive(Debug)] pub enum SecurityLevel { /// Only send an email on encrypted connection AlwaysEncrypt, @@ -63,7 +61,7 @@ pub struct SmtpTransportBuilder { /// Zero means no limitation connection_reuse_count_limit: u16, /// Enable connection reuse - enable_connection_reuse: bool, + connection_reuse: bool, /// Name sent during HELO or EHLO hello_name: String, /// Credentials @@ -74,6 +72,8 @@ pub struct SmtpTransportBuilder { ssl_context: SslContext, /// TLS security level security_level: SecurityLevel, + /// Enable UTF8 mailboxes in enveloppe or headers + smtp_utf8: bool, /// List of authentication mecanism, sorted by priority authentication_mecanisms: Vec, } @@ -89,9 +89,10 @@ impl SmtpTransportBuilder { server_addr: addr, ssl_context: SslContext::new(SslMethod::Tlsv1).unwrap(), security_level: SecurityLevel::Opportunistic, + smtp_utf8: false, credentials: None, connection_reuse_count_limit: 100, - enable_connection_reuse: false, + connection_reuse: false, hello_name: "localhost".to_string(), authentication_mecanisms: vec![Mecanism::CramMd5, Mecanism::Plain], }), @@ -116,6 +117,12 @@ impl SmtpTransportBuilder { self } + /// Require SSL/TLS using STARTTLS + pub fn smtp_utf8(mut self, enabled: bool) -> SmtpTransportBuilder { + self.smtp_utf8 = enabled; + self + } + /// Set the name used during HELO or EHLO pub fn hello_name(mut self, name: &str) -> SmtpTransportBuilder { self.hello_name = name.to_string(); @@ -123,8 +130,8 @@ impl SmtpTransportBuilder { } /// Enable connection reuse - pub fn enable_connection_reuse(mut self, enable: bool) -> SmtpTransportBuilder { - self.enable_connection_reuse = enable; + pub fn connection_reuse(mut self, enable: bool) -> SmtpTransportBuilder { + self.connection_reuse = enable; self } @@ -297,12 +304,17 @@ impl EmailTransport for SmtpTransport { } // Mail - let mail_options = match self.server_info + let mail_options = match (self.server_info .as_ref() .unwrap() - .supports_feature(&Extension::EightBitMime) { - true => Some("BODY=8BITMIME"), - false => None, + .supports_feature(&Extension::EightBitMime), + self.server_info + .as_ref() + .unwrap() + .supports_feature(&Extension::EightBitMime)) { + (true, true) => Some("BODY=8BITMIME SMTPUTF8"), + (true, false) => Some("BODY=8BITMIME"), + (false, _) => None, }; try_smtp!(self.client.mail(&from_address, mail_options), self); @@ -342,7 +354,7 @@ impl EmailTransport for SmtpTransport { } // Test if we can reuse the existing connection - if (!self.client_info.enable_connection_reuse) || + if (!self.client_info.connection_reuse) || (self.state.connection_reuse_count >= self.client_info.connection_reuse_count_limit) { self.reset(); }