Why Nodemailer is working locally but not in Production? - node.js

When I try to send an email locally it works but in production, in the network tab I get everything right just email doesn't want to send and I don't get any error.
try {
const { name, email, message } = req.body;
const transporter = nodemailer.createTransport({
port: 465,
host: "smtp.gmail.com",
auth: {
user: process.env.NEXT_PUBLIC_GMAIL_EMAIL,
pass: process.env.NEXT_PUBLIC_GMAIL_PASSWORD,
},
secure: true,
});
const mailData = {
from: process.env.NEXT_PUBLIC_GMAIL_EMAIL,
to: process.env.NEXT_PUBLIC_EMAIL_WHICH_RECIEVES_CONTACT_INFO,
subject: `Message From ${email}`,
text: message,
};
transporter.sendMail(mailData, function (err, info) {
if (err) console.log(err);
else console.log(info);
});
res.status(200).json({ message: "Email sent" });
} catch (error: any) {
res.status(500).json({ message: error.message });
}

I kind of had a similar issue with nodemailer and Next.js, try to wrap the transporter in a Promise, hopefully it works for you too:
await new Promise((resolve, reject) => {
transporter.sendMail(mailData, (err, info) => {
if (err) {
console.error(err);
reject(err);
} else {
resolve(info);
}
});
});

Related

Nodemailer is not working in live but locally working fine

function sendEmail(num, email, customerName) {
var readHTMLFile = function (path, callback) {
fs.readFile(path, { encoding: 'utf-8' }, function (err, html) {
if (err) {
throw err;
callback(err);
}
else {
callback(null, html);
}
});
};
let transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
secure: true,
port: 465,
auth: {
user:process.env.USEREMAIL,
pass:process.env.USERPASS
},
});
readHTMLFile(__dirname + '/views/layouts/first.html', function (err, html) {
var template = handlebars.compile(html);
var replacements = {
otp: `${num}`,
customerName: `${customerName}`
};
var htmlToSend = template(replacements);
var mailOptions = {
from: process.env.USEREMAIL,
to: email,
subject: "Hello ✔",
html: htmlToSend
};
transporter.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
} else {
console.log("Email sent");
}
});
});
}
All this is working fine with my localhost:8000 but after I upload(hosted) with my cyclic.sh account, my app works and getting success message, but did not get any mail with my box. sendEmail function not working in live but working locally. what is issues of the sendEmail function
I had a same problem and fixed it by wrapping sendmail with a promise
new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, function (error, response) {
if (error) {
reject(error)
} else {
resolve("email sent")
}
});
})

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'
})
}
})
})

not sure why nodemailer isnt working properly

Not sure why this isnt working properly. i think the configuration looks right but I keep getting this error :getaddrinfo ENOTFOUND smpt.mydomian.com
let transporter = nodemailer.createTransport({
host: "smtp.mydomain.com",
port: 465,
secure: true,
auth: {
user: "abc#mydomain.com",
pass: "password",
},
});
let mailOptions = {
from: email,
to: "abc#domail.com",
subject: `New Lead ${fullName}`,
text: newMail,
};
// step 3
transporter.sendMail(mailOptions, (err, data) => {
if (err) {
console.log("there is an error " + err);
} else {
console.log("mail sent successfully");
}
});
});
in my opinion its better to create a class for that just like this
class Mailer {
sendMail = async (emailAddress) => {
let transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: testUser,
pass: testPass,
},
});
const option = {
from: `${EMAIL_ADDRESS}`,
to: emailAddress,
subject: "test Subject",
text: "Test text",
};
await transporter.sendMail(option, (err, info) => {
if (!err) {
console.log(`Email sent Successfully ... !`.green.underline.bold);
return true;
} else {
console.log(
`We have problem while sendil Email ... !`.red.underline.bold
);
return false;
}
});
};
}
i hope this class help you

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

Nodemailer returns nothing on sending mail

I'm using nodemailer to try and get an admin to send an email, but the code I have so far returns no info or error.
The promise returns with no issue, but it's always empty.
Trying to use transporter.verify returns no info or error as well.
There are no issues with finding the admin in question.
var deferred = Q.defer();
Admin.findOne({username: 'admin'}, function(err, res)
{
if(err) deferred.resolve(err);
if(res)
{
var admin = _.omit(res.toJSON(), 'password');
var transporter = nodemailer.createTransport("SMTP", {
service: 'gmail',
auth: {
user: 'sender#gmail.com',
pass: "password_here"
}
});
var mailOptions = {
from: 'sender#gmail.com',
to: 'destination#hotmail.com',
subject: 'TEST',
text: 'TEST',
html: '<p> TEST EMAIL </p>'
};
transporter.sendMail(mailOptions, function (err, info) {
if (err) deferred.reject(err);
if(info){
deferred.resolve(info);
} else {
deferred.resolve();
}
});
} else {
deferred.reject("Cannot find admin");
}
});
return deferred.promise;
Please edit the code, it looks like you have an error on mongo with 'Admin.findOne'
if(err) deferred.resolve(err);
to
if(err) deferred.reject(err);

Resources