成功获取登录后的 ck
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env python3
|
||||
"""邮箱IMAP读取测试脚本"""
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到path
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from douyu.config import Config
|
||||
from douyu.email_verifier import EmailVerifier
|
||||
from utils.logger import setup_logger
|
||||
|
||||
|
||||
def mask_email(email_address: str) -> str:
|
||||
"""隐藏邮箱中间部分,避免控制台泄露完整账号。"""
|
||||
if "@" not in email_address:
|
||||
return email_address
|
||||
|
||||
name, domain = email_address.split("@", 1)
|
||||
if len(name) <= 2:
|
||||
masked_name = name[0] + "*"
|
||||
else:
|
||||
masked_name = name[:2] + "*" * max(2, len(name) - 4) + name[-2:]
|
||||
|
||||
return f"{masked_name}@{domain}"
|
||||
|
||||
|
||||
def clean_preview(text: str, max_length: int = 120) -> str:
|
||||
"""清理正文预览,保持输出紧凑。"""
|
||||
preview = " ".join(text.split())
|
||||
preview = re.sub(r"\b\d{6}\b", "******", preview)
|
||||
if len(preview) <= max_length:
|
||||
return preview
|
||||
return preview[:max_length] + "..."
|
||||
|
||||
|
||||
def format_code(code: str, show_code: bool) -> str:
|
||||
"""格式化验证码输出,默认隐藏大部分数字。"""
|
||||
if not code:
|
||||
return "未提取到"
|
||||
if show_code:
|
||||
return code
|
||||
return f"****{code[-2:]}"
|
||||
|
||||
|
||||
def format_message_time(verifier: EmailVerifier, msg) -> str:
|
||||
"""格式化邮件时间。"""
|
||||
message_time = verifier._parse_message_time(msg)
|
||||
if not message_time:
|
||||
return "未知"
|
||||
return message_time.strftime("%Y-%m-%d %H:%M:%S %z")
|
||||
|
||||
|
||||
def load_account(config_path: str, index: int):
|
||||
"""从配置文件加载指定账号。"""
|
||||
config = Config(config_path)
|
||||
accounts = config.get_accounts()
|
||||
if not accounts:
|
||||
raise ValueError("config.yaml 中没有配置账号")
|
||||
|
||||
if index < 0 or index >= len(accounts):
|
||||
raise IndexError(f"账号索引超出范围: {index},当前共有 {len(accounts)} 个账号")
|
||||
|
||||
return accounts[index]
|
||||
|
||||
|
||||
def list_recent_messages(
|
||||
verifier: EmailVerifier,
|
||||
lookback_minutes: int,
|
||||
limit: int,
|
||||
show_code: bool,
|
||||
) -> None:
|
||||
"""列出最近邮件,并测试斗鱼验证码解析。"""
|
||||
verifier.connect()
|
||||
|
||||
try:
|
||||
status, _ = verifier._connection.select(verifier.mailbox, readonly=True)
|
||||
if status != "OK":
|
||||
raise RuntimeError(f"选择邮箱目录失败: {verifier.mailbox}")
|
||||
|
||||
since_dt = datetime.now() - timedelta(minutes=lookback_minutes)
|
||||
since = verifier._format_imap_date(since_dt)
|
||||
status, messages = verifier._connection.search(None, "SINCE", since)
|
||||
if status != "OK":
|
||||
raise RuntimeError(f"搜索邮件失败: status={status}")
|
||||
|
||||
message_ids = messages[0].split() if messages and messages[0] else []
|
||||
if not message_ids:
|
||||
print(f"最近 {lookback_minutes} 分钟没有邮件")
|
||||
return
|
||||
|
||||
recent_ids = list(reversed(message_ids[-limit:]))
|
||||
print(f"搜索范围: 最近 {lookback_minutes} 分钟")
|
||||
print(f"匹配邮件数: {len(message_ids)},展示最新 {len(recent_ids)} 封\n")
|
||||
|
||||
for index, message_id in enumerate(recent_ids, start=1):
|
||||
msg = verifier._fetch_message(message_id)
|
||||
if not msg:
|
||||
print(f"[{index}] 读取失败: id={message_id.decode(errors='ignore')}")
|
||||
continue
|
||||
|
||||
subject = verifier._decode_subject(msg.get("Subject", ""))
|
||||
from_addr = msg.get("From", "")
|
||||
body = verifier._get_email_body(msg)
|
||||
is_douyu = verifier._is_douyu_email(subject, from_addr, body)
|
||||
code = verifier._extract_verification_code(body) if is_douyu else ""
|
||||
|
||||
print(f"[{index}] 邮件ID: {message_id.decode(errors='ignore')}")
|
||||
print(f" 时间: {format_message_time(verifier, msg)}")
|
||||
print(f" 发件人: {from_addr}")
|
||||
print(f" 主题: {subject}")
|
||||
print(f" 斗鱼邮件: {'是' if is_douyu else '否'}")
|
||||
print(f" 验证码: {format_code(code, show_code)}")
|
||||
print(f" 正文预览: {clean_preview(body)}\n")
|
||||
finally:
|
||||
verifier.disconnect()
|
||||
|
||||
|
||||
def wait_verification_code(
|
||||
account,
|
||||
max_wait: int,
|
||||
interval: int,
|
||||
new_only: bool,
|
||||
show_code: bool,
|
||||
) -> None:
|
||||
"""等待并提取斗鱼验证码,不负责发送验证码邮件。"""
|
||||
verifier = EmailVerifier(
|
||||
imap_server=account.email_imap_server,
|
||||
imap_port=account.email_imap_port,
|
||||
username=account.email,
|
||||
password=account.email_password,
|
||||
)
|
||||
|
||||
after_timestamp = time.time() if new_only else None
|
||||
code = verifier.get_verification_code(
|
||||
max_wait=max_wait,
|
||||
interval=interval,
|
||||
after_timestamp=after_timestamp,
|
||||
)
|
||||
print(f"等待验证码结果: {format_code(code, show_code)}")
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
"""解析命令行参数。"""
|
||||
parser = argparse.ArgumentParser(description="测试邮箱IMAP是否能读取邮件和验证码")
|
||||
parser.add_argument("-c", "--config", default="config.yaml", help="配置文件路径")
|
||||
parser.add_argument("-i", "--index", type=int, default=0, help="账号索引")
|
||||
parser.add_argument("--lookback-minutes", type=int, default=30, help="读取最近多少分钟邮件")
|
||||
parser.add_argument("--limit", type=int, default=5, help="展示最近多少封邮件")
|
||||
parser.add_argument("--wait-code", action="store_true", help="额外等待并提取斗鱼验证码")
|
||||
parser.add_argument("--new-only", action="store_true", help="等待验证码时只接受脚本启动后的新邮件")
|
||||
parser.add_argument("--show-code", action="store_true", help="输出完整验证码")
|
||||
parser.add_argument("--max-wait", type=int, default=60, help="等待验证码最大秒数")
|
||||
parser.add_argument("--interval", type=int, default=2, help="验证码轮询间隔秒数")
|
||||
parser.add_argument("--log-level", default="INFO", help="日志级别")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""脚本入口。"""
|
||||
args = parse_args()
|
||||
setup_logger(level=args.log_level)
|
||||
|
||||
account = load_account(args.config, args.index)
|
||||
print("=== 邮箱IMAP读取测试 ===")
|
||||
print(f"账号索引: {args.index}")
|
||||
print(f"邮箱账号: {mask_email(account.email)}")
|
||||
print(f"IMAP服务器: {account.email_imap_server}:{account.email_imap_port}\n")
|
||||
|
||||
verifier = EmailVerifier(
|
||||
imap_server=account.email_imap_server,
|
||||
imap_port=account.email_imap_port,
|
||||
username=account.email,
|
||||
password=account.email_password,
|
||||
lookback_minutes=args.lookback_minutes,
|
||||
max_messages=args.limit,
|
||||
)
|
||||
list_recent_messages(
|
||||
verifier=verifier,
|
||||
lookback_minutes=args.lookback_minutes,
|
||||
limit=args.limit,
|
||||
show_code=args.show_code,
|
||||
)
|
||||
|
||||
if args.wait_code:
|
||||
print("=== 等待斗鱼验证码 ===")
|
||||
wait_verification_code(
|
||||
account=account,
|
||||
max_wait=args.max_wait,
|
||||
interval=args.interval,
|
||||
new_only=args.new_only,
|
||||
show_code=args.show_code,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user