如何从SNS主题订阅邮件中仅获取更新的S3 Key对象数据
实现SNS主题仅向邮件订阅者发送S3更新的Object数据
嘿,刚好做过类似的需求!要实现只给订阅邮件发S3更新的object数据,分两种方案,看你具体场景选:
方案1:用Lambda处理消息(精准提取Object内容,推荐)
如果必须让邮件里只收到object的JSON结构(就像你给的示例那样),那得通过Lambda做中间层来修改消息内容——毕竟SNS本身只能过滤消息,不能修改消息体。步骤如下:
1. 写Lambda处理代码(以Python为例)
Lambda会接收SNS发来的完整消息,提取出S3的object部分,再转发到邮件。这里用AWS SES发邮件,也可以转发到另一个SNS主题再让邮件订阅:
import json import boto3 # 初始化客户端 ses_client = boto3.client('ses') # 如果用SNS转发的话,替换成sns_client = boto3.client('sns') # 配置参数 VERIFIED_SENDER_EMAIL = "你的验证发件邮箱@xxx.com" TARGET_RECEIVER_EMAIL = "订阅者邮箱@xxx.com" # 如果用SNS转发,添加这个:NEW_SNS_TOPIC_ARN = "arn:aws:sns:区域:账号ID:你的新主题" def lambda_handler(event, context): # 从SNS事件里取出原始的S3事件消息 sns_raw_message = event['Records'][0]['Sns']['Message'] s3_event_data = json.loads(sns_raw_message) # 提取你需要的S3 object数据 target_object_data = s3_event_data['Records'][0]['s3']['object'] # 转成格式化的JSON字符串,方便邮件阅读 formatted_message = json.dumps(target_object_data, indent=2) # 用SES发送邮件 try: ses_client.send_email( Source=VERIFIED_SENDER_EMAIL, Destination={'ToAddresses': [TARGET_RECEIVER_EMAIL]}, Message={ 'Subject': {'Data': "S3对象更新通知"}, 'Body': {'Text': {'Data': formatted_message}} } ) print("邮件发送成功") except Exception as e: print(f"发送失败: {str(e)}") raise e # 如果用SNS转发的话,替换上面的SES代码: # sns_client.publish( # TopicArn=NEW_SNS_TOPIC_ARN, # Message=formatted_message, # Subject="S3对象更新通知" # ) return {'statusCode': 200, 'body': "消息处理完成"}
2. 配置Lambda权限
- 给Lambda添加
ses:SendEmail权限(如果用SES),或者sns:Publish权限(如果转发到新SNS主题)。 - 注意:SES的发件邮箱必须是已经在AWS控制台验证过的,不然发不了邮件。
- 确保Lambda的执行角色能被SNS触发(添加SNS到Lambda的触发时,AWS会自动配置基础权限)。
3. 调整SNS订阅
- 移除原来的邮件订阅(或者保留,如果你还需要完整消息的话),把Lambda添加为当前SNS主题的订阅者。
- 如果用SES直接发邮件,到这里就搞定了;如果用SNS转发,记得给新的SNS主题添加邮件订阅。
方案2:SNS消息过滤(仅过滤,不修改内容)
如果你的需求只是只接收S3对象更新的消息,接受邮件里还是完整的SNS JSON(但只包含S3相关事件),那用SNS自带的过滤策略更简单,不用写代码:
在SNS的邮件订阅设置里,添加以下过滤策略:
{ "Records": [ { "s3": { "object": [{"exists": true}] } } ] }
这个策略会自动过滤掉所有不包含s3.object字段的消息,只有S3对象更新的事件才会发送到邮件订阅者。但要注意:邮件里还是会收到完整的S3事件JSON,只是不会收到非S3的消息。
内容的提问来源于stack exchange,提问作者user9075162
相关产品推荐
相关产品推荐

