feat(transport-smtp): Change default authentication mecanism default handling

Change the default authentication mechanism selection check if the
connection is encrypted, and only test PLAIN when it is the case.
Also make the .authentication_mechnaism only take one mechanism, as
a user will specify it he wants to ensure one particular method will
be used.

Closes #65
This commit is contained in:
Alexis Mousset
2016-05-10 00:12:10 +02:00
parent 8fda23435c
commit b7039a7a69
5 changed files with 40 additions and 10 deletions

View File

@@ -72,7 +72,7 @@ pub struct EmailBuilder {
date_issued: bool,
}
/// todo
/// Simple email enveloppe representation
#[derive(PartialEq,Eq,Clone,Debug)]
pub struct Envelope {
/// The envelope recipients' addresses

View File

@@ -144,8 +144,8 @@
//! .security_level(SecurityLevel::AlwaysEncrypt)
//! // Enable SMTPUTF8 if the server supports it
//! .smtp_utf8(true)
//! // Configure accepted authentication mechanisms
//! .authentication_mechanisms(vec![Mechanism::CramMd5])
//! // Configure expected authentication mechanism
//! .authentication_mechanism(Mechanism::CramMd5)
//! // Enable connection reuse
//! .connection_reuse(true).build();
//!

View File

@@ -82,7 +82,15 @@ impl<S: Connector + Write + Read + Debug + Clone> Client<S> {
pub fn upgrade_tls_stream(&mut self, ssl_context: &SslContext) -> io::Result<()> {
match self.stream {
Some(ref mut stream) => stream.get_mut().upgrade_tls(ssl_context),
None => Ok(())
None => Ok(()),
}
}
/// Tells if the underlying stream is currently encrypted
pub fn is_encrypted(&self) -> bool {
match self.stream {
Some(ref stream) => stream.get_ref().is_encrypted(),
None => false,
}
}

View File

@@ -14,6 +14,8 @@ pub trait Connector: Sized {
fn connect(addr: &SocketAddr, ssl_context: Option<&SslContext>) -> io::Result<Self>;
/// Upgrades to TLS connection
fn upgrade_tls(&mut self, ssl_context: &SslContext) -> io::Result<()>;
/// Is the NetworkStream encrypted
fn is_encrypted(&self) -> bool;
}
impl Connector for NetworkStream {
@@ -43,6 +45,13 @@ impl Connector for NetworkStream {
};
Ok(())
}
fn is_encrypted(&self) -> bool {
match *self {
NetworkStream::Plain(_) => false,
NetworkStream::Ssl(_) => true,
}
}
}

View File

@@ -83,8 +83,8 @@ pub struct SmtpTransportBuilder {
security_level: SecurityLevel,
/// Enable UTF8 mailboxes in envelope or headers
smtp_utf8: bool,
/// List of authentication mechanisms, sorted by priority
authentication_mechanisms: Vec<Mechanism>,
/// Optionnal enforced authentication mechanism
authentication_mechanism: Option<Mechanism>,
}
/// Builder for the SMTP SmtpTransport
@@ -104,7 +104,7 @@ impl SmtpTransportBuilder {
connection_reuse_count_limit: 100,
connection_reuse: false,
hello_name: "localhost".to_string(),
authentication_mechanisms: vec![Mechanism::CramMd5, Mechanism::Plain],
authentication_mechanism: None,
})
}
None => Err(From::from("Could nor resolve hostname")),
@@ -175,8 +175,8 @@ impl SmtpTransportBuilder {
}
/// Set the authentication mechanisms
pub fn authentication_mechanisms(mut self, mechanisms: Vec<Mechanism>) -> SmtpTransportBuilder {
self.authentication_mechanisms = mechanisms;
pub fn authentication_mechanism(mut self, mechanism: Mechanism) -> SmtpTransportBuilder {
self.authentication_mechanism = Some(mechanism);
self
}
@@ -325,7 +325,20 @@ impl EmailTransport for SmtpTransport {
let mut found = false;
for mechanism in self.client_info.authentication_mechanisms.clone() {
// Compute accepted mechnism
let accepted_mechanisms = match self.client_info.authentication_mechanism {
Some(mechanism) => vec![mechanism],
None => {
match self.client.is_encrypted() {
// If encrypted, allow all mechanisms, with a preference for the simplest
true => vec![Mechanism::Plain, Mechanism::CramMd5],
// If not encrypted, do not all clear-text passwords
false => vec![Mechanism::CramMd5],
}
}
};
for mechanism in accepted_mechanisms {
if self.server_info.as_ref().unwrap().supports_auth_mechanism(mechanism) {
found = true;
try_smtp!(self.client.auth(mechanism, &username, &password), self);