在自動化運維、數據報告推送或用户通知等場景中,通過程序自動發送郵件是一項非常實用的技能。Python 標準庫中的 smtplibemail 模塊提供了完整的郵件發送能力,無需第三方依賴即可實現純文本、HTML 郵件以及附件的發送。本文將帶你用不到十分鐘,掌握從基礎到進階的郵件發送技巧。

1. 基礎配置:連接SMTP服務器

大多數郵箱服務商(如 Gmail、QQ、163)都提供 SMTP 服務。以 QQ 郵箱為例,需先在設置中開啓“SMTP服務”並獲取授權碼(不是登錄密碼)。

import smtplib
from email.mime.text import MIMEText
from email.header import Header

# 郵箱配置
sender = "your_email@qq.com"
password = "your_smtp_auth_code"  # 授權碼
receiver = "recipient@example.com"
smtp_server = "smtp.qq.com"
port = 465  # QQ郵箱SSL端口

2. 發送純文本郵件

使用 MIMEText 構造郵件內容,並通過 smtplib.SMTP_SSL 安全連接:

def send_text_email(subject, body):
    msg = MIMEText(body, 'plain', 'utf-8')
    msg['From'] = Header(sender)
    msg['To'] = Header(receiver)
    msg['Subject'] = Header(subject, 'utf-8')

    with smtplib.SMTP_SSL(smtp_server, port) as server:
        server.login(sender, password)
        server.sendmail(sender, [receiver], msg.as_string())
    print("郵件發送成功!")

# 使用示例
send_text_email("測試郵件", "這是一封由Python自動發送的純文本郵件。")

3. 發送HTML格式郵件

HTML 郵件支持富文本、鏈接、表格甚至內嵌樣式,適合發送美觀的報告:

from email.mime.multipart import MIMEMultipart

def send_html_email(subject, html_content):
    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = receiver
    msg['Subject'] = Header(subject, 'utf-8')

    # 添加HTML正文
    html_part = MIMEText(html_content, 'html', 'utf-8')
    msg.attach(html_part)

    with smtplib.SMTP_SSL(smtp_server, port) as server:
        server.login(sender, password)
        server.sendmail(sender, [receiver], msg.as_string())

# HTML模板示例
html = """
<h2>每日數據報告</h2>
<p>今日新增用户:<strong>1,234</strong></p>
<p>系統狀態:<span style="color:green">✅ 正常</span></p>
<a href="https://your-dashboard.com">查看詳情</a>
"""
send_html_email("【系統日報】2025-06-15", html)

4. 添加附件(圖片、PDF、Excel等)

要發送帶附件的郵件,需使用 MIMEBase 並設置正確的 Content-Type

from email.mime.base import MIMEBase
from email import encoders
import os

def send_email_with_attachment(subject, body, file_path):
    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = receiver
    msg['Subject'] = Header(subject, 'utf-8')

    # 添加正文
    msg.attach(MIMEText(body, 'plain', 'utf-8'))

    # 添加附件
    with open(file_path, "rb") as f:
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(f.read())
    encoders.encode_base64(part)
    part.add_header(
        'Content-Disposition',
        f'attachment; filename="{os.path.basename(file_path)}"'
    )
    msg.attach(part)

    with smtplib.SMTP_SSL(smtp_server, port) as server:
        server.login(sender, password)
        server.sendmail(sender, [receiver], msg.as_string())

# 發送帶Excel附件的郵件
send_email_with_attachment(
    "月度銷售報表",
    "附件為本月銷售數據,請查收。",
    "sales_report.xlsx"
)

5. 同時包含HTML正文與附件

實際應用中,常需既展示精美HTML內容,又附帶原始數據文件:

def send_rich_email(subject, html_body, attachment_path=None):
    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = receiver
    msg['Subject'] = Header(subject, 'utf-8')

    # HTML正文
    msg.attach(MIMEText(html_body, 'html', 'utf-8'))

    # 可選附件
    if attachment_path:
        with open(attachment_path, "rb") as f:
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(f.read())
        encoders.encode_base64(part)
        part.add_header(
            'Content-Disposition',
            f'attachment; filename="{os.path.basename(attachment_path)}"'
        )
        msg.attach(part)

    with smtplib.SMTP_SSL(smtp_server, port) as server:
        server.login(sender, password)
        server.sendmail(sender, [receiver], msg.as_string())

6. 注意事項

  • 授權碼安全:切勿將密碼或授權碼硬編碼在代碼中,建議使用環境變量:
import os
password = os.getenv("EMAIL_PASSWORD")
  • 不同郵箱配置
  • Gmail: smtp.gmail.com, port 465 或 587(需開啓“兩步驗證”並生成應用專用密碼);
  • 163郵箱: smtp.163.com, port 465。
  • 批量發送:可將 receiver 改為列表,並在 sendmail 中傳入多個收件人。

通過 smtplibemail 模塊,Python 能輕鬆實現專業級的郵件自動化。無論是每日報告、異常告警還是用户註冊確認,只需幾行代碼即可完成。掌握這項技能,讓你的程序真正“會説話”。現在,就去寫一個自動發送週報的小腳本吧!