凌峰创科服务平台

Python SMTP服务器如何搭建与配置?

Python 内置了 smtplib 模块,它使得发送邮件变得非常简单,我们将从基础开始,逐步深入到更高级和实际的应用场景。

Python SMTP服务器如何搭建与配置?-图1
(图片来源网络,侵删)

目录

  1. 核心概念: SMTP 是什么?
  2. 基础发送: 使用 smtplibemail 发送一封简单的纯文本邮件。
  3. 进阶发送: 发送 HTML 邮件、添加附件。
  4. 使用 Gmail 发送邮件: 最常见的需求,包括处理安全性问题。
  5. 完整示例代码: 一个可运行的脚本,包含错误处理。
  6. 最佳实践与注意事项

核心概念

  • SMTP (Simple Mail Transfer Protocol): 用于发送电子邮件的标准协议,你的 Python 脚本将扮演一个“邮件客户端”的角色,通过 SMTP 协议与邮件服务器(如 Gmail, Outlook, 公司的邮件服务器)通信,然后将邮件传递给收件人。
  • Python 标准库:
    • smtplib: 负责建立与 SMTP 服务器的连接,并执行发送邮件的命令(如登录、发送数据)。
    • email: 一个功能强大的库,用于构建符合邮件标准的复杂邮件内容,包括主题、发件人、收件人、正文(纯文本/HTML)、附件等。
    • 重要提示: 你需要同时使用这两个库。smtplib 只负责“投递”,而 email 负责构建“包裹”。

基础发送:纯文本邮件

这是最简单的邮件发送方式,我们将发送一封没有附件、没有格式的纯文本邮件。

步骤:

  1. 导入必要的模块:

    import smtplib
    from email.mime.text import MIMEText
    from email.header import Header
  2. 设置邮件内容:

    • subject: 邮件主题
    • sender: 发件人邮箱
    • receiver: 收件人邮箱 (可以是多个,用逗号分隔的字符串)
    • body: 邮件正文
  3. 创建邮件对象:

    Python SMTP服务器如何搭建与配置?-图2
    (图片来源网络,侵删)
    • MIMEText('邮件内容', 'plain', 'utf-8') 创建一个纯文本邮件对象。
      • 'plain' 表示纯文本,如果想用 HTML,则用 'html'
      • 'utf-8' 是编码,确保中文等特殊字符能正确显示。
  4. 设置邮件头:

    • ['From'], ['To'], ['Subject'] 是邮件的标准头信息。
    • Header() 用于处理非 ASCII 字符(如中文),防止乱码。
  5. 连接 SMTP 服务器并发送邮件:

    • smtplib.SMTP_SSL(host, port): 创建一个加密的 SSL 连接,现在大多数邮件服务商都推荐使用 SSL。
    • server.login(): 登录你的邮箱。
    • server.sendmail(): 发送邮件。
    • server.quit(): 关闭连接。

示例代码:

import smtplib
from email.mime.text import MIMEText
from email.header import Header
# 1. 邮件内容配置
sender = 'your_email@example.com'  # 替换为你的发件人邮箱
receivers = ['receiver1@example.com', 'receiver2@example.com']  # 替换为收件人邮箱列表
subject = 'Python SMTP 邮件测试'
body = '你好,\n\n这是一封由 Python SMTP 发送的测试邮件,\n\n祝好!'
# 2. 创建邮件对象
# 第一个参数是邮件正文,第二个参数是邮件类型,第三个参数是编码
message = MIMEText(body, 'plain', 'utf-8')
message['From'] = Header(sender)  # 发件人
message['To'] = Header(','.join(receivers))  # 收件人,多个收件人用逗号分隔
message['Subject'] = Header(subject, 'utf-8')  # 邮件主题
# 3. 连接服务器并发送邮件
try:
    # 使用 SSL 加密连接,以 Gmail 为例
    # host: SMTP 服务器地址
    # port: SMTP 服务器端口 (SSL 通常为 465)
    server = smtplib.SMTP_SSL('smtp.example.com', 465) # 替换为你的 SMTP 服务器地址和端口
    # 如果需要登录,请取消下面两行的注释
    # username = 'your_email@example.com'
    # password = 'your_password'  # 建议使用应用专用密码,而不是邮箱密码
    # server.login(username, password)
    server.sendmail(sender, receivers, message.as_string())
    print("邮件发送成功!")
except smtplib.SMTPException as e:
    print(f"邮件发送失败: {e}")
finally:
    server.quit()

进阶发送:HTML 邮件和附件

发送带格式的 HTML 邮件和附件是更常见的需求,这需要用到 email.mime.multipart.MIMEMultipart 来创建一个可以包含多个部分的邮件。

示例代码:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.header import Header
import os
# --- 邮件内容配置 ---
sender = 'your_email@example.com'
receivers = ['receiver@example.com']
subject = 'HTML 邮件与附件测试'
# --- 创建一个带有多部分的邮件对象 ---
msg = MIMEMultipart('alternative') # 'alternative' 表示正文有纯文本和HTML两种版本
msg['From'] = Header(sender)
msg['To'] = Header(','.join(receivers))
msg['Subject'] = Header(subject, 'utf-8')
# --- 1. 添加纯文本正文 (作为后备) ---
text_body = """
如果你正在阅读这封邮件,说明你的邮件客户端不支持 HTML 格式。
这是一封测试邮件。
"""
part1 = MIMEText(text_body, 'plain', 'utf-8')
msg.attach(part1)
# --- 2. 添加 HTML 正文 ---
html_body = """
<html>
  <body>
    <h1>你好,世界!</h1>
    <p>这是一封 <b>HTML</b> 格式的测试邮件。</p>
    <p>图片示例:<img src="cid:my_image_cid"></p>
  </body>
</html>
"""
part2 = MIMEText(html_body, 'html', 'utf-8')
msg.attach(part2)
# --- 3. 添加附件 ---
# 假设你有一个名为 'report.pdf' 的文件在当前目录
attachment_path = 'report.pdf' 
if os.path.exists(attachment_path):
    with open(attachment_path, 'rb') as f:
        # 创建附件对象
        part3 = MIMEApplication(f.read(), Name=os.path.basename(attachment_path))
    # 添加附件头信息
    part3['Content-Disposition'] = f'attachment; filename="{os.path.basename(attachment_path)}"'
    msg.attach(part3)
    print(f"附件 '{attachment_path}' 已添加。")
else:
    print(f"警告:附件文件 '{attachment_path}' 未找到,将跳过。")
# --- 发送邮件 ---
try:
    server = smtplib.SMTP_SSL('smtp.example.com', 465) # 替换为你的SMTP服务器
    # server.login(sender, 'your_password') # 如果需要登录
    server.sendmail(sender, receivers, msg.as_string())
    print("HTML邮件与附件发送成功!")
except smtplib.SMTPException as e:
    print(f"邮件发送失败: {e}")
finally:
    server.quit()

使用 Gmail 发送邮件

Gmail 是最常用的邮箱之一,但使用 Python 发送时需要注意几点:

Python SMTP服务器如何搭建与配置?-图3
(图片来源网络,侵删)
  1. 启用“两步验证” (2-Step Verification): 如果你的账户开启了此功能,你将无法直接使用你的账户密码登录 SMTP 服务器。
  2. 生成“应用专用密码” (App Password):
    • 登录你的 Google 账户。
    • 进入“安全性”(Security) 设置。
    • 在“两步验证”下方,找到“应用专用密码”(App passwords)。
    • 选择应用为“邮件”(Mail),设备为“其他(自定义名称)”,并为其命名("Python Script")。
    • Google 会生成一个 16 位的密码。请复制这个密码,它将是你 Python 脚本中使用的密码。

Gmail SMTP 服务器信息:

  • 服务器地址: smtp.gmail.com
  • SSL 端口: 465
  • TLS 端口: 587 (如果使用 smtplib.SMTP(),然后调用 starttls())

使用 Gmail 的示例代码:

import smtplib
from email.mime.text import MIMEText
from email.header import Header
sender = 'your_email@gmail.com'
receivers = ['receiver@example.com']
password = 'your_16_digit_app_password' # 在这里粘贴你的应用专用密码
subject = '来自 Gmail 的 Python 测试邮件'
body = '这封邮件是通过 Gmail SMTP 服务器发送的。'
message = MIMEText(body, 'plain', 'utf-8')
message['From'] = Header(sender)
message['To'] = Header(receivers[0]) # Gmail 收件人通常只写一个
message['Subject'] = Header(subject, 'utf-8')
try:
    # 使用 SSL 连接 (推荐)
    server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
    server.login(sender, password)
    server.sendmail(sender, receivers, message.as_string())
    print("邮件通过 Gmail 发送成功!")
except smtplib.SMTPAuthenticationError:
    print("发送失败!请检查邮箱地址和密码(确保是应用专用密码)。")
except smtplib.SMTPException as e:
    print(f"邮件发送失败: {e}")
finally:
    server.quit()

完整示例代码 (带配置和错误处理)

为了方便管理和复用,建议将配置信息(如服务器、密码)放在脚本外部或使用环境变量。

import smtplib
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
# --- 配置 (建议从环境变量读取,而不是硬编码) ---
SMTP_SERVER = os.getenv('SMTP_SERVER', 'smtp.example.com')
SMTP_PORT = int(os.getenv('SMTP_PORT', 465))
SMTP_USER = os.getenv('SMTP_USER', 'your_email@example.com')
SMTP_PASSWORD = os.getenv('SMTP_PASSWORD', 'your_password') # 或应用专用密码
def send_email(subject, body_html, body_text, sender, receivers, attachment_paths=None):
    """
    发送一封支持 HTML 和附件的邮件
    :param subject: 邮件主题
    :param body_html: HTML 格式邮件正文
    :param body_text: 纯文本格式邮件正文 (作为后备)
    :param sender: 发件人邮箱
    :param receivers: 收件人邮箱列表
    :param attachment_paths: 附件文件路径列表
    """
    msg = MIMEMultipart('alternative')
    msg['Subject'] = Header(subject, 'utf-8')
    msg['From'] = Header(sender)
    msg['To'] = Header(','.join(receivers))
    # 添加文本和HTML正文
    msg.attach(MIMEText(body_text, 'plain', 'utf-8'))
    msg.attach(MIMEText(body_html, 'html', 'utf-8'))
    # 添加附件
    if attachment_paths:
        for path in attachment_paths:
            if os.path.exists(path):
                with open(path, 'rb') as f:
                    part = MIMEApplication(f.read(), Name=os.path.basename(path))
                part['Content-Disposition'] = f'attachment; filename="{os.path.basename(path)}"'
                msg.attach(part)
            else:
                print(f"警告: 附件文件 '{path}' 未找到。")
    try:
        print(f"正在连接服务器 {SMTP_SERVER}:{SMTP_PORT}...")
        with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as server:
            if SMTP_USER and SMTP_PASSWORD:
                print("正在登录...")
                server.login(SMTP_USER, SMTP_PASSWORD)
            print(f"正在向 {receivers} 发送邮件...")
            server.sendmail(sender, receivers, msg.as_string())
            print("邮件发送成功!")
            return True
    except smtplib.SMTPAuthenticationError:
        print("错误: 认证失败,请检查用户名和密码。")
    except smtplib.SMTPException as e:
        print(f"错误: 邮件发送失败 - {e}")
    except Exception as e:
        print(f"发生未知错误: {e}")
    return False
# --- 使用示例 ---
if __name__ == '__main__':
    # 设置你的收件人
    my_receivers = ['friend1@example.com', 'friend2@example.com']
    # 设置邮件内容
    my_subject = "来自 Python 的问候"
    my_html_body = """
    <h2>你好!</h2>
    <p>这是一封由 Python 自动发送的邮件。</p>
    <p>希望你喜欢!</p>
    """
    my_text_body = "你好!\n\n这是一封由 Python 自动发送的邮件,\n\n希望你喜欢!"
    # 设置要附加的文件
    # my_attachments = ['report.pdf', 'data.csv'] # 确保这些文件存在
    # 调用函数发送邮件
    send_email(
        subject=my_subject,
        body_html=my_html_body,
        body_text=my_text_body,
        sender=SMTP_USER,
        receivers=my_receivers,
        # attachment_paths=my_attachments
    )

最佳实践与注意事项

  1. 安全性第一:

    • 不要硬编码密码: 永远不要把邮箱密码直接写在代码里,使用环境变量、配置文件或密钥管理服务。
    • 使用 SSL/TLS: 始终使用 SMTP_SSLSMTP(...) + starttls() 来加密你的连接,防止密码和邮件内容被窃听。
    • 应用专用密码: 对于 Gmail 等服务,使用应用专用密码,而不是主账户密码。
  2. 处理大附件:

    • email.mime 模块会将整个附件读入内存,如果附件非常大(几百MB),这可能会导致内存不足。
    • 对于超大附件,考虑使用专门的文件托管服务(如 Google Drive, Dropbox),然后在邮件中附上链接。
  3. 错误处理:

    • 始终使用 try...except 块来捕获 smtplib.SMTPException 及其子类(如 SMTPAuthenticationError, SMTPRecipientsRefused 等)。
    • 检查文件是否存在再尝试作为附件发送。
  4. 发送测试:

    • 在开发时,先用自己的邮箱作为收件人进行测试。
    • 注意不要频繁发送测试邮件,以免被邮件服务商标记为垃圾邮件发送者。
  5. 遵守法律法规:

    • 确保你有权向收件人发送邮件,遵守反垃圾邮件法(如 CAN-SPAM Act)。
    • 在邮件中提供退订链接是一个好习惯。
分享:
扫描分享到社交APP
上一篇
下一篇