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

如何在Flask发送的订阅通知邮件中添加退订超链接?

Flask订阅邮件添加退订超链接解决方案

1. 将纯文本邮件改为HTML格式

原邮件为纯文本格式,无法解析超链接,需切换为HTML邮件并设置正确的Content-Type头。修改邮件发送代码如下:

from email.mime.text import MIMEText

# 构造HTML格式的邮件内容,替换为你的域名和订阅者ID
subscriber_message = f"""
<html>
  <body>
    <p>You have been subscribed. Thank you.</p>
    <p>If you wish to be removed from the subscription list, <a href="https://your-domain.com/auth/unsubscribe/{subscriber.id}">click here</a>.</p>
  </body>
</html>
"""

# 封装HTML邮件,设置必要头信息
message = MIMEText(subscriber_message, 'html')
message['From'] = my_email
message['To'] = subscriber_email
message['Subject'] = "Subscription Confirmation"

server = smtplib.SMTP("smtp.gmail.com", 587)
server.starttls()
server.login(my_email, pw)
server.sendmail(my_email, subscriber_email, message.as_string())
server.quit()

说明:需将your-domain.com替换为你的实际域名,subscriber.id是当前订阅者在数据库中的唯一ID,用于生成专属退订链接。

2. 调整退订路由,支持用户点击操作

原delete-subscribers接口仅支持POST请求,无法直接通过链接触发(链接默认是GET请求),推荐以下两种实现方式:

方式一:新增退订确认页面(更友好)

先让用户确认退订操作,再执行删除逻辑:

# 显示退订确认页面
@auth.route('/unsubscribe/<int:subscriber_id>', methods=['GET'])
def unsubscribe_confirm(subscriber_id):
    sub = Subscribers.query.get(subscriber_id)
    if not sub:
        flash('Subscriber does not exist in database.', category='error')
        return redirect(url_for('home'))
    return render_template('unsubscribe_confirm.html', subscriber=sub)

# 处理退订请求(兼容原POST逻辑)
@auth.route('/delete-subscribers', methods=['POST'])
def delete_subscribers():
    # 优先从表单获取ID,兼容原JSON传参逻辑
    subscriber_id = request.form.get('subscriber_id')
    if not subscriber_id:
        sub_data = json.loads(request.data)
        subscriber_id = sub_data['subscribersId']
    
    sub = Subscribers.query.get(subscriber_id)
    if sub:
        db.session.delete(sub)
        db.session.commit()
        flash('Successfully unsubscribed.', category='success')
    else:
        flash('Subscriber does not exist in database.', category='error')
    
    return redirect(url_for('home'))

对应的unsubscribe_confirm.html模板示例:

<!DOCTYPE html>
<html>
<head>
    <title>Unsubscribe Confirmation</title>
</head>
<body>
    <h1>Are you sure you want to unsubscribe?</h1>
    <form method="POST" action="{{ url_for('auth.delete_subscribers') }}">
        <input type="hidden" name="subscriber_id" value="{{ subscriber.id }}">
        <button type="submit">Yes, Unsubscribe Me</button>
        <a href="{{ url_for('home') }}">Cancel</a>
    </form>
</body>
</html>

方式二:直接通过GET请求完成退订(简化版)

若无需确认步骤,可直接在GET路由中执行删除:

@auth.route('/unsubscribe/<int:subscriber_id>', methods=['GET'])
def unsubscribe(subscriber_id):
    sub = Subscribers.query.get(subscriber_id)
    if sub:
        db.session.delete(sub)
        db.session.commit()
        return "Successfully unsubscribed."
    else:
        return "Subscriber does not exist in database."

这种方式操作简单,但存在误触风险,需根据业务场景选择。

3. 安全优化建议

直接使用订阅者ID易被恶意批量攻击,建议为每个订阅者生成唯一退订token:

  1. 修改Subscribers模型:
from uuid import uuid4

class Subscribers(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(100), unique=True, nullable=False)
    # 添加唯一退订token字段
    unsubscribe_token = db.Column(db.String(64), unique=True, nullable=False, default=lambda: str(uuid4()))
  1. 更新邮件链接:
f"<a href='https://your-domain.com/auth/unsubscribe/{subscriber.unsubscribe_token}'>click here</a>"
  1. 修改退订路由:
@auth.route('/unsubscribe/<token>', methods=['GET'])
def unsubscribe(token):
    sub = Subscribers.query.filter_by(unsubscribe_token=token).first()
    if sub:
        db.session.delete(sub)
        db.session.commit()
        return "Successfully unsubscribed."
    else:
        return "Invalid unsubscribe link."

内容的提问来源于stack exchange,提问作者Dustin916

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:15:36