使用Python和SQLAlchemy实现高效的邮件发送系统

 更新时间:2025年05月11日 09:41:12   作者:码农阿豪@新空间  
在现代Web应用中,邮件通知是不可或缺的功能之一,无论是订单确认、文件处理结果通知,还是系统告警,邮件都是最常用的通信方式之一,本文将详细介绍如何基于 Python、SQLAlchemy 和 SMTP 协议,构建一个高效、可靠的邮件发送系统,需要的朋友可以参考下

引言

在现代Web应用中,邮件通知是不可或缺的功能之一。无论是订单确认、文件处理结果通知,还是系统告警,邮件都是最常用的通信方式之一。本文将详细介绍如何基于 Python、SQLAlchemy 和 SMTP 协议,构建一个高效、可靠的邮件发送系统。我们将从需求分析、数据库设计、代码实现到优化策略,一步步实现一个支持附件发送、多收件人管理的邮件服务。

1. 需求分析

我们的系统需要满足以下核心需求:

  1. 多收件人支持:

    • 支持直接指定收件人邮箱(如 receiver_email)。
    • 支持通过 user_id 查询关联的用户邮箱(存储在 User 表中)。
    • 自动去重,避免重复发送。
  2. 附件发送:

    • 支持发送文件附件(如CSV、Excel等)。
    • 确保附件读取和发送的稳定性。
  3. 错误处理与日志:

    • 记录邮件发送状态(成功/失败)。
    • 提供详细的错误日志,便于排查问题。
  4. 性能优化:

    • 避免重复构建邮件内容。
    • 支持批量发送,减少SMTP连接开销。

2. 数据库设计

邮件发送系统通常需要关联用户数据,因此我们使用 SQLAlchemy 定义数据模型:

2.1 User 表(存储用户信息)

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class User(db.Model):
    __tablename__ = 'user'
    
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), nullable=False, unique=True)
    username = db.Column(db.String(80), nullable=False)
    # 其他字段...

2.2 CustomerOrder 表(关联用户订单)

class CustomerOrder(db.Model):
    __tablename__ = 'customer_order'
    
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    tracking_number = db.Column(db.String(50), nullable=False)
    order_number = db.Column(db.String(50), nullable=False)
    # 其他字段...
    
    # 定义与User表的关系
    user = db.relationship('User', backref='orders')

3. 邮件发送核心实现

3.1 基础邮件发送(SMTP)

我们使用Python的 smtplib 和 email 库实现邮件发送:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import os

def send_email(to_email, subject, body, attachment_path=None):
    """发送邮件(支持附件)"""
    # 邮件服务器配置
    smtp_server = "smtp.qq.com"
    smtp_port = 465
    sender_email = "your_email@qq.com"
    password = "your_smtp_password"  # 建议使用环境变量
    
    # 创建邮件对象
    msg = MIMEMultipart()
    msg['From'] = sender_email
    msg['To'] = to_email
    msg['Subject'] = subject
    
    # 添加正文
    msg.attach(MIMEText(body, 'plain'))
    
    # 添加附件(如果有)
    if attachment_path:
        with open(attachment_path, "rb") as file:
            part = MIMEApplication(file.read(), Name=os.path.basename(attachment_path))
            part['Content-Disposition'] = f'attachment; filename="{os.path.basename(attachment_path)}"'
            msg.attach(part)
    
    # 发送邮件
    try:
        with smtplib.SMTP_SSL(smtp_server, smtp_port) as server:
            server.login(sender_email, password)
            server.sendmail(sender_email, to_email, msg.as_string())
        return True
    except Exception as e:
        print(f"邮件发送失败: {e}")
        return False

3.2 多收件人邮件发送(优化版)

结合SQLAlchemy查询,实现多收件人邮件发送:

def send_email_to_recipients(filepath, receiver_email=None):
    """发送邮件给指定邮箱和用户关联邮箱"""
    # 获取当前用户ID(假设通过PassportService)
    token, user_id = PassportService.current_user_id()
    
    # 收件人集合(自动去重)
    recipients = set()
    
    # 1. 添加直接指定的邮箱
    if receiver_email:
        recipients.add(receiver_email)
    
    # 2. 查询用户关联邮箱
    user = User.query.get(user_id)
    if user and user.email:
        recipients.add(user.email)
    
    if not recipients:
        print("无有效收件人")
        return False
    
    # 发送邮件(每个邮箱只发一次)
    success = True
    for email in recipients:
        if not send_email(email, "文件处理结果", "请查收附件", filepath):
            success = False
    
    return success

4. 优化策略

4.1 使用集合(Set)去重

recipients = set()
recipients.add("user1@example.com")  # 自动去重

4.2 减少SMTP连接次数

# 优化:复用SMTP连接
with smtplib.SMTP_SSL(smtp_server, smtp_port) as server:
    server.login(sender_email, password)
    for email in recipients:
        server.sendmail(...)

4.3 异步发送(Celery + Redis)

from celery import Celery

celery = Celery('tasks', broker='redis://localhost:6379/0')

@celery.task
def async_send_email(to_email, subject, body, attachment_path=None):
    send_email(to_email, subject, body, attachment_path)

5. 完整代码示例

# app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import os

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
db = SQLAlchemy(app)

# 定义User和CustomerOrder模型(略)

def send_email_with_attachment(filepath, receiver_email=None):
    """发送邮件给指定邮箱和用户关联邮箱"""
    # 获取当前用户ID
    token, user_id = PassportService.current_user_id()
    
    # 收件人集合
    recipients = set()
    if receiver_email:
        recipients.add(receiver_email)
    
    user = User.query.get(user_id)
    if user and user.email:
        recipients.add(user.email)
    
    if not recipients:
        return False
    
    # SMTP配置
    smtp_server = "smtp.qq.com"
    smtp_port = 465
    sender_email = "your_email@qq.com"
    password = "your_password"
    
    # 创建邮件内容
    msg = MIMEMultipart()
    msg['From'] = sender_email
    msg['Subject'] = "文件处理结果"
    msg.attach(MIMEText("请查收附件", 'plain'))
    
    # 添加附件
    with open(filepath, "rb") as file:
        part = MIMEApplication(file.read(), Name=os.path.basename(filepath))
        part['Content-Disposition'] = f'attachment; filename="{os.path.basename(filepath)}"'
        msg.attach(part)
    
    # 发送邮件
    try:
        with smtplib.SMTP_SSL(smtp_server, smtp_port) as server:
            server.login(sender_email, password)
            for email in recipients:
                msg['To'] = email
                server.sendmail(sender_email, email, msg.as_string())
        return True
    except Exception as e:
        print(f"发送失败: {e}")
        return False

6. 总结

本文详细介绍了如何基于 Python + SQLAlchemy + SMTP 实现高效邮件发送系统,核心优化点包括:

  1. 多收件人管理(自动去重)。
  2. 附件发送支持(文件读取优化)。
  3. 错误处理与日志(增强稳定性)。
  4. 性能优化(减少SMTP连接次数)。

通过合理的代码设计,我们可以构建一个健壮、可扩展的邮件通知系统,适用于订单处理、文件通知等场景。

以上就是使用Python和SQLAlchemy实现高效的邮件发送系统的详细内容,更多关于Python SQLAlchemy邮件发送的资料请关注脚本之家其它相关文章!

相关文章

  • 使用PySpider进行IP代理爬虫的技巧与实践分享

    使用PySpider进行IP代理爬虫的技巧与实践分享

    PySpider是一个基于Python的强大的开源网络爬虫框架,它使用简单、灵活,并且具有良好的扩展性,本文将介绍如何使用PySpider进行IP代理爬虫,并提供一些技巧和实践经验,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2024-03-03
  • Python实现树的先序、中序、后序排序算法示例

    Python实现树的先序、中序、后序排序算法示例

    这篇文章主要介绍了Python实现树的先序、中序、后序排序算法,结合具体实例形式分析了Python数据结构中树的定义及常用遍历、排序操作技巧,需要的朋友可以参考下
    2017-06-06
  • python使用response.read()接收json数据的实例

    python使用response.read()接收json数据的实例

    今天小编就为大家分享一篇python使用response.read()接收json数据的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • 用python绘制彩色螺旋线代码

    用python绘制彩色螺旋线代码

    大家好,本篇文章主要讲的是用python绘制彩色螺旋线代码,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Python实现模拟时钟代码推荐

    Python实现模拟时钟代码推荐

    本文给大家汇总介绍了下使用Python实现模拟时钟的代码,一共3个例子,后两个是基于QT实现,有需要的小伙伴可以参考下
    2015-11-11
  • Python+OpenCV人脸识别签到考勤系统实现(附demo)

    Python+OpenCV人脸识别签到考勤系统实现(附demo)

    本文主要介绍了Python+OpenCV人脸识别签到考勤系统实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程

    Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程

    这篇文章主要介绍了Centos7下源码安装Python3 shell 脚本自动安装Python3的相关知识,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • Python plt.title()函数实例详解

    Python plt.title()函数实例详解

    plt.title() 是 matplotlib 库中用于设置图形标题的函数,这篇文章主要介绍了Python plt.title()函数,需要的朋友可以参考下
    2023-03-03
  • Python中的enumerate() 函数用法详解

    Python中的enumerate() 函数用法详解

    enumerate()是python的内置函数,将一个可遍历iterable数据对象(如list列表、tuple元组或str字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for循环当中,这篇文章主要介绍了Python中的enumerate() 函数用法详解,需要的朋友可以参考下
    2024-01-01
  • python进阶教程之模块(module)介绍

    python进阶教程之模块(module)介绍

    这篇文章主要介绍了python进阶教程之模块(module)介绍,本文讲解了基础知识、引用方法、搜索的路径、模块包等知识,需要的朋友可以参考下
    2014-08-08

最新评论