如何使用 Lambda 函数将 nodemailer 连接到 Vue.js 和 Netlify 应用程序
How to connect nodemailer to a Vue.js and Netlify app using Lambda Functions
我在 Netlify 上有一个用 Vue.js 构建的静态网站,我有一个特定的需要来捕获从联系路由发送的 x-www-form-urlencoded
数据。
因为它是一个 spa 和动态呈现的表单,所以我在 index.html 中添加了它(预呈现并允许 Netlify 在加载时查看表单)
public/index.html
& src/views/Contact.vue
<form
netlify-honeypot="bot-field"
name="contact"
data-netlify="true" hidden>
<input name="bot-field" />
<input type="text" name="name" />
<input type="email" name="email" />
<input type="text" name="subject" />
<textarea rows="5" name="message"></textarea>
</form>
联系人视图:
<form
netlify-honeypot="bot-field"
name="contact" method="post"
data-netlify="true"
@submit.prevent="handleSubmit">
<input type="hidden" name="form-name" value="contact" />
<p style="opacity: 0;">
<label>Don’t fill this out if you're human: <input name="bot-field" /></label>
</p>
<p>
<label>Your Name: <input v-model="form.name" type="text" name="name" /></label>
</p>
<p>
<label>Your Email: <input v-model="form.email" type="email" name="email" /></label>
</p>
<p>
<label>Your Subject: <input v-model="form.subject" type="text" name="subject" /></label>
</p>
<p>
<label>Message: <textarea v-model="form.message" rows="5" name="message"></textarea></label>
</p>
<p>
<button>Send</button>
</p>
</form>
对组件中的数据属性进行建模,POST关闭数据的方法如下:
export default {
name: 'contact',
data: () => ({
form: {
name: '',
email: '',
subject: '',
message: '',
},
}),
methods: {
encode (data) {
return Object.keys(data)
.map(
key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`,
)
.join('&');
},
handleSubmit () {
const axiosConfig = {
header: { 'Content-Type': 'application/x-www-form-urlencoded' },
};
axios.post(
'/',
this.encode({
'form-name': 'contact',
...this.form,
}),
axiosConfig,
)
.then(() => console.log('success'))
.catch(e => console.error(e));
},
},
};
系统的下一部分是 Netlify 的 lambda 函数 运行。每次应用程序收到表单提交时,Netlify 都允许 submission-created
函数。您所要做的就是在项目的根目录中创建一个目录,其中包含 submission-created.js
文件。此目录需要在 netlify.toml 中指定,以便 Netlify 知道在哪里寻找您的函数。
另一个需要注意的是,如果您的函数需要依赖项,则需要将包含 node_modules 的文件夹压缩。我在 package.json 中使用 bestzip
依赖项自动执行此操作。
package.json
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"zip": "cd functions/submission-created && bestzip ../../functions-build/submission-created.zip *",
"clean": "rm -rf functions-build && mkdir functions-build",
"prebuild": "npm run clean && npm run zip"
}
如您所见,我处理这个问题的方法是在 functions/submission-created/submission-created.js
中编写函数的源代码我还有一个 functions-build
目录,它是 netlify.toml 中指定的目录,其中将包含压缩的提交创建文件夹。
基本上,我 npm init -y
functions/submission-created 目录和 npm install nodemailer
,当预置 运行s 时,它会删除当前的函数构建并重新创建它,然后将函数及其依赖项压缩到目录中。
这是netlify.toml
[build]
functions = "./functions-build"
最后,重要代码所在的是 submission-created.js
文件:
exports.handler = function(event, context, callback) {
const nodemailer = require('nodemailer');
const querystring = require('querystring');
const payload = querystring.parse(event.body);
const { name, email, subject, message } = payload;
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "xxx",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'xxx', // generated ethereal user
pass: 'xxx' // generated ethereal password
},
tls: {
rejectUnauthorized: false,
},
});
// setup email data with unicode symbols
let mailOptions = {
from: `"website enquiry " <${email}>`, // sender address
to: "admin@xxx.xx, enquiry@xxx.xx", // list of receivers
subject: `${subject} ✔`, // Subject line
text: `name: ${name}, \n email: ${email}, \n message: ${message}\n`, // plain text body
};
// send mail with defined transport object
transporter.sendMail(mailOptions)
.then(() => {
callback(null, { statusCode: 200, body: 'Success' });
})
.catch(e => callback(e, { statusCode: 500, body: 'Error sending email' }));
};
主要问题
该表格记录在 Netlify 上的提交中。问题出在函数上:
正在开发中(使用 netlify-lambda
在本地托管 lambda 函数)我收到了网站上输入的属性。
在生产中,属性未定义。并且完整的事件对象不会在函数中记录到控制台。
答案在于生产与开发中的事件参数。
修复:
// How to get post parameters in production
exports.handler = function(event, context, callback) {
const payload = JSON.parse(event.body).payload;
const { name, email, subject, message } = payload;
}
我在 Netlify 上有一个用 Vue.js 构建的静态网站,我有一个特定的需要来捕获从联系路由发送的 x-www-form-urlencoded
数据。
因为它是一个 spa 和动态呈现的表单,所以我在 index.html 中添加了它(预呈现并允许 Netlify 在加载时查看表单)
public/index.html
& src/views/Contact.vue
<form
netlify-honeypot="bot-field"
name="contact"
data-netlify="true" hidden>
<input name="bot-field" />
<input type="text" name="name" />
<input type="email" name="email" />
<input type="text" name="subject" />
<textarea rows="5" name="message"></textarea>
</form>
联系人视图:
<form
netlify-honeypot="bot-field"
name="contact" method="post"
data-netlify="true"
@submit.prevent="handleSubmit">
<input type="hidden" name="form-name" value="contact" />
<p style="opacity: 0;">
<label>Don’t fill this out if you're human: <input name="bot-field" /></label>
</p>
<p>
<label>Your Name: <input v-model="form.name" type="text" name="name" /></label>
</p>
<p>
<label>Your Email: <input v-model="form.email" type="email" name="email" /></label>
</p>
<p>
<label>Your Subject: <input v-model="form.subject" type="text" name="subject" /></label>
</p>
<p>
<label>Message: <textarea v-model="form.message" rows="5" name="message"></textarea></label>
</p>
<p>
<button>Send</button>
</p>
</form>
对组件中的数据属性进行建模,POST关闭数据的方法如下:
export default {
name: 'contact',
data: () => ({
form: {
name: '',
email: '',
subject: '',
message: '',
},
}),
methods: {
encode (data) {
return Object.keys(data)
.map(
key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`,
)
.join('&');
},
handleSubmit () {
const axiosConfig = {
header: { 'Content-Type': 'application/x-www-form-urlencoded' },
};
axios.post(
'/',
this.encode({
'form-name': 'contact',
...this.form,
}),
axiosConfig,
)
.then(() => console.log('success'))
.catch(e => console.error(e));
},
},
};
系统的下一部分是 Netlify 的 lambda 函数 运行。每次应用程序收到表单提交时,Netlify 都允许 submission-created
函数。您所要做的就是在项目的根目录中创建一个目录,其中包含 submission-created.js
文件。此目录需要在 netlify.toml 中指定,以便 Netlify 知道在哪里寻找您的函数。
另一个需要注意的是,如果您的函数需要依赖项,则需要将包含 node_modules 的文件夹压缩。我在 package.json 中使用 bestzip
依赖项自动执行此操作。
package.json
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"zip": "cd functions/submission-created && bestzip ../../functions-build/submission-created.zip *",
"clean": "rm -rf functions-build && mkdir functions-build",
"prebuild": "npm run clean && npm run zip"
}
如您所见,我处理这个问题的方法是在 functions/submission-created/submission-created.js
中编写函数的源代码我还有一个 functions-build
目录,它是 netlify.toml 中指定的目录,其中将包含压缩的提交创建文件夹。
基本上,我 npm init -y
functions/submission-created 目录和 npm install nodemailer
,当预置 运行s 时,它会删除当前的函数构建并重新创建它,然后将函数及其依赖项压缩到目录中。
这是netlify.toml
[build]
functions = "./functions-build"
最后,重要代码所在的是 submission-created.js
文件:
exports.handler = function(event, context, callback) {
const nodemailer = require('nodemailer');
const querystring = require('querystring');
const payload = querystring.parse(event.body);
const { name, email, subject, message } = payload;
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "xxx",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'xxx', // generated ethereal user
pass: 'xxx' // generated ethereal password
},
tls: {
rejectUnauthorized: false,
},
});
// setup email data with unicode symbols
let mailOptions = {
from: `"website enquiry " <${email}>`, // sender address
to: "admin@xxx.xx, enquiry@xxx.xx", // list of receivers
subject: `${subject} ✔`, // Subject line
text: `name: ${name}, \n email: ${email}, \n message: ${message}\n`, // plain text body
};
// send mail with defined transport object
transporter.sendMail(mailOptions)
.then(() => {
callback(null, { statusCode: 200, body: 'Success' });
})
.catch(e => callback(e, { statusCode: 500, body: 'Error sending email' }));
};
主要问题
该表格记录在 Netlify 上的提交中。问题出在函数上:
正在开发中(使用 netlify-lambda
在本地托管 lambda 函数)我收到了网站上输入的属性。
在生产中,属性未定义。并且完整的事件对象不会在函数中记录到控制台。
答案在于生产与开发中的事件参数。
修复:
// How to get post parameters in production
exports.handler = function(event, context, callback) {
const payload = JSON.parse(event.body).payload;
const { name, email, subject, message } = payload;
}