AWS Lambda 无法通过 AWS SES 发送电子邮件

AWS Lambda unable to send email through AWS SES

我已经验证了以下内容

  1. AWS SES 不在沙盒中。我可以通过控制台向未验证的电子邮件 ID 发送电子邮件。
  2. 我的 Lambda 函数附加了一个可以完全访问 SES 和 Lambda 的角色(因为它的初始基本测试提供了完全权限)

下面是来自 AWS 文档的基本代码,只是硬编码了我的电子邮件 ID。但是我收不到任何电子邮件。 lambda 代码运行成功,但我没有收到电子邮件。

import json
import os
import boto3
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

print('Loading function')


def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    #print("value1 = " + event['key1'])
    #print("value2 = " + event['key2'])
    #print("value3 = " + event['key3'])
    #return event['key1']  # Echo back the first key value
    #raise Exception('Something went wrong')
    SENDER = "[redacted email]"
    RECIPIENT = event['email']
    CONFIGURATION_SET = "ConfigSet"
    AWS_REGION = "us-east-2"
    SUBJECT = "Contact Us Form Details"
    # The email body for recipients with non-HTML email clients.
BODY_TEXT = "Hello,\r\nPlease see the attached file for a list of customers to contact."

# The HTML body of the email.
BODY_HTML = """\
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>
"""

# The character encoding for the email.
CHARSET = "utf-8"

# Create a new SES resource and specify a region.
client = boto3.client('ses',region_name='us-east-2')

# Create a multipart/mixed parent container.
msg = MIMEMultipart('mixed')
# Add subject, from and to lines.
msg['Subject'] = "Contact Us Form Details" 
msg['From'] ="[redacted email]" 
msg['To'] = "[redacted email]"

# Create a multipart/alternative child container.
msg_body = MIMEMultipart('alternative')

# Encode the text and HTML content and set the character encoding. This step is
# necessary if you're sending a message with characters outside the ASCII range.
textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)

# Add the text and HTML parts to the child container.
msg_body.attach(textpart)
msg_body.attach(htmlpart)

# Define the attachment part and encode it using MIMEApplication.
#att = MIMEApplication(open(ATTACHMENT, 'rb').read())

# Add a header to tell the email client to treat this part as an attachment,
# and to give the attachment a name.
#att.add_header('Content-Disposition','attachment',filename=os.path.basename(ATTACHMENT))

# Attach the multipart/alternative child container to the multipart/mixed
# parent container.
msg.attach(msg_body)

# Add the attachment to the parent container.
#msg.attach(att)
print(msg)
try:
    #Provide the contents of the email.
    response = client.send_raw_email(
        Source="[redacted email]",
        Destinations=[
            "[redacted email]"
        ],
        RawMessage={
            'Data':msg.as_string(),
        },
        #ConfigurationSetName=CONFIGURATION_SET
    )
# Display an error if something goes wrong. 
except ClientError as e:
    print(e.response['Error']['Message'])
else:
    print("Email sent! Message ID:"),
    print(response['MessageId'])

附上我的云表日志供参考

如果您在执行 lambda 时没有收到任何错误,那么很可能您没有命中 SES API。从我在您的代码中看到的情况来看,您缺少访问密钥 ID 和秘密访问密钥。尝试像这样配置您的 boto 客户端:

client = boto3.client(
    'ses',
    region_name=region,
    aws_access_key_id='aws_access_key_string',
    aws_secret_access_key='aws_secret_key_string'
)

还要确保您的 lambda 部署在与 SES 相同的区域。我看到您正在使用 us-east-2。 我看到的另一个差异也存在于文档中,即在官方 AWS 文档中,Destinations 实际上是 Destination。在没有 's' 的情况下尝试。 您还可以粘贴 lambda 的 cloudwatch 日志吗?我看到它应该在成功时打印消息 Id。是吗?

如果您的代码确实是您向我们展示的代码,那么它没有发送电子邮件的原因是您的一半代码没有被执行。

def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    #print("value1 = " + event['key1'])
    #print("value2 = " + event['key2'])
    #print("value3 = " + event['key3'])
    #return event['key1']  # Echo back the first key value
    #raise Exception('Something went wrong')
    SENDER = "[redacted email]"
    RECIPIENT = event['email']
    CONFIGURATION_SET = "ConfigSet"
    AWS_REGION = "us-east-2"
    SUBJECT = "Contact Us Form Details"
    # The email body for recipients with non-HTML email clients.
BODY_TEXT = "Hello,\r\nPlease see the attached file for a list of customers to contact."

当 AWS Lambda 执行该函数时,它会调用 lambda_handler()。根据 Python 格式,它将 执行所有缩进行 因为它们构成函数的一部分。这包括您的 print() 语句。

但是,从 BODY_TEXT = ... 行开始,没有缩进。这意味着该代码是“主”程序的一部分,不是 lambda_handler() 函数的一部分。它会在 Lambda 容器首次实例化时执行,但 不会 在函数被触发时执行。

底线:如果这是您的实际代码,您需要修正缩进。