Skip to content

Email Notifications

Overview

Valid syntax is as follows:

  • mailto://{user}:{password}@{domain}
  • mailto://{user}:{password}@{domain}:{port}
  • mailto://{domain}?user={user}&pass={password}
  • mailto://{user}:{password}@{domain}/{to_email}
  • mailto://{user}:{password}@{domain}/{to_email1}/{to_email2}/{to_emailN}

Adding an s to the schema (i.e. mailtos://) switches to a secure STARTTLS connection (port 587 by default):

  • mailtos://{user}:{password}@{domain}
  • mailtos://{user}:{password}@{domain}:{port}
  • mailtos://{domain}?user={user}&pass={password}
  • mailtos://{user}:{password}@{domain}/{to_email}
  • mailtos://{user}:{password}@{domain}/{to_email1}/{to_email2}/{to_emailN}

Apprise automatically detects many email providers based on the From address derived from your URL.
When a provider is recognized, Apprise automatically configures:

  • SMTP host
  • Port
  • Secure mode (SSL or STARTTLS)
  • Login format (full email vs user id)

In most cases, you only need to provide your email and password.

ProviderExample URLNotes
Google (Gmail)mailto://user:app-password@gmail.comIf 2-Step Verification is enabled, generate an App Password: https://security.google.com/settings/security/apppasswords
Yahoomailto://user:app-password@yahoo.comRequires an App Password: https://help.yahoo.com/kb/SLN15241.html
Fastmailmailto://user:app-password@fastmail.comApp Password must permit SMTP. See supported domains here.
GMXmailto://user:password@gmx.netAlso supports gmx.com, gmx.de, gmx.at, gmx.ch, gmx.fr.
Zohomailto://user:password@zoho.comProvider defaults are applied automatically.
Yandexmailto://user:password@yandex.comLogin may be user-id based depending on domain rules.
SendGrid (SMTP)mailto://apikey:password@sendgrid.com?from=noreply@yourdomain.comfrom= must use a validated sender identity.
QQ / Foxmailmailto://user:password@qq.comProvider defaults are applied automatically.
163.commailto://user:password@163.comProvider defaults are applied automatically.
Microsoft (Outlook, Hotmail, Office 365)Use azure:// insteadMicrosoft disabled SMTP basic authentication. Use the azure:// plugin.

This is not an exhaustive list. Additional domains are automatically detected when supported.

Email addresses may be written as:

  • user@example.com
  • Optional Name<user@example.com>

This syntax works in:

  • URL targets
  • from=
  • cc=
  • bcc=
  • reply=

If you need spaces inside a URL, encode them as %20.

Example:

from=Optional%20Name<noreply@example.com>
What you specifyWhat happens
No targets and no to=Apprise sends the email to the sender address (the derived From email).
Targets in the URL pathEach target becomes a recipient.
to= in the query stringTreated as an additional recipient (same as adding a target).
cc= / bcc=Applied to each generated email.
reply=Sets the Reply-To header (can be multiple).

If your provider is not automatically detected, configure SMTP manually.

Defaults:

  • mailto://: defaults to port 25
  • mailtos://: defaults to port 587 using STARTTLS

Most public providers require TLS. Prefer mailtos:// for external servers.

Send using a custom SMTP host:

  • mailtos://user:password@server.com?smtp=smtp.server.com&from=noreply@server.com

Include a From display name:

  • mailtos://user:password@server.com?smtp=smtp.server.com&from=Optional%20Name<noreply@server.com>

Force SSL (usually port 465):

  • mailtos://user:password@server.com:465?smtp=smtp.server.com&mode=ssl&from=noreply@server.com

If you run Postfix, Exim, or another internal relay that does not require authentication, omit user and pass.

mailto://localhost?from=john@example.ca

Internal relay host:

mailto://relay-server?from=noreply@example.com&to=alerts@example.com

If the SMTP host differs from the URL host:

mailto://server.com?smtp=smtp.server.com&from=noreply@server.com

If you want to set a display name, you can use either:

  • from=Optional%20Name<noreply@example.com> (preferred)
  • name=Optional%20Name&from=noreply@example.com

If both are provided, the name embedded in from= takes precedence.

Email supports custom header injection by prefixing query keys with a plus symbol (+).

This is useful for mail filters, internal routing, and tagging.

Set:

  • X-Token: abcdefg
Terminal window
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailto://localhost?to=john@example.ca&+X-Token=abcdefg"

If you need to control some of the headers being sent to the mail server, you can simply generate keyword arguments that are prefixed with the plus (+) symbol.

For example, assuming you wanted to also pass along the following email headers (in your payload):

  • X-Token: abcdefg
  • X-Apprise: is great

You would structure your email like so:

Terminal window
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailto://localhost?to=john@example.ca&+X-Token=abcdefg&+X-Apprise=is%20great"
  • Header values must be URL-encoded when they contain spaces.
  • Apprise automatically sets X-Application and merges in any headers you define.

By default, mailto://user:pass@domain sends to user@domain unless to= is specified.

Send to multiple recipients using either query form or path form:

  • mailto://user:pass@domain/?to=target@example.com,target2@example.com
  • mailto://user:pass@domain/target@example.com/target2@example.com
  • mailto://user:pass@domain/Accounting<accounting@example.com>/Billing<billing@example.com>

There is no hard-coded limit to recipient count, though your SMTP server may impose one.

cc= and bcc= apply to every email sent. If you notify 3 recipients, the same cc and bcc lists are used for each generated email.

Attachments are fully supported.

SMTP provider limits may apply. Apprise does not impose attachment size restrictions.

Apprise supports two PGP modes for outbound email, selected with the ?pgp= parameter.

ModeWhat it does
pgp=noNo PGP (default).
pgp=signSigns the email using the sender’s private key. Opportunistically also encrypts if a recipient public key is available.
pgp=encryptEncrypts the email using the recipient’s public key. No signing.

Both modes require the pgpy Python package:

Terminal window
pip install pgpy

If pgpy is not installed, Apprise logs a warning and sends the message without PGP protection.

Signing proves the email came from you. Apprise creates a detached signature using your private key and wraps the email in a multipart/signed MIME container (RFC 3156).

Provide the path to your ASCII-armoured private key with pgpprv=:

mailtos://user:pass@example.com?pgp=sign&pgpprv=/path/to/my-prv.asc

If no private key is found at send time, the notification fails. If the key exists but is passphrase-protected, Apprise rejects it (passphrase-protected keys are not supported).

Apprise also searches the persistent storage directory automatically — it looks for a file named {email}-prv.asc, pgp-prv.asc, prv.asc, or pgp-private.asc. This means if you have previously placed a key there, no pgpprv= parameter is needed.

When pgp=sign is active and a recipient public key is also available, Apprise goes further: it signs the message first, then encrypts the signed result. The output is multipart/encrypted — the recipient gets end-to-end protection along with proof of sender authenticity.

Encryption is opportunistic — it only happens when a public key is found. If no public key is available, the email is sent as multipart/signed only, without encryption. Send never fails silently due to a missing public key in sign mode.

To trigger sign + encrypt, combine pgp=sign with WKD lookup or an explicit public key:

mailtos://user:pass@example.com?pgp=sign&wkd=yes&pgpprv=/path/to/my-prv.asc
mailtos://user:pass@example.com?pgp=sign&pgppub=/path/to/recipient-pub.asc&pgpprv=/path/to/my-prv.asc

When pgp=encrypt is set, Apprise encrypts the email body using the recipient’s public key before handing it to the SMTP server. No signature is applied. The server and any intermediate relays never see the plaintext.

mailtos://user:pass@example.com?pgp=encrypt&pgppub=/path/to/recipient-pub.asc

For public keys (used by pgp=encrypt and the opportunistic-encrypt step of pgp=sign), Apprise searches these sources in order and uses the first key it finds:

  1. Explicit key file — a .asc file supplied via pgppub=
  2. Web Key Directory (WKD) — automatic HTTPS lookup, enabled with wkd=yes
  3. Local key file — Apprise scans the persistent storage namespace directory for the filenames listed in the public key search table below
  4. Auto-generated key pair — created on first use when persistent storage is configured and pgp_autogen is enabled in the asset (only for pgp=encrypt; the opportunistic step of pgp=sign never auto-generates)

For private keys (used by pgp=sign), Apprise searches:

  1. Explicit key file — a .asc file supplied via pgpprv=
  2. Local key file — Apprise scans the persistent storage namespace directory for the filenames listed in the private key search table below

WKD (RFC 9080) is a standard that lets mail clients automatically fetch a recipient’s public key from their mail provider without any manual key exchange. If the recipient’s provider publishes their key via WKD, enabling wkd=yes is all that is needed — no key file, no manual import.

Setting wkd=yes automatically implies pgp=encrypt, so both of the following URLs are equivalent:

mailtos://user:pass@example.com?wkd=yes
mailtos://user:pass@example.com?pgp=encrypt&wkd=yes

Apprise tries two URL forms (subdomain method first, then direct method) and caches successful results in memory for the duration of the session. If neither URL returns a key, Apprise falls back to the next discovery method.

When no public key is found by any other method, Apprise generates a fresh RSA-2048 key pair and writes both files to the persistent storage namespace directory:

FileRole
{localpart}-pub.ascPublic key — used to encrypt outbound messages
{localpart}-prv.ascPrivate key — auto-discovered by pgp=sign mode

{localpart} is the part of the sender’s From address before @, lowercased. For user@example.com, the files are user-pub.asc and user-prv.asc.

Because keygen() writes the private key alongside the public key, a single pgp=encrypt send that triggers auto-generation also makes signing available automatically. Any subsequent pgp=sign URL pointing at the same storage discovers user-prv.asc without a pgpprv= parameter.

Auto-generation is enabled by default when persistent storage is configured. It can be disabled at the asset level by setting pgp_autogen = False. Note that pgp_autogen only affects pgp=encrypt — the opportunistic-encrypt step of pgp=sign never auto-generates keys.

Apprise stores key material inside a hashed namespace directory under storage_path. The directory name is an 8-character hash derived deterministically from the URL, so the same URL always maps to the same directory. Use pgppub= and pgpprv= to point at absolute paths anywhere on the filesystem when you prefer not to use the cache at all.

Public keys are matched against recipient email addresses (first match wins):

PriorityFilename example
1{recipient@domain.com}-pub.asc (full address, lowercased)
1{recipient}-pub.asc (local part only, lowercased)
2pgp-public.asc
2pgp-pub.asc
2public.asc
2pub.asc

Priority 1 entries are generated for each recipient in order; the baseline filenames (priority 2) are tried last.

Private keys are matched against the sender (From) address (first match wins):

PriorityFilename example
1{sender@domain.com}-prv.asc (full address, lowercased)
1{sender}-prv.asc (local part only — this is what keygen() writes)
2pgp-private.asc
2pgp-prv.asc
2private.asc
2prv.asc

Passphrase-protected private keys are rejected regardless of how they are discovered.

When you manage Apprise through a YAML configuration file, the pgppub= and pgpprv= parameters can be written as clean YAML sub-keys instead of being embedded inside a long URL string. Because both parameters are handled by the Apprise Attachment system, you can supply either a local file path or an HTTP/HTTPS URL:

urls:
- mailtos://user:pass@smtp.example.com/:
pgp: sign
pgpprv: /path/to/my-prv.asc
pgppub: http://internal.example.com/keys/recipient-pub.asc
wkd: "yes"

This is especially useful when key paths are long or contain characters that would need URL-encoding in a query string.

The simplest way to supply a key without using pgppub= or pgpprv= is to copy it into the cache namespace directory using one of the filenames from the search order tables above. Apprise picks it up automatically on the next send — no URL change required.

To find the namespace directory for a given URL, use apprise storage list:

Terminal window
apprise storage list "mailtos://user:pass@example.com"

The uid column in the output (e.g. 2a3f8b1c) is the 8-character namespace hash for that URL — the same identifier shown on the Apprise-API review tab. The full cache directory is {storage-path}/2a3f8b1c/. Copy your key file into that directory with a matching name — for example user@example.com-pub.asc for a public key, or user-prv.asc for a private key — and Apprise will find it without any pgppub= or pgpprv= parameter.

When you notify multiple recipients in one URL, Apprise sends a separate email per recipient and performs the key lookup independently for each one. This means every recipient can have their own public key pre-placed in the cache directory and will receive their own individually encrypted copy.

For example, to send a signed+encrypted email to both alice@example.com and bob@example.com:

Terminal window
# First, find the namespace directory for your sending URL
apprise storage list "mailtos://user:pass@smtp.example.com"
# Output: uid 2a3f8b1c → cache dir is {storage-path}/2a3f8b1c/

Copy each recipient’s public key into that directory using the full-address filename format:

Terminal window
cp alice-key.asc {storage-path}/2a3f8b1c/alice@example.com-pub.asc
cp bob-key.asc {storage-path}/2a3f8b1c/bob@example.com-pub.asc

Then send to both at once:

Terminal window
apprise -t "Hello" -b "Secret message" \
"mailtos://user:pass@smtp.example.com/alice@example.com/bob@example.com?pgp=sign&pgpprv=/path/to/my-prv.asc"

Apprise sends two separate emails:

  • Alice receives a multipart/signed+encrypted message encrypted with alice@example.com-pub.asc.
  • Bob receives a multipart/signed+encrypted message encrypted with bob@example.com-pub.asc.

If a key file is missing for a particular recipient, the opportunistic fallback applies: that recipient receives a signed-only (unencrypted) copy. No other recipients are affected — each send is independent.

VariableRequiredDescription
userYes*SMTP username. May be a user id or a full email address. Can also be specified as ?user=.
passYes*SMTP password. Can also be specified as ?pass=.
domainYesDomain portion of the URL host. For mailto://user:pass@example.com, the domain is example.com.
portNoSMTP port. Defaults to 25 (mailto) and 587 (mailtos) unless provider defaults are applied.
smtpNoOverride the SMTP host. If set, provider detection is bypassed.
fromNoFrom address. Supports Optional Name<email@example.com>. Maps to the email From header.
nameNoLegacy alias for the From name. If both from= and name= are provided, from= takes precedence.
toNoRecipient override. Also supported via URL path targets.
ccNoCarbon Copy recipients. Comma separated. Name formatting is supported.
bccNoBlind Carbon Copy recipients. Comma separated. Name formatting is supported.
replyNoReply-To recipients. Comma separated. Name formatting is supported.
modeNoSecure mode: ssl or starttls. When using mailto://, specifying mode= upgrades to a secure connection.
pgpNoPGP mode: no (default), sign, or encrypt. Prefix shorthand accepted: n, s, e. Legacy yes/true implies encrypt (deprecated). none/false map to no.
pgppubNoPath or URL to a recipient’s ASCII-armoured PGP public key (.asc). When set, WKD and auto-generation are bypassed. Masked in privacy-safe URLs.
pgpprvNoPath to the sender’s ASCII-armoured PGP private key (.asc). Required for pgp=sign. Passphrase-protected keys are not supported. Masked in privacy-safe URLs.
pgpkeyNoDeprecated. Alias for pgppub=. Still accepted but emits a deprecation warning. Will be removed in a future release. Use pgppub= instead.
wkdNoEnable Web Key Directory key discovery (yes or no). Defaults to no. Setting wkd=yes implies pgp=encrypt when pgp= is not specified.
+HeaderNoAdd custom email headers by prefixing keys with +. Example: ?+X-Team=Ops.

* Not required for anonymous relays.

To avoid ambiguity, any URL parameter (?key=value) overrides values in the main URL:

  • mailto://usera:pass123@domain.com?user=foobar: the user of foobar would over-ride the user usera specified. However since the password was not over-ridden, the password of pass123 would be used still.
VariableDescription
overflowThis parameter can be set to either split, truncate, or upstream. This determines how Apprise delivers the message you pass it. By default this is set to upstream
👉 upstream: Do nothing at all; pass the message exactly as you received it to the service.
👉 truncate: Ensure that the message will fit within the service’s documented upstream message limit. If more information was passed then the defined limit, the overhead information is truncated.
👉 split: similar to truncate except if the message doesn’t fit within the service’s documented upstream message limit, it is split into smaller chunks and they are all delivered sequentially there-after.
formatThis parameter can be set to either text, html, or markdown. Some services support the ability to post content by several different means. The default of this varies (it can be one of the 3 mentioned at any time depending on which service you choose). You can optionally force this setting to stray from the defaults if you wish. If the service doesn’t support different types of transmission formats, then this field is ignored.
verifyExternal requests made to secure locations (such as through the use of https) will have certificates associated with them. By default, Apprise will verify that these certificates are valid; if they are not then no notification will be sent to the source. In some occasions, a user might not have a certificate authority to verify the key against or they trust the source; in this case you will want to set this flag to no. By default it is set to yes.
redirectBy default, Apprise will follow HTTP redirects (3xx responses) issued by the remote server, matching the behaviour of the underlying requests library. If you want to prevent custom headers and credentials from being forwarded to destinations that differ from the original URL, set this to no. By default it is set to yes.
ctoThis stands for Socket Connect Timeout. This is the number of seconds Requests will wait for your client to establish a connection to a remote machine (corresponding to the connect()) call on the socket. The default value is 4.0 seconds.
rtoThis stands for Socket Read Timeout. This is the number of seconds the client will wait for the server to send a response. The default value is 4.0 seconds.
emojisEnable Emoji support (such as providing :+1: would translate to 👍). By default this is set to no.
Note: Depending on server side settings, the administrator has the power to disable emoji support at a global level; but default this is not the case.
tzIdentify the IANA Time Zone Database you wish to operate as. By default this is detected based on the configuration the server hosting Apprise is running on. You can set this to things like America/Toronto, or any other properly formated Timezone describing your area.
retryThe number of additional delivery attempts to make after the first failure before giving up. Accepts an integer in the range 0 to 10. The default is 0 (no retries — a single attempt is made). When combined with wait, Apprise pauses the specified number of seconds between each attempt.
waitThe number of seconds to pause between retry attempts. Accepts a decimal value in the range 0.0 to 20.0; integer values are promoted to float automatically. The default is 0.5. This value is only meaningful when retry is greater than zero — a service with retry=0 makes exactly one attempt regardless of the wait value.
optionalWhen set to yes, a delivery failure for this service is silently absorbed. The overall notify() call still returns True even if this endpoint was unreachable, provided that every required (non-optional) service in the same batch succeeded. Setting this flag does not skip delivery or bypass retry logic — all configured retry attempts are still made before the failure is absorbed. By default this is set to no, meaning every failure is propagated to the caller.

Built-in provider example:

Terminal window
apprise -vv -t "Test Message Title" -b "Test Message Body" \
mailto:///example:mypassword@gmail.com

Send an email to a custom provider; since no smtp= was identified, the host example.com is also assumed to be the SMTP server.

Terminal window
# Assuming the {domain} is example.com
# Assuming the {user} is george
# Assuming the {password} is pass123
apprise -vv -t "Test Message Title" -b "Test Message Body" \
mailto://george:pass123@example.com
# The above URL could also have been written like:
# mailto://example.com?user=george&pass=pass123

If the SMTP Server differs from the domain (which is usually the case), your URL should include the ?smtp= keyword argument:

Terminal window
# Assuming the {domain} is example.com
# Assuming the {user} is george
# Assuming the {password} is pass123
apprise -vv -t "Test Message Title" -b "Test Message Body" \
mailto://george:pass123@example.com?smtp=smtp.example.com

In some cases, the {user} is an email address. In this case you can place this information in the URL parameters instead:

Terminal window
# Assuming the {domain} is example.com
# Assuming the {user} is george@example.com
# Assuming the {password} is pass123
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailto://example.com?user=george@example.com&pass=pass123"
# Note that the ampersand (&) that is used in the URL to separate
# one argument from another is also interpreted by the CLI as
# run in the background. Wrap your URL in quotes.
# Send an email to a smtp relay server you are hosting:
apprise -vv -t "Test Message Title" -b "Test Message Body" \
mailto://localhost?from=john@example.ca

Users with custom SMTP Servers will require a slightly more complicated configuration:

Terminal window
# Assuming the {smtp_server} is mail.example.com
# Assuming the {send_from} is joe@example.com
# Assuming the {login} is user1@example.com
# Assuming the {password} is pass123
# Assuming you want to use starttls (port 587)
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailtos://_?user=user1@example.com&pass=pass123&smtp=mail.example.com&from=joe@example.com"
# Notes (for above URL):
# - Since no `to=` was specified above, the `from` address is notified
# - mailtos:// defaults to starttls on 587; if you want to use port 465 (SSL)
# you would just need to add `mode=ssl` to the parameter of your URL.

Here is a more complicated example where you want to use ssl and a custom port:

Terminal window
# Assuming the {smtp_server} is mail.example.com
# Assuming the {send_from} is joe@example.com
# Assuming the {login} is user1@example.com
# Assuming the {password} is pass123
# Assuming you want to use ssl on port 12522
# Assuming you want your email to go to bob@example.com and jane@yahoo.ca
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailtos://example.com:12522?user=user1@example.com&pass=pass123&smtp=mail.example.com&from=joe@example.com&to=bob@example.com,jane@yahoo.ca&mode=ssl"

Local relay:

Terminal window
apprise -t "Test Title" -b "Test Body" \
mailto://localhost?to=john@example.com

Encrypt using WKD key discovery (no key file needed; pgp=encrypt is implied):

Terminal window
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailtos://user:pass@example.com?wkd=yes"

Encrypt using an explicit local key file:

Terminal window
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailtos://user:pass@example.com?pgp=encrypt&pgppub=/home/user/.gnupg/recipient-pub.asc"

Sign every email with your private key (opportunistically encrypts when WKD returns a public key):

Terminal window
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailtos://user:pass@example.com?pgp=sign&wkd=yes&pgpprv=/home/user/.gnupg/my-prv.asc"

Sign only — no public key lookup, always delivers a signed plain-text email:

Terminal window
apprise -vv -t "Test Message Title" -b "Test Message Body" \
"mailtos://user:pass@example.com?pgp=sign&pgpprv=/home/user/.gnupg/my-prv.asc"
Questions or Feedback?

Documentation

Notice a typo or an error? Report it or contribute a fix .

Technical Issues

Having trouble with the code? Open an issue on GitHub:

Made with love from Canada