• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    Python利用SMTP发送邮件的常见问题与解决方案详解

    发布者: 涵韵 | 发布时间: 2025-6-14 12:20| 查看数: 138| 评论数: 0|帖子模式

    引言

    在自动化办公和系统开发中,邮件发送功能是常见的需求。无论是发送通知、报告,还是传输文件,Python的smtplib和email库提供了便捷的实现方式。然而,在实际开发中,开发者常会遇到各种SMTP错误,如(-1, b'\x00\x00\x00')、AttributeError('characters_written')等,这些问题往往让人束手无策。
    本文将从实际案例出发,分析常见的SMTP错误,并提供完整的解决方案,帮助开发者快速定位和解决问题。同时,我们还会优化代码,使其更健壮、更易于维护。

    1. 问题背景

    在Python中,使用
    1. smtplib
    复制代码
    发送邮件时,通常会遇到两类问题:

    • 连接与认证问题(如授权码错误、SMTP服务器拒绝连接)
    • 数据编码与协议问题(如SSL/TLS握手失败、附件编码错误)
    以下是一个典型的邮件发送代码,它可能会触发上述错误:
    1. import smtplib
    2. from email.mime.text import MIMEText
    3. from email.mime.multipart import MIMEMultipart
    4. from email.mime.application import MIMEApplication
    5. import os
    6. import logging

    7. logger = logging.getLogger(__name__)

    8. def send_email_with_attachment(filepath, receiver_email):
    9.     sender_email = "your_email@qq.com"
    10.     password = "your_authorization_code"  # QQ邮箱授权码
    11.     smtp_server = "smtp.qq.com"
    12.     smtp_port = 465  # QQ邮箱SSL端口

    13.     msg = MIMEMultipart()
    14.     msg['From'] = sender_email
    15.     msg['To'] = receiver_email
    16.     msg['Subject'] = "文件处理结果通知"

    17.     # 邮件正文
    18.     msg.attach(MIMEText("请查收附件", 'plain'))

    19.     # 添加附件
    20.     try:
    21.         with open(filepath, "rb") as f:
    22.             part = MIMEApplication(f.read(), Name=os.path.basename(filepath))
    23.             part['Content-Disposition'] = f'attachment; filename="{os.path.basename(filepath)}"'
    24.             msg.attach(part)
    25.     except FileNotFoundError:
    26.         logger.error("附件文件不存在")
    27.         return False

    28.     # 发送邮件
    29.     try:
    30.         with smtplib.SMTP_SSL(smtp_server, smtp_port) as server:
    31.             server.login(sender_email, password)
    32.             server.sendmail(sender_email, receiver_email, msg.as_string())
    33.         return True
    34.     except Exception as e:
    35.         logger.error(f"发送邮件失败: {e}", exc_info=True)
    36.         return False
    复制代码
    运行此代码时,可能会遇到以下错误:

    2. 常见错误及解决方案

    错误1:SMTPResponseException: (-1, b'\x00\x00\x00')
    错误原因

    • 授权码错误或已过期。
    • SMTP服务器(如QQ邮箱)检测到异常登录,拒绝连接。
    • 网络或防火墙拦截了SMTP请求。
    解决方案
    1.检查授权码
    登录QQ邮箱 → 设置 → 账户 → 生成新的授权码,并替换代码中的password。
    2.更换SMTP端口(推荐使用587+TLS)
    QQ邮箱支持465(SSL)和587(TLS),后者更稳定:
    1. smtp_port = 587  # 改用TLS端口
    2. with smtplib.SMTP(smtp_server, smtp_port) as server:
    3.     server.starttls()  # 启用TLS加密
    4.     server.login(sender_email, password)
    复制代码
    3.检查网络环境
    关闭防火墙或切换网络(如使用手机热点测试)。
    错误2:AttributeError('characters_written')
    错误原因

    • Python 3.10+ 与 SMTP_SSL 的兼容性问题。
    • SSL/TLS握手失败,可能是由于OpenSSL版本不匹配。
    解决方案
    1.改用starttls()(推荐)
    避免使用SMTP_SSL,改用SMTP + starttls():
    1. with smtplib.SMTP(smtp_server, 587) as server:
    2.     server.starttls()  # 显式启用TLS
    3.     server.login(sender_email, password)
    复制代码
    2.降级Python或升级依赖库
    如果仍报错,尝试降级到Python 3.9,或更新pyopenssl:
    1. pip install --upgrade pyopenssl
    复制代码
    3. 优化后的邮件发送代码

    结合上述解决方案,优化后的代码如下:
    1. import smtplib
    2. from email.mime.text import MIMEText
    3. from email.mime.multipart import MIMEMultipart
    4. from email.mime.application import MIMEApplication
    5. import os
    6. import logging
    7. import base64

    8. logger = logging.getLogger(__name__)

    9. def send_email_with_attachment(filepath, receiver_email):
    10.     """发送带附件的邮件(支持QQ邮箱)"""
    11.     sender_email = "your_email@qq.com"
    12.     password = "your_authorization_code"  # 替换为最新授权码
    13.     smtp_server = "smtp.qq.com"
    14.     smtp_port = 587  # 使用TLS端口

    15.     # 检查附件是否存在
    16.     if not os.path.exists(filepath):
    17.         logger.error(f"附件文件不存在: {filepath}")
    18.         return False

    19.     # 创建邮件内容
    20.     msg = MIMEMultipart()
    21.     msg['From'] = sender_email
    22.     msg['To'] = receiver_email
    23.     msg['Subject'] = "文件处理结果通知"
    24.     msg.attach(MIMEText("请查收附件", 'plain'))

    25.     # 添加附件
    26.     try:
    27.         with open(filepath, "rb") as f:
    28.             part = MIMEApplication(f.read(), Name=os.path.basename(filepath))
    29.             part['Content-Disposition'] = f'attachment; filename="{os.path.basename(filepath)}"'
    30.             msg.attach(part)
    31.     except Exception as e:
    32.         logger.error(f"附件处理失败: {e}")
    33.         return False

    34.     # 发送邮件(使用TLS)
    35.     try:
    36.         with smtplib.SMTP(smtp_server, smtp_port) as server:
    37.             server.starttls()  # 启用TLS加密
    38.             server.login(sender_email, password)
    39.             server.sendmail(sender_email, receiver_email, msg.as_string())
    40.         logger.info("邮件发送成功")
    41.         return True
    42.     except smtplib.SMTPException as e:
    43.         logger.error(f"SMTP错误: {e}")
    44.     except Exception as e:
    45.         logger.error(f"未知错误: {e}", exc_info=True)
    46.     return False
    复制代码
    优化点
    1.更健壮的异常处理
    区分SMTPException和其他异常,便于排查问题。
    2.附件预检查
    发送前验证附件是否存在。
    3.日志记录
    使用logging记录详细错误信息。

    4. SMTP调试技巧

    手动测试SMTP连接
    使用openssl命令行工具测试SMTP服务是否可用:
    1. openssl s_client -connect smtp.qq.com:587 -starttls smtp -crlf
    复制代码
    输入以下命令(替换为你的邮箱和授权码):
    1. EHLO testAUTH LOGIN<base64编码的邮箱>  # 示例:echo -n "your_email@qq.com" | base64<base64编码的授权码>QUIT
    复制代码
    如果返回235 Authentication successful,说明SMTP配置正确。
    检查防火墙
    在Windows上,运行以下命令放行SMTP端口:
    1. netsh advfirewall firewall add rule name="SMTP" dir=in action=allow protocol=TCP localport=587
    复制代码
    5. 总结与最佳实践

    常见问题总结
    错误原因解决方案
    1. (-1, b'\x00\x00\x00')
    复制代码
    授权码错误/SMTP拒绝更新授权码,改用
    1. starttls()
    复制代码
    1. AttributeError('characters_written')
    复制代码
    Python 3.10+兼容性问题降级Python或改用
    1. SMTP
    复制代码
    +
    1. starttls()
    复制代码
    1. SSL: WRONG_VERSION_NUMBER
    复制代码
    SSL/TLS配置错误使用
    1. starttls()
    复制代码
    + 端口587
    最佳实践


    • 使用TLS(端口587)代替SSL(端口465),兼容性更好。
    • 定期更新授权码,避免因过期导致发送失败。
    • 添加日志记录,便于排查问题。
    • 手动测试SMTP连接,确保服务器可用。
    通过本文的分析和优化,你应该能够解决大多数Python邮件发送问题。如果你的场景涉及更复杂的需求(如批量发送、HTML邮件),可以进一步扩展代码逻辑。
    到此这篇关于Python利用SMTP发送邮件的常见问题与解决方案详解的文章就介绍到这了,更多相关Python SMTP发送邮件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:https://www.jb51.net/python/339987854.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表