arizuko › components › emaid
emaid
emaid reads mail over IMAP, checks the sender, sends replies over SMTP, and trusts the DMARC result of one named mail server.
emaid connects email to arizuko
emaid connects email to arizuko, so the agent can read incoming mail and send replies in the same thread.
emaid is the email channel adapter. It reads IMAP for inbound messages and sends outbound messages with SMTP. It keeps its own table that maps email threads, by Message-ID and References, to their chat_jid, so replies stay in the conversation. For routd, it is a normal channel adapter with the JID prefix email:.
emaid checks each inbound message against the DMARC result in the Authentication-Results header of the upstream mail server before the agent sees it. Verified mail gets verb=message. All other mail gets verb=untrusted, so route rules can quarantine it.
Email reaches every customer and needs sender checks
Email is the inbound channel that everyone has: every customer, vendor and ticket system can reach an arizuko agent with an SMTP address. Without emaid, there is no IMAP loop, no thread table and no sender check, and the agent cannot receive email at all.
Mail without authentication is easy to forge. An attacker who forges a reply to the bot must not get verb=mention. For this reason, emaid splits verb=message from verb=untrusted, and the sender check happens at the channel boundary, before routing.
Each message passes five steps
- emaid reads the IMAP
INBOXfor messages newer than the last seen UID, with IMAP IDLE where the server supports it. - It parses
Authentication-Results. A DMARC pass from the configured authserv-id, with an optional allowlist ofFromdomains, givesverb=message. Anything else givesverb=untrusted, with an optional[UNVERIFIED]subject prefix.EMAIL_STRICT_AUTH=1drops untrusted mail completely. - It looks up the thread row by
Message-IDorReferences. On a hit, it uses the existingchat_jid. On a miss, it creates a new one. - It posts to
/v1/messageson routd, with an ES256 service token fromAUTHD_SERVICE_KEY. - For outbound mail, routd calls
POST /send. emaid gives the body to SMTP withIn-Reply-ToandReferencesset from the thread row.
emaid sits between the mail server and routd
mail server (Gmail, Fastmail, …)
│ IMAP IDLE / poll
▼
emaid (parse Authentication-Results, classify verb)
│ POST /v1/messages (ES256 service token)
▼
routd
│ POST /send (callback to emaid)
▼
emaid (SMTP submit; In-Reply-To = thread root)
│
▼
mail server ──► recipient
- Inputs
- IMAP traffic on the configured mailbox, and HTTP callbacks from routd.
- Outputs
- SMTP submissions, and signed posts to routd.
- Dependencies
- A reachable routd, an IMAP and SMTP account, and a trusted upstream mail server whose authserv-id is set in
EMAIL_TRUSTED_AUTHSERV.
emaid trusts the DMARC result of one named mail server
emaid uses the library emersion/go-msgauth/authres. It runs no DMARC check of its own: it trusts the mail server that delivered the mail. The operator names that server with EMAIL_TRUSTED_AUTHSERV, and with no value, emaid refuses every message. Four settings control the classification:
EMAIL_TRUSTED_AUTHSERV- Required. The authserv-id whose DMARC result emaid trusts, for example
mx.google.com. EMAIL_TRUSTED_DOMAINS- Optional allowlist of
Fromdomains. When it is set, a DMARC pass is not enough, and the sender domain must also match. EMAIL_STRICT_AUTH- A true value,
true,1,yesoron, drops untrusted mail with no agent turn. The default isfalse, and untrusted mail still reaches the store withverb=untrusted. EMAIL_UNVERIFIED_SUBJECT_PREFIX- A true value adds an
[UNVERIFIED]prefix to the subject of untrusted mail.
routd never promotes an untrusted reply to the bot to verb=mention. Operators route verb=untrusted to a quarantine child group.
emaid runs alone with routd and a mail account
emaid is a plain Go binary. It needs a reachable routd, an IMAP and SMTP account and a writable directory for its thread store.
export ROUTER_URL=http://routd:8080
export AUTHD_URL=http://authd:8080
export AUTHD_SERVICE_NAME=emaid
export AUTHD_SERVICE_KEY=<key from authd>
export LISTEN_ADDR=:8080
export DATA_DIR=/srv/data/arizuko_demo
export EMAIL_IMAP_HOST=imap.fastmail.com EMAIL_IMAP_PORT=993
export EMAIL_SMTP_HOST=smtp.fastmail.com EMAIL_SMTP_PORT=587
export EMAIL_ACCOUNT=bot@example.com EMAIL_PASSWORD=<password>
export EMAIL_TRUSTED_AUTHSERV=mx.example.com
./emaid
GET /health returns 503 when the IMAP login fails or the read loop fails, and 200 after a successful read.
Email supports only plain sending
Email has no reactions, no edit and no delete. emaid implements send and fetch_history. Every other BotHandler verb returns chanlib.ErrUnsupported with a hint, so the agent can pick another action and the call does not fail without a sign.
Four sources cover the details
- components/channels: the shared adapter shape.
- [emaid/README.md]: the full table of environment variables, the verb support and the file map.
- [SECURITY.md]: the trust model, and why untrusted senders cannot escalate.
- concepts/routing: how to route
verb=untrustedto a quarantine child group.