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:

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.

A third auth method: 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).

After every edit

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.

  1. Create a Google Cloud project.

    Visit console.cloud.google.com/projectcreate. Pick any name. No billing required.

  2. 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 this

    OAuth consent screen → AudienceTest 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_denied at 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.

  3. Enable the Gmail API.

    APIs & Services → Library → Gmail API → Enable.

  4. 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
  5. 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"]
  6. Run the consent flow.

    localmail oauth-login horst-gmail

    A 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-login on its shell. It needs [serve].state_signing_key and [serve].oauth_callback_url set (a redirect URI you also register in the Google Cloud console). The CLI flow above needs neither.

  7. Test it.

    localmail sync --account horst-gmail --limit-per-folder 10

    This 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

  1. Turn on two-step verification.

    Required before you can create an app password. Visit account.microsoft.com/security → Advanced security options → Two-step verification.

  2. 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.

  3. 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"]
  4. 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.

  1. 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).

  2. 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.

  1. Install Proton Mail Bridge.

    Download from proton.me/mail/bridge. Requires a paid Proton plan (Plus, Unlimited, etc.).

  2. 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 like 1143), username (your Proton email), and a Bridge password (machine-generated; different from your Proton password).

  3. 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 trusted

    localmail 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.

  4. Store the Bridge password.

    localmail add-account proton
    # Paste the Bridge password from the Bridge UI.
Bridge must be running

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.

  1. 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.

  2. 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.

[[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
TLS is mandatory and verified

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.

You're done with setup

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.