Add email accounts
Tell localmail which mailboxes to mirror. Each account is
a row in the database — seeded from a
config.toml block or created point-and-click in the
admin web UI — plus one credential
stored in the OS keyring. The recipes below cover the major providers.
How accounts are defined
The database is the single source of truth for account configuration. There are two ways to get an account into it:
- config.toml + CLI (the recipes on this page). You
declare an
[[accounts]]block, then runlocalmail init-db(which seeds the row) orlocalmail add-account NAME/localmail oauth-login NAME(which seed the row from the block on first use if it isn't in the database yet). - The admin web UI —
create, edit, and delete accounts entirely from a browser, no
config.tomlrequired.
Seeding is one-directional and idempotent: TOML fills an
empty database, but once a row exists the database wins — editing the TOML
block afterwards logs a warning and changes nothing. Edit live accounts in
the admin UI or with the account CLI commands, not by re-running
init-db.
Each [[accounts]] block needs a name (your
handle for it everywhere on the CLI, and the keyring identifier) and an
auth_method — either "password" (anything with an
app password or plain IMAP password) or "oauth2" (currently
Gmail only):
[[accounts]]
name = "work-fastmail" # used on the CLI: localmail add-account work-fastmail
email = "you@example.com"
imap_host = "imap.fastmail.com"
imap_port = 993
auth_method = "password" # or "oauth2"
# Optional folder filters — see end of page
# folder_allow = ["INBOX", "Archive"]
# folder_deny = ["Drafts"]
# folder_deny_flags = ["\\Trash", "\\Junk", "\\All"]
Add as many [[accounts]] entries as you like. Each live
account runs in its own pair of daemon threads, so accounts don't block
each other. You can pause an account at any time with
localmail disable-account NAME (and resume with
enable-account) — it stays in the database but is skipped by
the daemon and one-shot sync.
archive
Accounts with auth_method = "archive" have no IMAP host and
are never synced — they're holding places for
imported mbox / Maildir mail. You
can't declare one in a TOML block; create it in the admin UI (or it's
created for you by the import flow).
Run localmail list-accounts to confirm localmail sees the
account and whether a credential (password or OAuth refresh token) is
stored. It's a quick sanity check.
Gmail
Gmail dropped plain-IMAP password support in 2022. You must use OAuth2. localmail uses the standard Google "desktop application" OAuth flow — you create your own Google Cloud project (free, no billing) so the credentials are yours, not someone else's.
-
Create a Google Cloud project.
Visit console.cloud.google.com/projectcreate. Pick any name. No billing required.
-
Configure the OAuth consent screen.
APIs & Services → OAuth consent screen.
- User type: External.
- Fill in app name, support email, developer email.
- Scopes: leave blank in the form — the IMAP scope is requested at runtime, not registered here.
Don't skip thisOAuth consent screen → Audience → Test users → + Add users → add the exact Google account address you'll sign in with. If you skip this step you'll get
Error 403: access_deniedat consent time. Google ignores dots in Gmail addresses for routing, but the test-users list expects the canonical form.Leave the project in Testing status — promoting to production would require Google's verification audit because
https://mail.google.com/is a restricted scope. -
Enable the Gmail API.
APIs & Services → Library → Gmail API → Enable.
-
Create OAuth client credentials.
APIs & Services → Credentials → Create Credentials → OAuth client ID.
- Application type: Desktop.
- After creation, click Download JSON. Save it
as:
~/.config/localmail/gmail_client_secret.json
-
Add the account to
config.toml.[gmail_oauth] client_secrets_file = "~/.config/localmail/gmail_client_secret.json" [[accounts]] name = "horst-gmail" email = "you@gmail.com" imap_host = "imap.gmail.com" imap_port = 993 auth_method = "oauth2" oauth_provider = "gmail" # Deny "All Mail" — every message is already under INBOX or a label, # so syncing All Mail roughly doubles the work for zero new content. folder_deny_flags = ["\\Trash", "\\Junk", "\\All"] -
Run the consent flow.
localmail oauth-login horst-gmailA browser opens, you grant access, and the refresh token is written to your keyring. From now on localmail mints short-lived access tokens automatically — no further interaction needed unless you revoke access at myaccount.google.com/permissions.
Prefer a browser?The admin web UI has a Connect Gmail button that runs the same consent flow from the account editor — handy when the server is remote and you can't run
oauth-loginon its shell. It needs[serve].state_signing_keyand[serve].oauth_callback_urlset (a redirect URI you also register in the Google Cloud console). The CLI flow above needs neither. -
Test it.
localmail sync --account horst-gmail --limit-per-folder 10This pulls the first 10 messages from each folder. Subsequent runs resume from where this left off.
Microsoft 365 / Outlook / Exchange Online
Microsoft is mid-deprecation of basic IMAP authentication. As of September 2024, personal Outlook.com and consumer accounts still allow IMAP with an app password; Microsoft 365 (work / school) tenants vary depending on whether your admin has enabled IMAP and allowed app passwords. Check with your IT admin if you're on a corporate tenant.
Personal Outlook.com / Hotmail / Live
-
Turn on two-step verification.
Required before you can create an app password. Visit account.microsoft.com/security → Advanced security options → Two-step verification.
-
Generate an app password.
Same Advanced security page → App passwords → Create a new app password. Copy the 16-character string immediately — you cannot view it again.
-
Add the account to
config.toml.[[accounts]] name = "personal-outlook" email = "you@outlook.com" imap_host = "outlook.office365.com" imap_port = 993 auth_method = "password" folder_deny_flags = ["\\Trash", "\\Junk"] -
Store the app password.
localmail add-account personal-outlook # Paste the 16-character app password at the prompt.
Microsoft 365 (work / school)
Most M365 tenants now require Modern Auth (OAuth2)
for IMAP and have basic auth disabled. localmail does not yet ship a
Microsoft OAuth provider — track
the issue
tracker for progress. If your admin still allows IMAP + app
passwords, follow the consumer recipe above (the IMAP host is the
same: outlook.office365.com). If they don't, you cannot
currently use localmail with that account.
On-premises Exchange Server
If your organisation runs Exchange Server (not Exchange Online) with
the IMAP role enabled, treat it as a generic IMAP server —
auth_method = "password", ask your admin for the IMAP
host name and port (usually 993). See the
generic IMAP section below.
Fastmail
Fastmail requires an app password for IMAP — your account password won't work.
-
Create an app password.
Sign in at app.fastmail.com → Settings → Privacy & Security → Connected apps & API tokens. Click New app password, give it a name like "localmail", restrict access to Mail (IMAP/SMTP).
-
Add it.
[[accounts]] name = "work-fastmail" email = "you@fastmail.com" imap_host = "imap.fastmail.com" imap_port = 993 auth_method = "password" # Then: localmail add-account work-fastmail
Proton Mail
Proton Mail does not expose an IMAP server directly — mail is end-to-end encrypted on Proton's infrastructure. To mirror it you install Proton Mail Bridge, which runs locally, decrypts your mail, and exposes a local IMAP server that localmail can talk to.
-
Install Proton Mail Bridge.
Download from proton.me/mail/bridge. Requires a paid Proton plan (Plus, Unlimited, etc.).
-
Sign in and add your account in Bridge.
The Bridge app shows you, per account: IMAP host (always
127.0.0.1), IMAP port (a random high port like1143), username (your Proton email), and a Bridge password (machine-generated; different from your Proton password). -
Add to
config.toml.[[accounts]] name = "proton" email = "you@proton.me" imap_host = "127.0.0.1" imap_port = 1143 # use the port Bridge shows you auth_method = "password"Bridge must use SSL, and its cert must be trustedlocalmail always connects over implicit TLS and verifies the server certificate — there is no plaintext, STARTTLS, or "skip verification" option. Set Bridge's IMAP connection security to SSL (not STARTTLS), and install the certificate Bridge presents into your OS trust store — Bridge can export it from its settings. Without that, verification fails and the connection is refused.
-
Store the Bridge password.
localmail add-account proton # Paste the Bridge password from the Bridge UI.
localmail talks to Bridge over local IMAP. If Bridge isn't running, the daemon will fail to connect and retry with exponential backoff. Set Bridge to launch on login (its preferences offer this) so the mirror keeps working unattended.
iCloud
iCloud Mail requires an app-specific password. Two-factor auth must be enabled on your Apple ID.
-
Generate an app-specific password.
Sign in at account.apple.com → Sign-In and Security → App-Specific Passwords → Generate. Label it "localmail". Copy the 19-character password Apple shows you.
-
Add to config.
[[accounts]] name = "icloud" email = "you@icloud.com" imap_host = "imap.mail.me.com" imap_port = 993 auth_method = "password" # Then: localmail add-account icloud
Yahoo Mail / AOL Mail
Both require an app password.
- Yahoo: Account Security → Generate app password
(requires 2FA enabled). Host:
imap.mail.yahoo.com, port 993. - AOL: Same flow at
login.aol.com.
Host:
imap.aol.com, port 993.
[[accounts]]
name = "yahoo"
email = "you@yahoo.com"
imap_host = "imap.mail.yahoo.com"
imap_port = 993
auth_method = "password"
Generic IMAP — your own server, Dovecot, Exchange on-prem, …
Anything that speaks IMAP with a plain password (or app password) works the same way.
[[accounts]]
name = "self-hosted"
email = "you@yourdomain.com"
imap_host = "mail.yourdomain.com"
imap_port = 993
auth_method = "password"
Then:
localmail add-account self-hosted
localmail connects over implicit TLS only (the port
993 style, TLS from the first byte) and verifies the
server certificate. There is no STARTTLS (port 143)
support and no config knob to skip verification. If your server uses a
self-signed certificate, add its CA to your operating system's trust store
so verification passes.
Filtering folders
You almost always want to skip Trash and Junk — they're noise. Three
knobs are available on each [[accounts]] entry:
| Knob | What it does | When to use |
|---|---|---|
folder_allow |
Whitelist by exact folder name. | You only care about a few folders (e.g.
["INBOX", "Archive"]). |
folder_deny |
Blacklist by exact folder name. | You want everything except a few folders. Brittle —
the folder name "Trash" on Fastmail is
"[Gmail]/Bin" on Gmail. |
folder_deny_flags |
Blacklist by RFC 6154 IMAP special-use flag. | Preferred. Provider-independent. Common
values: "\\Trash", "\\Junk",
"\\All", "\\Drafts". |
Use double backslashes inside TOML strings — the IMAP flag literally
starts with \, and TOML treats \ as an escape.
Test, then run a full sync
For each account you added, do a small sync first to confirm everything works:
localmail sync --account work-fastmail --limit-per-folder 50
Then drop the limit to mirror the rest. The next page describes long-running options.
From here on, the manual is reference material. Pick whichever interface you'd like to start with: the daemon for an always-on mirror, the CLI for scripted sync and search, the admin web UI to manage accounts and users from a browser, or the desktop app for a window to read your archive.