Services

Email over SMTP

Email through any SMTP provider (Postmark, SES, Mailgun, Gmail): text, HTML or both, to one or several people.

Version 1.0.0 · 1 function · 1 crate

#email#notifications#smtp

Functions

What use smtp.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use send_email from smtp (Quillo 0.6).

send_email(to: str, subject: str, text: str, html: str) → nullor an error

Sends a message from SMTP_FROM to to (one address, or several with commas): text, and html too unless it is empty. Waits for the server's answer.

Get it

$ quillo install smtp               # smtp.qwer into this folder$ quillo install smtp --example     # and its example, smtp.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/smtp.qwer$ curl -O https://quillolang.org/plugins/files/smtp.qwe

Then, in your program, all of it or only what you call:

main.qwe
use smtp.qweruse send_email from smtp      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
lettre = { version = "0.11", default-features = false, features = ["builder", "smtp-transport", "rustls-tls", "hostname"] }

Example

smtp.qwe
// A welcome email, sent in the background so the sign-up answers at once.////   SMTP_URL=smtps://user:password@smtp.example.com SMTP_FROM="Shop <shop@example.com>" quillo run smtp.qwe//   then open http://localhost:8080/welcome?to=ada@example.comuse "smtp.qwer"route GET /welcome ? { to: str } {    send_email(to, "Welcome to the shop", "Thanks for signing up!", "<h1>Welcome!</h1><p>Thanks for signing up.</p>")?    { sent: true }}
$ quillo run smtp.qwe$ curl 'localhost:8080/welcome?to=ada@example.com'

It sends through the SMTP server SMTP_URL names, from SMTP_FROM. The site's test runs it against a stand-in.

Source

smtp.qwer
//! Email sent over SMTP, through any provider (Postmark, SES, Mailgun, SendGrid, Fastmail, Gmail): text, HTML, or both.//! version: 1.0.0//!//! [dependencies]//! lettre = { version = "0.11", default-features = false, features = ["builder", "smtp-transport", "rustls-tls", "hostname"] }use lettre::message::{header::ContentType, Mailbox, MultiPart};use lettre::{Message, SmtpTransport, Transport};use std::sync::OnceLock;fn mailer() -> Result<&'static SmtpTransport, String> {    static M: OnceLock<SmtpTransport> = OnceLock::new();    if let Some(m) = M.get() {        return Ok(m);    }    let url = std::env::var("SMTP_URL").map_err(|_| "SMTP_URL is not set: smtps://user:password@smtp.example.com:465".to_string())?;    let m = SmtpTransport::from_url(&url).map_err(|e| e.to_string())?.timeout(Some(std::time::Duration::from_secs(20))).build();    Ok(M.get_or_init(|| m))}fn mailbox(s: &str) -> Result<Mailbox, String> {    s.trim().parse::<Mailbox>().map_err(|e| format!("`{}`: {}", s, e))}/// Sends a message from `SMTP_FROM` to `to` (one address, or several with commas): `text`, and `html` too unless it is empty. Waits for the server's answer.pub fn send_email(to: &str, subject: &str, text: &str, html: &str) -> Result<(), String> {    let from = std::env::var("SMTP_FROM").map_err(|_| "SMTP_FROM is not set: Shop <shop@example.com>".to_string())?;    let mut b = Message::builder().from(mailbox(&from)?).subject(subject);    for addr in to.split(',').filter(|a| !a.trim().is_empty()) {        b = b.to(mailbox(addr)?);    }    let m = if html.is_empty() {        b.header(ContentType::TEXT_PLAIN).body(text.to_string())    } else {        b.multipart(MultiPart::alternative_plain_html(text.to_string(), html.to_string()))    }    .map_err(|e| e.to_string())?;    mailer()?.send(&m).map(|_| ()).map_err(|e| e.to_string())}
Email APIs mail_api.qwer · 1.0.0Email sent through Resend, Postmark, SendGrid or Mailgun's HTTP APIs with one call and one message shape, attachments included, the provider picked by a word; and the request shown before it is sent.emailapinotificationsintegration7 views · 7 downloadsAWS Signature V4 aws_sign.qwer · 1.0.0AWS Signature V4 for any AWS API: the headers that sign a request for SES, SQS, DynamoDB or S3, and presigned URLs.awsapisignings3email10 views · 12 downloadsDiscord discord.qwer · 1.0.0Messages to Discord channels through webhooks: embeds with color, fields, images and timestamps built and checked against Discord's limits, mentions off unless asked for, threads, and the rate limit's wait reported.chatnotificationswebhooksdevops7 views · 8 downloadsFirebase messaging fcm.qwer · 1.0.0Notifications to Android, iOS and web apps through Firebase Cloud Messaging v1, with the service account's RS256 token made and kept until it expires.notificationspushmobilefirebase7 views · 8 downloadsMailchimp mailchimp.qwer · 1.0.0Keep a Mailchimp audience in step: members named by the MD5 of their lower-cased email, upserts that can run twice, batch subscribes of 500 with their bad rows reported, tags, unsubscribes and erasure, and webhook posts read from their nested form.emailnewsletterwebhooksbatch3 views · 8 downloadsMicrosoft Graph microsoft_graph.qwer · 1.0.0Microsoft 365 as an app: client-credentials tokens, 429s waited out as Retry-After says, every @odata.nextLink followed, mail sent and read, calendar views and events, OneDrive uploads small and by session, downloads, and batches.microsoftemailcalendaronedriveoauth3 views · 8 downloads
Thread
68Useful? Like it, or add to its thread below.

Thread 0 posts

On Email over SMTP: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.