Skip to content

Email Notifications

Overview

  • Image Support: No
  • Attachment Support: Yes
  • Message Character Limits:
    • Body: 32768
  • Supported Body Format(s):
    • ✓HTML
    • TEXT
  • Build Your Apprise URL

Email sends HTML by default and includes a plain-text alternative for mail clients that need it. Set ?format=text if you want to send a plain-text email only.

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

The From address has two components: the email address and the optional display name (what recipients see in their mail client instead of a raw address).

Historical form (still supported): name= accepted a display name and from= accepted an email address. Together they supplied both values:

name=No%20Reply&from=noreply@example.com
# Result: "No Reply" <noreply@example.com>

Modern form (preferred): Both parameters accept Display Name <email@example.com>, although using from= alone is recommended:

from=No%20Reply <noreply@example.com>
# Result: "No Reply" <noreply@example.com>

When from= contains Name <email>, you do not need to provide name=.

Behaviour summary:

ParametersDisplay nameEmail address
from=email onlyApp name (fallback)from= value
name=Name onlyname= valueDerived from URL user + host
from=email&name=Namename= valuefrom= value
from=Name <email> onlyEmbedded nameEmbedded email
name=Name <email> onlyEmbedded nameEmbedded email

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.

By default all attachments are sent as regular downloads (Content-Disposition: attachment). Adding ?inline=yes to your URL tells Apprise to embed image attachments inside the email body using the multipart/related MIME structure defined in RFC 2387 and the cid: URI scheme from RFC 2392.

When inline=yes is set:

  • HTML emails: Existing cid:filename references are preserved. Missing image references are appended automatically, and matching attachments receive inline MIME headers.
  • Plain-text emails: Images remain downloadable attachments, with [Image: filename] lines added to the body.
  • Non-image attachments: Files such as PDFs and spreadsheets remain regular downloads unless referenced explicitly by CID.

If you write your own cid: references in an HTML body, Apprise honours them and does not add a duplicate anchor:

<p>See the chart below:</p>
<img src="cid:chart.png">

When inline=yes is active and chart.png is attached, no extra anchor is added. The attachment still receives a Content-ID header.

If a cid:filename appears in the body but no attachment with that exact name was provided, Apprise logs a warning to help you debug the mismatch:

Email inline: no attachment matches cid:chart.png -- check the filename.

Send an HTML email with an image embedded inline:

Terminal window
apprise -vv -t "Report" -b "<h1>Summary</h1><p>See attached chart.</p>" \
"mailto://user:pass@example.com?inline=yes" \
--attach /path/to/chart.png

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 when either mode is selected, the notification fails instead of sending an unprotected message.

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, so 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: the filenames in the public key search table
  4. Auto-generated sender key: available only for a pgp=encrypt self-send when persistent storage and asset-level pgp_autogen are enabled; external recipient keys are never generated

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

  1. Explicit key file: a .asc file supplied via pgpprv=
  2. Local key file: the filenames in the private key search table

WKD (RFC 9080) lets Apprise fetch a recipient’s public key from their mail provider. When the provider publishes one, enable wkd=yes; no local key file is needed.

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.

Apprise never generates a recipient’s key. For a pgp=encrypt self-send, it may generate the sender’s RSA-2048 key pair when no key is found and persistent storage and pgp_autogen are enabled:

FileRole
{localpart}-pub.ascPublic key used for the encrypted self-send
{localpart}-prv.ascPrivate key used for later signing and decryption

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

The same storage can later discover user-prv.asc for pgp=sign without a pgpprv= parameter. Import this private key into the client that reads encrypted replies.

External recipients still require an existing key from pgppub=, WKD, or local storage. Set pgp_autogen = False on the asset to disable sender-key generation as well.

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, with 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, such as 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, so the 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. Accepts a plain email (noreply@example.com) or a combined Display Name <email> value. When the combined form is used, no name= is needed.
nameNoFrom display name. Historically accepted a name string only; now also accepts Display Name <email> format. When used with from=, name= sets the display name and from= sets the email. Do not combine with a from= that already embeds a name.
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. The prefixes n, s, and e are also accepted. none is treated as 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.
wkdNoEnable Web Key Directory key discovery (yes or no). Defaults to no. Setting wkd=yes implies pgp=encrypt when pgp= is not specified.
inlineNoEmbed image attachments inline in HTML email bodies (yes or no). Defaults to no. See Inline Attachments.
+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
overflowControls messages that exceed a service’s documented limit. The default is upstream.
👉 upstream: Send one message without splitting or truncating it for that limit.
👉 truncate: Keep the portion that fits and discard the rest.
👉 split: Prefer a readable break, fall back to a hard boundary, and send every part in order.
Splitting undeclared or structured content is best effort. Use upstream when the body must remain one intact document.
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 evaluates as 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, with 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?

Technical Issues

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

Made with love from Canada