NodeMailer- Sending email in nodejs [duplicate] - node.js

I don't know what I'm missing, I use the Nodemailer example:
var nodemailer = require("nodemailer");
// create reusable transport method (opens pool of SMTP connections)
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
auth: {
user: "gmail.user#gmail.com",
pass: "userpass"
}
});
// setup e-mail data with unicode symbols
var mailOptions = {
from: "Fred Foo βœ” <foo#blurdybloop.com>", // sender address
to: "bar#blurdybloop.com, baz#blurdybloop.com", // list of receivers
subject: "Hello βœ”", // Subject line
text: "Hello world βœ”", // plaintext body
html: "<b>Hello world βœ”</b>" // html body
}
// send mail with defined transport object
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
}else{
console.log("Message sent: " + response.message);
}
// if you don't want to use this transport object anymore, uncomment following line
//smtpTransport.close(); // shut down the connection pool, no more messages
});
I just changed the user and pass in auth to my gmail account info (also tried with their values), and I changed the "to" email address to my email address. I get:
{ [Error: connect ECONNREFUSED]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect' }
What am I missing? I don't see anything in the documentation that says I need to do anything more than this, so why won't it work? Thank you in advance.

It was a firewall issue. Turns out there was nothing wrong with the code, I just didn't understand what the error message implied.

I was also using a gmail account to send the email, you might need an Application-specific password from google to allow nodemailer to work properly.
https://support.google.com/mail/answer/1173270?hl=en

Following step:
Login gmail account.
Enable pop3 in settings tabs
Enable less secure apps at: Enable less secure apps for gmail account
Display Unlock Captcha at: Display unlock Captcha
Defined email option and sending
var mailOptions = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // use SSL
auth: {
user: 'gmail_account#gmail.com',
pass: 'password'
}
}
mailer = nodemailer.createTransport(mailOptions);
mailer.sendMail({
....
}, function(err, response) {
if (err) {
console.log(err);
}
console.log(response);
});
Hope this block code help you.

ECONNREFUSED inidcates that this is some kind of connection or firewall issue.
Can you connect to smtp.gmail.com port 465 with any other application from the same machine, for example with openssl?
openssl s_client -connect smtp.gmail.com:465

if you use new nodemailer version
nodemailer.createTransport({
host,
port,
secure:,
auth:{
user,
pass
}
})
more see https://github.com/andris9/nodemailer-wellknown

In my case I just had to disable my anti virus, Avast.
To white list on avast do this:
These steps may vary according to your Avast version, including the IP used here
1) Open Avast, go to: Menu -> Settings. (It is located on the top right corner)
2) Go to General Tab -> Exceptions -> Add Exception
3) Get the IP of your gmail, it is going to be with the error, I think.
4) Now paste the IP on your exception
Hope it helps.

The actual problem fix is that you need to place the SERVICE. Better if you use ENVIRONMENT VARIABLES
var transporter = nodemailer.createTransport({
service: process.env.EMAIL_SERVICE,
auth: {
user:process.env.EMAIL_USER,
pass:process.env.EMAIL_PASSWORD
}
})

firewall problem
to block the firewall in order to send email, you need to allow port or disable all port.
allowing specific port:
$ sudo ufw allow 587
to disable firewall
$ sudo ufw disable
$ sudo ufw reset

Related

POST Request returns 504 Online but works locally

Introduction
My POST request works offline i.e. on localhost, but doesn't work when the website is deployed.
I am using nextjs, node, nodemailer, axios and nginx. I have also used fetch instead of axios and it gave me the same issue.
The situation
I have a handleSubmit function, that takes some inputs from a contact form and sends it to my Gmail account:
axios({
method: "POST",
url: "/api/submit",
data: body,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}).then((response) => {
if (response.data.status === 'success') {
alert("Email sent, awesome!");
} else {
alert("Oops, something went wrong. Try again")
}
})
The api/submit.js is as follows:
import nodemailer from "nodemailer"
var transport = {
service: 'gmail',
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: process.env.USER,
pass: process.env.PASS
}
}
var transporter = nodemailer.createTransport(transport);
transporter.verify((error, success) => {
if (error) {
console.log("There was an error:" + error);
} else {
console.log("Server is ready to take messages")
}
})
export default async (req, res) => {
switch (req.method) {
case "POST":
var name = req.body.name;
var content = name " text "
var mail = {
from: name,
to: "myemail#gmail.com",
text: content
}
transporter.sendMail(mail, (err, data) => {
if (!err) {
res.json({
status: "success"
})
res.end();
}
})
break
case "GET":
res.status(200).json({name:"John Doe"})
break
default:
res.status(405).end()
break
}
}
The code works locally when I run npm run dev, or npm start it posts to http://localhost:3000/api/submit and I receive the email within seconds.
However, when I deploy the website on DigitalOcean and hit the submit button nothing happens for 60 seconds then I get a status code of 504 on my POST request. If I send a GET request to api/submit, it works and I see the JSON for that request, so it's an issue with the POST request specifically.
My Nginx logs it as the following:
2021/02/27 13:59:35 [error] 95396#95396: *3368 upstream timed out (110: Connection timed out) while reading response header from upstream, client: my.ip, server: website.com, request: "POST /api/submit HTTP/1.1", upstream: "http://127.0.0.1:3000/api/submit", host: "website.com", referrer: "https://website.com/contact"
I've been trying to debug it for days now, but I just can't figure it out.
Anyone have any ideas?
EDIT 01.03.2021 The problem is resolved embarrassingly.
Turns out the ports were all open, telnet worked for all mail ports and smtp hosts.
When I hard coded the username/password e.g. for ephemeral mail user: "blah#emphemeral.email", pass: "fakepassword"; the email would send in production.
Turns out my process.env.USER and process.env.PASS were not being replaced with the values of process.env.USER/PASS in .env during npm run build, because I was cloning my GitHub repo, which didn't contain my .env file. After creating my .env file on the server and running npm run build the code worked fine.
Thank you for the replies, sorry for the hassle.
Kindly check that from Digital Ocean where your application is deployed, port is opened or not for following host.
Host:smtp.gmail.com Port: 587
I guess that is not a problem with your code, but with the deploy process. Are you requesting to yor API adress directly or passing to a proxy? If you're using a proxy, maybe the proxy was not redirecting to your application in a right way
I think, it works for you in your local machine, as the localhost is there. But in the server, maybe, it's not the same.
You can check your hostnames in the server by the following command
cat /etc/hosts
If the host name is different, possibly you have the allow the CORS as well. A good place to check is in your browser inspect (in google chrome, right-click -> Inspect)
Then check if you find any message related the access to the server from your frontend.
I suspect I'm not the first to do this but it's rather embarrassing.
First, I confirmed that the ports were all open, telnet worked for all mail ports and smtp hosts.
Then, when I hard coded the username/password e.g. for ephemeral mail user: "blah#emphemeral.email", pass: "fakepassword"; the email would send in production.
Then I realized that my process.env.USER and process.env.PASS variables were not being replaced with the true values of process.env.USER/PASS in .env during npm run build, because I was cloning my GitHub repo, which didn't contain my .env file. Meaning I was trying to login as username = "process.env.USER" and password = "process.env.PASS".
After creating my .env file on the server and running npm run build the code worked fine.
Thank you for the replies and sorry for the hassle.

Email send through nodemailer goes into spam for gmail

I am sending email through nodemailer it goes into inbox of gmail if i run from local server but goes into spam of gmail if i run script from microsoft azure server.
following is my script
var nodemailer = require('nodemailer');
var EmailTemplates = require('swig-email-templates');
var smtpConfig = {
service: 'smtp.office365.com',
host: 'smtp.office365.com',
port: 587,
starttls: {
enable: true
},
secureConnection: true,
auth: {
user: 'xxxxx#yyyy.com',
pass: 'zzzzzz'
}
}
var templates = new EmailTemplates();
var transporter = nodemailer.createTransport(smtpConfig);
var context = {
username:'Rajesh',
email:'xxxxx#gmail.com',
link : 'www.google.co.in'
};
templates.render('activate_email.html', context, function(err, html,text, subject) {
transporter.sendMail({
from: '"Product NameπŸ‘₯" <no-reply#xxxxx.com>', // sender address
to: 'xxxx#gmail.com',
subject: 'Account activation',
html: html,
text:text
});
});
The truth is there is no simple one line solutions for your problem :) There are numerous reasons why this can happen, and here are some of them:
Your host is marked as a spam - this happens if you have not verified your e-mail or you are sending too much e-mails from the same host. Shared hosting is commonly marked as such, and therefore mail server will regularly mark them as a spam
Your from field is different than the one you're allowed to use - as I see you're using smtp, there are strict rules for the mail you can send. Of course you can always send e-mail from mark#facebook.com, but since your SMTP's host is not facebook.com, your e-mail will pretty sure marked as spam
You can sign your e-mail in many various mails, assuring the servers that this e-mail is send from you and it has proper signature. Check online for the ways to do so.
While developing you have sent numerous alike e-mails - sending the very same "test" e-mail is a common reason for your e-mails to get blacklisted
There are emojis in your subject - that is not a 100% reason, but servers are often marking such e-mails as spams, especially in other fields (like from)
Unfortunately as I said there is no one real reason, there could be many of them. I hope this helps at least a little :)
in my case i needed to specify the form, the from need to be = to user mail
auth: {
user: "xxx#yyy.com",
pass: "password",
},
from: xxx#yyy.com,
Please get rid of the πŸ‘₯ and try sending it again. I read in a article once that email clients don't like those icons because a lot of spammers are using them.
Try sending it to multiple gmail accounts. Other than that there's nothing wrong with the code. If you're on a shared hosting or local host it could also go into the junk folder. In that case you would have to look into sending the emails from a different IP, preferred in the same country as where you will send the emails to.
But first try to remove that icon!
PS. I would make this answer as a comment but I can't due to low rep.
For those who are still struggling for this problem. I suggest the following.
Make sure you add from field that matches with auth.user
let transporter = nodemailer.createTransport({
host: "smtp-mail.outlook.com",
secureConnection: false,
port: 587,
tls: {
ciphers: "SSLv3",
},
auth: {
user: <YOUR_EMAIL_ACCOUNT>,
pass: <YOUR_EMAIL_PASSWORD>,
},
from: <YOUR_EMAIL_ACCOUNT>,
});
Add text field describing your intent for the email in options payload
const mailOptions = {
from: `myCompany <mycompanyemail#gmail.com>`,
to: "recipient#gmail.com",
subject: "[MYCOMPANY] YOUR EMAIL VERIFICATION",
text: "Hello. This email is for your email verification.",
html: <h1>Hello</h1>,
};
If #1 or #2 doesn't solve your problem. Try using test-mailer and send email to their provided test email address. It will show you where your vulnerabilities are especially the part where you have to setup SPF, DKIM, and DMARC.
If you are using a custom domain setup SPF, DKIM, DMARC following this article.
Late to the party..
Try adding both HTML and Text Versions both in your emailConfig as below. That way the email will land up in the inbox. It worked for me.
var emailOptions = {
from: 'cxxxxxkxxxxx#xxxxx.com',
to: 'xxxx#xxxxxx.com',
cc:'sxxxxxxsh#xxxx.com, xxxa#xxx.com, aaaxxxx#xxxx.com',
bcc:'xxxxx.wrxxxk#xxxx.com',
subject: 'xxxxxxxxxx',
/* Adding HTML and Text Version, so the email will not land up in the Spam folder */
html: 'Hello Team! <br><br>Please find attached...<br><br>Thanks,<br>XXXXX',
text: 'Hello Team! <br><br>Please find attached...<br><br>Thanks,<br>XXXXX',
attachments: [{
// file on disk as an attachment, concatenating the file extension separately since NODE is not renaming the file properly with fs.renameSync
filename: finalFileNameWithoutExt + '.xlsx',
path: reportsLocationPathWithYearMonth + finalFileNameWithoutExt + '.xlsx' // stream this file
}]
};
HTML goes to junk, plain text doesn't

Email with nodemailer fails on Heroku

In my node.js-App, that runs on 1 Heroku worker, needs to send out emails from time to time. The logic is the following:
var transporter = Email.createTransport({
service: 'yahoo',
auth: {
user: process.env.CRAWLER_MAIL,
pass: process.env.CRAWLER_PWD
}
});
transporter.sendMail({
from: process.env.CRAWLER_MAIL,
to: process.env.CRAWLER_RCVR_MAIL,
subject: 'subject',
text: 'text'
}, function(err, result) {
if (err !== null) {
console.log(err);
} else {
...
}
});
I tested this with foreman start and it worked fine. Nonetheless, once deployed to Heroku, the transporter always emits an error with status code '564 : We were unable to deliver your message. Please try resending your message by adding some text.'
process.env. hold the correct values, I checked for that, and text is always a string.
What could be wrong?
I was not able to replicate your problem using my account details.
Could it be related to the sender/recipient emails? Are they both #yahoo.com addresses?
There has been some chatter in forums about yahoo groups emails specifically not working and giving that error. Something to do with Yahoo changing their DMARC policy recently.
Nodemailer loads predefined "well known" services from submodule nodemailer-wellknown
This is the current definition loaded when using service: 'yahoo' in your createTransport():
https://github.com/andris9/nodemailer-wellknown/blob/master/services.json#L160
A few thing worth trying:
Switch the smtp server to plus.smtp.mail.yahoo.com.
Try the username with and without #yahoo.com
Make sure you are sending from a real email address - and not an alias.
We use Mandrill for SMTP on Heroku with our Nodemailer app.
Very reliable and the first 12k emails sent per month are free!
Can you try using it without the service option and specifying the SMTP sever manually as shown below.
var transporter = Email.createTransport(smtpTransport({
host: 'smtp.mail.yahoo.com',
port: 465,
auth: {
user: process.env.CRAWLER_MAIL,
pass: process.env.CRAWLER_PWD
}
}));
I had this problem some time ago and was solved when I bypassed the service
Try this code :
I know it looks same but there are small changes that might solve your problem. Give it a try as it worked fine with foreman start and do let me know if it did any good...
var nodemailer = require('nodemailer');
var transporter = Email.createTransport({
service: 'yahoo',
auth: {
user: 'process.env.CRAWLER_MAIL',
pass: 'process.env.CRAWLER_PWD'
}
});
transporter.sendMail({
from: 'process.env.CRAWLER_MAIL',
to: 'process.env.CRAWLER_RCVR_MAIL',
subject: 'subject',
text: 'text'
});

Preventing Spam; Using Nodemailer; Using Sendmail

I'm using the Nodemailer Node.js module to interface with sendmail. However, my emails go directly to the spam folder when reached by a Gmail account. Why are my emails being shit-canned? It must be something to do with the headers of the email, but I have no idea what it could be.
I'm not really familiar with emails and what spam filters look for, so could someone please provide me with some details on what to watch out for?
Thanks for reading. :)
I've faced with the same issue and was able to fix it by updating 'from' field to this format:
from: 'Sender Name <some-random-email#gmail.com>'
complete code:
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 587,
secure: false,
requireTLS: true,
auth: {
user: 'some-random-email#gmail.com',
pass: 'pass'
},
from: 'some-random-email#gmail.com'
});
const mailOptions = {
from: 'Sender Name <some-random-email#gmail.com>'
to: 'some-new-random-email#gmail.com',
subject: 'Subject',
text: 'Text'
};
return transporter.sendMail(mailOptions, (error, info) => {
...
});
Here's a few reasons:
So You'd Like to Send Some Email (Through Code) (2010)
There are also blacklists of ip addresses. Anything coming from these would just be ignored or regarded as spam.
If your email is sent from a server which doesn't seem to be linked to the from address you'll have potential issues as well.
Detecting spam and trying not to be seen as spam are both non trivial things. That's why a lot of mailing lists are done through a specialist provider.
In case if your IP is blacklisted, you will need to use third party email service like:
MailJet: it's free plan has limitation of 200 mails per day. https://github.com/mailjet/mailjet-apiv3-nodejs/blob/master/README.md
SendGrid: Free plan has 100 mails/day https://sendgrid.com
Mailgun: 10000 mails/month free https://www.mailgun.com
Check their documentation for integration with your application.
data/mail.private - change to wherever your Open DKIM private key file is located.
var client = require('nodemailer').createTransport({
secure: false,
pool: true,
host: 'yourdomain.io',
port: app.nconf.get('mail:port'),
auth: {
user: app.nconf.get('mail:user'),
pass: app.nconf.get('mail:pass')
},
dkim: {
domainName: 'yourdomain.io',
keySelector: 'mail',
privateKey: require('fs').readFileSync('data/mail.private', {
encoding: 'utf8'
})
}
})

Nodemailer: ECONNREFUSED

I don't know what I'm missing, I use the Nodemailer example:
var nodemailer = require("nodemailer");
// create reusable transport method (opens pool of SMTP connections)
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
auth: {
user: "gmail.user#gmail.com",
pass: "userpass"
}
});
// setup e-mail data with unicode symbols
var mailOptions = {
from: "Fred Foo βœ” <foo#blurdybloop.com>", // sender address
to: "bar#blurdybloop.com, baz#blurdybloop.com", // list of receivers
subject: "Hello βœ”", // Subject line
text: "Hello world βœ”", // plaintext body
html: "<b>Hello world βœ”</b>" // html body
}
// send mail with defined transport object
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
}else{
console.log("Message sent: " + response.message);
}
// if you don't want to use this transport object anymore, uncomment following line
//smtpTransport.close(); // shut down the connection pool, no more messages
});
I just changed the user and pass in auth to my gmail account info (also tried with their values), and I changed the "to" email address to my email address. I get:
{ [Error: connect ECONNREFUSED]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect' }
What am I missing? I don't see anything in the documentation that says I need to do anything more than this, so why won't it work? Thank you in advance.
It was a firewall issue. Turns out there was nothing wrong with the code, I just didn't understand what the error message implied.
I was also using a gmail account to send the email, you might need an Application-specific password from google to allow nodemailer to work properly.
https://support.google.com/mail/answer/1173270?hl=en
Following step:
Login gmail account.
Enable pop3 in settings tabs
Enable less secure apps at: Enable less secure apps for gmail account
Display Unlock Captcha at: Display unlock Captcha
Defined email option and sending
var mailOptions = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // use SSL
auth: {
user: 'gmail_account#gmail.com',
pass: 'password'
}
}
mailer = nodemailer.createTransport(mailOptions);
mailer.sendMail({
....
}, function(err, response) {
if (err) {
console.log(err);
}
console.log(response);
});
Hope this block code help you.
ECONNREFUSED inidcates that this is some kind of connection or firewall issue.
Can you connect to smtp.gmail.com port 465 with any other application from the same machine, for example with openssl?
openssl s_client -connect smtp.gmail.com:465
if you use new nodemailer version
nodemailer.createTransport({
host,
port,
secure:,
auth:{
user,
pass
}
})
more see https://github.com/andris9/nodemailer-wellknown
In my case I just had to disable my anti virus, Avast.
To white list on avast do this:
These steps may vary according to your Avast version, including the IP used here
1) Open Avast, go to: Menu -> Settings. (It is located on the top right corner)
2) Go to General Tab -> Exceptions -> Add Exception
3) Get the IP of your gmail, it is going to be with the error, I think.
4) Now paste the IP on your exception
Hope it helps.
The actual problem fix is that you need to place the SERVICE. Better if you use ENVIRONMENT VARIABLES
var transporter = nodemailer.createTransport({
service: process.env.EMAIL_SERVICE,
auth: {
user:process.env.EMAIL_USER,
pass:process.env.EMAIL_PASSWORD
}
})
firewall problem
to block the firewall in order to send email, you need to allow port or disable all port.
allowing specific port:
$ sudo ufw allow 587
to disable firewall
$ sudo ufw disable
$ sudo ufw reset

Resources