Python Lambda将上传到s3的文件作为电子邮件附件发送

Python Lambda将上传到s3的文件作为电子邮件附件发送,python,email,amazon-s3,aws-lambda,boto3,Python,Email,Amazon S3,Aws Lambda,Boto3,我们有一个在线表单,让人们可以选择上传多个文件。表单是由第三方创建的,因此我与他们没有任何关系。当有人使用表单上传文件时,它会将文件转储到s3存储桶中的新文件夹中。我希望能够做到以下几点: 获取由表单填充器上载触发的文件 将文件附加到电子邮件 将电子邮件发送给特定的人 我已经做了很多研究,但我对编码还是新手,我正在尝试使用Python,我已经决定将Python作为我的第一种合适的语言 到目前为止,我得到的代码是从我看到的其他示例中借用并调整的。但到目前为止,当我将单个文件上传到bucket的根目

我们有一个在线表单,让人们可以选择上传多个文件。表单是由第三方创建的,因此我与他们没有任何关系。当有人使用表单上传文件时,它会将文件转储到s3存储桶中的新文件夹中。我希望能够做到以下几点:

获取由表单填充器上载触发的文件 将文件附加到电子邮件 将电子邮件发送给特定的人

我已经做了很多研究,但我对编码还是新手,我正在尝试使用Python,我已经决定将Python作为我的第一种合适的语言

到目前为止,我得到的代码是从我看到的其他示例中借用并调整的。但到目前为止,当我将单个文件上传到bucket的根目录时,它只向我发送了包含这些文件的电子邮件。不能将多个文件放入bucket中的一个文件夹中。这似乎是因为文件夹中文件路径中的
/
中断了
sendrawmail
功能

此lambda设置为在s3存储桶上创建新文件时通过
PUT
通知触发。 更新:我现在使用了不同的代码,并得到了一个解决方案。请看底部

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
import boto3

def lambda_handler(event, context):
    file_obj = event["Records"][0]
    bucket_name = str(file_obj['s3']['bucket']['name'])
    key = str(file_obj['s3']['object']['key'])
    msg = MIMEMultipart()
    new_body = "test body"
    text_part = MIMEText(new_body, _subtype="html")
    msg.attach(text_part)

    filename = str(event["Records"][0]['s3']['object']['key'])
    msg["To"] = "test@test.com"
    msg["From"] = "test@test.com"
    s3_object = boto3.client('s3')
    s3_object = s3_object.get_object(Bucket=str(bucket_name), Key=str(key))
    body = s3_object['Body'].read()

    part = MIMEApplication(body, filename)
    part.add_header("Content-Disposition", 'attachment', filename=filename)
    msg.attach(part)
    ses_aws_client = boto3.client('ses', 'eu-west-1')
    ses_aws_client.send_raw_email(RawMessage={"Data" : msg.as_bytes()})
我所希望的是,当上传一个文件夹或多个文件时,我会收到一封包含所有文件作为附件的电子邮件(我意识到邮件的容量限制为10mb)。但是,当有多个文件时,它似乎在发送多封电子邮件,每封电子邮件一个文件。如果文件位于文件夹中,因此有一个键值,其中有一个斜杠,则send_raw_电子邮件会显示以下错误:

[ERROR] ClientError: An error occurred (InvalidParameterValue) when calling the SendRawEmail operation: Expected ';', got "/"
我想我需要以某种方式对路径进行编码?有没有办法将所有新上传的文件整理成一封电子邮件

任何帮助都是非常受欢迎的

编辑1:根据Jeril的回答,我正在共享故障的完整日志条目。另外,我在我的原始代码块中遗漏了一行,所以我也将更新它

12:14:59
[ERROR] ClientError: An error occurred (InvalidParameterValue) when calling the SendRawEmail operation: Expected ';', got "/" Traceback (most recent call last):   File "/var/task/lambda_function.py", line 26, in lambda_handler     ses_aws_client.send_raw_email(RawMessage={"Data" : msg.as_bytes()})   File "/var/runtime/botocore/client.py", line 320, in _api_call     return self._make_api_call(opera
[ERROR] ClientError: An error occurred (InvalidParameterValue) when calling the SendRawEmail operation: Expected ';', got "/"
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 26, in lambda_handler
    ses_aws_client.send_raw_email(RawMessage={"Data" : msg.as_bytes()})
  File "/var/runtime/botocore/client.py", line 320, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 623, in _make_api_call
    raise error_class(parsed_response, operation_name)
更新: 我现在已经成功地获得了这项工作的基本功能:

导入操作系统路径
进口boto3
导入电子邮件
从botocore.exceptions导入ClientError
从email.mime.multipart导入MIMEMultipart
从email.mime.text导入MIMEText
从email.mime.application导入MIMEApplication
s3=两个客户端(“s3”)
def lambda_处理程序(事件、上下文):
#替换sender@example.com用你的“发件人”地址。
#必须通过Amazon SES验证此地址。
SENDER=“测试”
#替换recipient@example.com带有“收件人”地址。如果你的帐户
#仍在沙箱中,必须验证此地址。
收件人=“测试”
#指定一个配置集。如果您不想使用配置
#设置、注释以下变量,然后
#ConfigurationSetName=配置\设置下面的参数。
#配置设置=“配置设置”
AWS_REGION=“eu-west-1”
主题=“测试发送带有附件的表格”
#这是将我们需要的文件从S3 bucket拉入电子邮件的过程的开始。
#获取已触发事件的记录
FILEOBJ=事件[“记录”][0]
#从触发事件的记录中提取bucket名称
BUCKET_NAME=str(FILEOBJ['s3']['BUCKET']['NAME'])
#提取对象键(基本上是文件名/路径-注意在S3中有
#没有文件夹,路径是已触发事件记录的一部分(名称)
KEY=str(FILEOBJ['s3']['object']['KEY'])
#仅从文件中提取文件名的最后一部分。这就是文件的内容
#将在上载到S3存储桶之前调用
FILE_NAME=os.path.basename(键)
#使用文件名,为lambda创建新的文件位置。这是必须的
#在tmp目录中,因为这是lambdas允许您最多存储到的唯一位置
#500mb的内容,因此使用“/tmp/”+前缀
TMP_文件名='/TMP/'+文件名
#将文件从事件(上面提取)下载到tmp位置
s3.下载_文件(BUCKET_名称、密钥、TMP_文件名称)
#明确说明附件将具有tmp文件路径/名称。你可以
#如果您愿意,请使用以下说明中的TMP_文件名。
附件=TMP\u文件\u名称
#具有非HTML电子邮件客户端的收件人的电子邮件正文。
BODY\u TEXT=“您好,\r\n请参阅与最近提交内容相关的附件。”
#电子邮件的HTML正文。
BODY_HTML=“”\
你好
请参阅最近提交的相关附件

""" #电子邮件的字符编码。 CHARSET=“utf-8” #创建新的SES资源并指定区域。 客户机=boto3.客户机('ses',地区名称=AWS\U地区) #创建多部分/混合父容器。 msg=MIMEMultipart('mixed') #添加主题、起始行和结束行。 msg['Subject']=主语 msg['From']=发件人 msg['To']=收件人 #创建多部分/备选子容器。 msg_body=MIMEMultipart('备选方案') #对文本和HTML内容进行编码并设置字符编码。这一步很简单 #如果要发送字符超出ASCII范围的消息,则需要此选项。 textpart=MIMEText(BODY_TEXT.encode(字符集),‘普通’,字符集) htmlpart=MIMEText(BODY_HTML.encode(CHARSET),'HTML',CHARSET) #将文本和HTML部分添加到子容器中。 msg_body.attach(文本部分) msg_body.attach(htmlpart) #定义附件部件并使用MIMEApplication对其进行编码。 att=MIMEApplication(打开(附件'rb').read()) #添加标题,告知电子邮件客户端将此部分视为附件, #并给附件起一个名字。 att.add_头('Content-Disposition','attachment',filename=os.path.basename(附件)) #将multipart/alternative子容器附加到multipart/mixed子容器 #父容器。 msg.attach(msg_body) #添加附件