Python 提供了内置的 smtplib 模块,用于通过 SMTP(Simple Mail Transfer Protocol) 协议发送电子邮件。SMTP 是一种简单的邮件传输协议,广泛用于电子邮件服务。

以下是 Python 使用 SMTP 发送邮件的完整指南。


1. 基本使用:发送简单文本邮件

1.1 示例:发送文本邮件

以下是使用 smtplib 发送邮件的最简单示例。

import smtplib
from email.mime.text import MIMEText

# 邮件发送方和接收方
sender = "youremail@example.com"
receiver = "receiver@example.com"

# 邮件内容
subject = "Python SMTP 邮件测试"
body = "这是一封通过 Python 发送的测试邮件。"

# 创建 MIMEText 对象
message = MIMEText(body, "plain", "utf-8")
message["From"] = sender
message["To"] = receiver
message["Subject"] = subject

# 发送邮件
try:
    # 连接到 SMTP 服务器
    smtp = smtplib.SMTP("smtp.example.com", 587)  # 使用 587 端口(适用于 TLS)
    smtp.starttls()  # 启用 TLS 加密
    smtp.login("youremail@example.com", "yourpassword")  # 登录 SMTP 服务器
    smtp.sendmail(sender, receiver, message.as_string())  # 发送邮件
    print("邮件发送成功!")
except Exception as e:
    print("邮件发送失败:", e)
finally:
    smtp.quit()  # 断开连接

1.2 关键点解释

  1. smtplib.SMTP
  2. 用于连接 SMTP 服务器。
  3. 常见的端口:
  4. 587:适用于 TLS(推荐)。
  5. 465:适用于 SSL。
  6. 25:不加密(不推荐)。
  7. starttls()
  8. 启用 TLS 加密。
  9. MIMEText
  10. 用于构建电子邮件正文。
  11. 参数说明:
  12. 第一个参数:邮件内容。
  13. 第二个参数:内容类型(plain 表示纯文本,html 表示 HTML 格式)。
  14. 第三个参数:编码格式(通常为 utf-8)。

2. 发送带附件的邮件

如果需要发送带附件的邮件,可以使用 email.mime.multipart 模块。

2.1 示例:发送带附件的邮件

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# 邮件发送方和接收方
sender = "youremail@example.com"
receiver = "receiver@example.com"

# 创建邮件对象
message = MIMEMultipart()
message["From"] = sender
message["To"] = receiver
message["Subject"] = "Python SMTP 邮件测试(带附件)"

# 添加邮件正文
body = "这是一封带附件的测试邮件。"
message.attach(MIMEText(body, "plain", "utf-8"))

# 添加附件
file_path = "example.txt"  # 附件文件路径
with open(file_path, "rb") as attachment:
    mime_base = MIMEBase("application", "octet-stream")
    mime_base.set_payload(attachment.read())
    encoders.encode_base64(mime_base)  # 对附件内容进行 Base64 编码
    mime_base.add_header(
        "Content-Disposition", f"attachment; filename={file_path}"
    )
    message.attach(mime_base)

# 发送邮件
try:
    smtp = smtplib.SMTP("smtp.example.com", 587)
    smtp.starttls()
    smtp.login("youremail@example.com", "yourpassword")
    smtp.sendmail(sender, receiver, message.as_string())
    print("邮件发送成功!")
except Exception as e:
    print("邮件发送失败:", e)
finally:
    smtp.quit()

3. 发送 HTML 格式的邮件

为了让邮件更美观,可以使用 HTML 格式的内容。

3.1 示例:发送 HTML 邮件

import smtplib
from email.mime.text import MIMEText

# 邮件发送方和接收方
sender = "youremail@example.com"
receiver = "receiver@example.com"

# HTML 内容
html_content = """
<!DOCTYPE html>
<html>
<body>
    <h1 style="color:blue;">Python SMTP HTML 邮件测试</h1>
    <p>这是一封通过 Python 发送的 HTML 格式的邮件。</p>
</body>
</html>
"""

# 创建 HTML 邮件
message = MIMEText(html_content, "html", "utf-8")
message["From"] = sender
message["To"] = receiver
message["Subject"] = "Python HTML 邮件测试"

# 发送邮件
try:
    smtp = smtplib.SMTP("smtp.example.com", 587)
    smtp.starttls()
    smtp.login("youremail@example.com", "yourpassword")
    smtp.sendmail(sender, receiver, message.as_string())
    print("HTML 邮件发送成功!")
except Exception as e:
    print("邮件发送失败:", e)
finally:
    smtp.quit()

4. 批量发送邮件

批量发送邮件时,可以将多个接收者地址放入 To 字段中,或使用循环发送。

4.1 示例:批量发送邮件

import smtplib
from email.mime.text import MIMEText

# 邮件发送方
sender = "youremail@example.com"
receivers = ["receiver1@example.com", "receiver2@example.com", "receiver3@example.com"]

# 邮件内容
subject = "Python 批量邮件测试"
body = "这是一封通过 Python 发送的批量测试邮件。"

# 创建 MIMEText 对象
message = MIMEText(body, "plain", "utf-8")
message["From"] = sender
message["Subject"] = subject

# 发送邮件
try:
    smtp = smtplib.SMTP("smtp.example.com", 587)
    smtp.starttls()
    smtp.login("youremail@example.com", "yourpassword")
    for receiver in receivers:
        message["To"] = receiver
        smtp.sendmail(sender, receiver, message.as_string())
        print(f"邮件已发送给:{receiver}")
except Exception as e:
    print("邮件发送失败:", e)
finally:
    smtp.quit()

5. 使用第三方邮件服务

5.1 使用 Gmail SMTP

Gmail 提供免费的 SMTP 服务,可以通过以下方式发送邮件。

注意:
  1. 确保在 Gmail 设置中启用了 “允许不太安全的应用”(或生成应用专用密码)。
  2. Gmail SMTP 服务器地址:smtp.gmail.com
import smtplib
from email.mime.text import MIMEText

# 邮件发送方和接收方
sender = "yourgmail@gmail.com"
receiver = "receiver@example.com"

# 邮件内容
subject = "Gmail SMTP 测试"
body = "这是一封通过 Gmail SMTP 发送的测试邮件。"

# 创建 MIMEText 对象
message = MIMEText(body, "plain", "utf-8")
message["From"] = sender
message["To"] = receiver
message["Subject"] = subject

# 发送邮件
try:
    smtp = smtplib.SMTP("smtp.gmail.com", 587)
    smtp.starttls()
    smtp.login("yourgmail@gmail.com", "yourpassword")  # 或使用应用专用密码
    smtp.sendmail(sender, receiver, message.as_string())
    print("Gmail 邮件发送成功!")
except Exception as e:
    print("邮件发送失败:", e)
finally:
    smtp.quit()

5.2 使用 QQ 邮箱 SMTP

QQ 邮箱也支持 SMTP 服务,但需在设置中开启 SMTP 服务 并获取授权码。

  • QQ 邮箱 SMTP 服务器地址:smtp.qq.com
  • 端口:465(SSL)或 587(TLS)。
  • import smtplib
    from email.mime.text import MIMEText
    
    # 邮件发送方和接收方
    sender = "yourqq@qq.com"
    receiver = "receiver@example.com"
    
    # 邮件内容
    subject = "QQ 邮箱 SMTP 测试"
    body = "这是一封通过 QQ 邮箱 SMTP 发送的测试邮件。"
    
    # 创建 MIMEText 对象
    message = MIMEText(body, "plain", "utf-8")
    message["From"] = sender
    message["To"] = receiver
    message["Subject"] = subject
    
    # 发送邮件
    try:
        smtp = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 使用 SSL 加密
        smtp.login("yourqq@qq.com", "yourauthorizationcode")  # QQ 邮箱授权码
        smtp.sendmail(sender, receiver, message.as_string())
        print("QQ 邮件发送成功!")
    except Exception as e:
        print("邮件发送失败:", e)
    finally:
        smtp.quit()
    

    6. 常见问题及解决方法

    6.1 常见错误

    1. smtplib.SMTPAuthenticationError

    2. 表示邮箱用户名或密码(授权码)错误。
    3. 解决方法:检查邮箱账号、密码或授权码是否正确。
    4. smtplib.SMTPConnectError

    5. 表示无法连接到 SMTP 服务器。
    6. 解决方法:检查服务器地址和端口是否正确,网络是否通畅。
    7. smtplib.SMTPDataError

    8. 表示邮件内容不符合 SMTP 协议。
    9. 解决方法:检查邮件格式,确保邮件头和正文正确。
    10. Gmail 或 QQ 邮箱登录失败

    11. 检查是否启用了 SMTP 服务。
    12. 使用应用专用密码或授权码,而不是直接使用邮箱密码。

    7. 总结

    通过 Python 的 smtplib 模块,您可以轻松实现以下功能:

    1. 发送普通文本邮件。
    2. 发送带附件的邮件。
    3. 发送 HTML 格式的邮件。
    4. 批量发送邮件。

    此外,还可以结合第三方邮件服务(如 Gmail、QQ 邮箱)实现更高效的邮件发送。对于企业级应用,建议使用邮件 API(如 SendGridAWS SES)以提升邮件发送的可靠性和扩展性。


    以下将继续扩展 Python SMTP发送邮件 的内容,涵盖更高级应用、邮件模板、邮件队列、自动化发送、第三方邮件服务集成以及常见问题的深入解决方案。


    8. 高级邮件发送功能

    8.1 发送带图片的邮件

    在邮件正文中嵌入图片,可以增强邮件的视觉效果。通过 MIMEImage 模块实现。

    发送嵌入图片的邮件

    import smtplib
    from email.mime.text import MIMEText
    from email.mime.multipart import MIMEMultipart
    from email.mime.image import MIMEImage
    
    # 邮件发送方和接收方
    sender = "youremail@example.com"
    receiver = "receiver@example.com"
    
    # 创建邮件对象
    message = MIMEMultipart("related")
    message["From"] = sender
    message["To"] = receiver
    message["Subject"] = "带嵌入图片的邮件测试"
    
    # 邮件正文(HTML 格式)
    html_content = """
    <!DOCTYPE html>
    <html>
    <body>
        <h1>Python 邮件测试</h1>
        <p>这是一个带嵌入图片的邮件测试。</p>
        <img src="cid:image1">
    </body>
    </html>
    """
    message.attach(MIMEText(html_content, "html", "utf-8"))
    
    # 添加图片
    with open("example.jpg", "rb") as img:
        mime_image = MIMEImage(img.read())
        mime_image.add_header("Content-ID", "<image1>")  # 用于 HTML 中引用
        message.attach(mime_image)
    
    # 发送邮件
    try:
        smtp = smtplib.SMTP("smtp.example.com", 587)
        smtp.starttls()
        smtp.login("youremail@example.com", "yourpassword")
        smtp.sendmail(sender, receiver, message.as_string())
        print("邮件发送成功!")
    except Exception as e:
        print("邮件发送失败:", e)
    finally:
        smtp.quit()
    

    8.2 使用 HTML 模板生成邮件内容

    在实际应用中,邮件内容通常来源于模板。可以使用 Jinja2 模板引擎动态生成 HTML 内容。

    安装 Jinja2

    pip install Jinja2
    
    示例:渲染 HTML 邮件模板
    1. 创建 HTML 模板(email_template.html
    <!DOCTYPE html>
    <html>
    <body>
        <h1>欢迎,{
      
      { name }}!</h1>
        <p>这是您的定制化邮件内容。</p>
        <p>日期:{
      
      { date }}</p>
    </body>
    </html>
    

    html 4

    在画布上打开

    1. 使用 Jinja2 渲染模板
    from jinja2 import Environment, FileSystemLoader
    import smtplib
    from email.mime.text import MIMEText
    from email.mime.multipart import MIMEMultipart
    from datetime import datetime
    
    # 加载模板
    env = Environment(loader=FileSystemLoader("."))
    template = env.get_template("email_template.html")
    
    # 渲染模板
    html_content = template.render(name="Alice", date=datetime.now().strftime("%Y-%m-%d"))
    
    # 邮件发送方和接收方
    sender = "youremail@example.com"
    receiver = "receiver@example.com"
    
    # 创建邮件对象
    message = MIMEMultipart()
    message["From"] = sender
    message["To"] = receiver
    message["Subject"] = "使用 HTML 模板的邮件"
    
    # 添加渲染后的 HTML 内容
    message.attach(MIMEText(html_content, "html", "utf-8"))
    
    # 发送邮件
    try:
        smtp = smtplib.SMTP("smtp.example.com", 587)
        smtp.starttls()
        smtp.login("youremail@example.com", "yourpassword")
        smtp.sendmail(sender, receiver, message.as_string())
        print("邮件发送成功!")
    except Exception as e:
        print("邮件发送失败:", e)
    finally:
        smtp.quit()
    

    8.3 定时发送邮件

    可以使用 scheduleAPScheduler 库实现邮件的定时发送。

    安装 schedule

    pip install schedule
    
    示例:定时发送邮件

    import smtplib
    from email.mime.text import MIMEText
    import schedule
    import time
    
    # 邮件发送函数
    def send_email():
        sender = "youremail@example.com"
        receiver = "receiver@example.com"
        subject = "定时邮件"
        body = "这是一个定时发送的测试邮件。"
    
        message = MIMEText(body, "plain", "utf-8")
        message["From"] = sender
        message["To"] = receiver
        message["Subject"] = subject
    
        try:
            smtp = smtplib.SMTP("smtp.example.com", 587)
            smtp.starttls()
            smtp.login("youremail@example.com", "yourpassword")
            smtp.sendmail(sender, receiver, message.as_string())
            print("邮件发送成功!")
        except Exception as e:
            print("邮件发送失败:", e)
        finally:
            smtp.quit()
    
    # 定时任务:每天早上 9 点发送邮件
    schedule.every().day.at("09:00").do(send_email)
    
    print("定时任务已启动...")
    while True:
        schedule.run_pending()
        time.sleep(1)
    

    9. 集成第三方邮件服务

    除了直接使用 SMTP,还可以通过第三方邮件服务(如 SendGridAWS SESMailgun 等)发送邮件,这些服务通常提供更高的可靠性和扩展性。


    9.1 使用 SendGrid

    安装 SendGrid SDK

    pip install sendgrid
    
    示例:使用 SendGrid 发送邮件

    from sendgrid import SendGridAPIClient
    from sendgrid.helpers.mail import Mail
    
    # 创建邮件对象
    message = Mail(
        from_email="youremail@example.com",
        to_emails="receiver@example.com",
        subject="SendGrid 邮件测试",
        html_content="<strong>这是一封通过 SendGrid 发送的测试邮件。</strong>"
    )
    
    # 发送邮件
    try:
        sg = SendGridAPIClient("your_sendgrid_api_key")  # 替换为你的 SendGrid API 密钥
        response = sg.send(message)
        print(f"邮件发送成功,状态码:{response.status_code}")
    except Exception as e:
        print(f"邮件发送失败:{e}")
    

    9.2 使用 AWS SES

    安装 Boto3

    pip install boto3
    
    示例:使用 AWS SES 发送邮件

    import boto3
    
    # 创建 SES 客户端
    ses = boto3.client(
        "ses",
        aws_access_key_id="your_aws_access_key",
        aws_secret_access_key="your_aws_secret_key",
        region_name="us-east-1"  # 替换为你的 AWS 区域
    )
    
    # 发送邮件
    response = ses.send_email(
        Source="youremail@example.com",
        Destination={
            "ToAddresses": ["receiver@example.com"]
        },
        Message={
            "Subject": {
                "Data": "AWS SES 邮件测试"
            },
            "Body": {
                "Html": {
                    "Data": "<h1>这是一封通过 AWS SES 发送的测试邮件。</h1>"
                }
            }
        }
    )
    
    print(f"邮件发送成功!Message ID:{response['MessageId']}")
    

    10. 邮件自动化与队列

    在大规模邮件发送场景中(如营销邮件),可以结合消息队列(如 RabbitMQRedis 等)实现邮件自动化发送。

    示例:结合 Celery 和 Redis 实现邮件队列
    1. 安装依赖
    pip install celery[redis] smtplib
    
    1. 创建 Celery 配置
    from celery import Celery
    import smtplib
    from email.mime.text import MIMEText
    
    app = Celery("tasks", broker="redis://localhost:6379/0")
    
    @app.task
    def send_email_task(to_email, subject, body):
        sender = "youremail@example.com"
        message = MIMEText(body, "plain", "utf-8")
        message["From"] = sender
        message["To"] = to_email
        message["Subject"] = subject
    
        try:
            smtp = smtplib.SMTP("smtp.example.com", 587)
            smtp.starttls()
            smtp.login("youremail@example.com", "yourpassword")
            smtp.sendmail(sender, to_email, message.as_string())
            smtp.quit()
            print(f"邮件已发送给:{to_email}")
        except Exception as e:
            print(f"邮件发送失败:{e}")
    
    1. 调用任务
    from tasks import send_email_task
    
    # 调用任务
    send_email_task.delay("receiver@example.com", "Celery 邮件测试", "这是一封通过 Celery 发送的测试邮件。")
    

    11. 总结

    通过扩展,您现在掌握了以下高级邮件发送功能:

    1. 邮件内容增强:嵌入图片、使用 HTML 模板。
    2. 定时和批量发送:使用 schedule 或任务队列(如 Celery)。
    3. 集成第三方服务:如 SendGrid 和 AWS SES,提升邮件可靠性。
    4. 邮件队列:使用 Celery 实现高效的邮件队列管理。

    无论是个人项目还是企业应用,这些技能都可以帮助您构建高效、灵活的邮件发送系统!

    作者:小宝哥Code

    物联沃分享整理
    物联沃-IOTWORD物联网 » 033-Python SMTP发送邮件

    发表回复