如何使用Lambda函数将nodemailer连接到Vue.js和Netlify应用程序

时间:2019-03-31 11:14:51

标签: javascript vue.js lambda nodemailer netlify

我在Netlify上拥有一个静态网站,该网站使用Vue.js构建,并且我特别需要捕获x-www-form-urlencoded从联系路线发送的数据。

因为它是水疗中心和动态呈现的表单,所以我在index.html中都添加了它(以预先呈现并允许Netlify在加载时查看表单)

public/index.htmlsrc/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的文件夹。我使用bestzip依赖项在package.json中自动执行此操作。

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创建的目录,npm install nodemailer运行prebuid时,它删除了当前的function-build并重新创建它,然后使用以下命令将这些函数压缩到目录中:这是依赖性。

这里是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函数),我收到了在网站上输入的属性。

在生产中,属性未定义。并且完整事件对象不会在函数中记录到控制台。

1 个答案:

答案 0 :(得分:1)

答案在于生产与开发中的事件参数。

解决方案:

// 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;
}