Email sending has become a common feature in modern applications since it is a fast, efficient, cost-effective communication method. As developers, we should have proper knowledge in implementing email-sending features in any language we work with to satisfy customer needs.
So, in this article, I will go over three ways to send emails using Rust to give you a better understanding.
Compared to other languages, email-sending options in Rust are limited. However, there are three main options for sending emails with Rust: SMTP, lettre and Amazon SES.
Let's go through the benefits and drawbacks followed by step-by-step tutorial for each option.
1. Using SMTP
Simple Mail Transfer Protocol (SMTP) is a well-known protocol for sending emails across networks. When you send an email using an email service provider like Gmail, an outgoing SMTP server collects and connects it with the receiving server. SMTP defines the guidelines on how these two servers communicate and receive emails.
Advantages of using SMTP
- Supports both incoming and outgoing email delivery.
- In case of a failure, it will provide the reason.
- Supports bulk emailing.
- Easy to get started and quick email delivery.
- Supports email tracking.
- Can have a dedicated server if needed.
Disadvantages of using SMTP
- Some firewalls can block the common SMTP port.
- The SMTP security issue is becoming worse.
- It is impossible to send binary files via SMTP without transforming them into text files.
- Its simplicity places a limit on how useful it can be.
- Slower than using an API service.
Tutorial: How to send emails with Rust and SMTP
Sending emails with Rust and SMTP is pretty straightforward. First, you need to update the cargo.toml
file with the dependencies. cargo.toml
file is the manifest file used by the Rust package manager.
1
2
3
[dependencies]
tokio = { version = "1", features = ["full"] }
lettre = { version = "0.10.0-beta.2", default-features = false, features = ["smtp-transport", "tokio1-rustls-tls", "hostname", "r2d2", "builder"] }
Then, update your main.rs
file with the below code to send emails.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use lettre::{
transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message,
Tokio1Executor,
};
#[tokio::main]
// Creating basic data structure for the email
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let smtp_credentials =
Credentials::new("smtp_username".to_string(), "smtp_password".to_string());
let mailer = AsyncSmtpTransport::<Tokio1Executor>::relay("smtp.email.com")?
.credentials(smtp_credentials)
.build();
let from = "Sender <sender@gmail.com>";
let to = "receiver <receiver@gmail.com>";
let subject = "Sending email with Rust";
let body = "<h1>This is my first email</h1>".to_string();
send_email_smtp(&mailer, from, to, subject, body).await
}
// Email sending function
async fn send_email_smtp(
mailer: &AsyncSmtpTransport<Tokio1Executor>,
from: &str,
to: &str,
subject: &str,
body: String,
) -> Result<(), Box<dyn std::error::Error>> {
let email = Message::builder()
.from(from.parse()?)
.to(to.parse()?)
.subject(subject)
.body(body.to_string())?;
mailer.send(email).await?;
Ok(())
}
2. Using lettre
lettre is a mailer library that can be used to send emails with Rust. It was introduced in July 2022 and supports all the Rust versions after Rust 1.56.0. lettre has more than 975K downloads and healthy daily use.
Advantages of using lettre
- Support Unicode.
- Async support.
- High security with encryption and authentication.
- Straightforward email builders.
- Internationalized email support
- Provide several email transport methods.
Disadvantages of using lettre
- Does not support email parsing.
- New library.
- Lack of community support.
Tutorial: How to send emails with Rust and lettre
As mentioned, using lettre is very simple. First, you have to update the cargo.toml
file with lettre dependency.
1
2
[dependencies]
lettre = "0.10"
Then, you can use the below code to send emails with your Rust application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
use lettre::transport::smtp::authentication::Credentials;
use lettre::{Message, SmtpTransport, Transport};
let email = Message::builder()
.from("Sender <sender@gmail.com>".parse().unwrap())
.to("Receiver <receiver@gmail.com>".parse().unwrap())
.subject("Sending email with Rust")
.body(String::from("This is my first email"))
.unwrap();
let creds = Credentials::new("smtp_username".to_string(), "smtp_password".to_string());
// Open a remote connection to gmail
let mailer = SmtpTransport::relay("smtp.gmail.com")
.unwrap()
.credentials(creds)
.build();
// Send the email
match mailer.send(&email) {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {:?}", e),
}
3. Using Amazon SES
Amazon Simple Email Service, or Amazon SES, is one of the most popular email services used in modern applications. Developers love to use it in their applications since it is highly scalable, flexible, and cost-effective. In addition, it ensures high security and eliminates most of the issues with traditional SMTP servers.
Advantages of using Amazon SES
- It is a cloud-based service.
- High security and scalability.
- Bulk email sending.
- Provides reputation and deliverability dashboards.
- Provide a mailbox simulator.
- Sender identity management.
Disadvantages of using Amazon SES
- Need an AWS account.
- Initial configuration can take time.
- Steam learning curve.
Tutorial: How to send emails with Rust and Amazon SES
Having an AWS account is a mandatory requirement to use Amazon SES. If you don't have an AWS account, you can easily create a new account by following the steps in this guideline.
After creating an account, you can start implementing email service on your Rust application. First, you need to update the cargo.toml
file with dependencies. Here, we are using rusoto_ses to create an SES client.
1
2
3
4
5
6
[dependencies]
tokio = { version = "1", features = ["full"] }
lettre = { version = "0.10.0-beta.2", default-features = false, features = ["builder"] }
rusoto_core = { version = "0.46", default-features = false, features = ["rustls"] }
rusoto_ses = { version = "0.46", default-features = false, features = ["rustls"] }
base64 = "0.13"
Then, you can use the below code to send emails with your Rust application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use lettre::Message;
use rusoto_ses::{RawMessage, SendRawEmailRequest, Ses, SesClient};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ses_client = SesClient::new(rusoto_core::Region::UsEast1);
let from = "Sender <sender@gmail.com>";
let to = "receiver <receiver@gmail.com>";
let subject = "Sending email with Rust";
let body = "<h1>This is my first email</h1>".to_string();
send_email_ses(&ses_client, from, to, subject, body).await
}
async fn send_email_ses(
ses_client: &SesClient,
from: &str,
to: &str,
subject: &str,
body: String,
) -> Result<(), Box<dyn std::error::Error>> {
let email = Message::builder()
.from(from.parse()?)
.to(to.parse()?)
.subject(subject)
.body(body.to_string())?;
let raw_email = email.formatted();
let ses_request = SendRawEmailRequest {
raw_message: RawMessage {
data: base64::encode(raw_email).into(),
},
..Default::default()
};
ses_client.send_raw_email(ses_request).await?;
Ok(())
}
Conclusion
This article discussed three methods we can use to implement email sending with Rust, alongside their pros and cons. I hope these suggestions will help you to implement the best email features for your Rust applications.