Flask-Mail无法发送邮件:连接拒绝与内部服务器异常求助
问题描述
我正在开发一款Web应用,通过HTML表单获取用户邮箱地址后发送一次性验证码(OTP),用于网站后续访问验证:
- 模板文件夹中有两个HTML文件,分别用于收集用户邮箱和输入OTP;
- 通过
config.json文件存储发送OTP的账号ID和密码。
现有Python代码
from flask import Flask, render_template, request from random import randint import json from flask_mail import * with open('config.json','r') as f: params = json.load(f)['params'] mail = Mail(app) otp = randint(100,999) #otp production app.config['MAIL_SERVER'] = 'smtp.gmail.com' app.config['MAIL_PORT'] = 465 app.config['MAIL_USE_TLS'] = False app.config['MAIL_USE_SSL'] = True app.config['MAIL_USERNAME'] = params['gmail-user'] app.config['MAIL_PASSWORD'] = params['gmail-password'] @app.route('/') def home(): return(render_template('otpgive.html')) @app.route('/getOTP', methods = ['POST']) def getOTP(): #OTP send and Verify here email_id = request.form['usermail'] msg = Message('OTP for the APPLICATION', sender = 'my_email', recipients = [email_id]) #my_email is the email through which i plan to send messages. msg.body = "Greetings! Your email has been verified successfully. Kindly note your OTP is " + str(otp) mail.send(msg) return render_template('otpconfirm.html') @app.route('/validateOTP', methods = ['POST']) def validateOTP(): userotp = request.form['otp'] if (otp == int(userotp)): return ("Email Verified Succcessfully ") else: return render_template('otpgive.html',msg = 'incorrect otp') if __name__ == '__main__': app.run(debug = False) #app.run(host='0.0.0.0',port=5000, debug = True)
已尝试的无效方案
- 关闭防火墙;
- 设置端口为0.0.0.0;
- 设置
debug = False。
错误表现
预期应用能成功向用户发送邮件,但实际出现以下错误:
Internal Server Error
服务器遇到内部错误,无法完成您的请求。可能是服务器过载或应用存在错误。
ConnectionRefusedError:
[WinError 10061] 由于目标计算机积极拒绝,无法连接。
问题排查与解决方案
1. 修复代码初始化顺序
代码中先初始化mail = Mail(app),但此时Flask应用实例app还未创建,邮箱配置也未加载,这是导致内部错误的直接原因。正确顺序如下:
from flask import Flask, render_template, request from random import randint import json from flask_mail import Mail, Message # 1. 先创建Flask应用实例 app = Flask(__name__) # 2. 加载配置并设置邮箱参数 with open('config.json','r') as f: params = json.load(f)['params'] app.config['MAIL_SERVER'] = 'smtp.gmail.com' app.config['MAIL_PORT'] = 465 app.config['MAIL_USE_TLS'] = False app.config['MAIL_USE_SSL'] = True app.config['MAIL_USERNAME'] = params['gmail-user'] app.config['MAIL_PASSWORD'] = params['gmail-password'] # 3. 最后初始化Mail对象 mail = Mail(app)
2. 解决Gmail SMTP连接拒绝问题
Gmail默认拦截第三方应用登录,需做以下配置:
- 启用应用专用密码:若账号开启了两步验证,需在Google账号安全设置中生成应用专用密码,替换
config.json中的密码; - 切换SMTP端口:尝试使用TLS端口587,对应修改配置:
MAIL_PORT = 587、MAIL_USE_TLS = True、MAIL_USE_SSL = False; - 检查账号权限:确保Google账号未限制SMTP服务访问。
3. 修复OTP全局变量问题
当前OTP是全局变量,多用户同时请求会导致验证码被覆盖,建议将OTP存储在用户会话中:
from flask import session @app.route('/getOTP', methods = ['POST']) def getOTP(): email_id = request.form['usermail'] otp = randint(1000,9999) # 建议使用4位OTP提升安全性 session['otp'] = otp # 发件人需替换为实际的Gmail账号 msg = Message('应用验证OTP', sender=params['gmail-user'], recipients=[email_id]) msg.body = f"您好!您的邮箱验证验证码是:{otp}" mail.send(msg) return render_template('otpconfirm.html') @app.route('/validateOTP', methods = ['POST']) def validateOTP(): userotp = request.form['otp'] if session.get('otp') == int(userotp): session.pop('otp') # 验证成功后清除会话中的OTP return "邮箱验证成功!" else: return render_template('otpgive.html', msg='验证码错误,请重新获取')
4. 修正发件人地址
代码中sender = 'my_email'需替换为实际的发件邮箱(即params['gmail-user']),否则邮件服务会拒绝发送请求。
内容的提问来源于stack exchange,提问作者HS077
相关产品推荐
相关产品推荐

