Async-Notify is a simple, asyncio-based notification library for Apps.
Notify is built on top of python asyncio for send notifications asynchronous with support of twilio, telegram, o365, email, slack, onesignal and many others.
The finality of Async-Notify is to provide us a subset of communication providers for sending different notifications in a non-blocking mode.. The main goal of Async-Notify is using only asyncio-based technologies.
- Python >= 3.11
- asyncio (https://pypi.python.org/pypi/asyncio/)
The core install is deliberately slim: it carries only what the
provider-agnostic core path needs. Providers that depend on a third-party SDK
ship that SDK in an extra — install async-notify[<extra>] for one
provider (for example pip install async-notify[telegram]),
async-notify[all] for every provider, or async-notify[server]
for the Redis-backed notify server.
| Provider | Notify(...) alias |
Extra required |
|---|---|---|
| Amazon (AWS) e-mail | aws |
none — core install |
| Dialpad | dialpad |
none — core install (aiohttp) |
| Dummy (testing) | dummy |
none — core install |
| Generic e-mail | email |
none — core install |
| Gmail | gmail |
google |
| Office 365 (Microsoft Graph) | office365 |
azure |
| OneSignal push | onesignal |
push |
| Outlook (Microsoft Graph) | outlook |
azure |
| SendGrid | sendgrid |
none — core install |
| Amazon SES | ses |
ses |
| Slack | slack |
slack |
| SMTP | smtp |
none — core install |
| Microsoft Teams | teams |
azure |
| Telegram | telegram |
telegram |
| Twilio SMS | twilio |
twilio |
| XMPP | xmpp |
xmpp |
| Zoom | zoom |
none — core install (aiohttp) |
Other extras: all (every provider SDK plus the extras below), server
(notify server: cloudpickle, qworker, redis), uvloop, templates
(extra Jinja2 extensions) and default (aiogram + slack_bolt).
The notify console script (notify/__main__.py) starts the Redis-backed
notification server and therefore requires the server extra; without it
the script exits with an import error for cloudpickle.
Currently Async-Notify supports the following providers:
- Amazon SES
- Email (SMTP)
- Gmail
- Office 365 (Microsoft Graph;
outlookis a compatible alias) - Telegram (requires aiogram)
- Twilio (SMS)
- OneSignal
- XMPP stanzas
send(template=...) accepts either a template filename (resolved on
TEMPLATE_DIR, unchanged since earlier versions) or raw Jinja2 source
text, auto-detected by a conservative heuristic (a Jinja2 delimiter
{{, {%, {#, or a line break means source; anything else is treated as
a filename). Use template_is_source=True/False to force either
interpretation when the heuristic can't decide (for example a body with no
Jinja markup and no newline, which is indistinguishable from a filename).
# raw source — new in 1.6.0
await Notify("smtp").send(
recipient=[actor],
subject="Welcome",
template="<p>Hola {{ recipient.account.address }} — {{ message }}</p>",
message="…",
)
# filename — unchanged behaviour
await Notify("smtp").send(recipient=[actor], template="welcome.html")
# forced, for a body with no Jinja markup
await Notify("telegram").send(
recipient=[chat], template="Hello world", template_is_source=True,
)Security note: autoescape is disabled, so a template compiled from a
string executes arbitrary Jinja2 and emits unescaped output. Template
source must come from trusted operators (configuration, database rows
written by staff) — never from end-user input. End-user data belongs in the
message parameters, not in the template body itself.
office365 (and its backward-compatible alias outlook) now send mail
through Microsoft Graph (msgraph-sdk), not the legacy Outlook REST
API — one Graph message per send() call, to every recipient. Four auth
flows share one MSAL-backed credential: client_credentials (app-only,
secret or certificate), on_behalf_of (OAuth2 OBO — a signed-in user's
token exchanged for a Graph token, send-only, never queued), delegated
(headless device-code bootstrap, then silent cached refresh), and the
deprecated password (ROPC).
# App-only, sending as a shared mailbox
mail = Notify(
"office365", auth_flow="client_credentials",
client_id="CLIENT_ID", client_secret="CLIENT_SECRET", tenant_id="TENANT_ID",
sender="noreply@contoso.com",
)
async with mail as m:
[result] = await m.send(
recipient=[alice, bob], subject="Report", template="report.html",
cc=["ops@contoso.com"], attachments=["/tmp/report.pdf"], importance="high",
)
assert result.success
# One-time headless delegated bootstrap (no browser redirect):
# $ python -m notify.providers.office365.login --username me@contoso.comToken caches are pluggable (memory default, file, redis) and
encrypted (Fernet) for the persistent stores unless
allow_unencrypted=True is explicit. Full flow reference, tenant/app
permission prerequisites, send-as/OBO semantics, and the migration notes
for the use_credentials default change and the removed
o365/Office365-REST-Python-Client dependencies live in
docs/providers.rst.
- Slack
- Facebook Messenger
- Discord
- IRC
- Summary of set up
- Configuration
- Dependencies
- Database configuration
- How to run tests
- Deployment instructions
Please have a look at the Contribution Guide
- Writing tests
- Code review
- Repo owner or admin
- Other community or team contact
Async-Notify is copyright of Jesus Lara (https://phenobarbital.info) and is licensed under BSD license. I am providing code in this repository under an open source licenses, remember, this is my personal repository; the license that you receive is from me and not from my employeer.