Site icon Mailtrap

How to Send Emails in Rust: SMTP and email API Methods Explained

This article explores the practical steps and considerations for utilizing Rust to manage email sending, from setting up SMTP to leveraging APIs for sending emails.

Ready to deliver your emails?
Try Mailtrap for Free

How to send emails using Rust and SMTP

The lettre crate is among the most straightforward methods to send emails from Rust via SMTP. The following sections cover different scenarios using lettre crate and they include:

Feel free to copy-paste the scripts below minding your credentials as well as recipient and sender addresses, and SMTP endpoints. Also, note that these are designed for Mailtrap SMTP users. 

Later in the article, we cover the API method. And here, we’d like to offer some pointers for Mailtrap users. 

Send emails using lettre crate

  1. Add ‘lettre’ to the ‘Cargo.toml’ file:
[dependencies]
lettre = "0.10"
lettre_email = "0.9"

Note: the lettre and lettre_email versions might be updated when you’re reading this article. Click here for the latest versions. 

  1. Write the email-sending script:
use lettre::{Message, SmtpTransport, Transport};
use lettre::smtp::authentication::Credentials;

fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    // Define the email
    let email = Message::builder()        .from("Your Name <your.email@example.com>".parse().unwrap())        .reply_to("your.email@example.com".parse().unwrap())        .to("Recipient Name <recipient.email@example.com>".parse().unwrap())        .subject("Rust Email")        .body(String::from("Hello, this is a test email from Rust!"))        .unwrap();
    // Set up the SMTP client    let creds = Credentials::new("Mailtrap_smtp_username".to_string(), "Mailtrap_smtp_password".to_string());
    // Open a remote connection to gmail    let mailer = SmtpTransport::relay("your_mailtrap_Host.io")?        .credentials(creds)        .build();
    // Send the email    match mailer.send(&email) {        Ok(_) => println!("Email sent successfully!"),        Err(e) => eprintln!("Could not send email: {:?}", e),    }
    Ok(())
}

Important: Replace all the variables with your actual credentials, relay endpoints, and corresponding email addresses.  

  1. TLS handling 

If you’re a Mailtrap user, TLS handling is required. lettre supports ‘None’, ‘Starttls’ and ‘Required’ TLS settings. The TLS settings are specified in the SmtpTransport block, and here’s what the TLS-enabled script might look like. 

use lettre::{Message, SmtpTransport, Transport}; 
use lettre::transport::smtp::{authentication::{Credentials}}; 

fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    // Build an email message using the builder pattern
    let email = Message::builder()
        // Set the sender's name and email address
        .from("Your Name <your address@gmail.com>".parse().unwrap()) 
        // Set the recipient's name and email address
        .to("Recipient Name <receiver address@gmail.com>".parse().unwrap()) 
        // Set the subject of the email
        .subject("Rust Email") 
        // Set the body content of the email
        .body(String::from("Hello World, this is a test email from Rust!")) 
        .unwrap();

    // Create SMTP client credentials using username and password
    let creds = Credentials::new("mailtrap_username".to_string(), "mailtrap_password".to_string()); 

    // Open a secure connection to the SMTP server using STARTTLS
    let mailer = SmtpTransport::starttls_relay("your_mailtrap_host.io")
        .unwrap()  // Unwrap the Result, panics in case of error
        .credentials(creds)  // Provide the credentials to the transport
        .build();  // Construct the transport

    // Attempt to send the email via the SMTP transport
    match mailer.send(&email) { 
        // If email was sent successfully, print confirmation message
        Ok(_) => println!("Email sent successfully!"), 
        // If there was an error sending the email, print the error
        Err(e) => eprintln!("Could not send email: {:?}", e), 
    }

    Ok(())
}

Note: your_mailtrap _host will vary depending on your purpose. For example, if you’re using Mailtrap, then the Host is live.smtp.mailtrap.io 

  1. Run your application

Use the cargo run command to run your application. Assuming the setup is correct, rust will send the email to specified recipients. 

How to send HTML email with Rust?

To send an HTML email, we’ll reuse and modify the lettre script with STARTTLS.

Simply, you need to set the content type of the email body to text/html. This can be done by using the message::SinglePart and message::MultiPart modules to construct the email body properly.

Here’s the modified code:

use lettre::{transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport};
use lettre::message::{Mailbox, MultiPart, SinglePart};

fn main() ->  std::result::Result<(), Box<dyn std::error::Error>> {

    // Define the HTML content
    let html_content = r#"
        <html>
            <body>
                <h1>Hello!</h1>
                <p>This is a <strong>test email</strong> from Rust!</p>
            </body>
        </html>
    "#;

    let from_email = "Your Name <sender@example.com>".parse::<Mailbox>().unwrap();
    let to_email = "Recipient Name <recipient@example.com>".parse::<Mailbox>().unwrap();

    // Define the email with HTML part
    let email = Message::builder()
        .from(from_email)
        .to(to_email)
        .subject("Rust Email")
        .multipart(
            MultiPart::alternative().singlepart(SinglePart::html(html_content.to_string())),
        )
        .unwrap();

    // Set up the SMTP client credentials
    let creds = Credentials::new("username".to_string(), "password".to_string());

    // Open a remote connection to the SMTP server with STARTTLS
    let mailer = SmtpTransport::starttls_relay("your_mailtrap_host.io")
        .unwrap()
        .credentials(creds)
        .build();

    // Send the email
    match mailer.send(&email) {
        Ok(_) => println!("Email sent successfully!"),
        Err(e) => eprintln!("Could not send email: {:?}", e),
    }

    Ok(())
}

Notes on code modifications:  

How to send an email with attachments in Rust?

Again, we’ll reuse and modify the script above to include attachments.

This code demonstrates how to send an email with attachments using the lettre crate in Rust and the Mailtrap SMTP server. 

use lettre::transport::smtp::authentication::Credentials;
use lettre::{Message, SmtpTransport, Transport};
use lettre::message::{Mailbox, MultiPart, SinglePart, Attachment, Body};
use std::fs;

fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {


    let image = fs::read("picture.png")?;
    let image_body = Body::new(image);

    let from_email = "Your Name <sender@example.com>".parse::<Mailbox>().unwrap();
    let to_email = "Recipient Name <recipient-email@example.com>".parse::<Mailbox>().unwrap();

    let email = Message::builder()
                    .from(from_email)
                    .to(to_email)
                    .subject("Hello")
                    .multipart(
                        MultiPart::mixed()
                            .multipart(
                                MultiPart::alternative()
                                    .singlepart(SinglePart::plain(String::from("Hello, world! :)")))
                                    .multipart(
                                        MultiPart::related()
                                            .singlepart(SinglePart::html(String::from(
                                                "<p><b>Hello</b>, <i>world</i>! <img src=cid:123></p>",
                                            )))
                                            .singlepart(
                                                Attachment::new_inline(String::from("123"))
                                                    .body(image_body, "image/png".parse().unwrap()),
                                            ),
                                    ),
                            )
                            .singlepart(Attachment::new(String::from("example.com")).body(
                                String::from("fn main() { println!(\"Hello, World!\") }"),
                                "text/plain".parse().unwrap(),
                            )),
                    )?;

    let creds = Credentials::new("username".to_string(), "password".to_string());
   
    // Open a remote connection to the SMTP server with STARTTLS
    let mailer = SmtpTransport::starttls_relay("your_mailtrap_hosting.io").unwrap()
        .credentials(creds)
        .build();

    // Send the email
    match mailer.send(&email) {
        Ok(_) => println!("Email sent successfully!"),
        Err(e) => eprintln!("Could not send email: {:?}", e),
    }

    Ok(())
}

Notes on code modifications:

When using the script, you need to replace the "picture.png", with the file path you’re using.

Sending email to multiple recipients using Rust

You can send to multiple recipients by chaining  .to(),.cc(), and.bcc()methods. Each recipient is added by parsing a string that contains the email address and optionally the name of the recipient. 

Check the updated sending script. 

// [dependencies]
// lettre="0.10"

use lettre::{transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport};
use lettre::message::{Mailbox, MultiPart, SinglePart};

fn main() ->  std::result::Result<(), Box<dyn std::error::Error>> {

    // Define the HTML content
    let html_content = r#"
        <html>
            <body>
                <h1>Hello!</h1>
                <p>This is a <strong>test email</strong> from Rust!</p>
            </body>
        </html>
    "#;

    let from_email = "Your Name <sender@example.com>".parse::<Mailbox>().unwrap();
    let to_email = "Recipient Name <receiver@example.com>".parse::<Mailbox>().unwrap();

    // Define the email with HTML part
    let email = Message::builder()
        .from(from_email)
        .to(to_email) 
        // You can also add CC and BCC recipients
        .cc("Recipient CC <recipient.cc@example.com>".parse::<Mailbox>().unwrap())
        .bcc("Recipient BCC <recipient.bcc@example.com>".parse::<Mailbox>().unwrap())
        .subject("Rust Email")
        .multipart(
            MultiPart::alternative().singlepart(SinglePart::html(html_content.to_string())),
        )
        .unwrap();

    // Set up the SMTP client credentials
    let creds = Credentials::new("username".to_string(), "password".to_string());

    // Open a remote connection to the SMTP server with STARTTLS
    let mailer = SmtpTransport::starttls_relay("your_mailtrap_hosting.io")
        .unwrap()
        .credentials(creds)
        .build();

    // Send the email
    match mailer.send(&email) {
        Ok(_) => println!("Email sent successfully!"),
        Err(e) => eprintln!("Could not send email: {:?}", e),
    }

    Ok(())
}

How to send emails using Rust and Mailtrap API?

To send emails using the Mailtrap Email API in Rust, use an HTTP client library to make a POST request to the API endpoint. 

The commonly used HTTP client library in Rust is reqwest, and I chose it because it’s among the easiest to implement.

Now, start by adding the necessary dependencies. Add reqwest and tokio to your Cargo.toml because reqwest is an async library:

[dependencies]
reqwest = { version = "0.11", features = ["json"] }
serde_json = "1.0"
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

Here’s an exemplary script to send emails with Rust and Mailtrap API. 

use reqwest;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let api_url = "https://send.api.mailtrap.io/api/send";
    let api_key = "your_api_key";
    let email_payload = json!({
        "from": {"email" : "your_verified_domain"},
        "to": [{"email": "receiver@example.com"}],
        "subject": "Test Email",
        "text": "This is a test email using Rust and Mailtrap API!",
    });

    let client = reqwest::Client::new();
    let response = client
        .post(api_url)
        .header("Content-Type", "application/json")
        .header("Api-Token", api_key)
        .body(email_payload.to_string()) // Serialize the JSON payload to a string
        .send()
        .await?;

    if response.status().is_success() {
        println!("Email sent successfully!");
    } else {
        println!("Failed to send email. Status: {:?}", response.status());

        // Print the response body for additional information
        let body = response.text().await?;
        println!("Response body: {}", body);
    }

    Ok(())
}

Notes on the Mailtrap API method:

Before running this code, ensure that you have the reqwest and tokio crates added to your Cargo.toml file with the appropriate versions and features enabled.

Send emails using sendmail crate

The sendmail crate sends emails by interfacing with the sendmail command available on many Unix-like systems. This means that the system where your Rust application is running must have a sendmail-compatible program installed and properly configured.

The quick tutorial below assumes you have a proper sendmail-compatible program installed and configured. Otherwise, the method won’t work. 

If you need a tutorial on setting up sendmail on Ubuntu, check the one in the link. 

  1. Add sendmail command to the Cargo.toml:
[dependencies]
sendmail = "2.0"
  1. Use the script below to send your email:
extern crate sendmail;
use sendmail::email;

fn main() {

    // Configure email body and header
    // Send the email
    match email::send(
        // From Address
        "sender@example.com",
        // To Address
        &["receiver@example.com"],
        // Subject
        "Subject - Hello World!",
        // Body
        "<html><body><h1>I am the body. Hello Wolrd!<br/><br/>And I accept html.</h1></body></html>"
    ) {
        Ok(_) => println!("Email sent successfully!"),
        Err(e) => eprintln!("Could not send email: {:?}", e),
    }
}

Keynotes on using the sendmail crate:

Trust Rust 

Rust’s versatility extends to email communication, providing developers with powerful tools to send emails effectively. Whether through SMTP or API integration, the language’s safety features and performance make it an excellent choice for managing email-related tasks in modern applications.

Exit mobile version