chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

24
vendor/lettre/examples/README.md vendored Normal file
View File

@@ -0,0 +1,24 @@
# Lettre Examples
This folder contains examples showing how to use lettre in your own projects.
## Message builder examples
- [basic_html.rs] - Create an HTML email.
- [maud_html.rs] - Create an HTML email using a [maud](https://github.com/lambda-fairy/maud) template.
## SMTP Examples
- [smtp.rs] - Send an email using a local SMTP daemon on port 25 as a relay.
- [smtp_tls.rs] - Send an email over SMTP encrypted with TLS and authenticating with username and password.
- [smtp_starttls.rs] - Send an email over SMTP with STARTTLS and authenticating with username and password.
- [smtp_selfsigned.rs] - Send an email over SMTP encrypted with TLS using a self-signed certificate and authenticating with username and password.
- The [smtp_tls.rs] and [smtp_starttls.rs] examples also feature `async`hronous implementations powered by [Tokio](https://tokio.rs/).
These files are prefixed with `tokio1_` or `asyncstd1_`.
[basic_html.rs]: ./basic_html.rs
[maud_html.rs]: ./maud_html.rs
[smtp.rs]: ./smtp.rs
[smtp_tls.rs]: ./smtp_tls.rs
[smtp_starttls.rs]: ./smtp_starttls.rs
[smtp_selfsigned.rs]: ./smtp_selfsigned.rs

View File

@@ -0,0 +1,33 @@
use lettre::{
message::header::ContentType, transport::smtp::authentication::Credentials, AsyncSmtpTransport,
AsyncStd1Executor, AsyncTransport, Message,
};
#[async_std::main]
async fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new async year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy with async!"))
.unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
// Open a remote connection to gmail using STARTTLS
let mailer: AsyncSmtpTransport<AsyncStd1Executor> =
AsyncSmtpTransport::<AsyncStd1Executor>::starttls_relay("smtp.gmail.com")
.unwrap()
.credentials(creds)
.build();
// Send the email
match mailer.send(email).await {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {e:?}"),
}
}

View File

@@ -0,0 +1,33 @@
use lettre::{
message::header::ContentType, transport::smtp::authentication::Credentials, AsyncSmtpTransport,
AsyncStd1Executor, AsyncTransport, Message,
};
#[async_std::main]
async fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new async year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy with async!"))
.unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
// Open a remote connection to gmail
let mailer: AsyncSmtpTransport<AsyncStd1Executor> =
AsyncSmtpTransport::<AsyncStd1Executor>::relay("smtp.gmail.com")
.unwrap()
.credentials(creds)
.build();
// Send the email
match mailer.send(email).await {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {e:?}"),
}
}

93
vendor/lettre/examples/autoconfigure.rs vendored Normal file
View File

@@ -0,0 +1,93 @@
use std::{env, process, time::Duration};
use lettre::SmtpTransport;
fn main() {
tracing_subscriber::fmt::init();
let smtp_host = match env::args().nth(1) {
Some(smtp_host) => smtp_host,
None => {
println!("Please provide the SMTP host as the first argument to this command");
process::exit(1);
}
};
// TLS wrapped connection
{
tracing::info!(
"Trying to establish a TLS wrapped connection to {}",
smtp_host
);
let transport = SmtpTransport::relay(&smtp_host)
.expect("build SmtpTransport::relay")
.timeout(Some(Duration::from_secs(10)))
.build();
match transport.test_connection() {
Ok(true) => {
tracing::info!("Successfully connected to {} via a TLS wrapped connection (SmtpTransport::relay). This is the fastest option available for connecting to an SMTP server", smtp_host);
}
Ok(false) => {
tracing::error!("Couldn't connect to {} via a TLS wrapped connection. No more information is available", smtp_host);
}
Err(err) => {
tracing::error!(err = %err, "Couldn't connect to {} via a TLS wrapped connection", smtp_host);
}
}
}
println!();
// Plaintext connection which MUST then successfully upgrade to TLS via STARTTLS
{
tracing::info!("Trying to establish a plaintext connection to {} and then upgrading it via the SMTP STARTTLS extension", smtp_host);
let transport = SmtpTransport::starttls_relay(&smtp_host)
.expect("build SmtpTransport::starttls_relay")
.timeout(Some(Duration::from_secs(10)))
.build();
match transport.test_connection() {
Ok(true) => {
tracing::info!("Successfully connected to {} via a plaintext connection which then got upgraded to TLS via the SMTP STARTTLS extension (SmtpTransport::starttls_relay). This is the second best option after the previous TLS wrapped option", smtp_host);
}
Ok(false) => {
tracing::error!(
"Couldn't connect to {} via STARTTLS. No more information is available",
smtp_host
);
}
Err(err) => {
tracing::error!(err = %err, "Couldn't connect to {} via STARTTLS", smtp_host);
}
}
}
println!();
// Plaintext connection (very insecure)
{
tracing::info!(
"Trying to establish a plaintext connection to {}",
smtp_host
);
let transport = SmtpTransport::builder_dangerous(&smtp_host)
.timeout(Some(Duration::from_secs(10)))
.build();
match transport.test_connection() {
Ok(true) => {
tracing::info!("Successfully connected to {} via a plaintext connection. This option is very insecure and shouldn't be used on the public internet (SmtpTransport::builder_dangerous)", smtp_host);
}
Ok(false) => {
tracing::error!(
"Couldn't connect to {} via a plaintext connection. No more information is available",
smtp_host
);
}
Err(err) => {
tracing::error!(err = %err, "Couldn't connect to {} via a plaintext connection", smtp_host);
}
}
}
}

49
vendor/lettre/examples/basic_html.rs vendored Normal file
View File

@@ -0,0 +1,49 @@
use lettre::{
message::{header, MultiPart, SinglePart},
FileTransport, Message, Transport,
};
fn main() {
// The html we want to send.
let html = r#"<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello from Lettre!</title>
</head>
<body>
<div style="display: flex; flex-direction: column; align-items: center;">
<h2 style="font-family: Arial, Helvetica, sans-serif;">Hello from Lettre!</h2>
<h4 style="font-family: Arial, Helvetica, sans-serif;">A mailer library for Rust</h4>
</div>
</body>
</html>"#;
// Build the message.
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Hello from Lettre!")
.multipart(
MultiPart::alternative() // This is composed of two parts.
.singlepart(
SinglePart::builder()
.header(header::ContentType::TEXT_PLAIN)
.body(String::from("Hello from Lettre! A mailer library for Rust")), // Every message should have a plain text fallback.
)
.singlepart(
SinglePart::builder()
.header(header::ContentType::TEXT_HTML)
.body(String::from(html)),
),
)
.expect("failed to build email");
// Create our mailer. Please see the other examples for creating SMTP mailers.
// The path given here must exist on the filesystem.
let mailer = FileTransport::new("./");
// Store the message when you're ready.
mailer.send(&email).expect("failed to deliver message");
}

58
vendor/lettre/examples/maud_html.rs vendored Normal file
View File

@@ -0,0 +1,58 @@
use lettre::{
message::{header, MultiPart, SinglePart},
FileTransport, Message, Transport,
};
use maud::html;
fn main() {
// The recipient's name. We might obtain this from a form or their email address.
let recipient = "Hei";
// Create the html we want to send.
let html = html! {
head {
title { "Hello from Lettre!" }
style type="text/css" {
"h2, h4 { font-family: Arial, Helvetica, sans-serif; }"
}
}
div style="display: flex; flex-direction: column; align-items: center;" {
h2 { "Hello from Lettre!" }
// Substitute in the name of our recipient.
p { "Dear " (recipient) "," }
p { "This email was sent with Lettre, a mailer library for Rust!"}
p {
"This example uses "
a href="https://crates.io/crates/maud" { "maud" }
". It is about 20% cooler than the basic HTML example."
}
}
};
// Build the message.
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Hello from Lettre!")
.multipart(
MultiPart::alternative() // This is composed of two parts.
.singlepart(
SinglePart::builder()
.header(header::ContentType::TEXT_PLAIN)
.body(String::from("Hello from Lettre! A mailer library for Rust")), // Every message should have a plain text fallback.
)
.singlepart(
SinglePart::builder()
.header(header::ContentType::TEXT_HTML)
.body(html.into_string()),
),
)
.expect("failed to build email");
// Create our mailer. Please see the other examples for creating SMTP mailers.
// The path given here must exist on the filesystem.
let mailer = FileTransport::new("./");
// Store the message when you're ready.
mailer.send(&email).expect("failed to deliver message");
}

23
vendor/lettre/examples/smtp.rs vendored Normal file
View File

@@ -0,0 +1,23 @@
use lettre::{message::header::ContentType, Message, SmtpTransport, Transport};
fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy!"))
.unwrap();
// Open a local connection on port 25
let mailer = SmtpTransport::unencrypted_localhost();
// Send the email
match mailer.send(&email) {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {e:?}"),
}
}

View File

@@ -0,0 +1,46 @@
use std::fs;
use lettre::{
message::header::ContentType,
transport::smtp::{
authentication::Credentials,
client::{Certificate, Tls, TlsParameters},
},
Message, SmtpTransport, Transport,
};
fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy!"))
.unwrap();
// Use a custom certificate stored on disk to securely verify the server's certificate
let pem_cert = fs::read("certificate.pem").unwrap();
let cert = Certificate::from_pem(&pem_cert).unwrap();
let tls = TlsParameters::builder("smtp.server.com".to_owned())
.add_root_certificate(cert)
.build()
.unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
// Open a remote connection to the smtp server
let mailer = SmtpTransport::builder_dangerous("smtp.server.com")
.port(465)
.tls(Tls::Wrapper(tls))
.credentials(creds)
.build();
// Send the email
match mailer.send(&email) {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {e:?}"),
}
}

31
vendor/lettre/examples/smtp_starttls.rs vendored Normal file
View File

@@ -0,0 +1,31 @@
use lettre::{
message::header::ContentType, transport::smtp::authentication::Credentials, Message,
SmtpTransport, Transport,
};
fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy!"))
.unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
// Open a remote connection to gmail using STARTTLS
let mailer = SmtpTransport::starttls_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:?}"),
}
}

31
vendor/lettre/examples/smtp_tls.rs vendored Normal file
View File

@@ -0,0 +1,31 @@
use lettre::{
message::header::ContentType, transport::smtp::authentication::Credentials, Message,
SmtpTransport, Transport,
};
fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy!"))
.unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
// 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:?}"),
}
}

View File

@@ -0,0 +1,37 @@
// This line is only to make it compile from lettre's examples folder,
// since it uses Rust 2018 crate renaming to import tokio.
// Won't be needed in user's code.
use lettre::{
message::header::ContentType, transport::smtp::authentication::Credentials, AsyncSmtpTransport,
AsyncTransport, Message, Tokio1Executor,
};
use tokio1_crate as tokio;
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new async year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy with async!"))
.unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
// Open a remote connection to gmail using STARTTLS
let mailer: AsyncSmtpTransport<Tokio1Executor> =
AsyncSmtpTransport::<Tokio1Executor>::starttls_relay("smtp.gmail.com")
.unwrap()
.credentials(creds)
.build();
// Send the email
match mailer.send(email).await {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {e:?}"),
}
}

View File

@@ -0,0 +1,37 @@
// This line is only to make it compile from lettre's examples folder,
// since it uses Rust 2018 crate renaming to import tokio.
// Won't be needed in user's code.
use lettre::{
message::header::ContentType, transport::smtp::authentication::Credentials, AsyncSmtpTransport,
AsyncTransport, Message, Tokio1Executor,
};
use tokio1_crate as tokio;
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let email = Message::builder()
.from("NoBody <nobody@domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
.to("Hei <hei@domain.tld>".parse().unwrap())
.subject("Happy new async year")
.header(ContentType::TEXT_PLAIN)
.body(String::from("Be happy with async!"))
.unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
// Open a remote connection to gmail
let mailer: AsyncSmtpTransport<Tokio1Executor> =
AsyncSmtpTransport::<Tokio1Executor>::relay("smtp.gmail.com")
.unwrap()
.credentials(creds)
.build();
// Send the email
match mailer.send(email).await {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {e:?}"),
}
}