Frequently Asked Questions
Common questions and troubleshooting.
General
Config file not found
Run mp config init to create the config file at
~/.config/mailypoppins/config.toml. The interactive wizard will walk you through
SMTP/IMAP credentials, test connections, discover server mailboxes, and assign roles.
Password not found in keyring
Run mp config set-password to store your SMTP or IMAP password in the
OS keyring (macOS Keychain, Windows Credential Manager, or Linux Secret Service).
Passwords are never stored in the config file.
Email not approved for sending
The draft workflow requires explicit approval before sending. Run
mp mark-approved <selector> to change a draft's status from
draft to approved; only approved emails can be sent. In the
TUI, x approves and sends the current draft in one step. To reverse an
accidental approval, run mp mark-draft <selector> and the draft is
editable again.
SMTP authentication failed
Check your credentials with mp config show and re-run
mp config set-password smtp if needed. For OAuth2 accounts, try
mp config oauth2-login to refresh the token.
My draft came out without a signature
A signature is a Markdown file in ~/.config/mailypoppins/signatures/,
and the account needs one of them set as its default.
mp config show prints the directory, the current default, and every
file it found; press cs in the TUI to set the default, or to create
a signature if there is none yet.
mp warns that my [accounts.signatures] tables are dead
Signatures moved out of config.toml into their own Markdown files.
The first run after the upgrade copied your entries to
~/.config/mailypoppins/signatures/ and kept the account default.
mailypoppins does not edit config.toml for you: delete the
[accounts.signatures] tables yourself and the notice stops.
Read the notice before you delete anything. It lists any entry that could not be copied out, and those tables are the only place that content still exists.
I want one row per message, not per conversation
By default the list groups each mailbox by conversation. Press tc (or
run "Conversation view on / off for this account" from the command palette) to list
the account one row per message; press it again to group it once more. The TUI keeps
the choice per account in ~/.config/mailypoppins/tui.json as
{"flat_list_accounts": ["work"]}. The desktop app keeps its own
choice in its local preferences, and tc, the palette and the
"Conversation view" switch on the account's Settings card all change it. The Drafts
mailbox always lists one draft per row.
I forgot a key binding
Press : or Ctrl+p to open the command palette, type part of
an action's name and press Enter to run it against the current context.
Keys are grouped in mnemonic families (c compose, t thread,
conversation view and attachments, f find, s sync and settings, g
go-to), so pressing a leader alone pops up a which-key list of its continuations.
? shows the full catalogue, and mp dump-keys prints the same
table outside the TUI.
OAuth2 / Exchange
IMAP is disabled for my organization
Your Microsoft 365 tenant may have IMAP disabled. Contact IT to enable it, or use
auth_method = "graph" in your account config, which bypasses IMAP/SMTP
entirely and uses the Microsoft Graph API for all mail operations.
Needs admin consent for API permissions
The IMAP.AccessAsUser.All and SMTP.Send permissions often
require admin consent. Request your IT administrator to grant consent via Azure portal
> Entra ID > App registrations > API permissions.
OAuth2 token expired
Run mp config oauth2-login --account <name> to re-authenticate.
Access tokens expire after roughly one hour and are auto-refreshed, but refresh tokens
expire after approximately 90 days of inactivity.
AUTHENTICATE failed with OAuth2
This can mean IMAP is disabled for the account, the token has wrong scopes, or admin
consent is missing. Check the app permissions in Azure and ensure IMAP is enabled. If
your tenant blocks IMAP, consider switching to auth_method = "graph".
Sync and Workflow
How does sync work?
mp sync is additive by default: it only downloads new emails,
deduplicating by Message-ID. It uses a two-pass approach: first fetches headers (~50
bytes per message) to check what is new, then downloads full messages only for emails
not already stored locally.
What happens to messages deleted on the server?
The same sync pass prunes them. Every sync enumerates the whole mailbox even when it downloads only the newest messages, so a message the server no longer lists is removed from the local store whatever its age, and a mailbox cleaned up in another client converges on the next sync.
One pass holds removals back: the one that could not bring in everything that landed
since the previous sync, because a message missing from the store is not evidence that
it is gone from the server. The status line says so when it happens
(N removal(s) held back), and the next complete pass applies them. A
first sync is such a pass by definition, since nothing local is known yet: that covers
a brand-new account, and equally the first sync of an account you have had for months
after an upgrade rebuilds its local store.
A message that was moved converges as soon as the sync has read the copy in
its destination. On servers that issue a new identifier on a move (Exchange, Dovecot)
that is the same pass. On Gmail, archiving only removes the Inbox label and the copy
in All Mail keeps its original, old identifier, so a capped sync will not see it
again: the inbox row goes and the archived copy is re-filed by the next full sync
(sS in the TUI).
Can I use mailypoppins with multiple accounts?
Yes. Use the [[accounts]] array in config.toml. Each account
has its own SMTP/IMAP settings, local store, and mailboxes. Switch between accounts in
the TUI with ga.
How are attachments handled?
Incoming attachments are stored as blobs beside the message row, not as files you
browse. Use to in the TUI to open one (it is written to a private temp
directory first), ts to save it to a directory you choose, or
mp save from the CLI. For outgoing drafts, list file paths in the
attachments: frontmatter field, or point one entry at a folder to attach
every file inside it; forwarding a message
materialises its attachments under the account's
attachments/ directory and lists those paths for you.
Can I take a send back?
A send from the TUI is parked for email.send_hold_secs (default 20
seconds) before it reaches the transport. The status line shows the countdown and
u cancels it: nothing is transmitted and the approved draft stays in
place to edit or send again. Set send_hold_secs = 0 under
[email] to hand off immediately. The hold covers both SMTP and Graph
accounts; mp send and the batch send-approved run are never held.
Does it support HTML emails?
Outgoing emails are written in Markdown and converted to HTML for sending, with a
plaintext fallback. For incoming mail both parts are kept as blobs beside the message
row. In the preview pane an HTML message is shown as the plain text extracted from it
when the message was stored, word-wrapped like any other body, so its links, emphasis,
tables and lists come through as flat text. Press tb in the TUI to open the
original HTML in your browser when you want the sender's layout. On a draft, tb
opens the HTML it will be sent as, signature and quoted reply included.