diff --git a/examples/basic_html.rs b/examples/basic_html.rs index 7fd5261..d865c35 100644 --- a/examples/basic_html.rs +++ b/examples/basic_html.rs @@ -1,5 +1,7 @@ -use lettre::message::{header, MultiPart, SinglePart}; -use lettre::{FileTransport, Message, Transport}; +use lettre::{ + message::{header, MultiPart, SinglePart}, + FileTransport, Message, Transport, +}; fn main() { // The html we want to send. diff --git a/examples/maud_html.rs b/examples/maud_html.rs index ec92916..17d489b 100644 --- a/examples/maud_html.rs +++ b/examples/maud_html.rs @@ -1,5 +1,7 @@ -use lettre::message::{header, MultiPart, SinglePart}; -use lettre::{FileTransport, Message, Transport}; +use lettre::{ + message::{header, MultiPart, SinglePart}, + FileTransport, Message, Transport, +}; use maud::html; fn main() { diff --git a/examples/smtp_selfsigned.rs b/examples/smtp_selfsigned.rs index 378b032..873d304 100644 --- a/examples/smtp_selfsigned.rs +++ b/examples/smtp_selfsigned.rs @@ -1,8 +1,10 @@ use std::fs; use lettre::{ - transport::smtp::authentication::Credentials, - transport::smtp::client::{Certificate, Tls, TlsParameters}, + transport::smtp::{ + authentication::Credentials, + client::{Certificate, Tls, TlsParameters}, + }, Message, SmtpTransport, Transport, }; @@ -20,9 +22,10 @@ fn main() { // Use a custom certificate stored on disk to securely verify the server's certificate let pem_cert = fs::read("certificate.pem").unwrap(); let cert = Certificate::from_pem(&pem_cert).unwrap(); - let mut tls = TlsParameters::builder("smtp.server.com".to_string()); - tls.add_root_certificate(cert); - let tls = tls.build().unwrap(); + let tls = TlsParameters::builder("smtp.server.com".to_string()) + .add_root_certificate(cert) + .build() + .unwrap(); let creds = Credentials::new("smtp_username".to_string(), "smtp_password".to_string()); diff --git a/src/address/mod.rs b/src/address/mod.rs index 765914d..e9818ce 100644 --- a/src/address/mod.rs +++ b/src/address/mod.rs @@ -6,5 +6,7 @@ mod serde; mod envelope; mod types; -pub use self::envelope::Envelope; -pub use self::types::{Address, AddressError}; +pub use self::{ + envelope::Envelope, + types::{Address, AddressError}, +}; diff --git a/src/lib.rs b/src/lib.rs index 302a625..957986e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,8 +56,6 @@ pub mod transport; extern crate hyperx; pub use crate::address::Address; -use crate::address::Envelope; -use crate::error::Error; #[cfg(feature = "builder")] pub use crate::message::Message; #[cfg(feature = "file-transport")] @@ -77,6 +75,7 @@ pub use crate::transport::smtp::SmtpTransport; pub use crate::transport::smtp::Tokio02Connector; #[cfg(all(feature = "smtp-transport", feature = "tokio1"))] pub use crate::transport::smtp::Tokio1Connector; +use crate::{address::Envelope, error::Error}; #[cfg(any(feature = "async-std1", feature = "tokio02", feature = "tokio1"))] use async_trait::async_trait; diff --git a/src/message/body.rs b/src/message/body.rs index dda71b0..ab5f88f 100644 --- a/src/message/body.rs +++ b/src/message/body.rs @@ -1,5 +1,7 @@ -use std::io::{self, Write}; -use std::ops::Deref; +use std::{ + io::{self, Write}, + ops::Deref, +}; use crate::message::header::ContentTransferEncoding; diff --git a/src/message/mailbox/types.rs b/src/message/mailbox/types.rs index f68cc37..e1a95ee 100644 --- a/src/message/mailbox/types.rs +++ b/src/message/mailbox/types.rs @@ -54,7 +54,7 @@ impl Mailbox { /// # Examples /// /// ``` - /// use lettre::{Address, message::Mailbox}; + /// use lettre::{message::Mailbox, Address}; /// /// # use std::error::Error; /// # fn main() -> Result<(), Box> { @@ -163,7 +163,10 @@ impl Mailboxes { /// # Examples /// /// ``` - /// use lettre::{Address, message::{Mailbox, Mailboxes}}; + /// use lettre::{ + /// message::{Mailbox, Mailboxes}, + /// Address, + /// }; /// /// # use std::error::Error; /// # fn main() -> Result<(), Box> { @@ -182,7 +185,10 @@ impl Mailboxes { /// # Examples /// /// ``` - /// use lettre::{Address, message::{Mailbox, Mailboxes}}; + /// use lettre::{ + /// message::{Mailbox, Mailboxes}, + /// Address, + /// }; /// /// # use std::error::Error; /// # fn main() -> Result<(), Box> { @@ -201,7 +207,10 @@ impl Mailboxes { /// # Examples /// /// ``` - /// use lettre::{Address, message::{Mailbox, Mailboxes}}; + /// use lettre::{ + /// message::{Mailbox, Mailboxes}, + /// Address, + /// }; /// /// # use std::error::Error; /// # fn main() -> Result<(), Box> { @@ -225,7 +234,10 @@ impl Mailboxes { /// # Examples /// /// ``` - /// use lettre::{Address, message::{Mailbox, Mailboxes}}; + /// use lettre::{ + /// message::{Mailbox, Mailboxes}, + /// Address, + /// }; /// /// # use std::error::Error; /// # fn main() -> Result<(), Box> { diff --git a/src/message/mimebody.rs b/src/message/mimebody.rs index 10ea5bc..79c9849 100644 --- a/src/message/mimebody.rs +++ b/src/message/mimebody.rs @@ -6,15 +6,12 @@ use mime::Mime; use rand::Rng; /// MIME part variants -/// #[derive(Debug, Clone)] pub enum Part { /// Single part with content - /// Single(SinglePart), /// Multiple parts of content - /// Multi(MultiPart), } @@ -37,11 +34,9 @@ impl Part { } /// Parts of multipart body -/// pub type Parts = Vec; /// Creates builder for single part -/// #[derive(Debug, Clone)] pub struct SinglePartBuilder { headers: Headers, @@ -92,17 +87,16 @@ impl Default for SinglePartBuilder { /// # Example /// /// ``` -/// use lettre::message::{SinglePart, header}; +/// use lettre::message::{header, SinglePart}; /// /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// let part = SinglePart::builder() -/// .header(header::ContentType("text/plain; charset=utf8".parse()?)) -/// .body(String::from("Текст письма в уникоде")); +/// .header(header::ContentType("text/plain; charset=utf8".parse()?)) +/// .body(String::from("Текст письма в уникоде")); /// # Ok(()) /// # } /// ``` -/// #[derive(Debug, Clone)] pub struct SinglePart { headers: Headers, @@ -170,7 +164,6 @@ impl EmailFormat for SinglePart { } /// The kind of multipart -/// #[derive(Debug, Clone)] pub enum MultiPartKind { /// Mixed kind to combine unrelated content parts @@ -257,7 +250,6 @@ impl From for Mime { } /// Multipart builder -/// #[derive(Debug, Clone)] pub struct MultiPartBuilder { headers: Headers, @@ -323,7 +315,6 @@ impl Default for MultiPartBuilder { } /// Multipart variant with parts -/// #[derive(Debug, Clone)] pub struct MultiPart { headers: Headers, diff --git a/src/message/mod.rs b/src/message/mod.rs index 8718541..0ca9e5d 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -114,7 +114,6 @@ //! //!

Hello, world!

//! --0oVZ2r6AoLAhLlb0gPNSKy6BEqdS2IfwxrcbUuo1-- -//! //! ``` //! //! @@ -125,8 +124,8 @@ //! //! ```rust //! # use std::error::Error; +//! use lettre::message::{header, Body, Message, MultiPart, Part, SinglePart}; //! use std::fs; -//! use lettre::message::{Body, header, Message, MultiPart, Part, SinglePart}; //! //! # fn main() -> Result<(), Box> { //! let image = fs::read("docs/lettre.png")?; @@ -236,7 +235,6 @@ //! //! fn main() { println!("Hello, World!") } //! --0oVZ2r6AoLAhLlb0gPNSKy6BEqdS2IfwxrcbUuo1-- -//! //! ``` //! @@ -252,8 +250,7 @@ mod mailbox; mod mimebody; mod utf8_b; -use std::convert::TryFrom; -use std::time::SystemTime; +use std::{convert::TryFrom, time::SystemTime}; use uuid::Uuid; diff --git a/src/transport/file/mod.rs b/src/transport/file/mod.rs index 7ac3347..085ade1 100644 --- a/src/transport/file/mod.rs +++ b/src/transport/file/mod.rs @@ -9,8 +9,8 @@ //! //! # #[cfg(all(feature = "file-transport", feature = "builder"))] //! # fn main() -> Result<(), Box> { +//! use lettre::{FileTransport, Message, Transport}; //! use std::env::temp_dir; -//! use lettre::{Transport, Message, FileTransport}; //! //! // Write to the local temp directory //! let sender = FileTransport::new(temp_dir()); @@ -41,8 +41,8 @@ //! //! # #[cfg(all(feature = "file-transport-envelope", feature = "builder"))] //! # fn main() -> Result<(), Box> { +//! use lettre::{FileTransport, Message, Transport}; //! use std::env::temp_dir; -//! use lettre::{Transport, Message, FileTransport}; //! //! // Write to the local temp directory //! let sender = FileTransport::with_envelope(temp_dir()); @@ -133,14 +133,13 @@ //! ``` pub use self::error::Error; -use crate::address::Envelope; #[cfg(feature = "async-std1")] use crate::AsyncStd1Transport; #[cfg(feature = "tokio02")] use crate::Tokio02Transport; #[cfg(feature = "tokio1")] use crate::Tokio1Transport; -use crate::Transport; +use crate::{address::Envelope, Transport}; #[cfg(any(feature = "async-std1", feature = "tokio02", feature = "tokio1"))] use async_trait::async_trait; use std::{ diff --git a/src/transport/sendmail/mod.rs b/src/transport/sendmail/mod.rs index 513c1f7..a59157f 100644 --- a/src/transport/sendmail/mod.rs +++ b/src/transport/sendmail/mod.rs @@ -96,14 +96,13 @@ //! ``` pub use self::error::Error; -use crate::address::Envelope; #[cfg(feature = "async-std1")] use crate::AsyncStd1Transport; #[cfg(feature = "tokio02")] use crate::Tokio02Transport; #[cfg(feature = "tokio1")] use crate::Tokio1Transport; -use crate::Transport; +use crate::{address::Envelope, Transport}; #[cfg(any(feature = "async-std1", feature = "tokio02", feature = "tokio1"))] use async_trait::async_trait; use std::{ diff --git a/src/transport/smtp/client/async_net.rs b/src/transport/smtp/client/async_net.rs index fbec4c3..1c70d30 100644 --- a/src/transport/smtp/client/async_net.rs +++ b/src/transport/smtp/client/async_net.rs @@ -10,8 +10,10 @@ use std::{ task::{Context, Poll}, }; -use futures_io::{AsyncRead as FuturesAsyncRead, AsyncWrite as FuturesAsyncWrite}; -use futures_io::{Error as IoError, ErrorKind, Result as IoResult}; +use futures_io::{ + AsyncRead as FuturesAsyncRead, AsyncWrite as FuturesAsyncWrite, Error as IoError, ErrorKind, + Result as IoResult, +}; #[cfg(feature = "tokio02")] use tokio02_crate::io::{AsyncRead as _, AsyncWrite as _}; #[cfg(feature = "tokio1")] @@ -370,8 +372,7 @@ impl AsyncNetworkStream { #[cfg(feature = "async-std1-rustls-tls")] return { - use async_rustls::webpki::DNSNameRef; - use async_rustls::TlsConnector; + use async_rustls::{webpki::DNSNameRef, TlsConnector}; let domain = DNSNameRef::try_from_ascii_str(&domain)?; diff --git a/src/transport/smtp/client/connection.rs b/src/transport/smtp/client/connection.rs index 38f6f90..b19ef2b 100644 --- a/src/transport/smtp/client/connection.rs +++ b/src/transport/smtp/client/connection.rs @@ -6,13 +6,15 @@ use std::{ }; use super::{ClientCodec, NetworkStream, TlsParameters}; -use crate::address::Envelope; -use crate::transport::smtp::{ - authentication::{Credentials, Mechanism}, - commands::*, - error::Error, - extension::{ClientId, Extension, MailBodyParameter, MailParameter, ServerInfo}, - response::{parse_response, Response}, +use crate::{ + address::Envelope, + transport::smtp::{ + authentication::{Credentials, Mechanism}, + commands::*, + error::Error, + extension::{ClientId, Extension, MailBodyParameter, MailParameter, ServerInfo}, + response::{parse_response, Response}, + }, }; #[cfg(feature = "tracing")] diff --git a/src/transport/smtp/client/tls.rs b/src/transport/smtp/client/tls.rs index 4885427..54f6b0d 100644 --- a/src/transport/smtp/client/tls.rs +++ b/src/transport/smtp/client/tls.rs @@ -65,7 +65,7 @@ impl TlsParametersBuilder { /// Add a custom root certificate /// /// Can be used to safely connect to a server using a self signed certificate, for example. - pub fn add_root_certificate(&mut self, cert: Certificate) -> &mut Self { + pub fn add_root_certificate(mut self, cert: Certificate) -> Self { self.root_certs.push(cert); self } @@ -85,10 +85,7 @@ impl TlsParametersBuilder { /// Hostname verification can only be disabled with the `native-tls` TLS backend. #[cfg(feature = "native-tls")] #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))] - pub fn dangerous_accept_invalid_hostnames( - &mut self, - accept_invalid_hostnames: bool, - ) -> &mut Self { + pub fn dangerous_accept_invalid_hostnames(mut self, accept_invalid_hostnames: bool) -> Self { self.accept_invalid_hostnames = accept_invalid_hostnames; self } @@ -109,7 +106,7 @@ impl TlsParametersBuilder { /// /// This method should only be used as a last resort, as it introduces /// significant vulnerabilities to man-in-the-middle attacks. - pub fn dangerous_accept_invalid_certs(&mut self, accept_invalid_certs: bool) -> &mut Self { + pub fn dangerous_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> Self { self.accept_invalid_certs = accept_invalid_certs; self } diff --git a/src/transport/smtp/mod.rs b/src/transport/smtp/mod.rs index 61e47d5..aa4dff8 100644 --- a/src/transport/smtp/mod.rs +++ b/src/transport/smtp/mod.rs @@ -43,8 +43,7 @@ //! .body(String::from("Be happy!"))?; //! //! // Create TLS transport on port 465 -//! let sender = SmtpTransport::relay("smtp.example.com") -//! .expect("relay valid") +//! let sender = SmtpTransport::relay("smtp.example.com")? //! .build(); //! // Send the email via remote relay //! let result = sender.send(&email); @@ -52,107 +51,70 @@ //! # Ok(()) //! # } //! ``` - -//! #### Complete example //! -//! ```todo -//! # #[cfg(feature = "smtp-transport")] -//! # { -//! use lettre::transport::smtp::authentication::{Credentials, Mechanism}; -//! use lettre::{Email, Envelope, Transport, SmtpClient}; -//! use lettre::transport::smtp::extension::ClientId; +//! #### Authentication //! -//! let email_1 = Email::new( -//! Envelope::new( -//! Some(EmailAddress::new("user@localhost".to_string())?), -//! vec![EmailAddress::new("root@localhost".to_string())?], -//! )?, -//! "id1".to_string(), -//! "Hello world".to_string().into_bytes(), -//! ); +//! Example with authentication and connection pool: //! -//! let email_2 = Email::new( -//! Envelope::new( -//! Some(EmailAddress::new("user@localhost".to_string())?), -//! vec![EmailAddress::new("root@localhost".to_string())?], -//! )?, -//! "id2".to_string(), -//! "Hello world a second time".to_string().into_bytes(), -//! ); +//! ```rust,no_run +//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))] +//! # fn test() -> Result<(), Box> { +//! use lettre::{Message, Transport, SmtpTransport, transport::smtp::{PoolConfig, authentication::{Credentials, Mechanism}}}; //! -//! // Connect to a remote server on a custom port -//! let mut mailer = SmtpClient::new_simple("server.tld")? -//! // Set the name sent during EHLO/HELO, default is `localhost` -//! .hello_name(ClientId::Domain("my.hostname.tld".to_string())) -//! // Add credentials for authentication -//! .credentials(Credentials::new("username".to_string(), "password".to_string())) -//! // Enable SMTPUTF8 if the server supports it -//! .smtp_utf8(true) -//! // Configure expected authentication mechanism -//! .authentication_mechanism(Mechanism::Plain) -//! // Enable connection reuse -//! .connection_reuse(ConnectionReuseParameters::ReuseUnlimited).transport(); +//! let email = Message::builder() +//! .from("NoBody ".parse()?) +//! .reply_to("Yuin ".parse()?) +//! .to("Hei ".parse()?) +//! .subject("Happy new year") +//! .body(String::from("Be happy!"))?; //! -//! let result_1 = mailer.send(&email_1); -//! assert!(result_1.is_ok()); +//! // Create TLS transport on port 587 with STARTTLS +//! let sender = SmtpTransport::starttls_relay("smtp.example.com")? +//! // Add credentials for authentication +//! .credentials(Credentials::new("username".to_string(), "password".to_string())) +//! // Configure expected authentication mechanism +//! .authentication(vec![Mechanism::Plain]) +//! // Connection pool settings +//! .pool_config( PoolConfig::new().max_size(20)) +//! .build(); //! -//! // The second email will use the same connection -//! let result_2 = mailer.send(&email_2); -//! assert!(result_2.is_ok()); -//! -//! // Explicitly close the SMTP transaction as we enabled connection reuse -//! mailer.close(); +//! // Send the email via remote relay +//! let result = sender.send(&email); +//! assert!(result.is_ok()); +//! # Ok(()) //! # } //! ``` //! //! You can specify custom TLS settings: //! -//! ```todo -//! # #[cfg(feature = "native-tls")] -//! # { -//! use lettre::{ -//! ClientSecurity, ClientTlsParameters, EmailAddress, Envelope, -//! Email, SmtpClient, Transport, -//! }; -//! use lettre::transport::smtp::authentication::{Credentials, Mechanism}; -//! use lettre::transport::smtp::ConnectionReuseParameters; -//! use native_tls::{Protocol, TlsConnector}; +//! ```rust,no_run +//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))] +//! # fn test() -> Result<(), Box> { +//! use lettre::{Message, Transport, SmtpTransport, transport::smtp::client::{TlsParameters, Tls}}; //! -//! let email = Email::new( -//! Envelope::new( -//! Some(EmailAddress::new("user@localhost".to_string())?), -//! vec![EmailAddress::new("root@localhost".to_string())?], -//! )?, -//! "message_id".to_string(), -//! "Hello world".to_string().into_bytes(), -//! ); +//! let email = Message::builder() +//! .from("NoBody ".parse()?) +//! .reply_to("Yuin ".parse()?) +//! .to("Hei ".parse()?) +//! .subject("Happy new year") +//! .body(String::from("Be happy!"))?; //! -//! let mut tls_builder = TlsConnector::builder(); -//! tls_builder.min_protocol_version(Some(Protocol::Tlsv10)); -//! let tls_parameters = -//! ClientTlsParameters::new( -//! "smtp.example.com".to_string(), -//! tls_builder.build()? -//! ); +//! // Custom TLS configuration +//! let tls = TlsParameters::builder("smtp.example.com".to_string()) +//! .dangerous_accept_invalid_certs(true).build()?; //! -//! let mut mailer = SmtpClient::new( -//! ("smtp.example.com", 465), ClientSecurity::Wrapper(tls_parameters) -//! )? -//! .authentication_mechanism(Mechanism::Login) -//! .credentials(Credentials::new( -//! "example_username".to_string(), "example_password".to_string() -//! )) -//! .connection_reuse(ConnectionReuseParameters::ReuseUnlimited) -//! .transport(); +//! // Create TLS transport on port 465 +//! let sender = SmtpTransport::relay("smtp.example.com")? +//! // Custom TLS configuration +//! .tls(Tls::Required(tls)) +//! .build(); //! -//! let result = mailer.send(&email); -//! -//! assert!(result.is_ok()); -//! -//! mailer.close(); +//! // Send the email via remote relay +//! let result = sender.send(&email); +//! assert!(result.is_ok()); +//! # Ok(()) //! # } //! ``` -//! #[cfg(feature = "async-std1")] pub use self::async_transport::AsyncStd1Connector; diff --git a/src/transport/smtp/pool.rs b/src/transport/smtp/pool.rs index 92fae3a..18e2e1a 100644 --- a/src/transport/smtp/pool.rs +++ b/src/transport/smtp/pool.rs @@ -16,6 +16,11 @@ pub struct PoolConfig { } impl PoolConfig { + /// Create a new pool configuration with default values + pub fn new() -> Self { + Self::default() + } + /// Minimum number of idle connections /// /// Defaults to `0` diff --git a/src/transport/smtp/transport.rs b/src/transport/smtp/transport.rs index 912c330..1ea0b5d 100644 --- a/src/transport/smtp/transport.rs +++ b/src/transport/smtp/transport.rs @@ -8,8 +8,7 @@ use super::PoolConfig; use super::{ClientId, Credentials, Error, Mechanism, Response, SmtpConnection, SmtpInfo}; #[cfg(any(feature = "native-tls", feature = "rustls-tls"))] use super::{Tls, TlsParameters, SUBMISSIONS_PORT, SUBMISSION_PORT}; -use crate::address::Envelope; -use crate::Transport; +use crate::{address::Envelope, Transport}; #[allow(missing_debug_implementations)] #[derive(Clone)] diff --git a/src/transport/stub/mod.rs b/src/transport/stub/mod.rs index 6e66f59..0b27f89 100644 --- a/src/transport/stub/mod.rs +++ b/src/transport/stub/mod.rs @@ -9,8 +9,7 @@ //! ```rust //! # #[cfg(feature = "builder")] //! # { -//! use lettre::{Message, Transport}; -//! use lettre::transport::stub::StubTransport; +//! use lettre::{transport::stub::StubTransport, Message, Transport}; //! //! # use std::error::Error; //! # fn main() -> Result<(), Box> { @@ -29,12 +28,11 @@ //! # } //! ``` -use crate::address::Envelope; #[cfg(feature = "async-std1")] use crate::AsyncStd1Transport; #[cfg(feature = "tokio02")] use crate::Tokio02Transport; -use crate::Transport; +use crate::{address::Envelope, Transport}; #[cfg(any(feature = "async-std1", feature = "tokio02"))] use async_trait::async_trait; use std::{error::Error as StdError, fmt}; diff --git a/tests/transport_smtp_pool.rs b/tests/transport_smtp_pool.rs index 18154b5..0830a9a 100644 --- a/tests/transport_smtp_pool.rs +++ b/tests/transport_smtp_pool.rs @@ -1,7 +1,6 @@ #[cfg(all(test, feature = "smtp-transport", feature = "r2d2"))] mod test { - use lettre::address::Envelope; - use lettre::{SmtpTransport, Transport}; + use lettre::{address::Envelope, SmtpTransport, Transport}; use std::{sync::mpsc, thread};