how to send mail notification in node.js from getting response - node.js

I want to send the response through mail in table format.
In mail options html I declare the res.json(streamingTemplate)== and the following error is returned:
Unhandled rejection Error: Can't set headers after they are sent. at
ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11) at
ServerResponse.header
like that i got...
var sendStreamingTemplate = function (req, res) {
authToken = req.headers.authorization;
userAuthObj = JSON.parse(UserAuthServices.userAuthTokenValidator(authToken));
var todayDate = new Date();
var expireDate = new Date(userAuthObj.expire_date);
tokenOK = TokenValidator.validateToken(userAuthObj.user_id, authToken).then(function (userSessions) {
if (userSessions.length === 1) {
if (expireDate >= todayDate) {
StreamingTemplateId = req.params.id;
TemplateController.findById(StreamingTemplateId).then(function (streamingTemplate) {
if (streamingTemplate === null) {
res.status(404).json({
message: 'Streaming not found...'
})
} else {
console.log(streamingTemplate);
let transporter = nodemailer.createTransport({
host: 'smtp.zoho.com',
port: 465,
auth: true,
active: true,
secure: true,
requireTLS: true,
auth: {
user: 'aaaaaaa#domain.com',
pass: 'yyyyyyyy'
}
});
let mailOptions = {
from: 'aaaaaaa#domain.com',
to: 'bbbbbbbbb#domain.com',
subject: 'mail notification Test',
text: 'Hello !!!!!!!!!everything works fine',
html:res.json(streamingTemplate)// i want to send whatever response get i will send to through mail in table format
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log("mail not sent" +error.message);
}
console.log('success');
});
switch(streamingTemplate.template_name.toString().toLowerCase()){
case "stream":
res.json(streamingTemplate);
break;
case "broadcaster":
res.json(streamingTemplate);
break;
case "product":
res.json(streamingTemplate);
break;
default:
res.json(streamingTemplate);
break;
}
}
}).catch(function (err) {
res.status(500).json({
message: 'something went wrong...'
});
});
} else {
res.status(401).json({
message: 'Not Authorized...'
});
}
} else {
res.status(401).json({
message: 'Token Expired...'
});
}
}).catch(function (err) {
res.status(401).json({
message: 'Token Expired...'
});
});
};

The res.json() method is a terminal method, which ends the response writing the json specified in it. Therefore, while configuring the mailOptions, it should not be used.
let mailOptions = {
from: 'aaaaaaa#domain.com',
to: 'bbbbbbbbb#domain.com',
subject: 'mail notification Test',
text: 'Hello !!!!!!!!!everything works fine',
html: res.json(streamingTemplate) // Response should not be sent here
};
Instead, the streamingTemplate should be passed to the html argument of mailOptions.
let mailOptions = {
from: 'aaaaaaa#domain.com',
to: 'bbbbbbbbb#domain.com',
subject: 'mail notification Test',
text: 'Hello !!!!!!!!!everything works fine',
html: streamingTemplate // set the template here
};

Related

Sending an email to a user after submitting an enquiry

I'm trying to find a way to set up a contact us form, when a user is submitting an enquiry I should receive an email, also the user should receive an email telling that the enquiry reached us, I figured out that I should use nodemailer to send mails, now the first step is done which I receive an email whenever the user submitted an enquiry, the question is how can I send him an email after submitting the enquiry? excuse my bad English
Nodemailer setup
//email from the contact form using the nodemailer
router.post('/send', async(req, res) => {
console.log(req.body);
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USERNAME, //email resposible for sending message
pass: process.env.EMAIL_PASSWORD
}
});
const mailoptions = {
from: process.env.FROM_EMAIL,
to: process.env.EMAIL_USERNAME, //email that recives the message
subject: 'New Enquiry',
html: `<html><body><p>Name: ${req.body.name}</p><p> Email: ${req.body.email}</p><p>message: ${req.body.content}</p></body></html>`
}
transporter.sendMail(mailoptions, (err, info) => {
if (err) {
console.log('error');
res.send('message not sent'); //when its not ent
} else {
console.log('message sent' + info.response);
res.send('sent'); //when sent
}
})
});
module.exports = router;
So I tried some codes and code worked for me, it's sending to the admin and the client, hope it helps
router.post('/send', async(req, res, next) => {
console.log(req.body);
if (!req.body.name) {
return next(createError(400, "ERROR MESSAGE HERE"));
} else if (!req.body.email) {
return next(createError(400, "ERROR MESSAGE HERE"));
} else if (!req.body.email || !isEmail(req.body.email)) {
return next(createError(400, "ERROR MESSAGE HERE"));
} else if (!req.body.content) {
return next(createError(400, "ERROR MESSAGE HERE"));
}
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USERNAME, //email resposible for sending message
pass: process.env.EMAIL_PASSWORD
}
});
const mailOptionsAdmin = {
from: process.env.FROM_EMAIL,
to: process.env.EMAIL_USERNAME, //email that recives the message
subject: 'New Enquiry',
html: `<html><body><p>Name: ${req.body.name}</p><p> Email: ${req.body.email}</p><p>message: ${req.body.content}</p></body></html>`
}
const mailOptionsClient = {
from: process.env.FROM_EMAIL,
to: req.body.email, //email that recives the message
subject: 'Recivied',
html: `<html><body><p>message: We recived your enquiry</p></body></html>`
}
transporter.sendMail(mailOptionsAdmin, (err, info) => {
if (err) {
console.log('error');
res.send('message not sent'); //when its not ent
} else {
console.log('message sent' + info.response);
res.send('sent'); //when sent
transporter.sendMail(mailOptionsClient)
}
})
});

Nodemailer sending emails but getting ERR_HTTP_HEADERS_SENT

I don't why i'm getting this every time I try to use Nodemailer to send emails:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
to the client
at new NodeError (node:internal/errors:371:5)
at ServerResponse.setHeader (node:_http_outgoing:576:11)
the thing is it's working but i'm getting this error, by working I mean It sends the email.
The Code:
const sendEmail = async (email, subject, payload, template) => {
try {
// create reusable transporter object using the default SMTP transport
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USERNAME,
pass: process.env.EMAIL_PASSWORD,
},
});
const options = () => {
return {
from: process.env.FROM_EMAIL,
to: email,
subject: subject,
html: template,
};
};
// Send email
transporter.sendMail(options(), (error, info) => {
if (error) {
return error;
} else {
return res.status(200).json({
success: true,
});
}
});
} catch (error) {
throw error;
}
};
router.post("/", async (req, res, next) => {
try {
if (!req.body.newsletterEmail) {
return next(createError(400, "Please enter your email"));
} else if (!req.body.newsletterEmail || !isEmail(req.body.newsletterEmail)) {
return next(createError(400, "Please enter a valid email address"));
}
const checkEmail = await SubscribedEmails.findOne({ newsletterEmail: req.body.newsletterEmail });
if (checkEmail) {
return next(createError(400, "Email is already subscribed"));
} else {
//create new user
const newSubscribedEmail = new SubscribedEmails ({
newsletterEmail: req.body.newsletterEmail,
});
//save user and respond
const SubscribedEmail = await newSubscribedEmail.save();
res.status(200).json({
message: "Successfully subscribed",
SubscribedEmail,
});
const link = `${process.env.CLIENT_URL}/`;
await sendEmail(
SubscribedEmail.newsletterEmail,
"Welcome to our newsletter!",
{
link: link,
},
`<div> <p>Hi,</p> <p>You are subscribed to our.</p> <p> Please click the link below to view more</p> <a href=${link}>GO</a> </div>`
);
return res.status(200).send(link);
}
} catch(err) {
next(err);
}
});
This is likely due to some quirks with using Gmail with Nodemailer. Review the docs here - https://nodemailer.com/usage/using-gmail/
and configure your Gmail account here -
https://myaccount.google.com/lesssecureapps
Finally, you may run into issues with Captcha. Configure here - https://accounts.google.com/DisplayUnlockCaptcha

Node.js + Express

I was creating a contact form using nodemailer. I implemented it and it was working fine, but some time later I came back to do a final test in postman it started to give me the following error"message": Not Found - /contact and "stack": "Error: Not Found - /contact\n . I am not sure what's causing the error.
this is code:
const transport = {
host: 'smtp.gmail.com', // Don’t forget to replace with the SMTP host of your provider
port: 587,
secure: false, // use SSL
auth: {
user: process.env.GMAIL,
pass: process.env.PASSWORD
}
}
const transporter = nodemailer.createTransport(transport)
transporter.verify((error, success) => {
if (error) {
console.log(error);
} else {
console.log('Server is ready to take messages');
}
});
app.post('/contact', (req, res, next) => {
const name = req.body.name
const email = req.body.email
const message = req.body.message
const content = ` name: ${name} \n email: ${email} \n message: ${message} `
const mail = {
from: name,
// to: 'RECEIVING_EMAIL_ADDRESS_GOES_HERE', // Change to email address that you want to receive messages on
to: 'xxx#gmail.com', // Change to email address that you want to receive messages on
subject: 'New Message from Contact Form',
text: content
}
transporter.sendMail(mail, (err, data) => {
if (err) {
res.json({
status: 'fail'
})
} else {
res.json({
status: 'success'
})
}
})
})

nodemailer sendEmail doesn't wait in Node.js

When I make a request to my endpoint I need to get a successful response only if the email is sent! otherwise, it should throw an error:
myendpoint.js
router.post("/", upload.none(), async (req, res) => {
try {
let body = JSON.parse(req.body.contact);
await getDb("messages").insertOne({
name: body.name,
email: body.email,
phone: body.phone,
subject: body.subject,
message: body.message,
});
await sendEmail(body);
res.send(
JSON.stringify({
success: true,
msg: "Message has been sent successfully",
})
);
} catch (err) {
res.send(JSON.stringify({ success: false, msg: err }));
}
});
sendEmail.js
const sendEmail = async function (props) {
const transporter = nodemailer.createTransport({
service: process.env.EMAIL_SERVICE,
host: process.env.EMAIL_HOST,
auth: {
user: process.env.EMAIL_FROM,
pass: process.env.EMAIL_PASS,
},
});
const mailOptions = {
from: process.env.EMAIL_FROM,
to: process.env.EMAIL_TO,
name: props.name,
email: props.email,
phone: props.phone,
subject: props.subject,
text: props.message,
};
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
throw new Error("Message did Not send!");
}
});
};
the problem is before "await sendEmail(body);" ends and i get the error, i get the "Message has been sent successfully" and then server crashes!
what am i missing?
Check document function sendMail from nodemailer at here
If callback argument is not set then the method returns a Promise object. Nodemailer itself does not use Promises internally but it wraps the return into a Promise for convenience.
const sendEmail = async function (props) {
const transporter = nodemailer.createTransport({
service: process.env.EMAIL_SERVICE,
host: process.env.EMAIL_HOST,
auth: {
user: process.env.EMAIL_FROM,
pass: process.env.EMAIL_PASS,
},
});
const mailOptions = {
from: process.env.EMAIL_FROM,
to: process.env.EMAIL_TO,
name: props.name,
email: props.email,
phone: props.phone,
subject: props.subject,
text: props.message,
};
// remove callback and function sendMail will return a Promise
return transporter.sendMail(mailOptions);
};
Hello you can change your Transporter sendMail to :
return await transporter.sendMail(mailOptions);
Or You can Use Promise.
const handler = async ({ subject, name, body, contact }) => {
const transporter = nodemailer.createTransport({
service: "zoho",
// Disable MFA here to prevent authentication failed: https://accounts.zoho.com/home#multiTFA/modes
// ********************* OR *****************
// set up Application-Specific Passwords here: https://accounts.zoho.com/home#security/device_logins
auth: { user: process.env.NEXT_PUBLIC_EMAIL_ADDRESS, pass: process.env.NEXT_PUBLIC_EMAIL_PASSWORD },
});
return transporter
.sendMail(mailOptions({ subject, name, body, contact }))
.then((info) => {
if (process.env.NODE_ENV !== "production") console.log("Email sent: " + info.response);
return true;
})
.catch((err) => {
if (process.env.NODE_ENV !== "production") console.log("error sending mail", err);
return false;
});
};

how to send mail with data that data from database using nodejs?

this is my code: i am getting perfect output in postman.but i want the output to send through my mail.In this code var result i am getting error i cannot able to get the responses.
var startBroadcasting = function (req, res) {
authToken = req.headers.authorization;
userAuthObj = JSON.parse(UserAuthServices.userAuthTokenValidator(authToken));
var todayDate = new Date();
var expireDate = new Date(userAuthObj.expire_date);
tokenOK = TokenValidator.validateToken(userAuthObj.user_id, authToken).then(function (userSessions) {
if (userSessions.length === 1) {
if (expireDate >= todayDate) {
template_id = req.params.id;
image_id = req.params.img_id;
TemplateController.findById(template_id, {
attributes: {
exclude: ['created_by', 'created_on', 'updated_by', 'updated_on']
},
include: [{
attributes: {
exclude: ['created_by', 'created_on', 'updated_by', 'updated_on']
},
model: Broadcasting,
where: {
id: image_id,
}
},
]
}
).then(function (templatefindByid) {
BccSetting.findAll({
where: {
template_id: template_id
}
}).then(bccSettings => {
res.status(200).json({
id: templatefindByid.id,
name: templatefindByid.name,
template_images: templatefindByid.template_images,
bcc_settings: bccSettings,
})
}).catch(err => {
console.log(err);
res.status(404).json({
message: ' not found...'
});
});
}).catch(function (err) {
console.log(err);
res.status(404).json({
message: 'not found...'
});
});
} else {
res.status(401).json({
message: 'Not ...'
});
}
} else {
res.status(401).json({
message: 'Expired...'
});
}
}).catch(function (err) {
res.status(401).json({
message: 'Expired...'
});
});
var result = "Hi " + template_images.client_name + "!We are pleased to inform you that " + template_images.client_name + " newschannel streaming has been stopped sucessfully on " +template_images.destination_type + "" +
"" +
"This email was sent from a notification-only address that cannot accept incoming email. Please do not reply to this message.";
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
auth: true,
active: true,
secure: true,
requireTLS: true,
auth: {
user: 'trans#gmail.com',
pass: 'wertyy'
}
});
let mailOptions = {
from: 'trans#gmail.com',
to: 'wwww#gmail.com',
bcc: bcc_setting.bcc_setting,// here i want bcc setting data
subject: 'yvnuyybymyed',
html: 'result'
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log("mail not sent" + error.message);
}
console.log('success');
});
};

Resources