
本文详解 flask 中如何将 html 表单提交的数据(姓名、邮箱、电话、消息)安全可靠地通过 gmail smtp 发送至指定邮箱,重点解决“表单能接收数据但邮件未发出”的常见问题。
在 Flask 应用中实现联系表单的邮件发送功能,关键在于后端路由逻辑的完整性:仅定义 send_email() 函数是不够的,必须在处理 POST 请求的视图函数(如 contact())中显式调用该函数并传入表单数据。从日志可见,POST /contact 请求已成功触发("POST /contact HTTP/1.1" 200 -),且控制台输出了表单内容(如 Sara、[email protected] 等),说明数据已正确接收;但邮件未发出,根本原因正是 send_email() 函数未被调用。
✅ 正确的后端实现(main.py)
确保你的 contact() 视图函数完整包含以下逻辑:
from flask import Flask, render_template, request, flash
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
app = Flask(__name__)
app.secret_key = 'your-secret-key' # 用于 flash 消息(可选)
@app.route('/contact', methods=['GET', 'POST'])
def contact():
if request.method == 'POST':
# 1. 获取表单数据
name = request.form.get('name', '').strip()
email = request.form.get('email', '').strip()
phone = request.form.get('phone', '').strip()
message = request.form.get('message', '').strip()
# 2. 基础校验(建议添加)
if not all([name, email, message]):
flash('Please fill in all required fields.', 'error')
return render_template('contact.html', msg_sent=False)
try:
# 3. 调用邮件发送函数 —— 这是缺失的关键步骤!
send_email(name, email, phone, message)
return render_template('contact.html', msg_sent=True)
except Exception as e:
print(f"Email sending failed: {e}")
flash('Failed to send message. Please try again.', 'error')
return render_template('contact.html', msg_sent=False)
# GET 请求:渲染初始页面
return render_template('contact.html', msg_sent=False)
def send_email(name, email, phone, message):
smtp_server = 'smtp.gmail.com'
smtp_port = 587
smtp_username = 'your_gmail@gmail.com' # 替换为你的 Gmail 地址
smtp_password = 'your_app_password' # ⚠️ 必须使用 Google App Password,非账户密码!
from_email = smtp_username
to_email = 'recipient@example.com' # 替换为目标邮箱
subject = f'New Contact Form Submission from {name}'
# 构建标准 MIME 邮件(比纯字符串更可靠)
msg = MIMEMultipart()
msg['From'] = from_email
msg['To'] = to_email
msg['Subject'] = subject
msg.attach(MIMEText(
f'Name: {name}\nEmail: {email}\nPhone: {phone}\nMessage:\n{message}',
'plain'
))
try:
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # 启用 TLS 加密
server.login(smtp_username, smtp_password)
server.send_message(msg) # 推荐用 send_message() 替代 sendmail()
print("✅ Email sent successfully.")
except Exception as e:
print(f"❌ SMTP Error: {e}")
raise? 关键注意事项
-
Gmail App Password 是必需的:
自 2022 年起,Google 已禁用「低安全性应用访问」。你必须:- 在 Google 账户安全设置 中开启「两步验证」;
- 在「App passwords」页面生成一个 16 位专用密码(选择「Mail」→「Other」),将此密码填入 smtp_password,而非你的 Gmail 登录密码。
-
避免硬编码敏感信息:
生产环境务必使用环境变量管理 smtp_username 和 smtp_password:import os smtp_username = os.getenv('GMAIL_USER') smtp_password = os.getenv('GMAIL_APP_PASSWORD') HTML 模板需支持状态反馈:
你的 contact.html 中已正确使用 msg_sent 变量控制提示文案({% if msg_sent %}),确保 render_template() 调用时传入该参数。错误处理不可省略:
添加 try...except 捕获 SMTP 异常,并通过 print() 或日志记录具体错误(如认证失败、连接超时),这是调试邮件功能的第一手线索。
✅ 总结
表单数据“收得到却发不出”,90% 的情况源于视图函数中遗漏了 send_email(...) 的调用。只要确保:
- contact() 路由在 POST 方法下获取数据并调用发送函数;
- 使用有效的 Gmail App Password;
- 采用 MIMEMultipart 构建规范邮件体;
- 添加基础校验与异常捕获;
你的 Flask 联系表单即可稳定、安全地将用户消息送达指定邮箱。










