You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:35:29