Man page
The mailfire(1) manual page, as installed with the packages and the Homebrew cask.
After a package or Homebrew installation, read it with man mailfire; in a source checkout, use
man ./docs/mailfire.1.
| MAILFIRE(1) | User Commands | MAILFIRE(1) |
NAME
mailfire - send email from the command line via Mailgun, Gmail, or SMTP
SYNOPSIS
mailfire [send] [flags]
mailfire [send] --preview path [flags]
mailfire validate [--json] [-c path]
mailfire resend [--list | --force | id...]
[--json] [-c path]
mailfire auth login | status | refresh |
logout --provider gmail [flags]
mailfire queue list | stats [--json] [-c
path]
mailfire queue show [--raw] [--json] id [-c
path]
mailfire queue delete id... [--json] [-c
path]
mailfire version [--json]
mailfire export-templates [--json] folder
mailfire -h | --help
DESCRIPTION
mailfire sends email from the command line through one of three providers, selected with [sending].provider: the Mailgun HTTP API (the default), the Gmail API with send-only OAuth authorization, or standard SMTP submission to an existing email provider or local relay. The message body is read from piped standard input, a regular file with --file, or an explicit string with --message. Plain text, Markdown, and HTML bodies are supported; Markdown and HTML are rendered into a built-in, responsive email template or a custom template file.
Without a subcommand, send is assumed. On success the message ID is printed to standard output: Mailgun's or Gmail's ID, or for SMTP the Message-ID header Mailfire generated. For SMTP, success means the submission server accepted the message (a 250 reply), not that it reached the recipient's mailbox.
If sending fails because of a network error, a temporary server error, or rate limiting, the composed message is stored for later retrying with mailfire resend (unless deferral is disabled).
SUBCOMMANDS
- send
- Compose and send an email. This is the default subcommand.
- validate
- Check, step by step, that the configuration file is found and valid TOML (or that MAILFIRE_* environment variables replace it), that all mandatory keys are well-formed, and that the selected provider accepts the credentials: Mailgun checks the API key and domain; SMTP connects, negotiates TLS, and authenticates without issuing MAIL, RCPT, or DATA (no recipient is probed); Gmail checks the stored authorization, refreshing it when it is about to expire. No mail is sent.
- auth
- Manage the Gmail authorization; see GMAIL AUTHORIZATION.
- resend
- Retry deferred messages, oldest first. A message is removed only after successful delivery. Messages that are not yet eligible for a retry are skipped unless --force is given; see DEFERRED MESSAGES.
- queue
- Inspect and delete deferred messages without sending. queue list shows each message with its attempt count and next retry; queue show id shows its recipients, subject, age, attempts, last error, and next retry; queue stats shows totals; queue delete id... deletes the given messages. list, show, and stats never send, change, or remove messages.
- version
- Print the version, commit, and build date.
- export-templates folder
- Export all four built-in templates as self-contained, editable HTML template files. Creates the folder if needed and refuses to overwrite existing template files. No configuration or provider credentials are required.
Every subcommand accepts -h and --help.
OPTIONS
Flags of send
- --to addr
- Recipient, repeatable. Required, at least once, unless --preview is given. Accepts user@example.com or Name <user@example.com>. Comma-separated lists are not supported, because commas are legal in display names.
- --cc addr
- Carbon copy recipient, repeatable.
- --bcc addr
- Blind carbon copy recipient, repeatable.
- --from addr
- Sender; overrides the from setting of the configuration file. Required if the configuration file does not set from.
- --subject text
- Subject line. Required unless --preview is given.
- --txt
- Body is plain text. This is the default.
- --md
- Body is Markdown, rendered into the selected template. A plain-text alternative is sent as well. Local images referenced as  are attached and displayed inline; remote image URLs are left untouched.
- --html
- Body is an HTML fragment, wrapped in the selected template. A plain-text alternative is derived from it.
- --html-raw
- Body is a complete HTML document, sent as-is. A plain-text alternative is derived from it.
Exactly one of the four body format flags may be given.
- --file path
- Read the body from a file instead of standard input. Only regular files are accepted; named pipes and devices are refused.
- --message text
- Use an explicit body string instead of standard input. Aliases: --m and -m. Cannot be combined with --file, even when either value is empty. Terminal standard input is never read. An empty body is permitted only with attachments; otherwise the error is "mail body missing: use stdin, --file or --message". Piped input is still read when attachments are supplied.
Sender and recipient mailboxes require dotted DNS domains with valid, nonempty labels and no leading or trailing hyphens. Quoted names and local parts, plus addresses and Unicode are supported. No DNS lookup is performed. Invalid input is rejected before sending and is never deferred.
- --template name
- Email template: card (default), card-serif, plain or plain-serif. Overrides template or template_file in the [sending] section of the configuration file. Only with --md or --html.
Cannot be combined with --template-file.
- --template-file path
- Use a custom Go text/template file, overriding the configured template. Only with --md or --html. Cannot be combined with --template, even when either value is empty. Paths support a leading ~; relative paths use the current working directory. Available fields are .Subject, .Lang (default en), .Preheader, .Body and .Footer. Escape plain text with {{html .Subject}} or {{html .Preheader}}; insert HTML with {{.Body}} and {{.Footer}}. CSS is inlined and Outlook conditional comments are preserved.
- --preheader text
- Hidden inbox preview text. Only with --md or --html.
- HTML fragment appended as footer. Only with --md or --html.
- --attach path
- Attach a file, repeatable.
- --test
- Use Mailgun test mode: the API validates the request, but nothing is delivered. Test sends are never deferred. SMTP and Gmail have no validation-only mode, so --test is a usage error with them rather than a real delivery; use validate or --preview instead.
- --no-defer
- Fail immediately instead of storing the message for a later resend.
- --timeout duration
- Per-request timeout of the selected provider: for Mailgun and Gmail the API request (connection setup, upload, response; for Gmail also a token refresh), for SMTP the whole connection and transaction (connect, TLS, authentication, submission). Accepts Go duration syntax such as 15s or 1m. Overrides the provider's timeout setting ([mailgun], [smtp], or [gmail]); the default is 30 seconds.
- --dedup-key key
- Skip repeats of this notification: a send with the same key, sending domain, and recipients is skipped (exit status 0) within the cooldown after a delivery, while an earlier one is deferred, or for one minute after an interrupted attempt. See NOTIFICATION DEDUPLICATION.
- --cooldown duration
- Suppression window started by this send when it is delivered, such as 30m. Requires --dedup-key. Overrides [dedup].cooldown; the default is one hour.
- --preview path
- Render the body locally and write the HTML to path instead of sending; with -, write only the HTML to standard output. See LOCAL PREVIEW.
- --json
- Print the result as one JSON document on standard output; see JSON OUTPUT. Cannot be combined with --preview.
- -c, --config path
- Use this configuration file instead of searching the default locations.
- -h, --help
- Show help.
Flags of resend
- --list
- Show deferred messages (ID, date, to, subject, size) without sending.
- --force
- Ignore the cooldown and backoff. With id arguments, also retry messages that were rejected permanently.
- --timeout duration
- Per-request timeout for each resent message, as for send; it overrides the timeout of the provider each message is resent through. A run retrying several messages may therefore take longer than a single timeout.
- --json
- Print the result, or with --list the listing, as one JSON document; see JSON OUTPUT.
- -c, --config path
- Use this configuration file.
- -h, --help
- Show help.
Without further arguments all eligible deferred messages are retried; with one or more id arguments only those messages are retried. --list cannot be combined with IDs.
Flags of queue
- --raw
- For show: print the stored request (message content, attachments included) instead of the metadata. It never contains credentials.
- --json
- Print the result as one JSON document; see JSON OUTPUT. With show --raw, the stored request is included base64-encoded.
- -c, --config path
- Use this configuration file.
- -h, --help
- Show help.
queue delete validates all IDs first: if any is unknown, it reports them and deletes nothing.
Flags of validate
- --timeout duration
- Timeout of the provider check; overrides the provider's timeout setting.
- --json
- Print the result as one JSON document; see JSON OUTPUT.
- -c, --config path
- Use this configuration file.
- -h, --help
- Show help.
Flags of auth
- --provider gmail
- The provider to authorize (required).
- --no-browser
- login: print the consent URL instead of opening a browser, plus an SSH port-forwarding hint.
- --port port
- login: listen for the OAuth callback on this local port instead of a random one, so it can be forwarded over SSH.
- --manual
- login: read the callback URL from standard input instead of receiving it (requires --port).
- --timeout duration
- Token request timeout; overrides [gmail].timeout.
- --json
- status, refresh, logout: print the result as one JSON document.
- -c, --config path
- Use this configuration file (only its [gmail] section is read).
Flags of version and export-templates
- --json
- Print the result as one JSON document; see JSON OUTPUT.
- -h, --help
- Show help.
CONFIGURATION
mailfire reads a TOML configuration file. The first existing file of the following locations is used:
Linux and macOS:
./.mailfire.conf $HOME/.config/mailfire/mailfire.conf /etc/mailfire/mailfire.conf
Windows:
.\.mailfire.conf %APPDATA%\mailfire\mailfire.conf %PROGRAMDATA%\mailfire\mailfire.conf
The option --config overrides the search. Environment variables override individual settings and can replace the file; see ENVIRONMENT. Strings must be quoted. On Linux and macOS a warning is printed when the file is accessible by group or others; fix it with chmod 600.
A system-wide configuration is usually insecure, because anyone who can read it can use the API key.
[mailgun]
- api_key
- String, mandatory. The Mailgun API key.
- region
- String, mandatory. Either us or eu.
- timeout
- Duration string, optional, default 30s. Per-request timeout for Mailgun API calls, covering connection setup, upload, and response reading. Empty, zero, negative, and malformed values are rejected. Can be overridden with --timeout. A resend run retrying several messages may take longer than a single timeout.
[sending]
- provider
- String, optional, default mailgun. Either mailgun or smtp. Existing configurations continue using Mailgun unless this is set to SMTP.
- domain
- String, mandatory. The sending domain as configured at Mailgun, or the stable Mailfire sending and deduplication domain for SMTP.
- from
- String, optional. Default sender, either user@example.com or My Name <user@example.com>. Can be overridden with --from. If not set, --from is mandatory.
- template
- String, optional, default card. Email template for --md and --html: card, card-serif, plain or plain-serif. Can be overridden with --template or --template-file. Mutually exclusive with a nonempty template_file.
- template_file
- String, optional. Custom template path for Markdown and HTML bodies. Mutually exclusive with a nonempty template. Either template flag overrides this setting. A leading ~ is expanded; relative paths use the current working directory.
[smtp]
Used only when [sending].provider is smtp. No Mailgun API key or domain registration is required for SMTP submission.
- host
- SMTP server hostname, mandatory for SMTP.
- port
- SMTP server port from 1 through 65535, mandatory for SMTP.
- security
- Mandatory for SMTP: tls for implicit TLS (normally port 465), starttls for required STARTTLS (normally port 587), or none only for an explicitly trusted local plaintext relay. Mailfire never falls back to plaintext when STARTTLS is unavailable or fails.
- username, password
- Optional SMTP username/password pair. Both must be set together. Passwords are never stored in deferred messages, logs, diagnostics, or JSON output. Credentials are refused for security = none. Common PLAIN, LOGIN, and CRAM-MD5 mechanisms are selected only after TLS.
- timeout
- Optional positive duration. It covers connection setup, TLS, authentication, and SMTP submission. It is overridden by --timeout.
SMTP acceptance (a 250 response after DATA) confirms only that the submission server accepted the transaction; it does not prove final recipient delivery. If any recipient is rejected at RCPT TO, the transaction is aborted before DATA, so nobody receives a partial send; the error names the recipient. Account setup is provider-specific: Gmail and other large providers usually require an app password (or OAuth, see [gmail]); an ordinary account password is not a supported shortcut.
[gmail]
Used by [sending].provider gmail and by mailfire auth.
- credentials
- Optional path of the owner-only credential file; default $HOME/.config/mailfire/gmail-credentials.json (%APPDATA%\mailfire\gmail-credentials.json on Windows).
- timeout
- Optional positive duration for Gmail API and token requests; overridden by --timeout.
[logging]
- logfile
- String, optional. Logging is disabled unless a logfile is given. One JSON object per sending attempt is written per line.
- loglevel
- String, optional, default information.
- error
- Failed attempts only: time, message ID, recipients, status code.
- information
- Time, message ID, recipients, subject, status code.
- debug
- Time, message ID, sender, recipients, subject, message size, status code, API response body.
- max_size
- String, optional, default 50M. When exceeded, the oldest log lines are removed. Accepts a number of bytes or a K, M, or G suffix.
[defer]
- defer
- Boolean, optional, default true. Store messages whose delivery failed for a later retry.
- defer_dir
- String, optional. Directory for deferred messages; created on demand. Defaults to $HOME/.local/share/mailfire (%LOCALAPPDATA%\mailfire on Windows).
- max_size
- String, optional, default 50M. When exceeded, the oldest deferred messages are removed.
- resend_cooldown
- Duration string, optional, default 5m. Wait after deferral before mailfire resend retries a message; also the base of the retry backoff.
- max_age
- Duration string, optional, no default. When set (for example 168h), messages deferred longer ago are removed whenever a message is deferred or mailfire resend runs, and each removal is reported. resend checks the age again right before each retry, so a message that exceeds max_age during a run is removed rather than sent. Without it, messages are kept until sent or deleted, subject to max_size.
[dedup]
- state_dir
- String, optional. Directory for notification deduplication state; created on demand. Independent of the [defer] settings: deduplication also works with defer = false. Defaults to $HOME/.local/share/mailfire/dedup (%LOCALAPPDATA%\mailfire\dedup on Windows). Inside defer_dir only its subdirectory dedup may be used; symbolic links are resolved for this check.
- cooldown
- Duration string, optional, default 1h. How long a delivered notification suppresses repeats with the same --dedup-key. Can be overridden with --cooldown.
Example
[mailgun]
api_key = "<your-api-key>"
region = "eu" [sending]
domain = "example.com"
from = "My Name <user@example.com>" [logging]
logfile = "~/logs/mailfire.log"
loglevel = "information"
max_size = "100M" [defer]
defer = true
max_size = "100M"
resend_cooldown = "5m"
DEFERRED MESSAGES
A deferred message becomes eligible for mailfire resend once resend_cooldown has passed. Each failed retry doubles the wait, measured from the latest attempt and capped at one hour; a cooldown longer than one hour is used unchanged. The stored message is never changed; only its retry information (attempts, last attempt, last error) is recorded. Messages deferred by older versions have no retry information and are treated as never retried.
A message that Mailgun rejects permanently is kept, marked failed, and skipped by later runs. Retry it with mailfire resend --force id or remove it with mailfire queue delete id.
Concurrent mailfire processes coordinate through the lock file .lock in the defer directory, so overlapping runs cannot resend or delete the same message twice. Exactly-once delivery is still not guaranteed: when a request times out or the connection drops after Mailgun accepted the message, it stays deferred and a later resend may deliver it again.
A deferred message records the provider and the non-secret account it was sent through (the Mailgun domain; the SMTP username, host, port, and security mode; the Google account ID) and is resent through that provider with its current credentials, even when the default provider changed meanwhile. SMTP messages also keep their envelope (Bcc recipients included) and their Message-ID, which stays the same on every retry. Credentials are never stored with deferred messages. If the provider is no longer configured or a different account is configured, the message is not attempted; it stays queued with unchanged retry state and is resent normally once the configuration is restored.
Duplicates are possible with every provider: when the connection drops or times out after the server accepted the message (for SMTP, a lost final reply after DATA), the outcome is unknown, the message stays deferred, and a later resend may deliver it again.
GMAIL AUTHORIZATION
mailfire auth login --provider gmail opens Google's consent page (installed-app loopback flow with PKCE and state validation) and stores the access token, its expiry, and the refresh token in the credential file (mode 0600). Only the gmail.send scope is requested, plus openid, which yields only an opaque account ID used to bind deferred messages to the account; no mailbox or profile access is requested. Access tokens are refreshed automatically before sends; sends and refreshes never open a browser.
auth refresh exchanges the refresh token even when the cached access token is still valid, without sending mail or touching the queue. Google may expire refresh tokens unused for six months; schedule a monthly refresh for infrequent senders under the same user as the sends. Refreshing cannot prevent revocation, password or policy changes, or the seven-day limit of OAuth apps in testing mode. auth status shows whether credentials exist, auth logout removes them locally (it does not revoke Google's grant).
Gmail sends only as the authenticated account or its configured send-as aliases and enforces its own sending and size limits.
LOCAL PREVIEW
send --preview path renders the message body through the same pipeline as a send (Markdown, template, preheader, footer, and CSS inlining) and writes the result to path, or to standard output for -. Unlike --test, which asks Mailgun to validate a complete request, a preview never contacts Mailgun and needs no configuration file, Mailgun settings, recipients, sender, or subject. Only the template selection is read from a configuration file, MAILFIRE_SENDING_TEMPLATE, or MAILFIRE_SENDING_TEMPLATE_FILE; other settings and variables are ignored. Supplied addresses and subjects are still checked. Nothing is sent, deferred, deduplicated, or logged.
- --md and --html produce the rendered HTML part. Local Markdown images are embedded as data: URLs, so the preview is one portable file; remote image URLs are unchanged. A send attaches local images instead.
- --txt shows the escaped body in a <pre> block.
- --html-raw writes the supplied document unchanged.
An existing output file is replaced atomically, keeping its permissions, but only after rendering succeeded; a failed preview leaves it untouched. A symbolic link as output is followed; a link to a missing file is refused and left unchanged. An output that is one of the inputs (body file or standard input redirected from a file, footer, template, Markdown image, or configuration file), also through a symbolic or hard link, is refused. With --preview -, diagnostics go to standard error; use ./- for a file named -.
--attach, --test, --no-defer, --timeout, --dedup-key, and --cooldown only affect sending and are rejected with --preview. --json is rejected too: a preview writes HTML, not a command result. A failed preview exits with status 1, or with 2 for an invalid configuration file or template setting.
JSON OUTPUT
With --json, send, resend (also with --list), queue, validate, version, and export-templates print exactly one JSON document on standard output, on one line, instead of the human-readable output; also for failures, including invalid invocations, whenever the command line contains a --json flag. --json counts only where it is read as a flag: not as the value of another flag and not after a -- terminator. Every document has schema_version (currently 1), command, outcome, and exit_code; when the exit status is not 0, an error object adds a stable code (such as usage_error, config_error, auth_failed, temporary_failure, or rejected) and a human-readable message. Timestamps are RFC 3339 in UTC. Exit statuses are unchanged. Diagnostics and warnings stay on standard error, and --help always prints text. Documents never contain the API key or message content, except the stored request with queue show --raw --json.
resend reports one record per message (sent, skipped, failed, or expired) and a summary; its outcome is partial when some messages were sent and others failed. The full schema, error codes, and compatibility rules are documented at https://mailfire.system42.io/reference/json-output/.
NOTIFICATION DEDUPLICATION
Deduplication is opt-in: only sends with --dedup-key are checked. A notification is identified by the key, the sending domain, and all recipients (to, cc, and bcc, compared case-insensitively in any order); different keys, domains, or recipients never interfere. A send is skipped, with exit status 0 and a line starting with skipped: on standard output that says when it becomes eligible again, while
- the same notification was delivered within its cooldown (the --cooldown or cooldown of the delivered send; skipped repeats do not extend it),
- the same notification is still deferred, even if marked permanently rejected (retry it with resend --force or remove it with queue delete): the first deferred message is kept and no duplicate is queued, or
- an attempt was interrupted (for example by a crash) less than one minute ago and may have been delivered.
Only a delivery starts the cooldown, by send or by a successful resend. Failed and deferred sends do not, and --test sends neither check nor start it. If the system clock moves backward, affected cooldowns end immediately. A concurrent send of the same notification waits until the first one's outcome is recorded, so the two cannot both slip through. Corrupt or unreadable state is an error and nothing is sent: send exits with status 2. resend keeps a deferred notification whose state it cannot use (unsafe state_dir, corrupt or unreadable state, a lock failure) queued without sending it, reports it as failed, and exits with status 5. Remove the named file to reset that notification.
To send a repeat anyway, omit --dedup-key. resend --force is unrelated: it ignores the retry wait of deferred messages, not the notification cooldown.
ENVIRONMENT
Every configuration setting can be supplied through an environment variable named MAILFIRE_SECTION_KEY, using the uppercased TOML names. Precedence, highest first: command-line options, environment variables, the configuration file, defaults. A setting supplied by a command-line option ignores its environment and file values without validating them. Exception: setting both MAILFIRE_SENDING_TEMPLATE and MAILFIRE_SENDING_TEMPLATE_FILE to nonempty values is always a configuration error, even with --template or --template-file. Values use the same syntax and validation as in the configuration file. Empty or whitespace-only variables are treated as unset and never clear a file setting or default.
When no configuration file is found and at least one variable is set, the environment is the only source; it must then supply the selected provider's required settings (Mailgun: API key, region, and domain; SMTP: host, port, security, and domain; Gmail: nothing beyond the provider). A file given with --config must still exist and be valid.
- MAILFIRE_MAILGUN_API_KEY
- MAILFIRE_MAILGUN_REGION
- MAILFIRE_MAILGUN_TIMEOUT
- The [mailgun] settings.
- MAILFIRE_SMTP_HOST
- MAILFIRE_SMTP_PORT
- MAILFIRE_SMTP_SECURITY
- MAILFIRE_SMTP_USERNAME
- MAILFIRE_SMTP_PASSWORD
- MAILFIRE_SMTP_TIMEOUT
- The [smtp] settings.
- MAILFIRE_GMAIL_CREDENTIALS
- MAILFIRE_GMAIL_TIMEOUT
- The [gmail] settings.
- MAILFIRE_GMAIL_CLIENT_ID
- MAILFIRE_GMAIL_CLIENT_SECRET
- Developer override of the built-in Google OAuth client; not needed for normal use.
- MAILFIRE_SENDING_PROVIDER
- MAILFIRE_SENDING_DOMAIN
- MAILFIRE_SENDING_FROM
- MAILFIRE_SENDING_TEMPLATE
- MAILFIRE_SENDING_TEMPLATE_FILE
- The [sending] settings. A nonempty template variable replaces the file's template or template_file selection; setting both variables is always an error, even with a template option. --template and --template-file override a single template variable, even an invalid one.
- MAILFIRE_LOGGING_LOGFILE
- MAILFIRE_LOGGING_LOGLEVEL
- MAILFIRE_LOGGING_MAX_SIZE
- The [logging] settings.
- MAILFIRE_DEFER_DEFER
- MAILFIRE_DEFER_DEFER_DIR
- MAILFIRE_DEFER_MAX_SIZE
- MAILFIRE_DEFER_RESEND_COOLDOWN
- MAILFIRE_DEFER_MAX_AGE
- The [defer] settings. MAILFIRE_DEFER_DEFER accepts true or false.
- MAILFIRE_DEDUP_STATE_DIR
- MAILFIRE_DEDUP_COOLDOWN
- The [dedup] settings. --cooldown overrides the environment.
Errors name the variable that supplied an invalid value. mailfire validate reports where settings came from; credentials are never shown.
EXIT STATUS
- 0
- Success (sent, validated, resent, or information shown).
- 1
- Usage error: missing flags, unknown subcommand, conflicting formats.
- 2
- Configuration error: missing file, invalid TOML, missing or invalid keys.
- 3
- Authentication error: credentials were rejected (Mailgun 401 or 403, SMTP 535), or Gmail is not authorized (not logged in, or the authorization was revoked or expired).
- 4
- Sending failed and the message was deferred for a later mailfire resend.
- 5
- Sending failed and the message was not deferred (--no-defer or defer = false).
Exit status 5 is also used when the provider rejects a message permanently (any other Mailgun or Gmail 4xx response, an SMTP 5xx reply such as a rejected recipient, missing STARTTLS, or an untrusted certificate), when a --test send fails with a retryable error (test sends are never deferred), and when the message cannot be stored in the defer directory. validate exits with 4 when the provider cannot be reached reliably (the check can be retried later), and with 2 when Mailgun does not know the domain. auth exits with 3 when Gmail is not authorized and 4 for a transient token endpoint failure. resend returns the most severe outcome of all attempts, ranked 3, 5, 4, 0; a message that fails with 4 stays deferred. queue exits with 1 for an unknown message ID and with 5 when the defer directory cannot be read or a message cannot be deleted. send exits with 0 when --dedup-key skips a repeated notification, and with 2 when the deduplication state cannot be used. --preview exits with 1 when rendering or writing the output fails.
Errors are written to standard error in plain language, naming the failing step. With --json, the JSON document reports the same exit status in exit_code.
EXAMPLES
Export and use a custom template:
mailfire export-templates ./my-templates mailfire --md --template-file ./my-templates/card.html \
--to user@example.com --subject "Report" --file report.md
Preview a custom template locally, without credentials:
mailfire --md --template-file ./my-templates/card.html \
--footer footer.html --file report.md --preview report.html
Send a Markdown message from standard input:
mailfire --md --to user@example.com --subject "Have a nice day" <<EOF # This is an Email It is written in markdown. It's delivered as HTML. EOF
Send files as attachments:
mailfire --to user@example.com --subject "The files" \
--attach ~/doc1.pdf --attach ~/image.png
Verify configuration and payload without delivering anything:
mailfire --test --to user@example.com --subject "Test" <<< "Hello"
Check configuration and credentials:
mailfire validate
List, then retry deferred messages:
mailfire resend --list mailfire resend
Alert at most once per 30 minutes, for example from a monitoring check:
mailfire --dedup-key disk-full-db1 --cooldown 30m \
--to ops@example.com --subject "Disk full on db1" <<< "df: 98%"
Inspect and delete a deferred message:
mailfire queue stats mailfire queue show 20261015T123045.123456789-9f3ab2c17e4d88aa mailfire queue delete 20261015T123045.123456789-9f3ab2c17e4d88aa
Use the JSON output in scripts:
mailfire --json --to ops@example.com --subject "Backup" --message ok \
| jq -r .message_id mailfire queue list --json \
| jq -r '.messages[] | select(.status == "failed") | .id'
FILES
- ./.mailfire.conf
- $HOME/.config/mailfire/mailfire.conf
- /etc/mailfire/mailfire.conf
- Configuration file locations on Linux and macOS, in search order.
- %APPDATA%\mailfire\mailfire.conf
- %PROGRAMDATA%\mailfire\mailfire.conf
- Configuration file locations on Windows, after .\.mailfire.conf.
- $HOME/.config/mailfire/gmail-credentials.json
- Default Gmail credential file (%APPDATA%\mailfire\gmail-credentials.json on Windows).
- $HOME/.local/share/mailfire
- Default directory for deferred messages (%LOCALAPPDATA%\mailfire on Windows).
- $HOME/.local/share/mailfire/dedup
- Default directory for notification deduplication state (%LOCALAPPDATA%\mailfire\dedup on Windows).
SEE ALSO
Documentation: https://mailfire.system42.io
Source code and issues: https://github.com/thorstenkramm/mailfire
AUTHOR
Thorsten Kramm.
| October 17, 2026 | mailfire |