c语言sscanf函数的用法是什么
313
2022-10-05
AWS SES 的监控和日志
简单的记录一下最近完成的一个任务。
AWS SES服务可以允许开发人员在软件中发送批量的邮件通知。具体怎么配置的,这里就简单概述一下,主要是记录一下他的监控和日志的配置和实现。
配置
AWS 控制台 -> Services - > SES创建域名,确认DKIM,更新DNS记录配置SMTP联系AWS客服移除SES邮件限制
监控和告警
下面看看重点。SES批量发送邮件很容易被对方的邮件判断成垃圾邮件,因此他有Metrics里面两个指标,一个是bounce rate,一个是 complaint rate。前者是接收方的邮箱不存在或者无法发送导致反弹回来,后者是对方认为SES是垃圾邮件,回复一个抗议的信息。当bounce rate和 complaint rate超过一定的比例之后,AWS会发送通知,如果置之不理,那么再达到临界值,这个服务就会被AWS禁止掉。豆子公司就曾经发生过这种意外,导致服务被AWS强制停止,折腾了1个晚上才恢复。
为了避免这种事情发生,我们需要定期的监控,如果发现指标接近临界值,就立刻给管理员发送警告。管理员收到警告之后,需要能够查看日志记录,定位出问题的邮件。在极端情况下,如果账号泄露导致发送大量异常垃圾邮件,而AWS又真的停止了这个服务,需要和客服交流,更换所有的IAM role,限制IP等操作,再要求AWS放行。监控Metric的警报在cloudwatch里面就可以很容易的实现。当警报触发时候,发送给对应的邮件通知SNS Topic就可以了。
当然,我们也可以用第三方的软件,比如Nagios,他本身有很多针对AWS的插件,也可以用来监控。Nagios的好处是他的告警系统很强,可以给值班的人发送短信通知,而且价格比aws的便宜。
记录SES的邮件日志
这个是重难点。SES默认不会给你长期保存记录单的,因此需要自己处理一下。目前豆子公司对于发送出去的SES邮件,每次都会触发 SNS的 一个Topic,这个Topic 又绑定了2个不同的lambda 函数,分别把这个邮件写入 Dynamodb 和 S3 中保存
SNS里面的topic,一个是发邮件给teams channel,一个是触发Lambda
Dynamodb
SES记录到Dynamodb的示意图
首先创建一个dynamoDB的表,包括下面的属性
Table-name: SESNotifications.primary Partition key: SESMessageId.primary Sort key: SnsPublishTime.
然后,为了快速查询,我们需要添加secondary index。毕竟dynamodb的卖点就在于快速查询,如果只有SESMessageID来扫描的话就太慢了
Index name Partition key Sort keySESMessageType-Index SESMessageType (String) SnsPublishTime (String)SESMessageComplaintType-Index SESComplaintFeedbackType (String) SnsPublishTime (String)
第三步,配置IAM Role
IAM Role
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "dynamodb:PutItem", "dynamodb:UpdateItem" ], "Resource": "arn:aws:dynamodb:us-west-2:065816533466:table/SESNotifications" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:CreateLogGroup", "logs:PutLogEvents" ], "Resource": "*" } ] }
最后是 Lambda 脚本
console.log("Loading event"); var aws = require("aws-sdk"); var ddb = new aws.DynamoDB({ params: { TableName: "SESNotifications" } }); exports.handler = function (event, context, callback) { console.log("Received event:", JSON.stringify(event, null, 2)); var SnsPublishTime = event.Records[0].Sns.Timestamp; var SnsTopicArn = event.Records[0].Sns.TopicArn; var SESMessage = event.Records[0].Sns.Message; SESMessage = JSON.parse(SESMessage); var SESMessageType = SESMessage.notificationType; var SESMessageId = SESMessage.mail.messageId; var SESDestinationAddress = SESMessage.mail.destination.toString(); var LambdaReceiveTime = new Date().toString(); var SESSubject = SESMessage.mail.commonHeaders.subject; console.log("Type is ", SESMessageType) console.log("Subject is ", SESSubject) if (SESMessageType == "Bounce") { var SESreportingMTA = SESMessage.bounce.reportingMTA; var SESbounceSummary = JSON.stringify(SESMessage.bounce.bouncedRecipients); var itemParams = { Item: { SESMessageId: { S: SESMessageId }, SnsPublishTime: { S: SnsPublishTime }, SESreportingMTA: { S: SESreportingMTA }, SESDestinationAddress: { S: SESDestinationAddress }, SESbounceSummary: { S: SESbounceSummary }, SESMessageType: { S: SESMessageType }, SESSubject: { S: SESSubject }, }, }; ddb.putItem(itemParams, function (err, data) { if (err) { callback(err) } else { console.log(data); callback(null,) } }); } else if (SESMessageType == "Delivery") { console.log('Create Delivery info') // var SESsmtpResponse1 = SESMessage.delivery.smtpResponse; // var SESreportingMTA1 = SESMessage.delivery.reportingMTA; // var itemParamsdel = { // Item: { // SESMessageId: { S: SESMessageId }, // SnsPublishTime: { S: SnsPublishTime }, // SESsmtpResponse: { S: SESsmtpResponse1 }, // SESreportingMTA: { S: SESreportingMTA1 }, // SESDestinationAddress: { S: SESDestinationAddress }, // SESMessageType: { S: SESMessageType }, // SESSubject: { S: SESSubject }, // }, // }; // console.log(itemParamsdel) // ddb.putItem(itemParamsdel, function (err, data) { // if (err) { // console.log(err) // callback(err) // } else { // console.log(data); // callback(null,) // } // }); } else if (SESMessageType == "Complaint") { var SESComplaintFeedbackType = SESMessage.complaint.complaintFeedbackType; var SESFeedbackId = SESMessage.complaint.feedbackId; var itemParamscomp = { Item: { SESMessageId: { S: SESMessageId }, SnsPublishTime: { S: SnsPublishTime }, SESComplaintFeedbackType: { S: SESComplaintFeedbackType }, SESFeedbackId: { S: SESFeedbackId }, SESDestinationAddress: { S: SESDestinationAddress }, SESMessageType: { S: SESMessageType }, SESSubject: { S: SESSubject }, }, }; ddb.putItem(itemParamscomp, function (err, data) { if (err) { callback(err) } else { console.log(data); callback(null,) } });
结果如下所示
S3
类似的,我可以配置把当天的邮件汇总写入S3的一个key中
S3 bucket access policy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::ses-outgoing-emails", "arn:aws:s3:::ses-outgoing-emails/*" ] } ] }
Lambda 权限
创建一个role 绑定默认 AWSLambdaBasicExecutionRole的 Policy即可
#### Lambda 代码 console.log('Loading function'); exports.handler = function(event, context) { console.log('Received event:', JSON.stringify(event, null, 2)); var AWS = require('aws-sdk'); AWS.config.update({region:'us-west-2'}); // get curret AEDT time process.env.TZ = 'Australia/Sydney'; var mytimestamp = new Date(); var year = mytimestamp.getFullYear(); var month = mytimestamp.getMonth(); month += 1; var day = mytimestamp.getDate(); var hours = mytimestamp.getHours(); var minutes = mytimestamp.getMinutes(); var seconds = mytimestamp.getSeconds(); // set bucket=ses-outgoing-emails/yyyy-mm-dd, filename=yyyy-mm-dd-hour-minute-second var bucketname = 'ses-outgoing-emails/'+ year + '-' + month + '-' + day; var myfilename = 'Outgoing-' + year + '-' + month + '-' + day + '-' + hours + minutes + seconds; // parse SNS message var alarm_msg = event.Records[0].Sns.Message; var params = {Key: myfilename, Body: 'Message Part 1. Here is the message payload'+alarm_msg+'MORETHINGS'}; // init s3 connection var s3bucket = new AWS.S3({params: {Bucket: bucketname}}); // start uploading s3bucket.putObject(params, function (error, data) { if (error) { console.log("Error in posting Content [" + error + "]"); return false; } /* end if error */ else { console.log("Successfully posted Content"); } /* end else error */ }) };
汇总的报告
有的时候,需要看看最近一段时间的SES的Metric状态,可以通过AWS CLI来获取。下面的命令可以输出一个状态报告,因为他的结果本身是一个JSON格式,我们可以直接在Excel里面转换打开,一目了然。
aws ses get-send-statistics --region us-west-2
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~