如何构建自己的无服务器联系表单
要求是什么?
导航到 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 指标,如
内存利用率、调用次数和执行持续时间。