AWS SES S3 处理入站电子邮件
Posted
技术标签:
【中文标题】AWS SES S3 处理入站电子邮件【英文标题】:AWS SES S3 process inbound email 【发布时间】:2016-04-15 21:30:34 【问题描述】:我正在开发基于 AWS SES 的电子邮件发布系统。对于所有传入的电子邮件,我已设置路由以将消息保存在 S3 存储桶中,以便我可以异步处理它们。我遇到的问题是消息以原始格式保存在 S3 存储桶中:标题、电子邮件正文等 + 加密附件(一个巨大的字符串) - 都在一个文件中。
有没有办法将电子邮件与附件分开并将两者保存在 AWS SES 级别的单独文件中?我正在尝试直接从 AWS 获取所需格式的数据,并避免在流程中添加另一个处理步骤。
如果 AWS SES 不提供这样的功能,那么处理这些消息以获得上述结果的正确方法是什么?
【问题讨论】:
您下载和查看原始电子邮件的工作流程是什么?我刚刚开始使用 AWS SES。 您需要编写代码来解析 MIME 数据。如果您编写 Java,这可能会有所帮助:***.com/questions/3444660/java-email-message-parser. 【参考方案1】:看起来不可能让 SES 自动为您拆分电子邮件。根据文档here:
Amazon SES 为您提供未经修改的原始电子邮件,通常是 采用多用途 Internet 邮件扩展 (MIME) 格式。
每当 SES 将新的电子邮件文件放入 S3 时,我都会使用 S3 或 SNS 来触发 Lambda 函数。 Lambda 函数可以根据需要拆分文件,然后将这些新文件写入另一个 S3 存储桶。
【讨论】:
是否有任何您知道的文档可以描述如何创建 Lambda 函数?我收到了 SES 的电子邮件,我只需将附件复制到 S3。 Mark 从 s3 中存储的 ses 对象中解析一个需要的标头和内容,然后通过文件或 db 记录将它们存储在本地,这样就不需要对 S3 进一步的拉取请求,这是否更有意义?一个用例是,在后端,我们可以查看 /admin/emails 例如,每封电子邮件都会循环显示信息(就像一个 webmail 客户端),每个页面加载都需要发出一个 s3 请求作为对本地目录或本地数据库请求,您对此有何建议?继续使用 S3 还是使用本地环境? 有关此(在 python 中)的特定实现的一些其他详细信息,请参阅 Casper 的这篇博文:medium.com/caspertechteam/…。 TL;DR:他们使用 python 库来解析附件并将它们保存到 S3 存储桶中。 完整参考实现见:github.com/martysweet/aws-lambda-attachment-extractor【参考方案2】:关于如何编写 Lambda 的问题。这是我们的 Lambda 的一部分。最重要的是 parseEvent 函数。和 data.event.Records[0] 将为您提供详细信息
exports.handler = function(event, context, callback)
var AWS = require('aws-sdk');
// Validate characteristics of a SES event record.
if (!event ||
!event.hasOwnProperty('Records') ||
event.Records.length !== 1 ||
event.Records[0].hasOwnProperty('eventSource') ||
event.Records[0].eventSource !== 'aws:ses' ||
event.Records[0].eventVersion !== '1.0')
callback(null, 'disposition':'STOP_RULE_SET');
email = data.event.Records[0].ses.mail;
subjectLine = event.Records[0].ses.mail.commonHeaders.subject;
关键是 event.Record[0].ses.mail。不幸的是,我无法通过谷歌搜索找到它的结构,我确信我以前见过它。
【讨论】:
不应该否定“event.Records[0].hasOwnProperty('eventSource')”这一行吗? 好消息是我们的代码没有损坏。它非常适合我们。自从我写那段代码以来已经有很长时间了,差不多 2 年前,我什至不记得了。它可能需要“!”或不。感谢您指出这一点。【参考方案3】:对于稍后返回此问题的任何人,这是您从 SES 调用 Lambda 函数时获得的 JSON 结构的链接。
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-notifications-examples.html
需要一些搜索才能到达该页面 ;-)
从链接中,Lambda 通知看起来像这样,
"notificationType": "Received",
"receipt":
"timestamp": "2015-09-11T20:32:33.936Z",
"processingTimeMillis": 406,
"recipients": [
"recipient@example.com"
],
"spamVerdict":
"status": "PASS"
,
"virusVerdict":
"status": "PASS"
,
"spfVerdict":
"status": "PASS"
,
"dkimVerdict":
"status": "PASS"
,
"action":
"type": "S3",
"topicArn": "arn:aws:sns:us-east-1:012345678912:example-topic",
"bucketName": "my-S3-bucket",
"objectKey": "\email"
,
"mail":
"timestamp": "2015-09-11T20:32:33.936Z",
"source": "0000014fbe1c09cf-7cb9f704-7531-4e53-89a1-5fa9744f5eb6-000000@amazonses.com",
"messageId": "d6iitobk75ur44p8kdnnp7g2n800",
"destination": [
"recipient@example.com"
],
"headersTruncated": false,
"headers": [
"name": "Return-Path",
"value": "<0000014fbe1c09cf-7cb9f704-7531-4e53-89a1-5fa9744f5eb6-000000@amazonses.com>"
,
"name": "Received",
"value": "from a9-183.smtp-out.amazonses.com (a9-183.smtp-out.amazonses.com [54.240.9.183]) by inbound-smtp.us-east-1.amazonaws.com with SMTP id d6iitobk75ur44p8kdnnp7g2n800 for recipient@example.com; Fri, 11 Sep 2015 20:32:33 +0000 (UTC)"
,
"name": "DKIM-Signature",
"value": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=ug7nbtf4gccmlpwj322ax3p6ow6yfsug; d=amazonses.com; t=1442003552; h=From:To:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Date:Message-ID:Feedback-ID; bh=DWr3IOmYWoXCA9ARqGC/UaODfghffiwFNRIb2Mckyt4=; b=p4ukUDSFqhqiub+zPR0DW1kp7oJZakrzupr6LBe6sUuvqpBkig56UzUwc29rFbJF hlX3Ov7DeYVNoN38stqwsF8ivcajXpQsXRC1cW9z8x875J041rClAjV7EGbLmudVpPX 4hHst1XPyX5wmgdHIhmUuh8oZKpVqGi6bHGzzf7g="
,
"name": "From",
"value": "sender@example.com"
,
"name": "To",
"value": "recipient@example.com"
,
"name": "Subject",
"value": "Example subject"
,
"name": "MIME-Version",
"value": "1.0"
,
"name": "Content-Type",
"value": "text/plain; charset=UTF-8"
,
"name": "Content-Transfer-Encoding",
"value": "7bit"
,
"name": "Date",
"value": "Fri, 11 Sep 2015 20:32:32 +0000"
,
"name": "Message-ID",
"value": "<61967230-7A45-4A9D-BEC9-87CBCF2211C9@example.com>"
,
"name": "X-SES-Outgoing",
"value": "2015.09.11-54.240.9.183"
,
"name": "Feedback-ID",
"value": "1.us-east-1.Krv2FKpFdWV+KUYw3Qd6wcpPJ4Sv/pOPpEPSHn2u2o4=:AmazonSES"
],
"commonHeaders":
"returnPath": "0000014fbe1c09cf-7cb9f704-7531-4e53-89a1-5fa9744f5eb6-000000@amazonses.com",
"from": [
"sender@example.com"
],
"date": "Fri, 11 Sep 2015 20:32:32 +0000",
"to": [
"recipient@example.com"
],
"messageId": "<61967230-7A45-4A9D-BEC9-87CBCF2211C9@example.com>",
"subject": "Example subject"
【讨论】:
请注意,这是传递给 Lambda 的事件。这不是实际的电子邮件本身,因此没有body
。如果您不需要它并且可以使用提供的内容,很好,但是如果您需要body
,您可能需要将 SES 电子邮件保存到 S3,从该事件中获取文件名(密钥),从 S3 读取电子邮件,然后解析文件内容(MIME 电子邮件格式)以提取body
。
任何希望使用上述建议保存到 s3 并在 lambda 中读取它的人都知道 AWS 创建了一个缓冲区,例如hackernoon.com/…以上是关于AWS SES S3 处理入站电子邮件的主要内容,如果未能解决你的问题,请参考以下文章
通过 Laravel / PHP 的 Mandrill 入站电子邮件
如何将原始电子邮件 (MIME) 从 AWS SES 转换为 Gmail?