使用 AWS Amplify 的无服务器联系表单
在构建应用程序时,发送电子邮件是一项经常需要的功能。此外,电子邮件中发送的数据很可能需要存储在数据库中,以便进行记录保存、分析或其他处理。
AWS 提供一系列服务,帮助您快速安全地设置 API、数据库和电子邮件传输。具体来说,AWS Amplify提供了许多我们需要的开箱即用功能,而Amazon SES则会代表我们发送电子邮件。
服务概览
AWS Amplify 是一套服务,涵盖 UI 组件和以用例为中心的 CLI 到 CI/CD 控制台和后端脚手架 GUI。
另一方面,Amazon SES 提供了可扩展的电子邮件发送电子邮件解决方案,并被 Reddit 和 Netflix 等公司采用。
在这篇文章中,我们将使用 Amplify CLI 及其 JavaScript 库来创建联系表单的后端,并使用 Amazon SES 将该信息发送到我们的电子邮件。
入门
如果您还没有 AWS 账户或安装 Amplify CLI,请按照本指南操作。
🚨 该项目使用了 lambda 环境变量。通过 CLI 执行此操作的功能是在 版本 中引入的
5.1.0
。您可能需要运行npm install -g @aws-amplify/cli
以确保使用的是最新版本。
设置完成后,contact-form-starter
从此github url克隆此分支。
克隆项目后,安装依赖项并运行项目。以下是一些有用的命令:
// visit: https://github.com/mtliendo/amplify-email-recipes/tree/contact-form-starter
git clone git@github.com:mtliendo/amplify-email-recipes.git
cd amplify-email-recipes
git checkout contact-form-starter
npm install
npm run dev
项目启动后,请访问localhost:3000
并看到以下屏幕:
了解我们的后端
使用上图作为参考,我们后端所需的 Amplify 服务按以下顺序排列:
-
AppSync:完全托管的 GraphQL API
-
DynamoDB:NoSQL 数据库
-
Lambda:FaaS/云功能
简而言之,当用户填写联系表单时,该信息将通过我们的 API 存储在数据库中。成功保存后,将自动触发发送电子邮件的功能。
听起来很多。让我们看看要怎么做才能让它工作。
初始化我们的后端🚀
我们将通过打开终端并确保我们位于项目的根目录中来开始创建后端。
从这里开始,我们将通过运行以下命令来初始化 Amplify:
amplify init
我们将为项目命名,并在出现提示时选择n
拒绝默认配置。这是因为我们将把应用程序部署为静态站点。在 NextJS 中,该构建目录的名称为out
。
在终端中,接受所有提示,除了Distribution Directory Path
输入out
。
整个流程应该如下面的屏幕截图所示:
最后,选择后AWS profile
我们将选择我们想要使用的配置文件。
该流程应类似于以下屏幕截图:
添加 API
我们的应用程序已准备好使用 Amplify CLI,接下来我们将创建后端。如前所述,我们使用 AWS AppSync,它是一个托管的 GraphQL API。
传统上,发送电子邮件时会使用 REST API。然而,我发现,随着需求的变化,AppSync 在处理授权和其他一些功能方面提供了更大的灵活性。
要在 Amplify 中添加 API,我们只需在项目终端中输入以下命令:
amplify add api
在 CLI 提示符中,选择以下选项:
-
GraphQL
-
[enter] 接受默认名称
-
API 密钥
-
“联系表单公共 API”
-
[输入] 接受默认值 7 天
-
[输入] 接受“不,我已经完成了。”
-
[enter] 接受默认的“N”选项
-
[输入] 表示具有字段的单个对象
-
“y”立即编辑架构
-
选择您喜欢的编辑器
通过提示选择这些选项,我们告诉 Amplify 我们希望如何构建我们的 API。
此时,Amplify 已打开一个名为 的文件,schema.graphql
其中包含一个示例 Todo 对象。请将该文件中的所有内容替换为以下内容:
type Candidate
@model
@auth(rules: [{ allow: public, operations: [create] }]) {
id: ID!
name: String!
email: AWSEmail!
}
为了解释清楚这里发生的事情,我们首先创建一个名为 的类型Candidate
。在我们的应用中,Candidate代表提交其信息的用户。
该@model
文本称为指令。当 Amplify 看到该指令时,它将自动创建一个 DynamoDB 表,并针对与其关联的类型(在本例中为 Candidate)创建 CRUDL 操作。
该@auth
指令在我们的 API 上设置了授权规则。这里我们声明:“我们希望我们的 API 对任何拥有 API 密钥的人开放,但我们只希望他们能够在我们的数据库中创建条目,而不能读取、更新或删除条目。”
接下来的几行是与 Candidate 关联的字段。这里要求每个 Candidate 都有一个唯一的 ID(使用 自动创建ID
)、一个名称和一个电子邮件——AWS 有一个名为 AWSEmail 的原语,可以自动验证电子邮件模式。
这样,我们的 API 和数据库就可以部署了。在此之前,我们先来看一下我们的函数。
设置我们的函数触发器
AWS Lambda 是一个事件驱动函数。也就是说,它会作为对某些事件的响应而被调用。通常,这是一个类似 的端点/pets
,但在我们的应用程序中,我们希望每当有项目添加到数据库时都会调用此函数。
幸运的是,Amplify 允许我们从 CLI 进行设置,从而处理这个过程。
在我们的终端中,让我们看一下以下提示:
-
amplify add function
-
Lambda 函数(无服务器函数)
-
“contactformuploader”作为函数名称
-
NodeJS
-
Lambda 触发器
-
Amazon DynamoDB 流
-
在当前 Amplify 项目中使用 API 类别 graphql @model 支持的 DynamoDB 表
-
[enter] 不配置高级设置
-
[enter] 立即编辑本地函数
-
选择您喜欢的编辑器
这将在编辑器中打开该函数。在删除内容之前,我们先来讨论一下生成的代码。
当我们数据库中的记录发生变化时(变化可以是INSERT
、MODIFY
或事件),该信息将作为数据流REMOVE
发送到我们的 lambda 函数。
但是,我们的数据库可能会承受很大的流量。因此,我们不必每次都触发 lambda 表达式来处理单个更改,而是可以批量发送更改,这被称为“分片”。无需过多技术细节,但这就是生成的代码进行迭代的原因event.Records
。
为了使这个概念深入人心,这里有一个图表来展示流和分片:
完成这个小课程后,让我们用以下内容替换 lambda 函数中的内容:
const aws = require('aws-sdk')
const ses = new aws.SES()
exports.handler = async (event) => {
for (const streamedItem of event.Records) {
if (streamedItem.eventName === 'INSERT') {
//pull off items from stream
const candidateName = streamedItem.dynamodb.NewImage.name.S
const candidateEmail = streamedItem.dynamodb.NewImage.email.S
await ses
.sendEmail({
Destination: {
ToAddresses: [process.env.SES_EMAIL],
},
Source: process.env.SES_EMAIL,
Message: {
Subject: { Data: 'Candidate Submission' },
Body: {
Text: { Data: `My name is ${candidateName}. You can reach me at ${candidateEmail}` },
},
},
})
.promise()
}
}
return { status: 'done' }
}
当候选人提交信息时,此函数将自动调用。其中event
包含相关的数据流。因此,从这里开始,我们的工作就很简单了:
从流中抓取项目并发送电子邮件。
使用 AWS SDK,我们sendEmail
从ses
模块中调用该函数。
搞定这些之后,我们至少已经触及了后端的所有部分。不过,我们仍然还有一些未完成的部分。
-
我们的函数没有与 SES 交互的权限
-
我们需要设置这个
process.env.SES_EMAIL
变量 -
我们尚未设置 SES
-
我们的前端代码尚未设置与后端交互。
让我们稍微换个话题,从第三项开始,然后再回顾其他项。
设置SES
如前所述,Amazon Simple Email Service (SES) 提供了一种可扩展的电子邮件发送方式。首次设置 SES 时,AWS 会将您置于沙盒模式。
这意味着我们将面临以下限制:
-
我们只能向已验证的电子邮件地址发送/接收
-
我们每秒只能发送 1 封电子邮件
-
每天仅允许发送 200 封电子邮件
幸运的是,对于我们的应用程序来说,这不会有太大的影响。
首先,让我们进入终端并运行以下命令:
amplify console
出现提示时,选择“Amplify console”。
📝 您可能会被要求登录您的 AWS 账户
登录后,在控制台顶部的搜索栏中搜索“SES”并按回车键。
您应该会看到与上图类似的视图。如果没有,您可能需要点击顶部横幅才能进入这个更新的 UI。
从这里执行以下步骤:
-
点击橙色的“创建身份”按钮
-
选择“电子邮件地址”选项并输入您想要的电子邮件
-
点击橙色的“创建身份”按钮
就这样!设置这项服务的邮箱地址其实很简单……😅
在我们回到代码之前,我们需要做两件事。
首先,通过单击已验证身份屏幕上的复制图标来复制电子邮件的 ARN,如下面的屏幕截图所示:
把它存到记事本里。我们一会儿会用到它。
接下来,SES 会向你提供的邮箱地址发送一封确认邮件。点击验证链接,我们就可以返回代码了。
更新我们的 Lambda
回想一下,我们既需要授予函数访问 SES 的权限,又需要向函数添加一个名为 的环境变量SES_EMAIL
。
让我们首先更新权限。
在您的项目目录中,我们需要导航到以下目录:
amplify/backend/function/your-function-name/
在此目录中,您将看到src
lambda 的目录,以及一个名为的文件
your-function-name-cloudformation-template.json
选择此文件。
无需害怕,这个 JSON 代码被称为 Cloudformation,是 Amplify 在我们与 CLI 交互时为我们创建的。
它充满了设置和规则,我们即将添加更多。
搜索lambdaexecutionpolicy
(它应该位于第 132 行左右)。
此对象有一个Statement
当前包含单个对象的数组。该对象允许我们的函数在 AWS 中创建日志。
将以下对象添加到Statement
数组并保存:
{
"Action": ["ses:SendEmail"],
"Effect": "Allow",
"Resource": "the-arn-you-copied-from-ses"
}
这个小小的添加使我们的函数能够sendEmail
使用我们验证过的电子邮件来调用该函数。
该lambdaexecutionpolicy
对象应如下面的屏幕截图所示(请注意,为了获得*
更大的灵活性,我删除了我的电子邮件):
下一步是将环境变量添加到我们的函数中。
返回终端,运行以下命令:
amplify update function
输入以下选项:
-
Lambda 函数(无服务器函数)
-
[选择您的函数名称]
-
环境变量配置
-
类型
SES_EMAIL
-
输入已通过 SES 验证的电子邮件
-
我受够了
-
不——我现在不想编辑本地文件
推动我们的后端
我们只在 CLI 中运行几个命令就完成了很多工作。这让我们的资源模板化了,但我们还没有将所有资源推送到 AWS。
让我们通过在终端中运行以下命令来解决这个问题:
amplify push
这将提供我们创建的主要资源表(回想一下,我们的数据库是由@model 指令创建的辅助资源)。
选择继续后,请选择以下选项:
-
是的——为 API 生成代码🔥
-
JavaScript
-
[enter] 允许默认文件路径
-
是的——生成所有可能的操作(回想一下,我们只允许
create
按照我们的模式) -
[输入] 接受最大深度 2
我们的终端需要几分钟才能完成,但一旦完成,我们的后端就完成了🎉
让我们通过赋予前端与后端对话的能力来完成这一步。
配置 Amplify 库
我们首先安装 AWS Amplify JavaScript 包:
npm i aws-amplify
安装完成后,我们将把前端和后端结合在一起。在 中_app.js
添加以下几行:
import Amplify from '@aws-amplify/core'
import config from '../src/aws-exports'
Amplify.configure(config)
在这里我们引入 Amplify 库,引入我们的配置(Amplify 生成它并将其放入.gitignore
),然后我们将我们的配置传递给 Amplify。
接下来ContactForm.js
,我们还将引入以下导入:
import { API } from 'aws-amplify'
import { createCandidate } from '../src/graphql/mutations'
📝 请随意查看
createCandidate
Amplify 为我们生成的突变文件。
API 类别是我们与 AppSync API 通信的方式。回想一下,这不仅应该将联系人存储在数据库中,还应该向我们已验证的地址发送电子邮件。
该ContactForm.js
文件包含以下几行代码:
// TODO: Add code to send email here
console.log('<send to backend here>')
将上面的代码替换为以下代码片段:
await API.graphql({
query: createCandidate,
variables: {
input: {
name,
email,
},
},
})
解决了这个问题之后,我们现在可以测试我们的项目了!
重启你的应用localhost:3000
并测试一下。如果一切顺利,几秒钟后你的收件箱里就会收到一封电子邮件🎉
📝 由于我们的邮件是通过 SES 发送的,它们可能会出现在垃圾邮件文件夹中或被您的邮件提供商标记。这是因为我们还没有使用 SES 设置 DKIM。虽然设置过程并不复杂,但这超出了本教程的范围。如果您感兴趣,可以点击此处了解更多信息。
托管我们的项目
在本地运行这个功能很棒,但对于联系表单,我们很可能希望它在互联网上实时运行。
幸运的是,Amplify 也允许我们从 CLI 执行此操作。
首先,在我们的终端中运行以下命令:
amplify add hosting
根据提示,我们将选择以下选项:
-
使用 Amplify 控制台进行托管
-
手动部署
一旦选择,我们可以运行以下命令来查看更改,接受后,我们的应用程序将被部署并在网络上上线:
amplify publish
将终端中生成的 URL 复制并粘贴到浏览器中进行查看。
您可能已经在 CLI 提示符中注意到,Amplify 还支持基于 Git 的部署。有关设置的更多信息,请参阅Amplify 文档。
回顾
在设置 AWS 服务时,使用 Amplify 可以处理很多繁重的工作,以便我们可以专注于实际的业务逻辑。
还要记住的是,Amplify 允许我们修改生成的 Cloudformation 模板,从而让我们拥有所部署的代码。
请务必关注本系列,或在 Twitter 上关注我,以便在本系列的下一期发布时收到通知:
发送带附件的电子邮件! 📧
到那时为止🤖
文章来源:https://dev.to/focusotter/serverless-contact-form-using-aws-amplify-1e9m