亚马逊AWS官方博客

关于 Amazon SES 你需要知道的一些事 – Tracking 篇 01

一.Amazon SES 是什么?

Amazon Simple Email Service 是一个易于使用且经济高效的电子邮件平台,有便于用户通过该平台,使用自己的电子邮件地址和域来发送或接收电子邮件。例如,用户可以发出诸如特惠促销之类的营销电子邮件,或下单确认通知等交易相关的电子邮件,还可以发出新闻简讯等其它类型的通信。在使用 Amazon SES 接收邮件时,还可以开发出各种实用的软件功能,例如:电子邮件自动回复程序、电子邮件取消订阅系统,以及根据所传入的电子邮件生成客服工单的应用程序。

二.Amazon SES 邮件追踪为什么重要?

主要有以下几个原因:

1. 追踪邮件是否成功送达。SES 邮件追踪可以告诉用户每一封邮件的送达状态,所以用户可以实时了解收件个体是否成功收到了邮件通知;

2. 诊断邮件送达问题。如果某些邮件送达失败或者延迟,SES 追踪可以查明原因,例如被 SPAM 过滤,超出发送限制等。这有助于用户优化邮件系统,提高邮件送达率;

3. 了解用户互动。邮件追踪包括收件个体的打开、点击等行为数据,这有助于分析和了解收件个体对邮件内容的关注或互动情况,从而制定更好的邮件营销和产品策略;

4. 检查发送流程。SES 追踪包含了整个邮件发送流程的数据,用户可以验证 SES 与应用系统、网络等的集成是否正确,邮件是否按预期发送;

5. 满足法规要求。某些行业或国家对邮件追踪有监管要求,SES 邮件追踪可以提供详细的审计线索,有助于满足这些合规性要求;

所以在很多业务场景下,都建议开启和使用 SES 邮件追踪功能,这可以带来很多价值。

三.如何监控 Amazon SES 发送活动?

Amazon SES 提供了使用事件、指标和统计信息监控发送活动的几种方法。事件是“通过跟踪用户指定的指标,得到的与发送活动相关的事情”。指标代表一个按时间顺序排列的数据点集,它们代表生成统计信息的受监控事件类型的值。统计信息是指定时间段的指标数据聚合。

设置监控的第一步是确定要监控的与电子邮件事件类型。用户可以在 SES 中选择以下要监控的事件类型:

  • Send(发送)– 发送请求成功,Amazon SES 将尝试将邮件发送到收件人的邮件服务器。
  • 呈现失败 – 由于模板呈现问题,未发送电子邮件。当模板数据丢失或模板参数与数据不匹配时,可能会发生此事件类型。
  • Reject(拒绝)– Amazon SES 已接受电子邮件,但确定它包含病毒,而未尝试将其发送到收件人的邮件服务器。
  • Delivery(送达)– Amazon SES 成功将电子邮件发送到收件人的邮件服务器。
  • 退信 – 收件人的邮件服务器永久拒绝了电子邮件的硬退信。
  • Complaint(投诉)– 电子邮件已成功送达收件人的邮件服务器,但收件人将其标记为垃圾邮件。
  • 送达延迟 – 由于出现临时问题,无法将电子邮件传送给收件人的邮件服务器。
  • Subscription(订阅)– 电子邮件已成功发送,但收件人通过单击电子邮件标头中的 List-Unsubscribe 或脚注中的 Unsubscribe 链接更新了订阅首选项。
  • Open(打开)– 收件人已收到邮件并在其电子邮件客户端中打开了邮件。
  • Click(单击)– 收件人单击了电子邮件中包含的一个或多个链接。

Amazon SES 可以将电子邮件发送事件发布到 Amazon CloudWatch、Amazon Kinesis Data Firehose、Amazon Pinpoint 或 Amazon Simple Notification Service。

后续会通过 Amazon CloudWatch 和 Amazon Kinesis Data Firehose 进行演示。

四.使用 Amazon CloudWatch 监控发送活动

4.1 创建配置集

4.2 创建 Event destinations

4.3 选择所有 Event types

4.4 选择 Amazon CloudWatch

可以看到有 3 类 Value source

4.5 测试 1 选择 Message tag

设置如下图所示:

测试代码如下:

import boto3

fromAddress = 'sender@example.com'
toAddresses = 'receiver@example.com'
htmlBody = """\
<html>
<body>
<h1>Hello!</h1>
<p>This is a test email form project01.</p>
<a href="http://my-poc-alb-012345678.ap-northeast-1.elb.amazonaws.com">Test Link</a>
</body>
</html>
"""


client = boto3.client('sesv2')

response = client.send_email(
    FromEmailAddress=fromAddress,
    Destination={
        'ToAddresses': [
            toAddresses,
        ]
    },
    Content={
        'Simple': {
            'Subject': {
                'Data': 'CloudWatch Track Test',
                'Charset': 'UTF-8'
            },
            'Body': {
                'Html': {
                    'Data': htmlBody,
                    'Charset': 'UTF-8'
                }
            }
        }
    },
    EmailTags=[
        {
            'Name': 'Project',
            'Value': 'project01'
        },
    ],
    ConfigurationSetName='my-poc-cs'
)

运行该测试代码,可以收到一封邮件,打开邮件,并点击链接。

然后打开 Amazon CloudWatch,观察 Amazon CloudWatch Metrics,可以看到在 Project 的维度下已经收集到了指标。

4.6 测试 2 选择 Link Tag

当一封邮件里有多个链接时,有时需要对不同的链接分别统计,那么这个时候,就需要在 Message Tag 的基础上用到 Link Tag。

首先修改之前的 Amazon CloudWatch dimensions。

测试代码如下:

import boto3

fromAddress = 'sender@example.com'
toAddresses = 'receiver@example.com'
htmlBody = """\
<html>
<body>
<h1>Hello!</h1>
<p>This is a test email form project02.</p>
<a ses:tags="Link:link01" href="http://my-poc-alb-012345678.ap-northeast-1.elb.amazonaws.com">Test Link 01</a>
<a ses:tags="Link:link02" href="http://my-poc-alb-012345678.ap-northeast-1.elb.amazonaws.com">Test Link 02</a>
</body>
</html>
"""


client = boto3.client('sesv2', region_name = 'ap-northeast-1')

response = client.send_email(
    FromEmailAddress=fromAddress,
    Destination={
        'ToAddresses': [
            toAddresses,
        ]
    },
    Content={
        'Simple': {
            'Subject': {
                'Data': 'CloudWatch Track Test',
                'Charset': 'UTF-8'
            },
            'Body': {
                'Html': {
                    'Data': htmlBody,
                    'Charset': 'UTF-8'
                }
            }
        }
    },
    EmailTags=[
        {
            'Name': 'Project',
            'Value': 'project02'
        },
    ],
    ConfigurationSetName='my-poc-cs'
)

运行该测试代码,可以收到一封邮件,打开邮件,点击 Test Link 01 一次,Test Link 02 两次。

通过 Amazon CloudWatch Metrics 可以观察到在 Project 这个 Message  Tag 的维度基础上,又增加了 Link Tag,而且可以区分开每个链接的点击次数。

如果不想监控某个链接的点击数,也可以通过添加 ses:no-track 来禁止追踪,更多细节可以查看此链接

4.6 测试 3 Email Header

接着我们再来验证最后一种 Value source,Email Header。 自定义邮件头(custom email header)是可以在发出的电子邮件中添加的额外邮件头信息。

添加自定义邮件头的一些主要优点包括:

  1. 追踪和分析:通过添加自定义头来追踪电子邮件的打开率、点击率等。这可以帮助分析邮件营销活动的效果。
  2. 防垃圾邮件:通过添加自定义头可以让你的邮件看起来不太像垃圾邮件,提高送达收件箱的机会。例如可以添加标识邮件来源的头。
  3. 测试和部署:通过自定义头可以用来在测试组和生产组之间标识不同版本的电子邮件。这可以帮助 A/B 测试等。
  4. 安全性:通过添加自定义头可以增加邮件在传输中的安全性。例如可以添加数字签名来验证邮件的真实性。
  5. 自定义功能:通过添加自定义头使你可以开发定制功能,比如订阅管理、在线阅读等。这些自定义头可以让电子邮件和 Web 应用更好地集成。
  6. 易于识别:有些自定义头信息可以使得这些邮件更容易被搜索和识别,从而提高开启率。

因此添加自定义邮件头可以优化邮件发送,增强分析功能,并启用更多高级应用和集成。但是需要谨慎使用,避免被当成垃圾邮件。

开启测试之前,首先修改之前的 Amazon CloudWatch dimensions:

测试代码如下:

import os
import boto3
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

SENDER = "sender@example.com"
RECIPIENT = "receiver@example.com"
SUBJECT = "CloudWatch Track Test"
BODY_HTML = """\
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>This is a test email form project03.</p>
<a href="http://my-poc-alb-012345678.ap-northeast-1.elb.amazonaws.com">Test Link</a>
</body>
</html>
"""

CHARSET = "utf-8"
msg = MIMEMultipart('mixed')
msg['Subject'] = SUBJECT
msg['From'] = SENDER
msg['To'] = RECIPIENT
msg_body = MIMEMultipart('alternative')
htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)
msg_body.attach(htmlpart)
msg.add_header('MyHeader','header01')
msg.attach(msg_body)

client = boto3.client('sesv2')
response = client.send_email(
    FromEmailAddress=SENDER,
    Destination={
        'ToAddresses': [
           RECIPIENT,
        ]
    },
    Content={
        'Raw': {
            'Data': msg.as_string()
        },
    },
    ConfigurationSetName='my-poc-cs-dest-01'
)

运行该测试代码,可以收到一封邮件,打开邮件,点击 Test Link 一次。

通过 Amazon CloudWatch Metrics 可以观察到相关 Dimension 已经生效。

五.对 Tracking 机制的 Deep Dive

5.1 Open(打开)事件的追踪

那 Amazon SES 是怎么追踪 Open 事件呢?我们来做一个测试。

首先,按照下图修改配置集 Configuration Set

运行测试代码:

import boto3

fromAddress = 'sender@example.com'
toAddresses = 'receiver@example.com'
htmlBody = """\
<html>
<body>
<h1>Hello!</h1>
<p>This is a test email for open event.</p>
</body>
</html>
"""


client = boto3.client('sesv2', region_name = 'ap-northeast-1')

response = client.send_email(
    FromEmailAddress=fromAddress,
    Destination={
        'ToAddresses': [
            toAddresses,
        ]
    },
    Content={
        'Simple': {
            'Subject': {
                'Data': 'SES Open Track Test',
                'Charset': 'UTF-8'
            },
            'Body': {
                'Html': {
                    'Data': htmlBody,
                    'Charset': 'UTF-8'
                }
            }
        }
    },
    EmailTags=[
        {
            'Name': 'OpenTrack',
            'Value': 'opentrack01'
        },
    ],
    ConfigurationSetName='my-poc-cs'
)

收到邮件后,打开测试邮件

在 Amazon CloudWatch 中查看相关 metric,邮件被打开了 1 次。

接下来我们查看这封邮件的源代码,可以发现邮件里多了一张图片。在通过 Amazon SES 发送的每封电子邮件中插入一个 1 x 1 像素的透明 GIF 图像,并包含一个对此图像文件的唯一引用;当此图像被下载时,SES 可以准确地分辨出哪封邮件被谁打开过。更多详情可以参考这个链接

5.2 Click(单击)事件的追踪

除了 Open Tacking,Amazon SES 还提供了 Click Tracking。为了跟踪单击情况,Amazon SES 会修改电子邮件正文中的每个链接。当收件人打开某个链接时,链接请求将被发送到 Amazon SES 服务器,然后立即被转发到目标地址。与打开情况跟踪一样,每个重定向链接都是唯一的。这样使 Amazon SES 能够确定哪些收件人单击了链接,他们何时单击了链接,以及用来访问链接的电子邮件。我们用前面已经发送的两封带有 Link 的邮件来验证下,查看这两封邮件的源代码。

第一封:

第二封:

可以看到 URL 分别为:

  1. http://g3z3qhww.r.ap-northeast-1.awstrack.me/L0/http:%2F%2Fmy-poc-=alb-854041574.ap-northeast-1.elb.amazonaws.com/1/0106018c496b23b8-c4cb3332-4=8dc-4ec9-8a96-7df7b52de193-000000/VlgEfzGaA_V-EK4jzHE4LlyjQ9A=3D136
  2. http://g3z3qhww.r.ap-northeast-1.awstrack.me/L0/http:%2F%2Fmy-poc-=alb-854041574.ap-northeast-1.elb.amazonaws.com/2/0106018c496b23b8-c4cb3332-4=8dc-4ec9-8a96-7df7b52de193-000000/X8Zh-hQEVhc4ycNgRXEOZVL28FQ=3D136
  3. http://g3z3qhww.r.ap-northeast-1.awstrack.me/L0/http:%2F%2Fmy-poc-=alb-854041574.ap-northeast-1.elb.amazonaws.com/1/0106018c53d66251-d2a68772-5=093-4a76-811f-e6a652d44ce2-000000/XVb4tvEgU51WFx5SMxnvxN7pBfs=3D136

每一个都不同。有的读者已经发现了,Amazon SES 会修改链接的 URL,那这里是否可以使用用户自己的域名呢?答案是可以。接下来我们就会介绍如何在 SES 中使用自定义域名。

5.3 Tracking 追踪中使用自定义域名

使用 Amazon SES 追踪时,配置自定义域名有以下几个主要优势和应用场景:

  1. 加强品牌识别度。使用自定义域名而不是 SES 默认域名,可以让邮件中的所有链接都带有用户自己的域名,这有助于加强品牌识别度;
  2. 提高送达率。某些 ISP 和企业邮件服务器会针对特定发送域名设立严格的垃圾邮件过滤规则。使用自定义域名可以避开针对 Amazon 默认域名的过滤;
  3. 符合 DMARC 策略。使用自定义域名可以更轻松地设置 DMARC 记录来防止地址伪造。这可提高您域名的安全性和可信度;
  4. 重要邮件通知。对于某些验证邮件、账单提醒等重要通知,使用用户自己的域名更能令人信服;

接下来我们分别通过配置 HTTP 域和 HTTPS 域两种方法来演示一下。演示前我们需要在 SES 中配置 Verified identities,这里我使用了自己的测试域名。

配置完成后,会如下显示:

5.3.1 使用 HTTP

修改 Configuration Set,启用 Custom redirect domain,这里我使用的是 mydomain.ytpoc.click。

接下来在 DNS Recording 中追加 CNAME 记录,以将请求重定向到 SES 追踪域。注意,每个 Region 的追踪域是不同的,例如我这里使用的是亚太地区(东京),那么追踪域就是 r.ap-northeast-1.awstrack.me,具体其他 Region 的可以查看这个链接

运行测试代码,收到测试邮件后,查看它的源代码。

import boto3

fromAddress = 'sender@ytpoc.click'
toAddresses = 'receiver@example.com'
htmlBody = """\
<html>
<body>
<h1>Hello!</h1>
<p>This is a test email for custom http domain.</p>
<a href="http://my-poc-alb-012345678.ap-northeast-1.elb.amazonaws.com">Test Link</a>
</body>
</html>
"""


client = boto3.client('sesv2', region_name = 'ap-northeast-1')

response = client.send_email(
    FromEmailAddress=fromAddress,
    Destination={
        'ToAddresses': [
            toAddresses,
        ]
    },
    Content={
        'Simple': {
            'Subject': {
                'Data': 'Custom Http Domain Test',
                'Charset': 'UTF-8'
            },
            'Body': {
                'Html': {
                    'Data': htmlBody,
                    'Charset': 'UTF-8'
                }
            }
        }
    },
    EmailTags=[
        {
            'Name': 'Project',
            'Value': 'httpdomain'
        },
    ],
    ConfigurationSetName='my-poc-cs'
)

可以看到 OpenLink 和 ClickLink 中的 URL 都已经变成 custom domain 了。

5.3.2 使用 HTTPS

创建 Amazon Certificate Manager,后面的步骤需要用到证书,这里需要注意的是该 ACM 必须设置在 us-east-1 Region。

创建 Amazon CloudFront,源指向 r.ap-northeast-1.awstrack.me,其他 Region 的可以查看这个链接

这里的 Headers 需要放行 Host。

Alternate domain names 填写 mydomain.ytpoc.click,SSL 证书选择之前创建的 ACM 证书。

接着,修改 DNS 记录中的 mydomain.ytpoc.click,指向之前创建的 CloudFront。

最后,让我们来运行测试代码。

import boto3

fromAddress = 'sender@ytpoc.click'
toAddresses = 'receiver@example.com'
htmlBody = """\
<html>
<body>
<h1>Hello!</h1>
<p>This is a test email for custom https domain.</p>
<a href="https://thinkwithwp.com">Test Link</a>
</body>
</html>
"""


client = boto3.client('sesv2', region_name = 'ap-northeast-1')

response = client.send_email(
    FromEmailAddress=fromAddress,
    Destination={
        'ToAddresses': [
            toAddresses,
        ]
    },
    Content={
        'Simple': {
            'Subject': {
                'Data': 'Custom Https Domain Test',
                'Charset': 'UTF-8'
            },
            'Body': {
                'Html': {
                    'Data': htmlBody,
                    'Charset': 'UTF-8'
                }
            }
        }
    },
    EmailTags=[
        {
            'Name': 'Project',
            'Value': 'httpsdomain'
        },
    ],
    ConfigurationSetName='my-poc-cs'
)

收到邮件后,查看源代码。可以观察到 Click Tracking URL 已经变成 https custom domain 了,而 Open Tracking URL 仍然是 http custom domain。这是因为用户只能使用 HTTPS 域来追踪 Click Link。Amazon SES 仅支持在使用 HTTP 域来追踪 Open 事件。

六.结束语

通过本篇博客,我们主要演示和解读了如何使用 Amazon CloudWatch 来追踪 Amazon SES 的发送事件。下一篇我们会着重介绍如何使用 Amazon Kinesis Firehose 来细致分析 SES 的发送事件,敬请期待。

本篇作者

杨探

AWS 解决方案架构师,负责互联网行业云端架构咨询和设计。

唐冠群

亚马逊云科技客户技术经理。主要负责 Auto 行业客户的架构优化、成本管理、技术咨询等工作。拥有超过 10 年项目实施和客户支持经验。在加入 AWS 前曾就职于 IBM,主要服务于大型金融类客户。