patrol.Inbox opens one SMTP session per flush and sends one HTML email per project in the batch to every address in To. The body comes from patrol.EmailTemplate, an html/template: the message as a heading, then a table with the type, the capture time, every field, and the stacktrace with an editor link per frame.
The subject is Patrol - <project name>, Q-encoded so a non-ASCII project name survives. The Date header is written in the configured time zone.
The constructor
Section titled “The constructor”patrol.NewInbox(opts patrol.InboxOptions) (*patrol.Inbox, error)From, To, Host and Port are required, each with its own error. FromPassword is not: a relay on your own network that asks for no credentials works without it.
Options
Section titled “Options”| Field | Type | JSON | YAML and TOML | Required |
|---|---|---|---|---|
From |
string |
from |
From |
yes |
FromPassword |
string |
from_password |
FromPassword |
no |
To |
[]string |
to |
To |
yes |
Host |
string |
host |
Host |
yes |
Port |
int |
port |
Port |
yes |
TimeZone |
string |
time_zone |
TimeZone |
no |
From is both the envelope sender and the username for PLAIN authentication. Every address in To receives the same message, one RCPT TO each, in one transaction.
From: your_emailFromPassword: your_passwordTo: - alerts@example.comHost: smtp.gmail.comPort: 587TimeZone: Europe/AthensHow the session is built
Section titled “How the session is built”Per flush: dial, wrap in an SMTP client, upgrade with STARTTLS when the server advertises it, authenticate with PLAIN when the server advertises AUTH, send one message per project group, QUIT. A deadline on the context is applied to the connection, so a Close(ctx) with a timeout does bound this flusher.
What Test does
Section titled “What Test does”producer.Test(ctx) runs that same dial, upgrade and authentication, then quits without sending. It is the check that catches a wrong app password before an incident does.
A worked example
Section titled “A worked example”From _examples/basic/program:
// source: _examples/basic/program/main.go#L54-L59 // Email. emailFlusher, err := patrol.NewInbox(readConfig[patrol.InboxOptions]("inbox.yml")) if err != nil { log.Fatal(err) } eventFlushers = append(eventFlushers, emailFlusher)Gotchas
Section titled “Gotchas”Port 465 does not work. The session starts in plaintext and upgrades with STARTTLS, which is port 587 on every common provider. Implicit TLS, where the connection is encrypted from the first byte, is what 465 expects and is not implemented. Use 587.
Gmail needs an app password. FromPassword goes into smtp.PlainAuth. A Google account password will be refused; generate an app password and put that in the config file.
No files and no mentions. WithFile content is not attached and not linked. WithMentions is ignored.
The template escapes everything. patrol.EmailTemplate is an html/template, so a field value containing markup is rendered as text, not as HTML. The one exception is the frame link, which the template passes through the safe_url function because html/template would otherwise refuse the vscode:// scheme.
One email per project, to every recipient. Two project names in a batch is two emails to each address in To.