Flask 表单数据提交后如何正确调用邮件发送函数实现联系表单功能

本文详解 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 是必需的
    自 2025 年起,Google 已禁用「低安全性应用访问」。你必须:

    1. 在 Google 账户安全设置 中开启「两步验证」;
    2. 在「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(...) 的调用。只要确保:

  1. contact() 路由在 POST 方法下获取数据并调用发送函数;
  2. 使用有效的 Gmail App Password;
  3. 采用 MIMEMultipart 构建规范邮件体;
  4. 添加基础校验与异常捕获;

你的 Flask 联系表单即可稳定、安全地将用户消息送达指定邮箱。