Nodemailer keeps refusing authentication for invalid login (not using gmail) - node.js

I'm wrapping my head around the strangest issue ever right now. I'm using nodemailer and postfix to send email.
The following code is NOT working, giving me the following error : Error: Invalid login: 503 5.5.1 Error: authentication not enabled
let transporter = nodemailer.createTransport({
host: 'mydomain.com',
port: 465,
secure: false, // true for 465, false for other ports
auth: {
user: 'no-reply', // user
pass: 'a-hundred-percent-the-right-password' // password
}
});
But what is even more strange (and close to scary) is that the same code without any credentials specified is working fine! (But of course the email is going in the spams).
Does any body has an idea of what I could have done wrong ?

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.

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

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