How to make nodemailer reusable in multiple module? - node.js

I have implemented nodemailer after the user registration, in the following way:
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USERNAME,
pass: process.env.EMAIL_PASSWORD
}
});
let mailOptions = {
from: process.env.EMAIL_USERNAME,
to: user.email,
subject: 'Verify your account',
text: 'Click here for verify your account'
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
});
I don't like much this code because if I need to send an email in another module, I need to rewrite all the stuff above.
Since I'm new to NodeJS, I would like to know if I can remove this code redundancy make something like a utility or maybe an helper class. The goal is import the wrapper class and call a simple function to send the email.
Which is the best way to handle that?

I refactored your code to look like below and then save it as mail.js
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USERNAME,
pass: process.env.EMAIL_PASSWORD
}
});
let sendMail = (mailOptions)=>{
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
});
};
module.exports = sendMail;
in Your other modules, say activation.js
var mailer = require('./mail.js');
mailer({
from: process.env.EMAIL_USERNAME,
to: user.email,
subject: 'Verify your account',
text: 'Click here for verify your account'
};);

you can use module.exports as follow :
create common service mail.js and write your mail sent code here
mails.js
module.exports = function (){
// mail sent code
}
require mail.js where you write mail sent code in other service and call mail sent function
otherService.js
var mail = require('mail.js') // require mail sent in other service where you want to send mail
mail.sent() // call function of mail.js

I have created a class for this:
import NodeMailer from 'nodemailer'
import emailConfig from '../../config/mail' // read email credentials from your config
class EmailSender {
transport
constructor() {
this.transport = NodeMailer.createTransport({
host: emailConfig.MAIL_HOST,
port: emailConfig.MAIL_PORT,
auth: {
user: emailConfig.MAIL_USERNAME,
pass: emailConfig.MAIL_PASSWORD,
},
})
}
async sendMessage(to, subject, text, html) {
let mailOptions = {
from: emailConfig.MAIL_FROM_ADDRESS,
to,
subject,
text,
html,
}
await this.transport.sendMail(mailOptions)
}
}
export default new EmailSender()
Now you can implement it in your any routes:
router.get('/email', async (req, res) => {
try {
await EmailSender.sendMessage(
'bijaya#bijaya.com',
'Hello world',
'test',
'<h1>Test</h1>'
)
return res.status(200).send('Successfully sent email.')
} catch (exception) {
return res.status(500).send(exception.message)
}
})

Related

response: '535-5.7.8 Username and Password not accepted. Learn more at\n'

My Node js code is sending proper email on localhost but in backend there showing email and password not valid ?
const nodemailer = require("nodemailer");
const sendEmail = async (subject, message, send_to, sent_from, reply_to) => {
// Create Email Transporter
const transporter = nodemailer.createTransport({
host: process.env.EMAIL_HOST,
port: 465,
secure: true,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
// Options for sending email
const options = {
from: sent_from,
to: send_to,
reply_to: reply_to,
subject: subject,
html: message,
};
// Check email sent successfully or not
transporter.sendMail(options, function (err, info) {
if (err) {
console.log(err);
} else {
console.log(info);
}
});
};
module.exports = sendEmail;

Nodemailer not sending email in lambda function

I am developing an AWS lambda function using node.js 14.x for my runtime.
I create a nodemailer layer and upload it to my lambda function. I am trying to test my function and just return a simple console log but I don't see the console log anywhere including my cloud watch logs.
exports.handler = async (event) => {
// TODO implement
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
// user: process.env.USER_NAME,
// pass: process.env.EMAIL_PASS,
user: "********",
pass: "********",
},
});
const mailOptions = {
from: "taxs#gmail.com",
to: "trdmon#gmail.com",
subject: "subject",
text: "message",
};
transporter.sendMail(mailOptions, function (error, info) {
console.log('hit')
if (error) {
console.log(error);
} else {
console.log("Email sent: " + info.response);
}
});
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
If the transporter.sendEmail function were running I should see the console log. Any ideas why my function isn't running?

Nodemailer is sending emails with the same subject as thread

Nodemailer is sending emails as a thread if the email has the same subject as a previously sent email. But I want to send the emails as separate emails, even if they have the same subject as each other.
I have an application that sends notification emails to users. The emails all have the same subject: notification. This is causing the emails to show as a thread, at least in Gmail:
How can I make each notification email send separately?
const nodemailer = require('nodemailer');
const logger = require('./logger');
class Email {
constructor(email, to, pass) {
this.user = email;
this.to = to;
this.pass = pass;
}
get mailOptions() {
return {
from: this.user,
to: this.to,
subject: 'notification',
html: 'You received a new purchase in your shop.',
};
}
get transporter() {
const transporter = nodemailer.createTransport({
// for zoho emails
host: 'smtp.zoho.com',
port: 587,
secure: false,
auth: {
user: this.user,
pass: this.pass,
},
});
return transporter;
}
send(cb) {
this.transporter.sendMail(
this.mailOptions,
cb ||
((error, info) => {
if (error) console.log(error);
if (info) logger.log('silly', `message sent: ${info.messageId}`);
this.transporter.close();
})
);
}
sendSync() {
return new Promise((res, rej) =>
this.transporter.sendMail(this.mailOptions, (error, info) => {
if (error) rej(error);
else res(info);
this.transporter.close();
})
);
}
}
const email = new Email(
'somesendingemail#gmail.com',
'somereceivingemail#gmail.com',
'SendINgEmAIlPassWoRD'
);
email.send();

Send confirmation response after Nodemailer sendMail function done?

I need to return some response when I send a email through Nodemailer and I have this function:
async function dispatchEmail(email) {
const transporter = nodemailer.createTransport({
service: `${nconf.get('EMAIL_SMTP_SERVICE')}`,
auth: {
user: nconf.get('EMAIL_ACCOUNT'),
pass: nconf.get('EMAIL_PASSWORD'),
},
});
const mailOptions = {
from: `"Shagrat Team "${nconf.get('EMAIL_ACCOUNT')}`,
to: email,
subject: 'Hi from Shagrat Team !',
text: '',
html: '',
};
const success = await transporter.sendMail(mailOptions, async (error, sent) => {
if (error) {
return error;
}
return {some_response};
});
return success;
}
Where I need to send{some_response} with some value either true, false or something else, but I got 'undefined' value inside the same function or calling it externally:
const success = await dispatchEmail(emailConsumed);
What value can I return and catch it? because I need to test this function.
An exit is to return the transporter.sendmail () itself, which is a promise, in the return contera the data of the sending or the error, it is good to use a trycatch for other errors.
async function dispatchEmail(email) {
const transporter = nodemailer.createTransport({
service: `${nconf.get('EMAIL_SMTP_SERVICE')}`,
auth: {
user: nconf.get('EMAIL_ACCOUNT'),
pass: nconf.get('EMAIL_PASSWORD'),
},
});
const mailOptions = {
from: `"Shagrat Team "${nconf.get('EMAIL_ACCOUNT')}`,
to: email,
subject: 'Hi from Shagrat Team !',
text: '',
html: '',
};
return transporter.sendMail(mailOptions)
}
Another option is to use the nodemailer-promise module.
const success = await dispatchEmail(emailConsumed);
Result:
console.log(sucess);
{ envelope:
{ from: 'example#example.com',
to: [ 'example2#example.com' ] },
messageId:'01000167a4caf346-4ca62618-468f-4595-a117-8a3560703911' }

Implement a mailing solution in Express nodejs

I'm creating an API that handles account verification via email, password recovery and possibly other things.
I want to create one place to send emails across my entire API.
i'm using nodeMailer.
My current setup is i'm a calling a method on the user model that send EmailVerification email.
I want to create a template outside the User model that could send either password recovery, email verification or other things.. Depending on the params that i pass to the function.
My user model:
userSchema.methods.generateEmailVerificationToken = function() {
const token = jwt.sign({_id: this._id, role: this.role},
config.get('jwtPrivateKey'));
return token;
};
userSchema.methods.generateAuthToken = function() {
const token = jwt.sign({_id: this._id, role: this.role},
config.get('jwtPrivateKey'));
return token;
};
userSchema.methods.sendEmailVerification = function (user) {
sendMail(user);
};
and this is my sendMail function:
const nodemailer = require('nodemailer');
module.exports = function sendMail (user) {
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'mymail#gmail.com',
pass: 'mypass'
}
});
const mailOptions = {
from: 'mymail#gmail.com',
to: user.email,
subject: 'Email verification.',
html: `Please click this link to verify your email`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
}
Thank you

Resources