Metadata-Version: 2.4
Name: async-notify
Version: 1.6.1
Summary: Asyncio-based Library for sending notifications (messages) to users.
Author-email: Jesus Lara Gimenez <jesuslarag@gmail.com>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/phenobarbital/async-notify
Project-URL: Source, https://github.com/phenobarbital/async-notify
Project-URL: Tracker, https://github.com/phenobarbital/async-notify/issues
Project-URL: Documentation, https://github.com/phenobarbital/async-notify/
Project-URL: Funding, https://paypal.me/phenobarbital
Project-URL: Say Thanks!, https://saythanks.io/to/phenobarbital
Keywords: asyncio,notification,telegram,slack,email
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Classifier: Environment :: Web Environment
Classifier: Framework :: AsyncIO
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiosmtplib>=5.0
Requires-Dist: python-datamodel>=0.3.12
Requires-Dist: navconfig[default]>=2.2.0
Requires-Dist: jinja2>=3.1.4
Requires-Dist: cloudpickle>=3.1.0
Requires-Dist: emoji>=1.7.0
Requires-Dist: aiobotocore>=2.15.2
Requires-Dist: pillow>=8.3.2
Provides-Extra: uvloop
Requires-Dist: uvloop>=0.20.0; sys_platform != "win32" and extra == "uvloop"
Provides-Extra: default
Requires-Dist: aiogram>=3.14.0; extra == "default"
Requires-Dist: slack_bolt>=1.18.0; extra == "default"
Provides-Extra: telegram
Requires-Dist: aiogram>=3.14.0; extra == "telegram"
Requires-Dist: moviepy>=2.2.1; extra == "telegram"
Provides-Extra: push
Requires-Dist: onesignal-sdk>=2.0.0; extra == "push"
Provides-Extra: google
Requires-Dist: gmail>=0.6.3; extra == "google"
Requires-Dist: google-auth>=2.6.0; extra == "google"
Requires-Dist: google-auth-httplib2>=0.1.0; extra == "google"
Provides-Extra: azure
Requires-Dist: msal>=1.32.0; extra == "azure"
Requires-Dist: msgraph-core>=1.3.2; extra == "azure"
Requires-Dist: azure-identity>=1.23.0; extra == "azure"
Requires-Dist: msgraph-sdk>=1.22.0; extra == "azure"
Requires-Dist: cryptography>=42.0; extra == "azure"
Provides-Extra: templates
Requires-Dist: jinja2-time>=0.2.0; extra == "templates"
Requires-Dist: jinja2-iso8601>=1.0.0; extra == "templates"
Requires-Dist: jinja2-humanize-extension>=0.4.0; extra == "templates"
Provides-Extra: all
Requires-Dist: gmail>=0.6.3; extra == "all"
Requires-Dist: google-auth>=2.6.0; extra == "all"
Requires-Dist: google-auth-httplib2>=0.1.0; extra == "all"
Requires-Dist: onesignal-sdk>=2.0.0; extra == "all"
Requires-Dist: msal>=1.32.0; extra == "all"
Requires-Dist: PySocks>=1.7.1; extra == "all"
Requires-Dist: pyshorteners>=1.0.1; extra == "all"
Requires-Dist: twilio>=8.2.2; extra == "all"
Requires-Dist: slixmpp>=1.10.0; extra == "all"
Requires-Dist: slack_bolt>=1.18.0; extra == "all"
Requires-Dist: aiogram>=3.14.0; extra == "all"
Requires-Dist: aiobotocore>=2.15.2; extra == "all"
Requires-Dist: qworker>=1.12.7; extra == "all"
Requires-Dist: msgraph-core>=1.3.2; extra == "all"
Requires-Dist: azure-identity>=1.23.0; extra == "all"
Requires-Dist: msgraph-sdk>=1.22.0; extra == "all"
Requires-Dist: cryptography>=42.0; extra == "all"
Requires-Dist: moviepy>=2.2.1; extra == "all"
Provides-Extra: dev
Requires-Dist: aiounittest>=1.4.2; extra == "dev"
Requires-Dist: black>=24.10.0; extra == "dev"
Requires-Dist: build>=1.2.2; extra == "dev"
Requires-Dist: coverage[toml]>=7.6.0; extra == "dev"
Requires-Dist: flit>=3.10.1; extra == "dev"
Requires-Dist: hypothesis>=6.122.0; extra == "dev"
Requires-Dist: ipython>=8.18.1; extra == "dev"
Requires-Dist: mypy>=1.13.0; extra == "dev"
Requires-Dist: pylint>=3.3.0; extra == "dev"
Requires-Dist: pyperf>=2.8.0; extra == "dev"
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
Requires-Dist: pytest-cython>=0.3.1; extra == "dev"
Requires-Dist: pytest-xdist>=3.6.1; extra == "dev"
Requires-Dist: pytest-assume>=2.4.3; extra == "dev"
Requires-Dist: sphinx>=7.4.0; extra == "dev"
Requires-Dist: tox>=4.23.0; extra == "dev"
Requires-Dist: twine>=6.0.0; extra == "dev"
Dynamic: license-file

# Async-Notify #

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.

### Why Async-Notify? ###

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.

### Requirements ###

* Python >= 3.8
* asyncio (https://pypi.python.org/pypi/asyncio/)

### Quick Tutorial ###

Currently Async-Notify supports the following providers:

* Amazon SES
* Email (SMTP)
* Gmail
* Office 365 (Microsoft Graph; `outlook` is a compatible alias)
* Telegram (requires aiogram)
* Twilio (SMS)
* OneSignal
* Twitter
* XMPP stanzas

### Templates ###

`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).

```python
# 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.

### Microsoft Graph mail (`office365` / `outlook`) ###

`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).

```python
# 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.com
```

Token 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`](docs/providers.rst).

#### Future work: ####

* Slack
* Facebook Messenger
* Discord
* IRC

### How do I get set up? ###

* Summary of set up
* Configuration
* Dependencies
* Database configuration
* How to run tests
* Deployment instructions

### Contribution guidelines ###

Please have a look at the Contribution Guide

* Writing tests
* Code review

### Who do I talk to? ###

* Repo owner or admin
* Other community or team contact

### License ###

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.
