mailrules

module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: AGPL-3.0

README

MailRules

MailRules is a small daemon that sorts incoming email over IMAP, in real time, using rules you write in plain English or as structured conditions. It works with any IMAP provider (iCloud, Fastmail, Yahoo, Zoho, your own server), lets you choose the model that decides, and runs as one binary with the web UI built in.

A rule written in plain English, and new emails being filed into Jobs, Reading, Food and Trash by it

Website and hosted version: mailrules.app

It starts safe: it listens on this machine only, and dry-run is on, so it records what it would do and changes no mailbox until you switch dry-run off.

Releases are on the GitHub Releases page: binaries for Linux and macOS (amd64 and arm64), a Docker image at ghcr.io/turtlebyte-in/mailrules, and a Homebrew cask.

Documentation

The user guide covers everything below in detail:

Quickstart with Docker

docker run -d --name mailrules --restart unless-stopped \
  --read-only --tmpfs /tmp -p 127.0.0.1:8080:8080 \
  -e MAILRULES_COOKIE_SECURE=false -v mailrules-data:/data \
  ghcr.io/turtlebyte-in/mailrules:latest

Open http://127.0.0.1:8080 on the same machine. To use Docker Compose instead, see Install.

Quickstart with Homebrew

On macOS, and on Linux with Homebrew:

brew install --cask turtlebyte-in/tap/mailrules
mailrules serve

The cask comes from the tap TurtleByte-IN/homebrew-tap. The data directory is ./data in the directory you start it from, unless you set MAILRULES_DATA_DIR.

Quickstart with a single binary

Download the archive for your system and checksums.txt from the Releases page, check it and unpack it:

sha256sum --ignore-missing -c checksums.txt   # on macOS: shasum -a 256 --ignore-missing -c checksums.txt
tar xzf mailrules_<version>_linux_amd64.tar.gz
./mailrules serve

The macOS binaries are not signed; see Install if macOS refuses to open one. To build from source, or to run MailRules as a systemd service, see Install.

First steps

  1. Open http://127.0.0.1:8080 and create the admin account.
  2. Choose the decision model and give it a key, or skip that: rules made only of conditions need no model.
  3. Connect a mailbox with an app password, and pick a few starter rules.
  4. Watch Activity while dry-run is on, then switch dry-run off.

First run walks through each step.

Developing

  • make check: gofmt, go vet, golangci-lint, go test -race ./... with a coverage floor of 80% in internal/rules, internal/pipeline and internal/actions, the settings reference check and the web app's checks
  • make dev: the daemon, plus the Vite dev server when web/ exists
  • make build: builds the web app when web/ exists, then the single binary
  • make settings-doc: regenerates docs/guide/settings.md from internal/config; edit the help text there, not the page

The HTTP API is described in docs/api.md and the pre-release checklist is docs/smoke.md.

Suggest from my mail, which has the AI suggest rules from the mail already in a folder, is not part of this repository: the hosted MailRules adds it as a module. The free build answers its API route with 404 not_available and does not show its tab. A build adds modules through the public Go package ext (ext/daemon.Run starts the daemon with them); cmd/mailrules is this repository's build, with none.

Releases

Pushing a tag such as v0.1.4 runs .github/workflows/release.yml. It runs make check; GoReleaser (.goreleaser.yaml) then builds the web app and the binaries and publishes the GitHub Release with the archives and checksums.txt, not yet marked latest; and the multi-arch image is built from deploy/Dockerfile and pushed to ghcr.io/turtlebyte-in/mailrules with its version tag only. Next, .github/workflows/verify-release.yml installs every published format the way users do and runs it with scripts/release-smoke.sh: each archive on Linux amd64 and arm64 and macOS arm64 and Intel, the image on amd64 and arm64, and the Homebrew cask on macOS and Linux. Only when all of them pass does the release become the latest, the image get latest, and the cask go to the tap TurtleByte-IN/homebrew-tap (which needs the HOMEBREW_TAP_TOKEN secret; without it the cask is not published). A failed check leaves users on the previous release. The verify workflow can also be run by hand against any tag (Actions → verify-release → Run workflow). GitHub creates the image package as private the first time; make it public once in its package settings. To try the release build without publishing anything: goreleaser release --snapshot --clean --skip=publish.

Security

Report vulnerabilities privately with Report a vulnerability on the repository's Security tab, not in a public issue. See Security for the defaults and for running MailRules behind a reverse proxy.

License

Copyright (C) 2026 TurtleByte.

MailRules is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License, version 3 only, as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See LICENSE for the full text.

If you run a modified MailRules where other people use it over a network, the licence requires you to offer them your modified source. The web UI links to the source from the sidebar ("Source code"); point that link at your own copy.

The web UI bundles the Schibsted Grotesk and IBM Plex Mono fonts, which are licensed under the SIL Open Font License 1.1. Every Go dependency, and every npm package shipped in the web UI, is under MIT, BSD, ISC or Apache 2.0.

Directories

Path Synopsis
cmd
mailrules command
Command mailrules is the MailRules daemon and CLI: the free self-host build, with no modules (ext/daemon runs it).
Command mailrules is the MailRules daemon and CLI: the free self-host build, with no modules (ext/daemon runs it).
ext
Package ext is the plug-in point of the MailRules daemon: the one public package through which a module built outside this repository adds a feature.
Package ext is the plug-in point of the MailRules daemon: the one public package through which a module built outside this repository adds a feature.
daemon
Package daemon runs the MailRules command line: the daemon and web UI (serve), and the migrate, accounts, users, eval, rules, dry-run and version commands.
Package daemon runs the MailRules command line: the daemon and web UI (serve), and the migrate, accounts, users, eval, rules, dry-run and version commands.
internal
actions
Package actions is the only code that changes a mailbox: the executor that applies a rule's actions, and undo.
Package actions is the only code that changes a mailbox: the executor that applies a rule's actions, and undo.
api
Package api serves the HTTP API described in api/openapi.yaml.
Package api serves the HTTP API described in api/openapi.yaml.
composer
Package composer holds the two ways a user tries rules out before they act: the rule composer, which turns free text into validated draft rules, and the rule tester, which runs saved or draft rules over recent mail.
Package composer holds the two ways a user tries rules out before they act: the rule composer, which turns free text into validated draft rules, and the rule tester, which runs saved or draft rules over recent mail.
config
Package config loads daemon settings from environment variables and flags.
Package config loads daemon settings from environment variables and flags.
config/docgen command
Command docgen writes the settings reference, docs/guide/settings.md, from the settings internal/config registers, so the page cannot drift from the daemon.
Command docgen writes the settings reference, docs/guide/settings.md, from the settings internal/config registers, so the page cannot drift from the daemon.
contacts
Package contacts keeps the index of addresses the user has written to, built from the Sent folder.
Package contacts keeps the index of addresses the user has written to, built from the Sent folder.
crypto
Package crypto holds envelope encryption for mailbox credentials and password hashing.
Package crypto holds envelope encryption for mailbox credentials and password hashing.
events
Package events is the in-process event hub.
Package events is the in-process event hub.
learn
Package learn holds what the daemon learns from its own decisions and the user's corrections: learned sender rules, and the few-shot examples the fallback model is shown.
Package learn holds what the daemon learns from its own decisions and the user's corrections: learned sender rules, and the few-shot examples the fallback model is shown.
mail
Package mail defines the Mailbox interface every mail provider implements, and the types and errors shared by its callers.
Package mail defines the Mailbox interface every mail provider implements, and the types and errors shared by its callers.
mail/imap
Package imap implements mail.Mailbox over IMAP with go-imap v2.
Package imap implements mail.Mailbox over IMAP with go-imap v2.
mail/imap/imaptest
Package imaptest runs go-imap's in-memory IMAP server over TLS for integration tests.
Package imaptest runs go-imap's in-memory IMAP server over TLS for integration tests.
mail/mailtest
Package mailtest is an in-memory mail.Mailbox for tests of the packages that sit on top of the connector.
Package mailtest is an in-memory mail.Mailbox for tests of the packages that sit on top of the connector.
mail/presets
Package presets holds per-provider connection defaults: host, port, TLS mode, folder-name fallbacks for servers without SPECIAL-USE, and known quirks.
Package presets holds per-provider connection defaults: host, port, TLS mode, folder-name fallbacks for servers without SPECIAL-USE, and known quirks.
mailer
Package mailer sends email: the summary email.
Package mailer sends email: the summary email.
mailer/mailertest
Package mailertest is an in-memory mailer.Sender for tests of the packages that send email.
Package mailertest is an in-memory mailer.Sender for tests of the packages that send email.
message
Package message holds the email types shared by the IMAP connector, the rules engine and the model adapters.
Package message holds the email types shared by the IMAP connector, the rules engine and the model adapters.
models
Package models puts every model provider behind two interfaces: Decider (which rule does this email match?) and Generator (free-form structured output).
Package models puts every model provider behind two interfaces: Decider (which rule does this email match?) and Generator (free-form structured output).
models/anthropictest
Package anthropictest is a fake Anthropic API for tests: the Messages API, token counting and List Workspaces, answering as the test sets it up and recording what it was sent.
Package anthropictest is a fake Anthropic API for tests: the Messages API, token counting and List Workspaces, answering as the test sets it up and recording what it was sent.
pipeline
Package pipeline takes one new email from arrival to outcome: ingest (once), fetch and parse, evaluate the rules, ask the decision model when rules with an intent are in play, hand the winning rule's actions to the executor or park the email in Needs review, record it all, and learn.
Package pipeline takes one new email from arrival to outcome: ingest (once), fetch and parse, evaluate the rules, ask the decision model when rules with an intent are in play, hand the winning rule's actions to the executor or park the email in Needs review, record it all, and learn.
rules
Package rules holds the rule types, the condition matcher, validation, the evaluation order for one email and YAML import/export.
Package rules holds the rule types, the condition matcher, validation, the evaluation order for one email and YAML import/export.
settings
Package settings owns the settings a user changes while the daemon runs: the dry-run switch, the decision models and thresholds, retention, where trashed mail goes, whether the mailbox's own mail is left alone, and the model provider keys.
Package settings owns the settings a user changes while the daemon runs: the dry-run switch, the decision models and thresholds, retention, where trashed mail goes, whether the mailbox's own mail is left alone, and the model provider keys.
store
Package store owns the SQLite database: opening it, migrating it and, later, the repositories.
Package store owns the SQLite database: opening it, migrating it and, later, the repositories.
summary
Package summary is the summary email: a daily or weekly email of what MailRules sorted per rule, what it trashed and what waits in Needs review, with links into the web app.
Package summary is the summary email: a daily or weekly email of what MailRules sorted per rule, what it trashed and what waits in Needs review, with links into the web app.
telemetry
Package telemetry sets up logging (and, later, metrics).
Package telemetry sets up logging (and, later, metrics).
web
Package web serves the browser UI that is built into the binary.
Package web serves the browser UI that is built into the binary.
worker
Package worker runs one supervisor per mail account: it connects, watches the account's folder and feeds each arrival to the pipeline, strictly in UID order.
Package worker runs one supervisor per mail account: it connects, watches the account's folder and feeds each arrival to the pipeline, strictly in UID order.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL