29、基于 AWS 的在线游戏商店邮件通知服务搭建指南

基于 AWS 的在线游戏商店邮件通知服务搭建指南

1. 安装 AWS CLI

为了在部署无服务器函数和创建 S3 存储桶时节省时间,我们需要安装 AWS 命令行界面(AWS CLI)。它可以通过 pip 进行安装,支持 Python 2 和 Python 3,并且能在 Linux、macOS 和 Windows 等不同操作系统上运行。
具体操作步骤如下:
1. 打开终端,输入以下命令进行安装:

pip install awscli --upgrade --user

这里的 --upgrade 选项会让 pip 更新所有已安装的依赖项, --user 选项表示 pip 会将 AWS CLI 安装到本地目录,不会影响系统全局安装的库。在 Linux 系统上,使用 --user 选项安装 Python 包时,包会被安装到 .local/bin 目录,所以要确保该目录已添加到环境变量中。
2. 验证安装是否成功,输入以下命令:

aws --version

如果安装成功,你会看到类似如下的输出:

aws-cli/1.14.30 Python/3.6.2 Linux/4.9.0-3-amd64 botocore/1.8.34

从输出中可以看到 AWS CLI 版本、操作系统版本、Python 版本以及当前使用的 botocore 版本。botocore 是 AWS CLI 使用的核心库,boto 是 Python 的 SDK,可用于开发与 Amazon EC2 和 S3 等服务交互的软件。

2. 配置 AWS CLI

配置 AWS CLI 前,我们需要准备好访问密钥( aws_access_key_id aws_secret_access_key )、首选区域和输出格式(通常为 JSON)。
操作步骤如下:
1. 创建访问密钥:在 AWS 控制台页面右上角,点击用户名的下拉菜单,选择 “My Security Credentials”。在该页面中,选择 “Access keys (access key ID and secret access key)”,然后点击 “Create New Access Key”,会弹出一个对话框显示你的密钥,建议下载并妥善保存。
2. 查看 AWS 区域和端点:访问 https://docs.aws.amazon.com/general/latest/gr/rande.html 获取相关信息。
3. 配置 CLI:在命令行中输入以下命令:

aws configure

按照提示依次输入访问密钥、秘密访问密钥、区域和默认输出格式。

3. 配置简单邮件服务(SES)

Amazon 提供了简单邮件服务(SES),我们可以通过它在应用程序中发送邮件。这里我们将服务运行在沙盒模式下,即只能向经过验证的电子邮件地址发送邮件。如果要在生产环境中使用该服务,可以申请提高邮件发送限制。
操作步骤如下:
1. 准备两个电子邮件账户:例如,我使用自己的域名创建了 donotreply@dfurtado.com 用于发送邮件, pythonblueprints@dfurtado.com 用于接收邮件。在在线游戏商店应用中,用户会使用这个接收邮件地址,我们可以下一些订单来测试后续的通知功能。
2. 注册电子邮件:
- 登录 AWS 控制台,在搜索栏中搜索 “Simple Email Service”。
- 在左侧菜单中,点击 “Identity Management” 下的 “Email Addresses”。
- 点击 “Verify a New Email Address”,输入要验证的电子邮件地址,然后点击 “Verify This Email Address” 按钮。系统会向该地址发送一封验证邮件,点击其中的链接完成验证。
- 对另一个用于接收邮件的地址重复上述步骤。
3. 创建 SMTP 凭证:
- 再次点击左侧菜单中的 “SMTP Settings”。
- 点击 “Create My SMTP Credentials” 按钮,在新页面中输入所需的 IAM 用户名(例如 python-blueprints ),然后点击 “Create”。
- 凭证创建完成后,会显示 SMTP 用户名和密码,你可以选择下载保存。

4. 创建 S3 存储桶

为了向用户发送模板邮件,我们需要将模板文件复制到 S3 存储桶中。可以通过网页操作或使用刚安装的 AWS CLI 来完成。
使用以下命令在 eu-west-2 区域创建 S3 存储桶:

aws s3api create-bucket \
--bucket python-blueprints \
--region eu-west-2 \
--create-bucket-configuration LocationConstraint=eu-west-2

这里使用了 s3api 命令,它提供了与 AWS S3 服务交互的不同子命令。 create-bucket 子命令用于创建新的 S3 存储桶,我们指定了三个参数: --bucket 指定存储桶名称, --region 指定存储桶创建的区域, --create-bucket-configuration LocationConstraint 用于指定非 us-east-1 区域的存储桶位置。

5. 实现通知服务

现在所有准备工作已完成,存储在 python-blueprints S3 存储桶中的模板文件也已就位,接下来开始实现通知服务。

5.1 创建 app.py 文件并导入必要的模块

notifier 目录下创建 app.py 文件,并添加以下导入语句:

import smtplib
from http import HTTPStatus
from smtplib import SMTPAuthenticationError, SMTPRecipientsRefused
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import boto3
from botocore.exceptions import ClientError
from flask import Flask
from flask import request, Response
from jinja2 import Template
import json

这些模块的作用分别是:
- json :用于序列化和反序列化数据。
- HTTPStatus :用于在服务端点返回响应时使用 HTTP 状态常量。
- smtplib 及相关异常:用于发送邮件并处理可能出现的认证和收件人拒绝等异常。
- MIMEText MIMEMultipart :用于创建邮件内容和消息对象。
- boto3 :用于与 AWS 服务交互。
- Flask 相关模块:用于创建 Web 应用。
- Jinja2 :用于模板化邮件内容。

5.2 定义常量和创建 Flask 应用

app.py 文件中定义存储桶名称常量,并创建 Flask 应用:

S3_BUCKET_NAME = 'python-blueprints'
app = Flask(__name__)
5.3 定义自定义异常类

为了更好地处理 S3 相关的错误,我们定义一个自定义异常类:

class S3Error(Exception):
    pass
5.4 定义辅助函数
  • 发送邮件的函数
def _send_message(message):
    smtp = smtplib.SMTP_SSL('email-smtp.eu-west-1.amazonaws.com', 465)
    try:
        smtp.login(
            user='DJ********DER*****RGTQ',
            password='Ajf0u*****44N6**ciTY4*****CeQ*****4V')
    except SMTPAuthenticationError:
        return Response('Authentication failed',
                        status=HTTPStatus.UNAUTHORIZED)
    try:
        smtp.sendmail(message['From'], message['To'], message.as_string())
    except SMTPRecipientsRefused as e:
        return Response(f'Recipient refused {e}',
                        status=HTTPStatus.INTERNAL_SERVER_ERROR)
    finally:
        smtp.quit()
    return Response('Email sent', status=HTTPStatus.OK)

该函数接受一个 message 参数,首先创建一个 SMTP 连接对象,使用 SMTP_SSL 以满足 AWS 简单邮件服务的 TLS 要求。然后尝试登录 SMTP 服务器,如果认证失败则返回 UNAUTHORIZED 响应;如果登录成功,尝试发送邮件,若收件人拒绝则返回 INTERNAL_SERVER_ERROR 响应,最后关闭连接并返回 OK 响应。
- 加载模板文件并渲染的函数

def _prepare_template(template_name, context_data):
    s3_client = boto3.client('s3')
    try:
        file = s3_client.get_object(Bucket=S3_BUCKET_NAME, Key=template_name)
    except ClientError as ex:
        error = ex.response.get('Error')
        error_code = error.get('Code')
        if error_code == 'NoSuchBucket':
            raise S3Error(
             f'The bucket {S3_BUCKET_NAME} does not exist') from ex
        elif error_code == 'NoSuchKey':
            raise S3Error((f'Could not find the file "{template_name}" '
               f'in the S3 bucket {S3_BUCKET_NAME}')) from ex
        else:
            raise ex
    content = file['Body'].read().decode('utf-8')
    template = Template(content)
    return template.render(context_data)

该函数接受模板文件名和上下文数据作为参数,首先创建一个 S3 客户端,尝试从 S3 存储桶中获取模板文件。如果出现 NoSuchBucket NoSuchKey 错误,抛出自定义的 S3Error 异常;否则,读取文件内容,创建 Jinja2 模板对象并渲染上下文数据。

5.5 实现邮件通知端点
  • 订单接收确认邮件端点
@app.route("/notify/order-received/", methods=['POST'])
def notify_order_received():
    data = json.loads(request.data)
    order_items = data.get('items')
    customer = data.get('order_customer')
    customer_email = customer.get('email')
    customer_name = customer.get('name')
    order_id = data.get('id')
    total_purchased = data.get('total')
    message = MIMEMultipart('alternative')
    context = {
        'order_items': order_items,
        'customer_name': customer_name,
        'order_id': order_id,
        'total_purchased': total_purchased
    }
    try:
        email_content = _prepare_template(
            'order_received_template.html',
            context
        )
    except S3Error as ex:
        return Response(str(ex), 
       status=HTTPStatus.INTERNAL_SERVER_ERROR)
    message.attach(MIMEText(email_content, 'html'))
    message['Subject'] = f'ORDER: #{order_id} - Thanks for your order!'
    message['From'] = 'donotreply@dfurtado.com'
    message['To'] = customer_email
    return _send_message(message)

该端点处理 POST 请求,从请求数据中提取订单信息和客户信息,创建邮件消息对象,使用 _prepare_template 函数渲染模板,将渲染后的内容添加到邮件中,设置邮件主题、发件人和收件人,最后调用 _send_message 函数发送邮件。
- 订单发货通知邮件端点

@app.route("/notify/order-shipped/", methods=['POST'])
def notify_order_shipped():
    data = json.loads(request.data)
    customer = data.get('order_customer')
    customer_email = customer.get('email')
    customer_name = customer.get('name')
    order_id = data.get('id')
    message = MIMEMultipart('alternative')
    try:
        email_content = _prepare_template(
            'order_shipped_template.html',
            {'customer_name': customer_name}
        )
    except S3Error as ex:
        return Response(ex, status=HTTPStatus.INTERNAL_SERVER_ERROR)
    message.attach(MIMEText(email_content, 'html'))
    message['Subject'] = f'Order ID #{order_id} has been shipped'
    message['From'] = 'donotreply@dfurtado.com'
    message['To'] = customer_email
    return _send_message(message)

该端点同样处理 POST 请求,从请求数据中提取客户信息和订单 ID,创建邮件消息对象,使用 _prepare_template 函数渲染模板,设置邮件主题、发件人和收件人,最后发送邮件。

6. 创建邮件模板

在应用程序的根目录下创建 templates 目录,并在其中创建两个邮件模板文件。
- order_received_template.html

<html>
  <head>
  </head>
  <body>
    <h1>Hi, {{customer_name}}!</h1>
    <h3>Thank you so much for your order</h3>
    <p>
      <h3>Order id: {{order_id}}</h3>
    </p>
    <table border="1">
      <thead>
        <tr>
          <th align="left" width="40%">Item</th>
          <th align="left" width="20%">Quantity</th>
          <th align="left" width="20%">Price per unit</th>
        </tr>
      </thead>
      <tbody>
        {% for item in order_items %}
        <tr>
          <td>{{item.name}}</td>
          <td>{{item.quantity}}</td>
          <td>${{item.price_per_unit}}</td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
    <div style="margin-top:20px;">
      <strong>Total: ${{total_purchased}}</strong>
    </div>
  </body>
</html>
  • order_shipped_template.html
<html>
  <head>
  </head>
  <body>
    <h1>Hi, {{customer_name}}!</h1>
    <h3>We just want to let you know that your order is on its way! </h3>
  </body>
</html>

Jinja 2 语法与 Django 模板语言有很多相似之处。

7. 复制模板到 S3 存储桶

打开终端,运行以下命令将模板文件复制到之前创建的 S3 存储桶中:

aws s3 cp ./templates s3://python-blueprints --recursive

完成以上步骤后,我们就搭建好了基于 AWS 的在线游戏商店邮件通知服务,接下来可以部署我们的项目了。整个搭建过程的流程图如下:

graph TD;
    A[安装 AWS CLI] --> B[配置 AWS CLI];
    B --> C[配置简单邮件服务 SES];
    C --> D[创建 S3 存储桶];
    D --> E[实现通知服务];
    E --> F[创建邮件模板];
    F --> G[复制模板到 S3 存储桶];
    G --> H[部署项目];

通过以上详细的步骤和代码示例,你可以逐步搭建起一个完整的邮件通知服务,为在线游戏商店的用户提供订单确认和发货通知等功能。在实际应用中,你可以根据具体需求对代码和模板进行调整和扩展。

基于 AWS 的在线游戏商店邮件通知服务搭建指南

8. 部署项目

在完成了前面的所有准备工作后,我们就可以开始部署项目了。虽然文档中没有详细提及部署项目的具体步骤,但一般来说,对于基于 Flask 的项目部署到 AWS 可以借助 AWS Elastic Beanstalk 等服务,以下是一个大致的部署流程:
1. 创建 AWS Elastic Beanstalk 环境
- 登录 AWS 管理控制台,搜索 “Elastic Beanstalk” 并打开服务页面。
- 点击 “创建新环境”,选择 “Web 服务器环境”。
- 选择平台为 “Python”,并根据项目需求选择合适的 Python 版本。
- 上传项目代码,可以选择通过 ZIP 文件上传,确保包含 app.py 文件以及相关依赖。
2. 配置环境
- 在创建环境的过程中,可以配置环境变量,例如将之前创建的 AWS 访问密钥、SMTP 凭证等信息以环境变量的形式配置,避免硬编码在代码中。
- 配置实例类型、自动伸缩策略等,根据项目的预期流量和性能需求进行调整。
3. 部署应用
- 完成环境配置后,点击 “创建环境”,AWS Elastic Beanstalk 会自动创建和配置所需的资源,包括 EC2 实例、负载均衡器等。
- 等待环境创建完成,这可能需要几分钟到十几分钟不等,具体时间取决于资源的配置和 AWS 的负载情况。
- 环境创建成功后,会生成一个 URL,通过该 URL 可以访问部署的应用。

9. 测试邮件通知服务

在项目部署完成后,需要对邮件通知服务进行测试,确保订单接收确认邮件和订单发货通知邮件能够正常发送。
1. 模拟订单数据
- 可以使用工具如 Postman 或编写简单的 Python 脚本,向 /notify/order-received/ /notify/order-shipped/ 端点发送 POST 请求,模拟订单数据。
- 以下是一个使用 Python requests 库发送请求的示例:

import requests
import json

# 模拟订单接收数据
order_received_data = {
    "items": [
        {"name": "Game 1", "quantity": 1, "price_per_unit": 29.99},
        {"name": "Game 2", "quantity": 2, "price_per_unit": 19.99}
    ],
    "order_customer": {
        "email": "pythonblueprints@dfurtado.com",
        "name": "John Doe"
    },
    "id": "12345",
    "total": 69.97
}

# 发送订单接收确认邮件请求
response = requests.post("http://your-elastic-beanstalk-url/notify/order-received/",
                         data=json.dumps(order_received_data),
                         headers={"Content-Type": "application/json"})
print(response.text)

# 模拟订单发货数据
order_shipped_data = {
    "order_customer": {
        "email": "pythonblueprints@dfurtado.com",
        "name": "John Doe"
    },
    "id": "12345"
}

# 发送订单发货通知邮件请求
response = requests.post("http://your-elastic-beanstalk-url/notify/order-shipped/",
                         data=json.dumps(order_shipped_data),
                         headers={"Content-Type": "application/json"})
print(response.text)
  1. 检查邮件接收情况
    • 登录之前注册的接收邮件的邮箱(如 pythonblueprints@dfurtado.com ),检查是否收到了订单接收确认邮件和订单发货通知邮件。
    • 检查邮件内容是否正确显示了订单信息、客户信息等。
10. 常见问题及解决方法

在搭建和测试邮件通知服务的过程中,可能会遇到一些常见问题,以下是部分问题及解决方法:
| 问题描述 | 可能原因 | 解决方法 |
| ---- | ---- | ---- |
| 邮件无法发送 | SMTP 认证失败 | 检查 SMTP 用户名和密码是否正确,确保在 _send_message 函数中配置的信息与 AWS SES 创建的 SMTP 凭证一致。 |
| 模板文件无法加载 | S3 存储桶权限问题或文件不存在 | 检查 S3 存储桶的权限设置,确保应用程序有访问该存储桶的权限。同时,检查模板文件是否正确复制到了 S3 存储桶中。 |
| 端点请求返回错误响应 | 请求数据格式错误或代码逻辑问题 | 检查发送请求时的数据格式是否符合要求,确保 JSON 数据的键名和值类型正确。同时,检查 app.py 文件中的代码逻辑,查看是否有异常处理不当的情况。 |

11. 总结

通过以上详细的步骤,我们成功搭建了基于 AWS 的在线游戏商店邮件通知服务。整个过程涵盖了 AWS CLI 的安装和配置、简单邮件服务 SES 的使用、S3 存储桶的创建和管理、Flask 应用的开发以及邮件模板的创建和部署。以下是整个搭建过程的关键步骤总结:
1. 安装和配置 AWS CLI,获取并配置访问密钥。
2. 配置 Amazon SES,注册电子邮件地址并创建 SMTP 凭证。
3. 创建 S3 存储桶,用于存储邮件模板文件。
4. 实现通知服务,编写 app.py 文件,定义邮件发送和模板渲染的函数,以及处理订单接收和发货通知的端点。
5. 创建邮件模板文件,使用 Jinja 2 语法动态生成邮件内容。
6. 将模板文件复制到 S3 存储桶中。
7. 部署项目到 AWS Elastic Beanstalk 等服务。
8. 测试邮件通知服务,确保功能正常。

在实际应用中,可以根据业务需求对服务进行扩展和优化,例如增加更多的邮件通知类型、优化邮件模板的样式和内容、提高服务的性能和稳定性等。希望本文能够帮助你顺利搭建和部署在线游戏商店的邮件通知服务。

整个项目从开始搭建到最终部署的步骤流程图如下:

graph LR;
    A[准备工作] --> B[安装与配置];
    B --> C[服务搭建];
    C --> D[模板创建];
    D --> E[模板部署];
    E --> F[项目部署];
    F --> G[测试与优化];
    style A fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    style B fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    style C fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    style D fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    style E fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    style F fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    style G fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

通过这个流程,我们可以清晰地看到每个步骤之间的依赖关系和先后顺序,有助于更好地理解和实施整个项目。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值