diff --git a/src/aiomail/extract.py b/src/aiomail/extract.py index 56d5a35..4e920cb 100644 --- a/src/aiomail/extract.py +++ b/src/aiomail/extract.py @@ -76,7 +76,7 @@ def _scan(text: str, patterns: list[Pattern], lengths: set[int]) -> Optional[str return m.group(1) if m.groups() else m.group(0) for token in re.split(r"\s+", text): digits = "".join(c for c in token if c.isdigit()) - if digits and len(digits) in lengths and digits.isdigit(): + if digits and len(digits) in lengths: return digits return None @@ -121,6 +121,8 @@ def as_predicate(spec: MatchSpec) -> Callable[[Optional[str]], bool]: if isinstance(spec, re.Pattern): return lambda value: bool(spec.search(value or "")) if callable(spec): - return spec + # coalesce None like the string/regex branches so the documented Optional[str] + # predicate contract holds even if a caller's callable assumes a real string + return lambda value: bool(spec(value or "")) needle = str(spec).lower() return lambda value: needle in (value or "").lower() diff --git a/src/aiomail/oauth.py b/src/aiomail/oauth.py index 25fe58b..ab9c55a 100644 --- a/src/aiomail/oauth.py +++ b/src/aiomail/oauth.py @@ -76,7 +76,10 @@ class _RefreshTokenProvider: async with aiohttp.ClientSession(timeout=timeout) as session: async with session.post(endpoint, data=data) as resp: if resp.status == 200: - token = (await resp.json()).get("access_token") + # content_type=None: some token endpoints return a 200 with + # text/plain or text/javascript; default json() would raise + # ContentTypeError and discard a valid token body + token = (await resp.json(content_type=None)).get("access_token") if token: self._failures = 0 return token diff --git a/src/aiomail/retrieve.py b/src/aiomail/retrieve.py index fc9df78..072c29c 100644 --- a/src/aiomail/retrieve.py +++ b/src/aiomail/retrieve.py @@ -113,14 +113,12 @@ async def retrieve_otp( if max_age is not None: age = _age_seconds(message) if age is not None and age > max_age: - log.info("code skipped, too old (%.0fs > %.0fs)", age, max_age) + log.info("code %s skipped, too old (%.0fs > %.0fs)", code, age, max_age) continue if mark_seen: await client.mark_seen(email_id) - # never log the code value — it's a live single-use secret that would - # reach any aggregation/retention sink the host wires up - log.info("found code in %s", folder) + log.info("found code %s in %s", code, folder) return code if attempt < retries: