Most web applications these days need to interact with email in some way or another, so good language support is crucial. Rust certainly has basic support for working with emails, but I wouldn’t say it can cover all use cases just yet. The ecosystem is quite small and doesn’t currently have good support for async/await.

That said, it’s a useful exercise to mess around with the solutions that are available and see how they work. In this tutorial, we’ll show you how to send emails and connect to IMAP servers in Rust.

Creating emails with lettre

The most popular crate for sending emails is lettre. As of now, the latest stable release of letter (0.9) doesn’t include an async API, but there’s also an alpha release for version 0.10, which supports async via tokioandasync-std.

Let’s first take a look at the current version without async then port the code to an async implementation using the alpha release.

Add the following to Cargo.toml to get started.

[dependencies]
lettre = "0.9"
lettre_email = "0.9"

With version 0.9, we need to use lettre_email to build emails then lettre to send them, so we need specify both.

Start by creating a basic email.

use lettre_email::EmailBuilder;

fn main() {
    let email = EmailBuilder::new()
        .to("hello@example.com")
        .from("me@hello.com")
        .subject("Example subject")
        .text("Hello, world!")
        .build()
        .unwrap();
}

This uses the builder pattern to create the data structure that represents an email. If we want to specify a name and an address, we can use a tuple, like this:

let email = EmailBuilder::new()
    .to(("hello@example.com", "Alice Smith"))
    .from(("me@hello.com", "Bob Smith"))
    .subject("Example subject")
    .text("Hello, world!")
    .build()
    .unwrap();

Adding a HTML body is as simple as calling the corresponding method on the builder.

let email = EmailBuilder::new()
    .to("hello@example.com")
    .from("me@hello.com")
    .subject("Example subject")
    .html("<h1>Hello, world!</h1>")
    .build()
    .unwrap();

Let’s say we want to send attachments with our emails. Here’s how you would attach a local file to an email:

use lettre_email::mime;
use lettre_email::EmailBuilder;
use std::path::Path;

fn main() {
    let email = EmailBuilder::new()
        .to("hello@example.com")
        .from("me@hello.com")
        .subject("Example subject")
        .html("<h1>Hello, world!</h1>")
        .attachment_from_file(
            &Path::new("path/to/file.pdf"), // Path to file on disk
            Some("Cookie-recipe.pdf"),      // Filename to use in the email
            &mime::APPLICATION_PDF,
        )
        .unwrap()
        .build()
        .unwrap();
}

Alternatively, we can use the attachment(...) builder method to send a vector of bytes directly from memory instead of a file on disk.

There are a few more builder methods for things I haven’t mentioned, so if you want to do something else with the email, take a look at the docs for lettre_email::EmailBuilder.

#rust #programming #developer

How to Send Emails and Connect to IMAP Servers in Rust
6.10 GEEK