I am trying to create a form that will send data to the Mongo DB first then will send that data through the email by Nodemailer. Here are the 2 functions:
controller function
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 functon
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();
});
How can I include this Nodemailer part inside the above create listing function also how can I include that submited data inside email body. I assume current data.title and other options inside email body are wrong way.
Export your sendMail method and import it in your controller.
controller function
NodeMailer function
I would suggest creating a wrapper module around nodemailer, therefore you could reuse the
sendEmail
function multiple times.Make yourself a file called
email-client.js
or whatever you want. In this module, you can create a closure oversmtpTransport
and only export thesendEmail
function.email-client
Note:
smtpTransport.sendMail
returns a Promise, that we will deal with inside your controller.controller
First, you could import the
sendEmail
function that's exported fromemail-client.js
, then you can use this in your controller. Note ive changed the controller to be async & prefer mongoose Model.create (makes testing a little easier).Create separate mail.js or anyname.js
now import this file in controller js file
and use it like below
you can pass values or params inside sendMail function and access them in mail.js file to create custom message or title or name any
The most simple form here would be to just wrap the function with the callback ( the nodemailer one ) in a Promise:
Note that the
resolve(data)
here is effectively passing through the result to the next link in the Promise chain, which is better than nesting promise chains in the same scope just to have access to the same value. Then you also have the single point forcatch()
when either of methods fail.That said, it has been brought to attention the current API actually would return a
Promise
when invoked without a callback, but then you would probably wantasync
andawait
syntax in order to make access to things cleaner:It is also important to note that this approach is serial in execution. So here the mail is not sent unless the data is correctly saved. This may or may not be your intended case, but simply creating the wrapping Promise should at least the right direction to follow.