You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker化Python程序连接AWS SES时smtplib超时问题求助

解决Docker中Python连接AWS SES SMTP超时问题

核心问题分析

你遇到的连接超时,本质是SMTP协议交互顺序错误+容器网络/端口限制导致:SES返回220 service ready后,客户端未及时发送EHLO命令触发服务器超时;同时端口25大概率被云服务商或主机防火墙封禁。

针对性解决方案

1. 修正SMTP协议交互顺序

你的代码在starttls之后才调用ehlo,违反SMTP规范:必须先发送EHLO标识客户端,启动TLS后需再次发送EHLO重新握手。修改后的代码:

import smtplib
import ssl

smtp_host = 'email-smtp.us-west-2.amazonaws.com'
smtp_port = 587  # 优先用587/465,避免端口25被封禁
smtp_proto = 'tls'

with smtplib.SMTP(host=smtp_host, port=smtp_port, timeout=10) as connection:
    try:
        # 第一步:先发送EHLO标识客户端
        connection.ehlo()
        # 启动TLS加密
        ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
        connection.starttls(context=ctx)
        # TLS启动后再次发送EHLO完成握手
        connection.ehlo()

        connection.login(smtp_user, smtp_pass)
        connection.send_message(from_addr=sender, to_addrs=recipients, msg=message)
    except smtplib.SMTPHeloError as e:
        print(f"SMTP HELO Failed: {e}")
    except smtplib.SMTPAuthenticationError as e:
        print(f"SMTP AUTH Failed: {e}")
    except smtplib.SMTPException as e:
        print(f"Failed to send email: {e}")

2. 排查容器网络与端口限制

  • 禁用端口25:AWS默认限制EC2/容器的端口25出站流量,需改用587(STARTTLS)或465(SSL直连),这两个端口无发送限制。
  • 检查容器网络:若用Docker默认桥接网络,确保主机防火墙/安全组允许容器访问email-smtp.us-west-2.amazonaws.com的对应端口;可临时切换为host网络模式测试:
    docker run --network=host your-python-image
    
  • VPC环境特殊配置:若容器在AWS VPC内,需配置NAT网关允许出站访问互联网,或创建SES VPC端点直接访问服务。

3. 开启调试日志定位问题

添加调试日志查看SMTP交互细节,确认哪个环节卡住:

connection.set_debuglevel(1)  # 开启调试模式,打印所有SMTP命令与响应

4. 替代方案:使用AWS SDK(boto3)发送邮件

若SMTP方式仍有问题,直接调用AWS API更稳定,无需处理SMTP连接:

import boto3
from botocore.exceptions import ClientError

ses_client = boto3.client('ses', region_name='us-west-2')

try:
    response = ses_client.send_email(
        Source=sender,
        Destination={'ToAddresses': recipients},
        Message={
            'Subject': {'Data': '邮件主题', 'Charset': 'UTF-8'},
            'Body': {
                'Text': {'Data': '纯文本内容', 'Charset': 'UTF-8'},
                'Html': {'Data': '<h1>HTML内容</h1>', 'Charset': 'UTF-8'}
            }
        }
    )
except ClientError as e:
    print(e.response['Error']['Message'])
else:
    print(f"邮件发送成功!Message ID: {response['MessageId']}")

注意:需给容器配置IAM权限(ses:SendEmail或ses:SendRawEmail),可通过IAM角色或环境变量注入凭证。

内容的提问来源于stack exchange,提问作者vpseg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:05:12