docs: improve SMTP transport from_url (#1032)

This commit is contained in:
Paolo Barbolini
2025-02-02 13:38:03 +01:00
committed by GitHub
parent 55c7f57f25
commit 32e066464a
2 changed files with 137 additions and 107 deletions

View File

@@ -191,54 +191,72 @@ where
/// Creates a `AsyncSmtpTransportBuilder` from a connection URL /// Creates a `AsyncSmtpTransportBuilder` from a connection URL
/// ///
/// The protocol, credentials, host and port can be provided in a single URL. /// The protocol, credentials, host, port and EHLO name can be provided
/// Use the scheme `smtp` for an unencrypted relay (optionally in combination with the /// in a single URL. This may be simpler than having to configure SMTP
/// `tls` parameter to allow/require STARTTLS) or `smtps` for SMTP over TLS. /// through multiple configuration parameters and then having to pass
/// The path section of the url can be used to set an alternative name for /// those options to lettre.
/// the HELO / EHLO command.
/// For example `smtps://username:password@smtp.example.com/client.example.com:465`
/// will set the HELO / EHLO name `client.example.com`.
/// ///
/// <table> /// The URL is created in the following way:
/// <thead> /// `scheme://user:pass@hostname:port/ehlo-name?tls=TLS`.
/// <tr> ///
/// <th>scheme</th> /// `user` (Username) and `pass` (Password) are optional in case the
/// <th>tls parameter</th> /// SMTP relay doesn't require authentication. When `port` is not
/// <th>example</th> /// configured it is automatically determined based on the `scheme`.
/// <th>remarks</th> /// `ehlo-name` optionally overwrites the hostname sent for the EHLO
/// </tr> /// command. `TLS` controls whether STARTTLS is simply enabled
/// </thead> /// (`opportunistic` - not enough to prevent man-in-the-middle attacks)
/// <tbody> /// or `required` (require the server to upgrade the connection to
/// <tr> /// STARTTLS, otherwise fail on suspicion of main-in-the-middle attempt).
/// <td>smtps</td> ///
/// <td>-</td> /// Use the following table to construct your SMTP url:
/// <td>smtps://smtp.example.com</td> ///
/// <td>SMTP over TLS, recommended method</td> /// | scheme | `tls` query parameter | example | default port | remarks |
/// </tr> /// | ------- | --------------------- | -------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
/// <tr> /// | `smtps` | unset | `smtps://user:pass@hostname:port` | 465 | SMTP over TLS, recommended method |
/// <td>smtp</td> /// | `smtp` | `required` | `smtp://user:pass@hostname:port?tls=required` | 587 | SMTP with STARTTLS required, when SMTP over TLS is not available |
/// <td>required</td> /// | `smtp` | `opportunistic` | `smtp://user:pass@hostname:port?tls=opportunistic` | 587 | SMTP with optionally STARTTLS when supported by the server. Not suitable for production use: vulnerable to a man-in-the-middle attack |
/// <td>smtp://smtp.example.com?tls=required</td> /// | `smtp` | unset | `smtp://user:pass@hostname:port` | 587 | Always unencrypted SMTP. Not suitable for production use: sends all data unencrypted |
/// <td>SMTP with STARTTLS required, when SMTP over TLS is not available</td> ///
/// </tr> /// IMPORTANT: some parameters like `user` and `pass` cannot simply
/// <tr> /// be concatenated to construct the final URL because special characters
/// <td>smtp</td> /// contained within the parameter may confuse the URL decoder.
/// <td>opportunistic</td> /// Manually URL encode the parameters before concatenating them or use
/// <td>smtp://smtp.example.com?tls=opportunistic</td> /// a proper URL encoder, like the following cargo script:
/// <td> ///
/// SMTP with optionally STARTTLS when supported by the server. /// ```rust
/// Caution: this method is vulnerable to a man-in-the-middle attack. /// # let _ = r#"
/// Not recommended for production use. /// #!/usr/bin/env cargo
/// </td> ///
/// </tr> /// //! ```cargo
/// <tr> /// //! [dependencies]
/// <td>smtp</td> /// //! url = "2"
/// <td>-</td> /// //! ```
/// <td>smtp://smtp.example.com</td> /// # "#;
/// <td>Unencrypted SMTP, not recommended for production use.</td> ///
/// </tr> /// use url::Url;
/// </tbody> ///
/// </table> /// fn main() {
/// // don't touch this line
/// let mut url = Url::parse("foo://bar").unwrap();
///
/// // configure the scheme (`smtp` or `smtps`) here.
/// url.set_scheme("smtps").unwrap();
/// // configure the username and password.
/// // remove the following two lines if unauthenticated.
/// url.set_username("username").unwrap();
/// url.set_password(Some("password")).unwrap();
/// // configure the hostname
/// url.set_host(Some("smtp.example.com")).unwrap();
/// // configure the port - only necessary if using a non-default port
/// url.set_port(Some(465)).unwrap();
/// // configure the EHLO name
/// url.set_path("ehlo-name");
///
/// println!("{url}");
/// }
/// ```
///
/// The connection URL can then be used in the following way:
/// ///
/// ```rust,no_run /// ```rust,no_run
/// use lettre::{ /// use lettre::{
@@ -262,15 +280,11 @@ where
/// let mailer: AsyncSmtpTransport<Tokio1Executor> = /// let mailer: AsyncSmtpTransport<Tokio1Executor> =
/// AsyncSmtpTransport::<Tokio1Executor>::from_url( /// AsyncSmtpTransport::<Tokio1Executor>::from_url(
/// "smtps://username:password@smtp.example.com:465", /// "smtps://username:password@smtp.example.com:465",
/// ) /// )?
/// .unwrap()
/// .build(); /// .build();
/// ///
/// // Send the email /// // Send the email
/// match mailer.send(email).await { /// mailer.send(email).await?;
/// Ok(_) => println!("Email sent successfully!"),
/// Err(e) => panic!("Could not send email: {e:?}"),
/// }
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```

View File

@@ -139,54 +139,72 @@ impl SmtpTransport {
/// Creates a `SmtpTransportBuilder` from a connection URL /// Creates a `SmtpTransportBuilder` from a connection URL
/// ///
/// The protocol, credentials, host and port can be provided in a single URL. /// The protocol, credentials, host, port and EHLO name can be provided
/// Use the scheme `smtp` for an unencrypted relay (optionally in combination with the /// in a single URL. This may be simpler than having to configure SMTP
/// `tls` parameter to allow/require STARTTLS) or `smtps` for SMTP over TLS. /// through multiple configuration parameters and then having to pass
/// The path section of the url can be used to set an alternative name for /// those options to lettre.
/// the HELO / EHLO command.
/// For example `smtps://username:password@smtp.example.com/client.example.com:465`
/// will set the HELO / EHLO name `client.example.com`.
/// ///
/// <table> /// The URL is created in the following way:
/// <thead> /// `scheme://user:pass@hostname:port/ehlo-name?tls=TLS`.
/// <tr> ///
/// <th>scheme</th> /// `user` (Username) and `pass` (Password) are optional in case the
/// <th>tls parameter</th> /// SMTP relay doesn't require authentication. When `port` is not
/// <th>example</th> /// configured it is automatically determined based on the `scheme`.
/// <th>remarks</th> /// `ehlo-name` optionally overwrites the hostname sent for the EHLO
/// </tr> /// command. `TLS` controls whether STARTTLS is simply enabled
/// </thead> /// (`opportunistic` - not enough to prevent man-in-the-middle attacks)
/// <tbody> /// or `required` (require the server to upgrade the connection to
/// <tr> /// STARTTLS, otherwise fail on suspicion of main-in-the-middle attempt).
/// <td>smtps</td> ///
/// <td>-</td> /// Use the following table to construct your SMTP url:
/// <td>smtps://smtp.example.com</td> ///
/// <td>SMTP over TLS, recommended method</td> /// | scheme | `tls` query parameter | example | default port | remarks |
/// </tr> /// | ------- | --------------------- | -------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
/// <tr> /// | `smtps` | unset | `smtps://user:pass@hostname:port` | 465 | SMTP over TLS, recommended method |
/// <td>smtp</td> /// | `smtp` | `required` | `smtp://user:pass@hostname:port?tls=required` | 587 | SMTP with STARTTLS required, when SMTP over TLS is not available |
/// <td>required</td> /// | `smtp` | `opportunistic` | `smtp://user:pass@hostname:port?tls=opportunistic` | 587 | SMTP with optionally STARTTLS when supported by the server. Not suitable for production use: vulnerable to a man-in-the-middle attack |
/// <td>smtp://smtp.example.com?tls=required</td> /// | `smtp` | unset | `smtp://user:pass@hostname:port` | 587 | Always unencrypted SMTP. Not suitable for production use: sends all data unencrypted |
/// <td>SMTP with STARTTLS required, when SMTP over TLS is not available</td> ///
/// </tr> /// IMPORTANT: some parameters like `user` and `pass` cannot simply
/// <tr> /// be concatenated to construct the final URL because special characters
/// <td>smtp</td> /// contained within the parameter may confuse the URL decoder.
/// <td>opportunistic</td> /// Manually URL encode the parameters before concatenating them or use
/// <td>smtp://smtp.example.com?tls=opportunistic</td> /// a proper URL encoder, like the following cargo script:
/// <td> ///
/// SMTP with optionally STARTTLS when supported by the server. /// ```rust
/// Caution: this method is vulnerable to a man-in-the-middle attack. /// # let _ = r#"
/// Not recommended for production use. /// #!/usr/bin/env cargo
/// </td> ///
/// </tr> /// //! ```cargo
/// <tr> /// //! [dependencies]
/// <td>smtp</td> /// //! url = "2"
/// <td>-</td> /// //! ```
/// <td>smtp://smtp.example.com</td> /// # "#;
/// <td>Unencrypted SMTP, not recommended for production use.</td> ///
/// </tr> /// use url::Url;
/// </tbody> ///
/// </table> /// fn main() {
/// // don't touch this line
/// let mut url = Url::parse("foo://bar").unwrap();
///
/// // configure the scheme (`smtp` or `smtps`) here.
/// url.set_scheme("smtps").unwrap();
/// // configure the username and password.
/// // remove the following two lines if unauthenticated.
/// url.set_username("username").unwrap();
/// url.set_password(Some("password")).unwrap();
/// // configure the hostname
/// url.set_host(Some("smtp.example.com")).unwrap();
/// // configure the port - only necessary if using a non-default port
/// url.set_port(Some(465)).unwrap();
/// // configure the EHLO name
/// url.set_path("ehlo-name");
///
/// println!("{url}");
/// }
/// ```
///
/// The connection URL can then be used in the following way:
/// ///
/// ```rust,no_run /// ```rust,no_run
/// use lettre::{ /// use lettre::{
@@ -194,6 +212,7 @@ impl SmtpTransport {
/// SmtpTransport, Transport, /// SmtpTransport, Transport,
/// }; /// };
/// ///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let email = Message::builder() /// let email = Message::builder()
/// .from("NoBody <nobody@domain.tld>".parse().unwrap()) /// .from("NoBody <nobody@domain.tld>".parse().unwrap())
/// .reply_to("Yuin <yuin@domain.tld>".parse().unwrap()) /// .reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
@@ -204,15 +223,12 @@ impl SmtpTransport {
/// .unwrap(); /// .unwrap();
/// ///
/// // Open a remote connection to example /// // Open a remote connection to example
/// let mailer = SmtpTransport::from_url("smtps://username:password@smtp.example.com:465") /// let mailer = SmtpTransport::from_url("smtps://username:password@smtp.example.com")?.build();
/// .unwrap()
/// .build();
/// ///
/// // Send the email /// // Send the email
/// match mailer.send(&email) { /// mailer.send(&email)?;
/// Ok(_) => println!("Email sent successfully!"), /// # Ok(())
/// Err(e) => panic!("Could not send email: {e:?}"), /// # }
/// }
/// ``` /// ```
#[cfg(any(feature = "native-tls", feature = "rustls-tls", feature = "boring-tls"))] #[cfg(any(feature = "native-tls", feature = "rustls-tls", feature = "boring-tls"))]
#[cfg_attr( #[cfg_attr(