用smtplib发邮件前必须确认SMTP服务器地址、端口及TLS/SSL配置、邮箱授权码开启;三者任一错误均导致发信失败,且授权码需在邮箱设置中手动开启SMTP服务。

用 smtplib 发邮件前必须确认的三件事
发不出邮件?90% 是卡在这三个地方:SMTP 服务器地址写错、端口没开 TLS/SSL、邮箱授权码没开。Gmail、QQ 邮箱、163 都不认密码,只认「应用专用密码」或「授权码」,且需手动在邮箱设置里开启 SMTP 服务。
-
smtplib.SMTP_SSL('smtp.qq.com', 465)是 QQ 邮箱最稳组合;smtplib.SMTP('smtp.gmail.com', 587)必须跟server.starttls() - 用户名填完整邮箱(如
'xxx@qq.com'),密码填授权码(不是登录密码) - 发件人地址必须和登录账号一致,否则多数服务商直接拒信
爬虫异常时怎么触发通知,而不是等整个脚本崩了才想起来
别把 try...except 包在最外层——那样只能捕获最终崩溃,漏掉超时、解析失败、反爬返回空页这类“软失败”。应该在关键动作后主动检查结果是否符合预期。
- 请求后检查
response.status_code != 200,不是只看有没有抛requests.exceptions.RequestException - 解析后检查
len(soup.select('.item')) == 0,避免静默跳过空数据 - 用自定义异常(如
raise ValueError("No price found"))代替print(),确保能被统一捕获
schedule + smtplib 定时发通知容易卡死的两个原因
用 schedule 跑爬虫+发信,常出现“第一次成功,之后再也不触发”,其实是没处理阻塞和异常传播。它本身不带错误隔离,一个失败会停掉整个调度器。
- 每次任务必须包一层
try...except,并在 except 里发通知(比如记录到日志+发邮件),否则异常吞掉就停摆 -
schedule.run_pending()要放在循环里,但别用time.sleep(1)——太耗资源;改用schedule.idle_seconds精确休眠 - 如果用
threading.Timer或APScheduler替代,注意它们默认不共享主线程的 SMTP 连接,得每次新建或用连接池
微信/钉钉比邮件更及时,但 Webhook 地址不能硬编码在代码里
Webhook 地址含敏感信息,直接写死在脚本里,一提交 Git 就泄露。而且钉钉对消息频率有限制(每分钟最多 20 条),连续报错会进黑名单。
立即学习“Python免费学习笔记(深入)”;
- 把
webhook_url放进环境变量(os.getenv('DINGTALK_WEBHOOK'))或独立配置文件(config.json),加进.gitignore - 发钉钉前先检查时间戳:
if time.time() - last_notify_time > 60,避免一分钟内重复告警 - 钉钉卡片消息要严格遵循 JSON 格式,字段名错一个(比如
"msgtype"写成"msg_type")就返回 400,建议用requests.post(..., json=payload)自动序列化
真正难的不是发一次通知,而是让通知机制自己活下来——它得扛住网络抖动、邮箱限流、Webhook 失效、甚至你忘了关本地代理。留个心跳检测比堆功能更重要。


















