如何在该控制器功能中包括该nodemailer功能?

时间:2019-10-03 09:36:37

标签: node.js mongodb express mongoose nodemailer

我正在尝试创建一个表单,该表单首先将数据发送到Mongo数据库,然后再通过Nodemailer的电子邮件发送该数据。这是两个功能:

控制器功能

exports.createListing = (req, res) => {
    // Validate request
    if(!req.body.content) {
        return res.status(400).send({
            message: "Fields can not be empty"
        });
    }

    const listing = new Listing({
        title: req.body.title, 
        city: req.body.city,
        street: req.body.street,
        businessname: req.body.businessname,
        description: req.body.description
    });

    listing.save()
    .then(data => {
        res.send(data);
    }).catch(err => {
        res.status(500).send({
            message: err.message || "Some error occurred while creating the listing."
        });
    });
};

NodeMailer功能

 var smtpTransport = nodemailer.createTransport({
        service: 'Gmail',
        port: 465,
        auth: {
          user: 'YOUR_GMAIL_SERVER',
          pass: 'YOUR_GMAIL_PASSWORD'
        }
      });

      var mailOptions = {
        to: data.email,
        subject: 'ENTER_YOUR_SUBJECT',
        html: `<p>${data.title}</p>
              <p>${data.city}</p>
              <p>${data.street}</p>`,
              ...
      };

      smtpTransport.sendMail(mailOptions,
        (error, response) => {
          if (error) {
            res.send(error)
          } else {
            res.send('Success')
          }
          smtpTransport.close();
        });

如何在上面的“创建清单”功能中包括该Nodemailer部分,以及如何在电子邮件正文中包括该已提交的数据。我认为电子邮件正文中的当前data.title和其他选项是错误的方式。

4 个答案:

答案 0 :(得分:1)

这里最简单的形式是将函数与回调(nodemailer一个)包装在Promise中:

exports.createListing = (req, res) => {
    // Validate request
    if(!req.body.content) {
        return res.status(400).send({
            message: "Fields can not be empty"
        });
    }

    // Set options after the request was verified.

    const smtpTransport = nodemailer.createTransport({
        service: 'Gmail',
        port: 465,
        auth: {
          user: 'YOUR_GMAIL_SERVER',
          pass: 'YOUR_GMAIL_PASSWORD'
        }
    });

    const listing = new Listing({
        title: req.body.title, 
        city: req.body.city,
        street: req.body.street,
        businessname: req.body.businessname,
        description: req.body.description
    });

    listing.save()
    .then(data => new Promise((resolve, reject) => {
      var mailOptions = {
        to: data.email,
        subject: 'ENTER_YOUR_SUBJECT',
        html: `<p>${data.title}</p>
              <p>${data.city}</p>
              <p>${data.street}</p>`,
              ...
      };

      smtpTransport.sendMail(mailOptions,
        (error, response) => {
          if (error) {
            reject(error);
          } else {
            resolve(data);
          }

        });

    })
    .then(data => {
      smtpTransport.close(); // this awaited the actual send
      res.send(data); 
    }
    .catch(err => {
        res.status(500).send({
            message: err.message || "Some error occurred while creating the listing."
        });
    });
};

请注意,此处的resolve(data)有效地将结果传递到Promise链中的下一个链接,这比在相同范围内嵌套Promise链只是为了访问相同的值要好。然后,当其中任何一种方法失败时,您还将获得catch()的单点。

也就是说,已经引起注意的是,当前的API实际上在没有回调的情况下调用时会返回Promise,但是您可能需要按顺序使用asyncawait语法使访问更干净:

exports.createListing = async (req, res) => { // <-- mark block as async
    // Validate request
    if(!req.body.content) {
        return res.status(400).send({
            message: "Fields can not be empty"
        });
    }

    // Set options after the request was verified.

    const smtpTransport = nodemailer.createTransport({
        service: 'Gmail',
        port: 465,
        auth: {
          user: 'YOUR_GMAIL_SERVER',
          pass: 'YOUR_GMAIL_PASSWORD'
        }
    });

    const listing = new Listing({
        title: req.body.title, 
        city: req.body.city,
        street: req.body.street,
        businessname: req.body.businessname,
        description: req.body.description
    });

    try {                                    // try..catch for error handling

      let data = await listing.save();       // await the save

      var mailOptions = {
        to: data.email,
        subject: 'ENTER_YOUR_SUBJECT',
        html: `<p>${data.title}</p>
              <p>${data.city}</p>
              <p>${data.street}</p>`,
              ...
      };

      await smtpTransport.sendMail(mailOptions);   // await the sendMail

      smtpTransport.close(); // this awaited the actual send
      res.send(data); 
    } catch(err) {
      res.status(500).send({
         essage: err.message || "Some error occurred while creating the listing."
    }
};

同样重要的是要注意,这种方法在执行中是 serial 。因此,除非正确保存数据,否则不会发送邮件。这可能是您的预期情况,也可能不是您的预期情况,但是仅创建包装Promise至少应遵循正确的方向。

答案 1 :(得分:0)

创建单独的mail.js或anyname.js

var config  = require('../config/config.js');
var nodemailer = require('nodemailer');

var smtpTransport = nodemailer.createTransport({
    service :"gmail",
    host: "smtp.gmail.com",
    auth :
    {
        user: config.email,
        pass: config.password
    }
});


// setup email data with unicode symbols
var mailOptions = {
    from: config.email,
    to: 'user to send',
    subject :'message',
    text :' "Hi",\n You have successfully created an account"',
    html: '<b>Welcome?</b>' // html body
};

// sends mail
module.exports.sendMail  = function()
{
 // send mail with defined transport object
 smtpTransport.sendMail(mailOptions, (error, info) => {
    if (error)
    {
        return console.log(error);
    }
    console.log('Message sent: %s', info.messageId);});
}

现在将此文件导入控制器js文件

var mailer = require('./mail.js');

并像下面一样使用它

mailer.sendMail()

您可以在sendMail函数中传递值或参数,并在mail.js文件中访问它们以创建自定义消息或标题或任何名称

答案 2 :(得分:0)

我建议围绕nodemailer创建一个包装器模块,因此您可以多次重用sendEmail函数。

为自己创建一个名为email-client.js的文件或任何您想要的文件。在此模块中,您可以在smtpTransport上创建一个闭包,而仅导出sendEmail函数。

电子邮件客户端

const nodemailer = require("nodemailer");

const smtpTransport = nodemailer.createTransport({
    service: "Gmail",
    port: 465,
    auth: {
        user: "YOUR_GMAIL_SERVER",
        pass: "YOUR_GMAIL_PASSWORD"
    }
});

async function sendMail({ to, subject, html }) {
    return smtpTransport.sendMail({ to, subject, html });
}

module.exports = {
    sendMail
};

注意:smtpTransport.sendMail返回一个Promise,我们将在您的控制器内部处理该Promise。

控制器

首先,您可以导入从sendEmail导出的email-client.js函数,然后可以在控制器中使用它。请注意,我已将控制器更改为async,并更喜欢猫鼬Model.create(使测试变得更容易了)。

const { sendEmail } = require("./email-client.js");

exports.createListing = async (req, res) => {
    try {
        if (!req.body.content) {
            return res.status(400).send({
                message: "Fields can not be empty"
            });
        }

        const listing = await Listing.create({
            title: req.body.title,
            city: req.body.city,
            street: req.body.street,
            businessname: req.body.businessname,
            description: req.body.description
        });

        await sendEmail({
            to: "blabla",
            subject: "blabla",
            html: `<p>${listing.title}</p>
        <p>${listing.city}</p>
        <p>${listing.street}</p>`
        });

        return res.send("Success");
    } catch (error) {
        return res.status(500).send({
            message:
                error.message ||
                "Some error occurred while creating the listing."
        });
    }
};

答案 3 :(得分:0)

导出sendMail方法并将其导入到控制器中。

控制器功能

let sendMail = require('your nodemailer file').sendMail;
exports.createListing = (req, res) => {
    // Validate request
    if(!req.body.content) {
        return res.status(400).send({
            message: "Fields can not be empty"
        });
    }

    const listing = new Listing({
        title: req.body.title, 
        city: req.body.city,
        street: req.body.street,
        businessname: req.body.businessname,
        description: req.body.description
    });

    listing.save()
    .then(data => {
        sendMail({
        title: req.body.title, 
        city: req.body.city,
        street: req.body.street})
        res.send(data);
    }).catch(err => {
        res.status(500).send({
            message: err.message || "Some error occurred while creating the listing."
        });
    });
};

NodeMailer功能

var smtpTransport = nodemailer.createTransport({
        service: 'Gmail',
        port: 465,
        auth: {
          user: 'YOUR_GMAIL_SERVER',
          pass: 'YOUR_GMAIL_PASSWORD'
        }
      });



module.exports.sendmail = (data)=>{
return new Promise((resolve,reject)=>{

      var mailOptions = {
        to: data.email,
        subject: 'ENTER_YOUR_SUBJECT',
        html: `<p>${data.title}</p>
              <p>${data.city}</p>
              <p>${data.street}</p>`,
              ...
      };





      smtpTransport.sendMail(mailOptions,
        (error, response) => {
          if (error) {
            reject(error);
          } else {
            resolve('Success');
          }
          smtpTransport.close();
        });
});
};