Email with nodemailer fails on Heroku - node.js

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

Related

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

NodeMailer- Sending email in nodejs [duplicate]

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

Nodemailer with Gmail error: 454 4.7.0 Cannot authenticate due to temporary system problems

I am using nodemailer module with my nodejs/express.js app.
I am using gmail as the transporter.
It seems like every 20 successful emails sent, I will get this error:
454 4.7.0 Cannot authenticate due to temporary system problem
I'm testing out an invoice system so I'm regularly sending an email to the same email address for testing.
I am not using Google apps and I have set Gmail security to work with low security apps.
Invoices are important and if I cant guarantee all invoices will get sent to my customers, its going to be bad.
Is this normal?
app.get('/thankyou', function(req,res) {
var transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'somethinggggg#gmail.com',
pass: 'password here'
}
});
res.render('thankyou_email', function(err,html) {
var mailOptions = {
from: 'John Doe <somethinggggg#gmail.com>',
to: 'someoneee#icloud.com',
subject: 'Your order was received',
html: html
};
transporter.sendMail(mailOptions, function(error, info) {
if(error) {
console.log('error1: ' + error);
transporter.sendMail(mailOptions, function(error, info) {
if(error) {
console.log('error2: ' + error);
} else {
console.log('cool bro everything works2');
console.log(info);
}
});
} else {
console.log('cool bro everything works');
console.log(info);
}
});
res.render('thankyou_page');
});
As you can see, if I have an error I try to resend the email again, but still I receive the same error.
Also notice that I am using res.render() twice. I thought this was weird but it still works. The first res.render() I am using to generate the html for the email, and the last res.render() is to render the html in the response back to the client. I used to get an error about sending headers twice, but I don't see that error no more. Nevertheless ,it still worked.
Whose fault is this? Me? Nodemailer? Gmail?
If I were to sign up for Google apps will I still have this problem?
I have come across Nodemailer documentation and it was stated in Using OAuth2 that if a XOAuth2 token generator is used as the value for auth.xoauth2 when setting up transporter object then you do not need to set the value for user or pass as OAuth2 is used for authenticated.
XOAuth2 generator generates required accessToken itself if it is missing or expired. If authentication fails, a new token is requested and the authentication is retried once. If it still fails, an error is returned.
Sample code is given in the documentation. Though, I haven't personally tried using it, I hope it works with you. :)

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