Delete verification emails after code extraction
IMAP-delete Gmail/Hotmail verification messages once the code is parsed, with config toggles and non-blocking failure handling.
This commit is contained in:
1 parent
06044551c7
commit
187792d6be
3 files changed
+37
-1
No files matched your search
@@ -158,6 +158,7 @@ cp config.example.json config.json
|
|||||||
- `defaultDomains`:Cloudflare 等 catch-all 域名,用于生成注册邮箱
|
- `defaultDomains`:Cloudflare 等 catch-all 域名,用于生成注册邮箱
|
||||||
- 验证码实际进入 Gmail;用 **应用专用密码**,不是登录密码
|
- 验证码实际进入 Gmail;用 **应用专用密码**,不是登录密码
|
||||||
- 也可把账号密码只写在 `.env` 的 `GMAIL_USER` / `GMAIL_PASSWORD`
|
- 也可把账号密码只写在 `.env` 的 `GMAIL_USER` / `GMAIL_PASSWORD`
|
||||||
|
- 取到验证码后默认 **删除该邮件**(`gmail_delete_after_code: true`),避免 catch-all 邮箱堆积;失败不影响注册
|
||||||
|
|
||||||
#### B. Hotmail / Outlook
|
#### B. Hotmail / Outlook
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -186,5 +186,9 @@
|
|||||||
"// gmail_imap_password": "Gmail 应用专用密码(非登录密码)",
|
"// gmail_imap_password": "Gmail 应用专用密码(非登录密码)",
|
||||||
"gmail_imap_password": "",
|
"gmail_imap_password": "",
|
||||||
"gmail_imap_host": "imap.gmail.com",
|
"gmail_imap_host": "imap.gmail.com",
|
||||||
"gmail_imap_port": 993
|
"gmail_imap_port": 993,
|
||||||
|
"// gmail_delete_after_code": "Gmail 取到验证码后是否 IMAP 删除该邮件(失败不影响注册)",
|
||||||
|
"gmail_delete_after_code": true,
|
||||||
|
"// hotmail_delete_after_code": "Hotmail/Outlook 取到验证码后是否 IMAP 删除该邮件",
|
||||||
|
"hotmail_delete_after_code": true
|
||||||
}
|
}
|
||||||
@@ -1730,6 +1730,18 @@ def _hotmail_imap_get_code(mailbox_email, target_email, access_token, log_callba
|
|||||||
if code:
|
if code:
|
||||||
if log_callback:
|
if log_callback:
|
||||||
log_callback(f"[*] Hotmail/Outlook 从邮件中提取到验证码: {code}")
|
log_callback(f"[*] Hotmail/Outlook 从邮件中提取到验证码: {code}")
|
||||||
|
if _config_bool(config.get("hotmail_delete_after_code", True), default=True):
|
||||||
|
try:
|
||||||
|
imap.store(mid, "+FLAGS", r"(\Deleted)")
|
||||||
|
try:
|
||||||
|
imap.expunge()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if log_callback:
|
||||||
|
log_callback(f"[*] Hotmail/Outlook 已删除验证码邮件 mid={mid!r}")
|
||||||
|
except Exception as del_exc:
|
||||||
|
if log_callback:
|
||||||
|
log_callback(f"[Debug] Hotmail/Outlook 删除验证码邮件失败: {del_exc}")
|
||||||
return code
|
return code
|
||||||
return None
|
return None
|
||||||
finally:
|
finally:
|
||||||
@@ -1856,6 +1868,7 @@ def gmail_get_oai_code(
|
|||||||
raise Exception("Gmail IMAP 未配置:需要在 config.json 设置 gmail_imap_user/gmail_imap_password,或环境变量 GMAIL_USER/GMAIL_PASSWORD")
|
raise Exception("Gmail IMAP 未配置:需要在 config.json 设置 gmail_imap_user/gmail_imap_password,或环境变量 GMAIL_USER/GMAIL_PASSWORD")
|
||||||
imap_host = str(config.get("gmail_imap_host", "imap.gmail.com") or "imap.gmail.com").strip()
|
imap_host = str(config.get("gmail_imap_host", "imap.gmail.com") or "imap.gmail.com").strip()
|
||||||
imap_port = int(config.get("gmail_imap_port", 993) or 993)
|
imap_port = int(config.get("gmail_imap_port", 993) or 993)
|
||||||
|
delete_after = _config_bool(config.get("gmail_delete_after_code", True), default=True)
|
||||||
deadline = time.time() + timeout
|
deadline = time.time() + timeout
|
||||||
# Resend earlier: first mail often arrives in 5-40s; resend at 45s as safety net.
|
# Resend earlier: first mail often arrives in 5-40s; resend at 45s as safety net.
|
||||||
next_resend_at = time.time() + float(config.get("gmail_resend_after_sec", 45) or 45)
|
next_resend_at = time.time() + float(config.get("gmail_resend_after_sec", 45) or 45)
|
||||||
@@ -1927,6 +1940,22 @@ def gmail_get_oai_code(
|
|||||||
)
|
)
|
||||||
return subject, sender, recipient_blob
|
return subject, sender, recipient_blob
|
||||||
|
|
||||||
|
def _delete_message(conn, mid, code: str) -> None:
|
||||||
|
"""Best-effort delete of used verification mail; never blocks returning the code."""
|
||||||
|
if not delete_after or conn is None or mid is None:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
conn.store(mid, "+FLAGS", r"(\Deleted)")
|
||||||
|
try:
|
||||||
|
conn.expunge()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if log_callback:
|
||||||
|
log_callback(f"[*] Gmail IMAP 已删除验证码邮件 mid={mid!r} code={code}")
|
||||||
|
except Exception as exc:
|
||||||
|
if log_callback:
|
||||||
|
log_callback(f"[Debug] Gmail IMAP 删除验证码邮件失败: {exc}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while time.time() < deadline:
|
while time.time() < deadline:
|
||||||
raise_if_cancelled(cancel_callback)
|
raise_if_cancelled(cancel_callback)
|
||||||
@@ -1989,6 +2018,7 @@ def gmail_get_oai_code(
|
|||||||
f"[*] Gmail IMAP 从邮件中提取到验证码: {code} "
|
f"[*] Gmail IMAP 从邮件中提取到验证码: {code} "
|
||||||
f"(elapsed={elapsed:.1f}s polls={poll_n} via={qused or 'ALL'})"
|
f"(elapsed={elapsed:.1f}s polls={poll_n} via={qused or 'ALL'})"
|
||||||
)
|
)
|
||||||
|
_delete_message(conn, mid, code)
|
||||||
return code
|
return code
|
||||||
# Rare: code only in body — fetch full message once
|
# Rare: code only in body — fetch full message once
|
||||||
try:
|
try:
|
||||||
@@ -2009,6 +2039,7 @@ def gmail_get_oai_code(
|
|||||||
f"[*] Gmail IMAP 从邮件正文提取到验证码: {code} "
|
f"[*] Gmail IMAP 从邮件正文提取到验证码: {code} "
|
||||||
f"(elapsed={elapsed:.1f}s polls={poll_n})"
|
f"(elapsed={elapsed:.1f}s polls={poll_n})"
|
||||||
)
|
)
|
||||||
|
_delete_message(conn, mid, code)
|
||||||
return code
|
return code
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
_close_imap(imap)
|
_close_imap(imap)
|
||||||
|
|||||||
Reference in new issue
Block a user