Build and parse RFC 2822 email messages without sending them. Compose plain-text and HTML emails, add attachments, encode content, and parse raw message strings.
use plugin email Plugin snippets can be edited in the Playground, but native capabilities are executed locally with the Zolo CLI.
Functions (13)
- build_email Build a plain-text RFC 2822 email string
- build_html_email Build an HTML RFC 2822 email string
- build_mime_text Wrap text in a MIME text/plain part
- build_mime_html Wrap HTML in a MIME text/html part
- build_multipart Combine MIME parts into multipart/mixed
- build_attachment Create a base64 MIME attachment part
- encode_base64 Base64-encode a string
- encode_quoted_printable Quoted-printable encode a string
- parse_email_address Parse "Name <addr>" into name + address
- format_address Format name + address as "Name <addr>"
- validate_address Check if an email address is valid
- parse_headers Parse raw email headers into a table
- get_header Extract a single header value by name
From import to result
- 01Import only what you use
- 02Copy the smallest example
- 03Run it with the Zolo CLI
Overview¶
email is a dependency-free toolkit for composing and inspecting RFC 2822 email
messages as plain strings — it never opens a socket or sends anything. Every
function takes and returns ordinary strings (or simple tables), so a message is
just text you can build up, hand to an SMTP client, write to a file, or parse
back apart. There are no handles or stateful objects: each call is a pure
transformation.
The mental model is two-directional. To compose, start from a body with
build_email / build_html_email, or assemble MIME parts with the build_mime_*
and build_attachment helpers and glue them together with build_multipart;
encode tricky payloads with encode_base64 or encode_quoted_printable. To
inspect, run a raw message through parse_headers or pull one field with
get_header, and normalize address strings with parse_email_address,
format_address, and validate_address.
Common patterns¶
Build a complete plain-text message and read a header back out of it:
use plugin email::{build_email, get_header, validate_address}
let to = "bob@example.com"
if validate_address(to) {
let msg = build_email("alice@example.com", to, "Hello", "Hi Bob!")
print("subject is: {get_header(msg, "Subject")}")
}Assemble a multipart message with a text body and an attachment:
use plugin email::{build_mime_text, build_attachment, build_multipart}
let text = build_mime_text("See the attached report.")
let file = build_attachment("report.txt", "text/plain", "quarterly numbers")
let body = build_multipart([text, file])
print(body)Normalize and validate an address pulled from user input:
use plugin email::{parse_email_address, format_address, validate_address}
let parsed = parse_email_address("Alice Smith <alice@example.com>")
if validate_address(parsed["address"]) {
print("clean: {format_address(parsed["name"], parsed["address"])}")
}Build a plain-text RFC 2822 email string
Builds a complete RFC 2822 plain-text email string. The result can be passed to an SMTP library or written to a file.
use plugin email::{build_email}
let msg = build_email(
"alice@example.com",
"bob@example.com",
"Hello",
"Hi Bob, how are you?"
)
print(msg)Format the sender with a display name first, then drop it into the message:
use plugin email::{format_address, build_email, get_header}
let from = format_address("Alice Smith", "alice@example.com")
let msg = build_email(from, "bob@example.com", "Welcome", "Glad you joined!")
print(get_header(msg, "From")) // Alice Smith <alice@example.com>Build an HTML RFC 2822 email string
Like build_email but sets Content-Type: text/html. Use when the body contains HTML markup.
use plugin email::{build_html_email}
let msg = build_html_email(
"alice@example.com",
"bob@example.com",
"Newsletter",
"<h1>Hello</h1><p>Check out our <b>new</b> product!</p>"
)
print(msg)Wrap text in a MIME text/plain part
Wraps a plain-text string in a MIME text/plain part header block. Use this to construct individual parts before combining them with build_multipart.
use plugin email::{build_mime_text, build_mime_html, build_multipart}
let text_part = build_mime_text("This is the plain-text version.")
let html_part = build_mime_html("<p>This is the <b>HTML</b> version.</p>")
let combined = build_multipart([text_part, html_part])
print(combined)Wrap HTML in a MIME text/html part
Wraps an HTML string in a MIME text/html part header block.
use plugin email::{build_mime_html}
let part = build_mime_html("<p>Welcome to <em>Zolo</em>!</p>")
print(part)Combine MIME parts into multipart/mixed
Combines a table of MIME part strings into a multipart/mixed body using a fixed boundary. Pass the output as the body to an SMTP client.
use plugin email::{build_mime_text, build_attachment, build_multipart}
let text = build_mime_text("See attached file.")
let att = build_attachment("report.txt", "text/plain", "report contents")
let body = build_multipart([text, att])
print(body)Create a base64 MIME attachment part
Creates a base64-encoded MIME attachment part. data can be a string or bytes. The result is a single MIME part suitable for use with build_multipart.
use plugin email::{build_attachment, build_mime_text, build_multipart}
let att = build_attachment("hello.txt", "text/plain", "Hello, world!")
let text = build_mime_text("Please find the attachment.")
let msg = build_multipart([text, att])
print(msg)Base64-encode a string
Base64-encodes a string using standard alphabet. Useful for encoding binary payloads or credentials before embedding them in a message.
use plugin email::{encode_base64}
let encoded = encode_base64("username:password")
print(encoded)Quoted-printable encode a string
Encodes a string using quoted-printable encoding (RFC 2045), inserting soft line breaks at 76 characters. Use for non-ASCII subject lines or body text.
use plugin email::{encode_quoted_printable}
let encoded = encode_quoted_printable("Héllo wörld")
print(encoded)Parse "Name <addr>" into name + address
Parses address strings in "Name <email>", "<email>", or bare "email" format. Returns a table with name and address keys.
use plugin email::{parse_email_address}
let result = parse_email_address("Alice Smith <alice@example.com>")
print(result["name"]) // Alice Smith
print(result["address"]) // alice@example.com
let bare = parse_email_address("bob@example.com")
print(bare["address"]) // bob@example.comFormat name + address as "Name <addr>"
Formats a display name and email address into "Name <email>". If name is empty, returns "<email>".
use plugin email::{format_address}
let addr = format_address("Alice Smith", "alice@example.com")
print(addr) // Alice Smith <alice@example.com>
let anon = format_address("", "noreply@example.com")
print(anon) // <noreply@example.com>Check if an email address is valid
Performs basic RFC 5321 validation: checks for a single @, non-empty local part, valid domain labels, and no illegal characters. Does not make network requests.
use plugin email::{validate_address}
print(validate_address("alice@example.com")) // true
print(validate_address("not-an-email")) // false
print(validate_address("user@bad_domain.com")) // falseIt also accepts addresses wrapped in angle brackets, so you can validate a
"Name <addr>" string directly before composing a message:
use plugin email::{validate_address}
print(validate_address("Alice <alice@example.com>")) // true
print(validate_address("Alice <alice@localhost>")) // false (no domain dot)Parse raw email headers into a table
Parses the header section of a raw email string into a table of {header_name: value} pairs. Stops at the first blank line (header/body separator).
use plugin email::{build_email, parse_headers}
let raw = build_email("a@a.com", "b@b.com", "Test", "body")
let hdrs = parse_headers(raw)
print(hdrs)Folded (multi-line) headers are unfolded into a single value, so a long header parses as one entry:
use plugin email::{parse_headers}
let raw = "Subject: a very\r\n long subject\r\nTo: bob@example.com\r\n\r\nbody"
let hdrs = parse_headers(raw)
print(hdrs["Subject"]) // a very long subjectExtract a single header value by name
Finds and returns the value of a specific header (case-insensitive) from a raw email string, or nil if not found.
use plugin email::{build_email, get_header}
let raw = build_email("a@a.com", "b@b.com", "Hello", "body")
let subject = get_header(raw, "Subject")
print(subject) // Hello