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

AWS Glue Python作业发送带S3附件邮件失败问题排查

AWS Glue作业发送带S3附件邮件时遇到SMTP 554错误

我在使用AWS Glue作业发送包含S3桶中多个附件的邮件时遇到了问题。代码执行到server.login()都正常,但调用server.sendmail()时失败,错误信息如下:

Error: (554, b'Transaction failed: Expected '=', got "null"')

相关代码片段如下:

def sendEmail(TO, SUBJECT, BODY_HTML):
    msg = MIMEMultipart('alternative')
    msg['Subject'] = SUBJECT
    msg['From'] = SENDER
    msg['To'] = ','.join(RECIPIENT + TO)
    part1 = MIMEText(BODY_HTML, 'html')
    msg.attach(part1)
    s3 = boto3.resource('s3')
    bucket = s3.Bucket('sample-bucket')
    for obj in bucket.objects.filter(Delimiter='/', Prefix='sample-folder/'):
        filename = ((obj.key).split("/")[1])
        s3_object = s3_obj.s3_get_object(sample-bucket, 'sample-folder/'+ filename)
        body = s3_object['Body'].read()
        part = MIMEApplication(body, filename)
        part.add_header("Content-Disposition", 'attachment', filename=filename)
        msg.attach(part)

try:
    server = smtplib.SMTP(HOST, PORT)
    server.ehlo()
    server.starttls()
    server.ehlo()
    server.login(USERNAME_SMTP, PASSWORD_SMTP)
    server.sendmail(SENDER, RECIPIENT, msg.as_string())  # --Error--
    server.close()
    print (msg)
    print ("Email sent")

问题原因及修复方案

最可能导致这个SMTP 554错误的原因是邮件头To字段格式无效,同时代码中还有几处S3对象处理的问题,下面逐一说明:

  1. 收件人列表拼接错误
    代码中msg['To'] = ','.join(RECIPIENT + TO)存在逻辑漏洞:

    • 如果RECIPIENT是单个字符串(比如'a@example.com'),RECIPIENT + TO会把字符串拆成字符列表再和TO列表拼接,最终','.join会生成类似a,@,e,x,a,m,p,l,e,.,c,o,m,b@example.com的无效格式,这会导致邮件服务器解析邮件头时出错,触发554错误。
    • 同时server.sendmail()的第二个参数需要是收件人列表(而非单个字符串),如果RECIPIENT是单个邮箱,应该把它转为列表再和TO合并。

    修复方式:

    # 确保收件人是列表格式
    recipients = [RECIPIENT] + TO if isinstance(RECIPIENT, str) else RECIPIENT + TO
    msg['To'] = ','.join(recipients)
    # sendmail的第二个参数传入收件人列表
    server.sendmail(SENDER, recipients, msg.as_string())
    
  2. S3对象获取代码错误

    • 代码中s3_obj未定义,你之前初始化的是s3 = boto3.resource('s3'),应该用资源对象的方法来获取文件;
    • sample-bucket没有加引号,属于语法错误,需要用字符串包裹;
    • 当obj.key是sample-folder/(前缀本身)时,split("/")[1]会得到空字符串,导致文件名无效,需要跳过前缀目录本身。

    修复后的S3处理代码:

    s3 = boto3.resource('s3')
    bucket = s3.Bucket('sample-bucket')
    for obj in bucket.objects.filter(Prefix='sample-folder/'):
        # 跳过前缀目录本身(如果存在)
        if obj.key == 'sample-folder/':
            continue
        # 从key中提取文件名
        filename = obj.key.split("/")[-1]
        # 获取S3对象内容
        s3_object = s3.Object('sample-bucket', obj.key).get()
        body = s3_object['Body'].read()
        part = MIMEApplication(body, Name=filename)
        part.add_header("Content-Disposition", 'attachment', filename=filename)
        msg.attach(part)
    
  3. MIMEApplication初始化参数问题
    MIMEApplication(body, filename)的第二个参数是_subtype,不是文件名,正确的做法是用Name参数指定文件名,如上面修复代码所示,这样能确保附件的MIME头更规范。

总结

优先修复收件人列表的拼接错误,这是触发554错误的核心原因。同时修正S3对象处理的语法和逻辑问题,避免后续出现其他异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 15:53:12