diff --git a/lettre/Cargo.toml b/lettre/Cargo.toml index 8cd4769..bc5b0a2 100644 --- a/lettre/Cargo.toml +++ b/lettre/Cargo.toml @@ -17,7 +17,7 @@ travis-ci = { repository = "lettre/lettre" } [dependencies] bufstream = "^0.1" log = "^0.3" -openssl = "^0.9" +native-tls = "^0.1" base64 = "^0.6" hex = "^0.2" rust-crypto = "^0.2" diff --git a/lettre/src/lib.rs b/lettre/src/lib.rs index 7d07d79..c6e7e1c 100644 --- a/lettre/src/lib.rs +++ b/lettre/src/lib.rs @@ -4,7 +4,7 @@ //! emails have to implement `SendableEmail`. //! -#![deny(missing_docs, unsafe_code, unstable_features, warnings, missing_debug_implementations)] +#![deny(missing_docs, unsafe_code, unstable_features, warnings)] #[macro_use] extern crate log; @@ -12,7 +12,7 @@ extern crate base64; extern crate hex; extern crate crypto; extern crate bufstream; -extern crate openssl; +extern crate native_tls; extern crate emailaddress; extern crate serde_json; extern crate serde; diff --git a/lettre/src/smtp/client/mod.rs b/lettre/src/smtp/client/mod.rs index 46b7a35..f31354f 100644 --- a/lettre/src/smtp/client/mod.rs +++ b/lettre/src/smtp/client/mod.rs @@ -1,7 +1,7 @@ //! SMTP client use bufstream::BufStream; -use openssl::ssl::SslContext; +use native_tls::TlsConnector; use smtp::{CRLF, MESSAGE_ENDING}; use smtp::authentication::{Credentials, Mechanism}; use smtp::client::net::{Connector, NetworkStream, Timeout}; @@ -82,9 +82,9 @@ impl Client { } /// Upgrades the underlying connection to SSL/TLS - pub fn upgrade_tls_stream(&mut self, ssl_context: &SslContext) -> io::Result<()> { + pub fn upgrade_tls_stream(&mut self, tls_connector: &TlsConnector) -> io::Result<()> { match self.stream { - Some(ref mut stream) => stream.get_mut().upgrade_tls(ssl_context), + Some(ref mut stream) => stream.get_mut().upgrade_tls(tls_connector), None => Ok(()), } } @@ -113,7 +113,7 @@ impl Client { pub fn connect( &mut self, addr: &A, - ssl_context: Option<&SslContext>, + tls_connector: Option<&TlsConnector>, ) -> SmtpResult { // Connect should not be called when the client is already connected if self.stream.is_some() { @@ -130,7 +130,7 @@ impl Client { debug!("connecting to {}", server_addr); // Try to connect - self.set_stream(try!(Connector::connect(&server_addr, ssl_context))); + self.set_stream(try!(Connector::connect(&server_addr, tls_connector))); self.get_reply() } diff --git a/lettre/src/smtp/client/net.rs b/lettre/src/smtp/client/net.rs index f9d3147..413e518 100644 --- a/lettre/src/smtp/client/net.rs +++ b/lettre/src/smtp/client/net.rs @@ -1,7 +1,6 @@ //! A trait to represent a stream -use openssl::ssl::{Ssl, SslContext, SslStream}; - +use native_tls::{TlsConnector, TlsStream}; use smtp::client::mock::MockStream; use std::io; use std::io::{ErrorKind, Read, Write}; @@ -14,7 +13,7 @@ pub enum NetworkStream { /// Plain TCP stream Tcp(TcpStream), /// Encrypted TCP stream - Ssl(SslStream), + Ssl(TlsStream), /// Mock stream Mock(MockStream), } @@ -74,46 +73,38 @@ impl Write for NetworkStream { /// A trait for the concept of opening a stream pub trait Connector: Sized { /// Opens a connection to the given IP socket - fn connect(addr: &SocketAddr, ssl_context: Option<&SslContext>) -> io::Result; + fn connect(addr: &SocketAddr, tls_connector: Option<&TlsConnector>) -> io::Result; /// Upgrades to TLS connection - fn upgrade_tls(&mut self, ssl_context: &SslContext) -> io::Result<()>; + fn upgrade_tls(&mut self, tls_connector: &TlsConnector) -> io::Result<()>; /// Is the NetworkStream encrypted fn is_encrypted(&self) -> bool; } impl Connector for NetworkStream { - fn connect(addr: &SocketAddr, ssl_context: Option<&SslContext>) -> io::Result { + fn connect( + addr: &SocketAddr, + tls_connector: Option<&TlsConnector>, + ) -> io::Result { let tcp_stream = try!(TcpStream::connect(addr)); - match ssl_context { + match tls_connector { Some(context) => { - match Ssl::new(context) { - Ok(ssl) => { - ssl.connect(tcp_stream).map(NetworkStream::Ssl).map_err( - |e| { - io::Error::new(ErrorKind::Other, e) - }, - ) - } - Err(e) => Err(io::Error::new(ErrorKind::Other, e)), - } + context + .danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(tcp_stream) + .map(NetworkStream::Ssl) + .map_err(|e| io::Error::new(ErrorKind::Other, e)) } None => Ok(NetworkStream::Tcp(tcp_stream)), } } #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))] - fn upgrade_tls(&mut self, ssl_context: &SslContext) -> io::Result<()> { + fn upgrade_tls(&mut self, tls_connector: &TlsConnector) -> io::Result<()> { *self = match *self { NetworkStream::Tcp(ref mut stream) => { - match Ssl::new(ssl_context) { - Ok(ssl) => { - match ssl.connect(stream.try_clone().unwrap()) { - Ok(ssl_stream) => NetworkStream::Ssl(ssl_stream), - Err(err) => return Err(io::Error::new(ErrorKind::Other, err)), - } - } - Err(e) => return Err(io::Error::new(ErrorKind::Other, e)), + match tls_connector.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream.try_clone().unwrap()) { + Ok(ssl_stream) => NetworkStream::Ssl(ssl_stream), + Err(err) => return Err(io::Error::new(ErrorKind::Other, err)), } } NetworkStream::Ssl(_) => return Ok(()), diff --git a/lettre/src/smtp/mod.rs b/lettre/src/smtp/mod.rs index 9a8c462..cc3a229 100644 --- a/lettre/src/smtp/mod.rs +++ b/lettre/src/smtp/mod.rs @@ -62,8 +62,8 @@ //! .hello_name(ClientId::Domain("my.hostname.tld".to_string())) //! // Add credentials for authentication //! .credentials(Credentials::new("username".to_string(), "password".to_string())) -//! // Specify a TLS security level. You can also specify an SslContext with -//! // .ssl_context(SslContext::Ssl23) +//! // Specify a TLS security level. You can also specify an TlsConnector with +//! // .tls_connector(TlsConnector::Ssl23) //! .security_level(SecurityLevel::AlwaysEncrypt) //! // Enable SMTPUTF8 if the server supports it //! .smtp_utf8(true) @@ -108,7 +108,7 @@ use EmailTransport; use SendableEmail; -use openssl::ssl::{SslContext, SslMethod}; +use native_tls::TlsConnector; use smtp::authentication::{Credentials, Mechanism}; use smtp::client::Client; use smtp::commands::*; @@ -172,7 +172,6 @@ pub enum SecurityLevel { } /// Contains client configuration -#[derive(Debug)] pub struct SmtpTransportBuilder { /// Maximum connection reuse /// @@ -187,7 +186,7 @@ pub struct SmtpTransportBuilder { /// Socket we are connecting to server_addr: SocketAddr, /// SSL context to use - ssl_context: SslContext, + tls_connector: TlsConnector, /// TLS security level security_level: SecurityLevel, /// Enable UTF8 mailboxes in envelope or headers @@ -209,7 +208,7 @@ impl SmtpTransportBuilder { Some(addr) => { Ok(SmtpTransportBuilder { server_addr: addr, - ssl_context: SslContext::builder(SslMethod::tls()).unwrap().build(), + tls_connector: TlsConnector::builder().unwrap().build().unwrap(), security_level: SecurityLevel::AlwaysEncrypt, smtp_utf8: false, credentials: None, @@ -230,8 +229,8 @@ impl SmtpTransportBuilder { } /// Use STARTTLS with a specific context - pub fn ssl_context(mut self, ssl_context: SslContext) -> SmtpTransportBuilder { - self.ssl_context = ssl_context; + pub fn tls_connector(mut self, ssl_context: TlsConnector) -> SmtpTransportBuilder { + self.tls_connector = ssl_context; self } @@ -317,7 +316,6 @@ struct State { } /// Structure that implements the high level SMTP client -#[derive(Debug)] pub struct SmtpTransport { /// Information about the server /// Value is None before HELO/EHLO @@ -411,7 +409,7 @@ impl EmailTransport for SmtpTransport { try!(self.client.connect( &self.client_info.server_addr, match self.client_info.security_level { - SecurityLevel::EncryptedWrapper => Some(&self.client_info.ssl_context), + SecurityLevel::EncryptedWrapper => Some(&self.client_info.tls_connector), _ => None, }, )); @@ -439,7 +437,7 @@ impl EmailTransport for SmtpTransport { try_smtp!(self.client.smtp_command(StarttlsCommand), self); try_smtp!( self.client.upgrade_tls_stream( - &self.client_info.ssl_context, + &self.client_info.tls_connector, ), self );