如何构建自己的无服务器联系表单
要求是什么?
导航到 handler.js 文件
前端设置
JavaScript
最终输出
为什么选择 Dashbird?
DashBird 界面
静态网站使用 HTML、CSS 和 JavaScript 开发。
您无需设置任何数据库或服务器。GitHub 和 Netlify 为静态网站提供免费托管服务,只需在网站上添加联系表单即可。即使没有用户访问您的网站,您也需要支付服务器费用。使用无服务器 AWS,只有当有人访问您的网页时才会向您收费,如果没有流量,则无需付费。
在本文中,您将了解如何使用 SES(简单电子邮件服务)、Aws Lambda 和无服务器框架构建无服务器联系表单。
要求是什么?
- AWS 账户
- Node.js
- 无服务器框架 cli。
- DashBird 账户
让我们构建一个无服务器联系表单
首先我们需要安装 Serverless Framework cli。
打开终端并运行以下命令。
npm install -g serverless
sls login // SLS is a shortcut of serverless
sls 登录后,您需要使用无服务器框架配置您的 Aws 凭证。
在您的电脑中创建一个新目录。
mkdir contactform
cd contactfrom
Serverless 为我们提供了不同类型的模板,但我们使用 Nodejs 作为后端,因此我们正在创建 nodejs 模板。
serverless create --template aws-nodejs
上述命令生成样板。
现在我们需要初始化Package.json文件并安装一些依赖项。
npm init -y // generates package.json file
npm i -s body-parser cors express serverless-http aws-sdk
现在在您最喜欢的代码编辑器中打开联系表单文件夹。
导航到 handler.js 文件
清除 handler.js 中的所有内容,因为我们是从头开始编写的。
| const serverless = require("serverless-http"); | |
| const AWS = require("aws-sdk"); | |
| const express = require("express"); | |
| const cors = require("cors"); | |
| const bodyParser = require("body-parser"); | |
| const app = express(); | |
| if (!AWS.config.region) { | |
| AWS.config.update({ | |
| region: "add your region" //example us-east-1 | |
| }); | |
| } | |
| const ses = new AWS.SES(); | |
| app.use(cors()); | |
| // parse application/x-www-form-urlencoded | |
| app.use(bodyParser.urlencoded({ extended: false })); | |
| // parse application/json | |
| app.use(bodyParser.json()); | |
| app.post("/", (req, res) => { | |
| const name = req.body.name; | |
| const email = req.body.email; | |
| const message = req.body.message; | |
| }); | |
| module.exports.form = serverless(app); |
| const serverless = require("serverless-http"); | |
| const AWS = require("aws-sdk"); | |
| const express = require("express"); | |
| const cors = require("cors"); | |
| const bodyParser = require("body-parser"); | |
| const app = express(); | |
| if (!AWS.config.region) { | |
| AWS.config.update({ | |
| region: "add your region" //example us-east-1 | |
| }); | |
| } | |
| const ses = new AWS.SES(); | |
| app.use(cors()); | |
| // parse application/x-www-form-urlencoded | |
| app.use(bodyParser.urlencoded({ extended: false })); | |
| // parse application/json | |
| app.use(bodyParser.json()); | |
| app.post("/", (req, res) => { | |
| const name = req.body.name; | |
| const email = req.body.email; | |
| const message = req.body.message; | |
| }); | |
| module.exports.form = serverless(app); |
。
我们在第 15 行调用了 SES 构造函数和一个端点。如果您想了解如何使用 Express Checkout 创建无服务器端点,请参阅我的文章《使用无服务器、Express 和 Nodejs 构建和部署 Rest API》。
我们需要在post方法中调用ses.sendEmail(params,function(err,data){})方法。
参数
来源 — (字符串):
发送电子邮件的电子邮件地址。此电子邮件地址必须通过 Amazon SES 单独验证。
验证您的电子邮件地址
- 打开您的 Aws 控制台并在搜索栏中输入 ses
- 点击简单电子邮件服务。
- 打开后,在左侧边栏中单击电子邮件地址,添加您的电子邮件地址。
- 您将收到一封验证电子邮件。
目的地:
此电子邮件的目的地,由收件人、抄送和密送字段组成。
ToAddresses — 电子邮件地址数组。CcAddresses
— 电子邮件地址数组。BccAddresses
— 电子邮件地址数组。
信息:
主题[对象]:
邮件的主题:内容的简短摘要,将出现在收件人的收件箱中。
数据(字符串):表单的内容。
| const emailParams = { | |
| Source: "yourname@mail.com", // Your Verified Email | |
| Destination: { | |
| ToAddresses: ["yourname@mail.com"] // Your verfied Email | |
| }, | |
| ReplyToAddresses: [req.body.email], | |
| Message: { | |
| Body: { | |
| Text: { | |
| Charset: "UTF-8", | |
| Data: `${message} from ${req.body.email}` | |
| } | |
| }, | |
| Subject: { | |
| Charset: "UTF-8", | |
| Data: "You Received a Message from www.domainname.com" | |
| } | |
| } | |
| }; |
| const emailParams = { | |
| Source: "yourname@mail.com", // Your Verified Email | |
| Destination: { | |
| ToAddresses: ["yourname@mail.com"] // Your verfied Email | |
| }, | |
| ReplyToAddresses: [req.body.email], | |
| Message: { | |
| Body: { | |
| Text: { | |
| Charset: "UTF-8", | |
| Data: `${message} from ${req.body.email}` | |
| } | |
| }, | |
| Subject: { | |
| Charset: "UTF-8", | |
| Data: "You Received a Message from www.domainname.com" | |
| } | |
| } | |
| }; |
我们需要将这些 params 对象传递给 ses.sendEmail 方法。
更新了 handler.js 文件
| const serverless = require("serverless-http"); | |
| const AWS = require("aws-sdk"); | |
| const express = require("express"); | |
| const cors = require("cors"); | |
| const bodyParser = require("body-parser"); | |
| const app = express(); | |
| if (!AWS.config.region) { | |
| AWS.config.update({ | |
| region: "us-east-1" | |
| }); | |
| } | |
| const ses = new AWS.SES(); | |
| app.use(cors()); | |
| app.use(bodyParser.urlencoded({ extended: false })); | |
| app.use(bodyParser.json()); | |
| app.post("/", (req, res) => { | |
| const name = req.body.name; | |
| const email = req.body.email; | |
| const message = req.body.message; | |
| const emailParams = { | |
| Source: "yourname@mail.com", // Your Verified Email | |
| Destination: { | |
| ToAddresses: ["yourname@mail.com"] // Your verfied Email | |
| }, | |
| ReplyToAddresses: [req.body.email], | |
| Message: { | |
| Body: { | |
| Text: { | |
| Charset: "UTF-8", | |
| Data: `${message} from ${req.body.email}` | |
| } | |
| }, | |
| Subject: { | |
| Charset: "UTF-8", | |
| Data: "You Received a Message from www.domainname.com" | |
| } | |
| } | |
| }; | |
| ses.sendEmail(emailParams, (err, data) => { | |
| if (err) { | |
| res.status(402).send(`${err} ${err.stack}`); | |
| } | |
| if (data) { | |
| res.send(data); | |
| } | |
| }); | |
| }); | |
| module.exports.form = serverless(app); |
| const serverless = require("serverless-http"); | |
| const AWS = require("aws-sdk"); | |
| const express = require("express"); | |
| const cors = require("cors"); | |
| const bodyParser = require("body-parser"); | |
| const app = express(); | |
| if (!AWS.config.region) { | |
| AWS.config.update({ | |
| region: "us-east-1" | |
| }); | |
| } | |
| const ses = new AWS.SES(); | |
| app.use(cors()); | |
| app.use(bodyParser.urlencoded({ extended: false })); | |
| app.use(bodyParser.json()); | |
| app.post("/", (req, res) => { | |
| const name = req.body.name; | |
| const email = req.body.email; | |
| const message = req.body.message; | |
| const emailParams = { | |
| Source: "yourname@mail.com", // Your Verified Email | |
| Destination: { | |
| ToAddresses: ["yourname@mail.com"] // Your verfied Email | |
| }, | |
| ReplyToAddresses: [req.body.email], | |
| Message: { | |
| Body: { | |
| Text: { | |
| Charset: "UTF-8", | |
| Data: `${message} from ${req.body.email}` | |
| } | |
| }, | |
| Subject: { | |
| Charset: "UTF-8", | |
| Data: "You Received a Message from www.domainname.com" | |
| } | |
| } | |
| }; | |
| ses.sendEmail(emailParams, (err, data) => { | |
| if (err) { | |
| res.status(402).send(`${err} ${err.stack}`); | |
| } | |
| if (data) { | |
| res.send(data); | |
| } | |
| }); | |
| }); | |
| module.exports.form = serverless(app); |
打开您的 serverless.yml 文件并使用以下代码进行更新。
| service: contact-form | |
| provider: | |
| name: aws | |
| runtime: nodejs8.10 | |
| region: us-east-1 | |
| iamRoleStatements: | |
| - Effect: "Allow" | |
| Action: | |
| - "ses:SendEmail" | |
| Resource: "*" | |
| functions: | |
| app: | |
| handler: handler.form | |
| events: | |
| - http: ANY / | |
| - http: 'ANY {proxy+}' | |
| service: contact-form | |
| provider: | |
| name: aws | |
| runtime: nodejs8.10 | |
| region: us-east-1 | |
| iamRoleStatements: | |
| - Effect: "Allow" | |
| Action: | |
| - "ses:SendEmail" | |
| Resource: "*" | |
| functions: | |
| app: | |
| handler: handler.form | |
| events: | |
| - http: ANY / | |
| - http: 'ANY {proxy+}' | |
现在打开终端并运行 sls deploy 命令,即可在 AWS 中部署代码。运行该命令一段时间后,您的 API 端点就会显示在终端中。
前端设置
HTML标记
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name= "viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
| <title>Contact us</title> | |
| <link rel="stylesheet" href="style.css"> | |
| </head> | |
| <body> | |
| <div class="all"> | |
| <form action="" class="items"> | |
| <h1>Contact Us</h1> | |
| <div class="error-items"> | |
| <p style="color:red" class="error"></p> | |
| </div> | |
| <div> | |
| <label for="name">Name</label> | |
| <input type="text" id="name" required placeholder="Enter Your Name" class="name" /> | |
| </div> | |
| <div> | |
| <label for="email">Email</label> | |
| <input type="email" required placeholder="Your Email" id="email" class="normal" /> | |
| </div> | |
| <div class="area"> | |
| <label for="message" class="area-label">Message</label> | |
| <textarea type="text" placeholder="Message" required id="message" class="txt"></textarea> | |
| </div> | |
| <button>Send</button> | |
| </form> | |
| </div> | |
| <p class="success"></p> | |
| <script src="./script.js"></script> | |
| </body> | |
| </html> |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name= "viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
| <title>Contact us</title> | |
| <link rel="stylesheet" href="style.css"> | |
| </head> | |
| <body> | |
| <div class="all"> | |
| <form action="" class="items"> | |
| <h1>Contact Us</h1> | |
| <div class="error-items"> | |
| <p style="color:red" class="error"></p> | |
| </div> | |
| <div> | |
| <label for="name">Name</label> | |
| <input type="text" id="name" required placeholder="Enter Your Name" class="name" /> | |
| </div> | |
| <div> | |
| <label for="email">Email</label> | |
| <input type="email" required placeholder="Your Email" id="email" class="normal" /> | |
| </div> | |
| <div class="area"> | |
| <label for="message" class="area-label">Message</label> | |
| <textarea type="text" placeholder="Message" required id="message" class="txt"></textarea> | |
| </div> | |
| <button>Send</button> | |
| </form> | |
| </div> | |
| <p class="success"></p> | |
| <script src="./script.js"></script> | |
| </body> | |
| </html> |
CSS
| *{ | |
| box-sizing: border-box; | |
| padding: 0; | |
| margin: 0 | |
| } | |
| body{ | |
| font-family: sans-serif; | |
| } | |
| .items{ | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| margin: 2rem; | |
| font-size: 1.1rem; | |
| padding: 1rem; | |
| } | |
| input{ | |
| padding: 1rem; | |
| margin: .8rem; | |
| width: 25rem; | |
| height: 3rem; | |
| font-size: 1.1rem; | |
| border: 3px solid rgb(31, 121, 255); | |
| outline: none; | |
| } | |
| textarea{ | |
| width: 25rem; | |
| height: 10rem; | |
| padding: 1rem; | |
| display: flex; | |
| justify-content: center; | |
| outline: none; | |
| border: 3px solid rgb(31, 121, 255); | |
| font-size: 1.1rem; | |
| } | |
| .area{ | |
| display: flex; | |
| } | |
| .area-label{ | |
| margin-left:-2rem; | |
| } | |
| .txt{ | |
| margin-left:.6rem; | |
| } | |
| button{ | |
| padding: 1rem; | |
| width: 10rem; | |
| margin-top: 2rem; | |
| text-align: center; | |
| background-color: rgb(75, 224, 75); | |
| font-size: 1.3rem; | |
| color: rgb(2, 2, 15); | |
| box-shadow: 0 .2rem .2rem black; | |
| } | |
| .success{ | |
| background-color: rgb(75, 214, 224); | |
| font-size: 1.2rem; | |
| text-transform: capitalize; | |
| text-align: center; | |
| margin-top: 10rem; | |
| padding: 2rem; | |
| box-shadow: 0 .2rem .2rem rgb(0, 0, 0); | |
| display: none; | |
| } | |
| .error{ | |
| display: none; | |
| animation: move .2s ease-in ; | |
| } | |
| @keyframes move{ | |
| 0%{ | |
| opacity: 0; | |
| transform: translateY(-80%); | |
| } | |
| 50%{ | |
| opacity: .6; | |
| transform: translate(-20%); | |
| } | |
| 70%{ | |
| opacity: .7; | |
| transform: translate(20%); | |
| } | |
| 100%{ | |
| opacity: 1; | |
| transform: translate(0); | |
| } | |
| } |
| *{ | |
| box-sizing: border-box; | |
| padding: 0; | |
| margin: 0 | |
| } | |
| body{ | |
| font-family: sans-serif; | |
| } | |
| .items{ | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| margin: 2rem; | |
| font-size: 1.1rem; | |
| padding: 1rem; | |
| } | |
| input{ | |
| padding: 1rem; | |
| margin: .8rem; | |
| width: 25rem; | |
| height: 3rem; | |
| font-size: 1.1rem; | |
| border: 3px solid rgb(31, 121, 255); | |
| outline: none; | |
| } | |
| textarea{ | |
| width: 25rem; | |
| height: 10rem; | |
| padding: 1rem; | |
| display: flex; | |
| justify-content: center; | |
| outline: none; | |
| border: 3px solid rgb(31, 121, 255); | |
| font-size: 1.1rem; | |
| } | |
| .area{ | |
| display: flex; | |
| } | |
| .area-label{ | |
| margin-left:-2rem; | |
| } | |
| .txt{ | |
| margin-left:.6rem; | |
| } | |
| button{ | |
| padding: 1rem; | |
| width: 10rem; | |
| margin-top: 2rem; | |
| text-align: center; | |
| background-color: rgb(75, 224, 75); | |
| font-size: 1.3rem; | |
| color: rgb(2, 2, 15); | |
| box-shadow: 0 .2rem .2rem black; | |
| } | |
| .success{ | |
| background-color: rgb(75, 214, 224); | |
| font-size: 1.2rem; | |
| text-transform: capitalize; | |
| text-align: center; | |
| margin-top: 10rem; | |
| padding: 2rem; | |
| box-shadow: 0 .2rem .2rem rgb(0, 0, 0); | |
| display: none; | |
| } | |
| .error{ | |
| display: none; | |
| animation: move .2s ease-in ; | |
| } | |
| @keyframes move{ | |
| 0%{ | |
| opacity: 0; | |
| transform: translateY(-80%); | |
| } | |
| 50%{ | |
| opacity: .6; | |
| transform: translate(-20%); | |
| } | |
| 70%{ | |
| opacity: .7; | |
| transform: translate(20%); | |
| } | |
| 100%{ | |
| opacity: 1; | |
| transform: translate(0); | |
| } | |
| } |
JavaScript
- 我们需要向端点发出 ajax 请求。
| let name = document.querySelector("#name"); | |
| let email = document.querySelector("#email"); | |
| let message = document.querySelector("#message"); | |
| let error = document.querySelector(".error"); | |
| let btn = document.querySelector("button"); | |
| let success = document.querySelector(".success"); | |
| btn.addEventListener("click", submit); | |
| function submit(e) { | |
| e.preventDefault(); | |
| var xhr = new XMLHttpRequest(); | |
| xhr.open("POST", "yourendpoint", true); | |
| xhr.setRequestHeader("Content-type", "application/json"); | |
| xhr.onreadystatechange = function() { | |
| if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) { | |
| } | |
| }; | |
| var data = { | |
| name: name.value, | |
| email: email.value, | |
| message: message.value | |
| }; | |
| if (name.value && email.value && message.value) { | |
| success.style.display = "block"; | |
| success.innerHTML = "Thanks for submitting"; | |
| document.querySelector(".all").style.display = "none"; | |
| xhr.send(JSON.stringify(data)); | |
| } else { | |
| error.style.display = "block"; | |
| error.innerHTML = "Please Fill All Details"; | |
| } | |
| } |
| let name = document.querySelector("#name"); | |
| let email = document.querySelector("#email"); | |
| let message = document.querySelector("#message"); | |
| let error = document.querySelector(".error"); | |
| let btn = document.querySelector("button"); | |
| let success = document.querySelector(".success"); | |
| btn.addEventListener("click", submit); | |
| function submit(e) { | |
| e.preventDefault(); | |
| var xhr = new XMLHttpRequest(); | |
| xhr.open("POST", "yourendpoint", true); | |
| xhr.setRequestHeader("Content-type", "application/json"); | |
| xhr.onreadystatechange = function() { | |
| if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) { | |
| } | |
| }; | |
| var data = { | |
| name: name.value, | |
| email: email.value, | |
| message: message.value | |
| }; | |
| if (name.value && email.value && message.value) { | |
| success.style.display = "block"; | |
| success.innerHTML = "Thanks for submitting"; | |
| document.querySelector(".all").style.display = "none"; | |
| xhr.send(JSON.stringify(data)); | |
| } else { | |
| error.style.display = "block"; | |
| error.innerHTML = "Please Fill All Details"; | |
| } | |
| } |
最终输出
为了监控、调试和检测 lambda 的错误,我们使用Dashbird
为什么选择 Dashbird?
-
Dashbird 帮助我们主动监控健康和错误。
-
Dashbird 的一个主要特点是其用户友好的界面。
-
Dashbird 可视化您的所有 AWS Lambda 指标,如
内存利用率、调用次数和执行持续时间。
后端开发教程 - Java、Spring Boot 实战 - msg200.com










