Module smtp

Source
Available on crate feature smtp-transport only.
Expand description

The SMTP transport sends emails using the SMTP protocol.

This SMTP client follows RFC 5321, and is designed to efficiently send emails from an application to a relay email server, as it relies as much as possible on the relay server for sanity and RFC compliance checks.

It implements the following extensions:

§SMTP Transport

This transport uses the SMTP protocol to send emails over the network (locally or remotely).

It is designed to be:

  • Secured: connections are encrypted by default
  • Modern: unicode support for email contents and sender/recipient addresses when compatible
  • Fast: supports connection reuse and pooling

This client is designed to send emails to a relay server, and should not be used to send emails directly to the destination server.

The relay server can be the local email server, a specific host or a third-party service.

§Simple example with authentication

A good starting point for sending emails via SMTP relay is to do the following:

use lettre::{
    message::header::ContentType,
    transport::smtp::authentication::{Credentials, Mechanism},
    Message, SmtpTransport, Transport,
};

let email = Message::builder()
    .from("NoBody <nobody@domain.tld>".parse()?)
    .reply_to("Yuin <yuin@domain.tld>".parse()?)
    .to("Hei <hei@domain.tld>".parse()?)
    .subject("Happy new year")
    .header(ContentType::TEXT_PLAIN)
    .body(String::from("Be happy!"))?;

// Create the SMTPS transport
let sender = SmtpTransport::relay("smtp.example.com")?
    // Add credentials for authentication
    .credentials(Credentials::new(
        "username".to_owned(),
        "password".to_owned(),
    ))
    // Optionally configure expected authentication mechanism
    .authentication(vec![Mechanism::Plain])
    .build();

// Send the email via remote relay
sender.send(&email)?;
§Shortening configuration

It can be very repetitive to ask the user for every SMTP connection parameter. In some cases this can be simplified by using a connection URI instead.

For more information take a look at SmtpTransport::from_url or AsyncSmtpTransport::from_url.

use lettre::{
    message::header::ContentType,
    transport::smtp::authentication::{Credentials, Mechanism},
    Message, SmtpTransport, Transport,
};

let email = Message::builder()
    .from("NoBody <nobody@domain.tld>".parse()?)
    .reply_to("Yuin <yuin@domain.tld>".parse()?)
    .to("Hei <hei@domain.tld>".parse()?)
    .subject("Happy new year")
    .header(ContentType::TEXT_PLAIN)
    .body(String::from("Be happy!"))?;

// Create the SMTPS transport
let sender = SmtpTransport::from_url("smtps://username:password@smtp.example.com")?.build();

// Send the email via remote relay
sender.send(&email)?;
§Advanced configuration with custom TLS settings
use std::fs;

use lettre::{
    message::header::ContentType,
    transport::smtp::client::{Certificate, Tls, TlsParameters},
    Message, SmtpTransport, Transport,
};

let email = Message::builder()
    .from("NoBody <nobody@domain.tld>".parse()?)
    .reply_to("Yuin <yuin@domain.tld>".parse()?)
    .to("Hei <hei@domain.tld>".parse()?)
    .subject("Happy new year")
    .header(ContentType::TEXT_PLAIN)
    .body(String::from("Be happy!"))?;

// Custom TLS configuration - Use a self signed certificate
let cert = fs::read("self-signed.crt")?;
let cert = Certificate::from_pem(&cert)?;
let tls = TlsParameters::builder(/* TLS SNI value */ "smtp.example.com".to_owned())
    .add_root_certificate(cert)
    .build()?;

// Create the SMTPS transport
let sender = SmtpTransport::relay("smtp.example.com")?
    .tls(Tls::Wrapper(tls))
    .build();

// Send the email via remote relay
sender.send(&email)?;
§Connection pooling

SmtpTransport and AsyncSmtpTransport store connections in a connection pool by default. This avoids connecting and disconnecting from the relay server for every message the application tries to send. For the connection pool to work the instance of the transport must be reused. In a webserver context it may go about this:

use lettre::{
    message::header::ContentType,
    transport::smtp::{authentication::Credentials, PoolConfig},
    Message, SmtpTransport, Transport,
};

/// The global application state
#[derive(Debug)]
struct AppState {
    smtp: SmtpTransport,
    // ... other global application parameters
}

impl AppState {
    pub fn new(smtp_url: &str) -> Result<Self> {
        let smtp = SmtpTransport::from_url(smtp_url)?.build();
        Ok(Self { smtp })
    }
}

fn handle_request(app_state: &AppState) -> Result<String> {
    let email = Message::builder()
        .from("NoBody <nobody@domain.tld>".parse()?)
        .reply_to("Yuin <yuin@domain.tld>".parse()?)
        .to("Hei <hei@domain.tld>".parse()?)
        .subject("Happy new year")
        .header(ContentType::TEXT_PLAIN)
        .body(String::from("Be happy!"))?;

    // Send the email via remote relay
    app_state.smtp.send(&email)?;

    Ok("The email has successfully been sent!".to_owned())
}

Modules§

authentication
Provides limited SASL authentication mechanisms
client
SMTP client
commands
SMTP commands
extension
ESMTP features
response
SMTP response, containing a mandatory return code and an optional text message

Structs§

AsyncSmtpTransport
Asynchronously sends emails using the SMTP protocol
AsyncSmtpTransportBuilder
Contains client configuration. Instances of this struct can be created using functions of AsyncSmtpTransport.
Error
The Errors that may occur when sending an email over SMTP
PoolConfig
Configuration for a connection pool
SmtpTransport
Synchronously send emails using the SMTP protocol
SmtpTransportBuilder
Contains client configuration. Instances of this struct can be created using functions of SmtpTransport.

Constants§

SMTP_PORT
Default smtp port
SUBMISSIONS_PORT
Default submission over TLS port
SUBMISSION_PORT
Default submission port