fix: warn on dropped OAuth token, skip wasted final backoff, honor external cancel, fix digit-run split (v0.1.8)
aiomail-7: log a truncated body when a 200 token response has no access_token instead of silently discarding it. aiomail-8: connect() no longer sleeps after the last failed retry attempt. aiomail-9: _discard_mail now distinguishes its own task.cancel() from an external cancellation via asyncio.shield, so connect() no longer resists cancellation. aiomail-10: the digit-run fallback now matches contiguous \d+ runs instead of mashing digits across punctuation within a whitespace token (e.g. a date). aiomail-11: README's dynamic-matching example uses email.utils.parseaddr since a real From header is not a bare address. Also compresses essay docstrings to one-line-plus-nuance with zero behavior change (re-verified against the same negative controls). Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
@@ -11,22 +11,22 @@ This reads codes from email; it does not generate them (that is `pyotp`'s job).
|
||||
`requirements.txt`:
|
||||
|
||||
```
|
||||
aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.7
|
||||
aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.8
|
||||
# OAuth token providers (Microsoft / Google) need the extra:
|
||||
aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.7
|
||||
aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.8
|
||||
```
|
||||
|
||||
Direct:
|
||||
|
||||
```bash
|
||||
pip install "aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.7"
|
||||
pip install "aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.7"
|
||||
pip install "aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.8"
|
||||
pip install "aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.8"
|
||||
```
|
||||
|
||||
Requires `aioimaplib` and `beautifulsoup4` (pulled transitively). The `oauth`
|
||||
extra adds `aiohttp` for the refresh-token providers.
|
||||
|
||||
Drop the `@v0.1.7` suffix from the line above to install the latest unpinned.
|
||||
Drop the `@v0.1.8` suffix from the line above to install the latest unpinned.
|
||||
|
||||
## Password auth
|
||||
|
||||
@@ -61,11 +61,15 @@ Credentials are always supplied by you — nothing is hardcoded.
|
||||
|
||||
```python
|
||||
import re
|
||||
from email.utils import parseaddr
|
||||
await retrieve_otp(client, sender="uber.com") # substring
|
||||
await retrieve_otp(client, sender=re.compile(r"no-?reply@.*\.io")) # regex
|
||||
await retrieve_otp(client, sender=lambda f: f.endswith("@x.com")) # callable
|
||||
await retrieve_otp(client, sender=lambda f: parseaddr(f)[1].endswith("@x.com")) # callable
|
||||
```
|
||||
|
||||
A real `From` header is `Name <addr@x.com>`, not a bare address — `parseaddr` pulls
|
||||
the address out before matching (a plain `f.endswith(...)` would never match).
|
||||
|
||||
Subject headers are RFC2047-decoded before matching/extraction, so providers
|
||||
that encode non-ASCII subjects (`=?utf-8?B?...?=`) still match on plain text.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user