
本文详解 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 联系表单即可稳定、安全地将用户消息送达指定邮箱。