Flask物联网监控应用阈值触发时无法向登录用户发邮件
问题解决:Flask-Mail发送Gmail邮件连接断开+阈值触发邮件失败
核心问题分析
你遇到的smtplib.SMTPServerDisconnected: 连接意外关闭错误,核心原因是SMTP配置参数不匹配,同时current_user在API路由中存在未验证登录状态的潜在问题,可能导致邮件无法正常发送。
分步修复方案
1. 修正Gmail SMTP配置(解决连接断开问题)
Gmail的SMTP端口与加密方式是严格对应的:
- 端口465:必须使用SSL加密
- 端口587:必须使用TLS加密
你当前的配置将465与TLS绑定,完全不符合Gmail的要求,导致服务器主动断开连接。修改__init__.py中的配置:
from flask_mail import Mail mail = Mail() def create_app(): app = Flask(__name__) app.config.update(dict( MAIL_DEBUG = True, MAIL_SERVER = 'smtp.gmail.com', MAIL_PORT = 465, MAIL_USE_TLS = False, # 改为False,465端口用SSL MAIL_USE_SSL = True, # 改为True MAIL_USERNAME = 'sample@gmail.com', MAIL_PASSWORD = '你的应用密码', # 确保是开启两步验证后生成的应用密码 MAIL_DEFAULT_SENDER = 'sample@gmail.com' # 统一发件人,避免权限校验失败 )) mail.init_app(app) # 记得补充注册蓝图、初始化数据库等其他逻辑 return app
2. 确保current_user在API路由中有效(解决无收件人/报错问题)
你的/gas_value和/current_value是API接口,若前端通过AJAX请求,必须确保请求携带用户会话Cookie,同时添加登录验证避免未登录时触发邮件逻辑报错。修改views.py:
from flask_login import login_required, current_user # ...其他导入代码 @views.route('/gas_value') @login_required # 强制登录验证,确保只有已登录用户能触发警报 def gas_value(): gas_value = mq6_modules[0].mq.MQPercentage()["GAS_LPG"] if gas_value >= 0.2: gas_reading = GasReading(value=gas_value) db.session.add(gas_reading) db.session.commit() # 先检查用户邮箱是否存在,避免空值报错 if current_user.email: send_email( '燃气浓度过高警报', f'检测到燃气浓度值为{gas_value},已超过阈值0.2', current_user.email ) return jsonify({'gas_value': gas_value}) @views.route('/current_value') @login_required # 添加登录验证 def current_value(): current_value = powers[0].get_electricalsensor_readings() if current_value is not None: current_value_float = float(current_value) response = {'current_value': current_value} if current_value_float >= 0.2: current_reading = CurrentReading(value=current_value_float) db.session.add(current_reading) db.session.commit() if current_user.email: send_email( '电流负载过高警报', f'检测到电流值为{current_value_float},已超过阈值0.2', current_user.email ) return jsonify(response) else: return jsonify({'current_value': 'Unavailable'})
3. 验证Gmail账户配置
- 确保账户已开启两步验证,应用密码是在两步验证开启后生成的(Gmail已废弃低安全应用访问,必须用应用密码)
- 应用密码是16位无空格字符串,确认输入无错误
4. 测试邮件发送
添加测试路由验证配置是否正常:
@views.route('/test_email') @login_required def test_email(): try: send_email('测试邮件', '这是一封测试邮件', current_user.email) return '邮件发送成功' except Exception as e: return f'发送失败:{str(e)}'
额外优化建议
- 避免邮件轰炸:在数据库中记录最后一次发送警报的时间,设置冷却周期(如5分钟),防止阈值反复触发导致频繁发信
- 添加异常捕获:修改
send_email函数捕获异常,避免邮件发送失败导致整个请求崩溃:
from flask_mail import Message from . import mail import traceback def send_email(subject, body, recipient_email): try: msg = Message(subject, recipients=[recipient_email], sender='noreply@demo.com') msg.body = body mail.send(msg) return True except Exception as e: print(f"邮件发送失败: {str(e)}") traceback.print_exc() return False
内容的提问来源于stack exchange,提问作者Ae gis
相关产品推荐
相关产品推荐

