I've set up Nodemailer to work with Gmail using OAuth2. It works fine until the access token expires. At this point, despite having a refresh token, I get the following error message:
{
Error: Invalid status code 401
at ClientRequest.req.on.res (xxxxxxxxxxx)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:191:7)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:522:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
at TLSSocket.socketOnData (_http_client.js:411:20)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:191:7)
at readableAddChunk (_stream_readable.js:178:18)
at TLSSocket.Readable.push (_stream_readable.js:136:10)
at TLSWrap.onread (net.js:561:20)
type: 'FETCH',
sourceUrl: 'https://accounts.google.com/o/oauth2/token',
code: 'EAUTH',
command: 'AUTH XOAUTH2'
}
Here's my code. I've also tried including the refresh token and access token in the initial nodemailer setup, as well as including the expiry date. Each time I get the same result.
Nodemailer setup:
const nodemailer = require('nodemailer')
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
type: 'OAuth2',
clientId: 'xxxxxxxxxx',
clientSecret: 'xxxxxxxxxx'
}
});
transporter.on('token', token => {
console.log('A new access token was generated');
console.log('User: %s', token.user);
console.log('Access Token: %s', token.accessToken);
console.log('Expires: %s', new Date(token.expires));
});
E-mail setup:
const mailOptions = {
from: xxxxxxxxx,
to: xxxxxxxxx,
subject: 'Test Subject',
text: 'This is a test',
html: '<p>This is a test</p>',
auth: {
user: 'xxxxxxxxxxxx',
refreshToken: 'xxxxxxxxxxxxx',
accessToken: 'xxxxxxxxxxxxx'
}
}
E-mail send
transporter.sendMail(mailOptions, function(err, info){
if(err){
return console.log(err);
}
console.log('Message %s sent: %s', info.messageId, info.response)
})
Can anyone suggest what may be going wrong?
I know i am too late on this post. But i came here as i was facing same issue yesterday. I have fixed the issue and the issue was a silly mistake which was not mentioned anywhere.
So issue was in the process to create refresh token and access token in the google playground page. I selected correct scope (https://mail.google.com) but while creating code and refresh token i did not added my app client id and secret and google was taking a client id and secret of playground by default. So be careful to add your app's client id and secret in the playground.
To add your client id and password. Click on right top corner setting button. Click on checkbox saying use your own credentials and click on close. now if we create access refresh token Google will ask permission for our app instead of Google Playground.
It will resolve the 401 issue. This was not mentioned anywhere on any card created.
Check this SO post to direct you about the discussion on "refresh token", see answers by RobKohr and Radioreve.
And maybe this OAuth2 samples can help you to check the difference from your code.
Reference from Nodemailer site:
OAuth2 allows your application to store and use authentication tokens
instead of actual login credentials. This is great for security as
tokens or valid only for specific actions and can be easily revoked
thus, once stolen, can’t to as much harm as actual account
credentials. OAuth2 authentication in Nodemailer is mostly used with
Gmail and G Suite (née Google Apps) even though there are other
providers that support it as well.
Access Tokens needed for OAuth2 authentication are short lived so
these need to be regenerated from time to time. Nodemailer is able to
use both 3LO and 2LO to automatically regenerate the tokens but you
can also handle all token specific yourself.
You can refer to this SO post for addition information.
Related
My code looks like this
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const token = process.env['token']
const password = process.env['pw']
const { createConnection } = require('mysql');
const database = createConnection({
host: 'localhost',
port: '3306',
user: 'root',
password: password,
database: 'db2',
charset: 'utf8mb4'
});
database.connect();
I'm still trying to learn how to read these error messages, so I can't tell if the problem is with the mysql install or with the code or the connection itself.
Here's the error from the console
Any help is greatly appreciated
You are getting a ECONNREFUSED error, this is indicating that for whatever reason it can not connect to the database. Seeing that you are getting a -111 error code I would guess that your MySQL instance was not running (or not running on the specified ip/port combination) based on the MariaDB troubleshooting page.
As for how to read those errors can be a bit of search work, but it will always indicate where in your code the error originated from. In this case it was the 4th line: at Object.<anonymous> (/path/to/file/bot.js:17:10).
The last part here is really helpful. This tells us that it originated from the file bot.js at line 17, character 10. Or in other words the error came from calling the .connect() function. From there you can use Google to search what could result in that error when calling that function with the error code (the error code is usually somewhere at the bottom of the error message).
I need to send emails using Node.JS and have been using NodeMailer with Gmail as the service so far. However, I am now required to use a non-Gmail account to continue. I received the following details of the new account: (I've slightly edited it for this thread to remove sensitive information)
Email Address: no-reply#service.co.za
Account / User Name: no-reply#service.co.za
Password: 1234
Incoming server: mail.service.co.za
Outgoing (SMTP) server: smtp.service.co.za
SMTP Authentication: On (same Username as incoming)
SMTP Port: 587
My code is as follows:
let transporter = nodemailer.createTransport({
host: 'smtp.service.co.za',
port: 587,
secure: false,
auth: {
user: 'no-reply#service.co.za',
pass: '1234'
}
});
const mailOptions = {
from: 'Company <no-reply#service.co.za>',
to: "john#gmail.com",
};
Later in my code I add subjects and bodies to the email, depending on the function and send it. I get the following error:
Error: Hostname/IP doesn't match certificate's altnames: "Host: smtp.service.co.za. is not in the cert's altnames: DNS:*.jnb1.host-h.net"
I've tried quite a few of the solutions in other threads regarding this issue. The only one which works is adding:
tls: {
rejectUnauthorized: false
},
But this apparently causes the email to become insecure, which is not a viable solution to me. So could anyone tell me how to properly use all the details of the new account given to me to set up a secure SMTP emailing function using NodeMailer?
I am trying to authenticate an outlook email account using nodemailer.
But, I continuously get the same message:
{ Error: Invalid login: 535 5.7.3 Authentication unsuccessful [CY1PR03CA0041.namprd03.prod.outlook.com]
at SMTPConnection._formatError (/user_code/node_modules/nodemailer/lib/smtp-connection/index.js:591:19)
at SMTPConnection._actionAUTHComplete (/user_code/node_modules/nodemailer/lib/smtp-connection/index.js:1320:34)
at SMTPConnection._responseActions.push.str (/user_code/node_modules/nodemailer/lib/smtp-connection/index.js:1278:18)
at SMTPConnection._processResponse (/user_code/node_modules/nodemailer/lib/smtp-connection/index.js:747:20)
at SMTPConnection._onData (/user_code/node_modules/nodemailer/lib/smtp-connection/index.js:543:14)
at TLSSocket._socket.on.chunk (/user_code/node_modules/nodemailer/lib/smtp-connection/index.js:694:51)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at TLSSocket.Readable.push (_stream_readable.js:134:10)
code: 'EAUTH',
response: '535 5.7.3 Authentication unsuccessful [CY1PR03CA0041.namprd03.prod.outlook.com]',
responseCode: 535,
command: 'AUTH LOGIN' }
Here is my code for nodemailer:
const functions = require('firebase-functions');
var nodemailer=require('nodemailer')
var transporter = nodemailer.createTransport("SMTP", {
auth: {
user: 'username',
pass: 'password'
},
service: "hotmail"
exports.sendMail
=functions.database.ref('requestedChats').onWrite((event)=>{
const data = {
from: 'username#outlook.com',
to: 'mytest#gmail.com',
subject: 'Hello',
text: 'Test 1235'
}
transporter.sendMail(data, (err, info)=> {
if(err)
console.log(err)
else
console.log(info)
})
})'
I had this issue sometime. Check the outlook account, see if the mail service provider sent you an email to enable remote login.
Login attempt are rejected when you're trying to login from a new server (seems to be IP-based checking). Once you manually approve the login attempt, that server will be 'whitelisted'.
Also check for the subject (email title). It should be plain text and should not consist html code.
If you still have this issue or don't received any email from the mail service provider, this is a real issue and better off contact the mail service provider for support.
You have to enable Authenticated SMTP Email app for the O365 user
Check this answer
I had the same problem and the issue was this:
I was using credentials provided by my hosting provider. The default setting was that the credentials were secured with GEO security, meaning the credentials wouldn't work outside my country. I was deploying on Heroku whose servers are abroad. That's why I could send emails from localhost but not from deployed app.
After I disabled the GEO security everything worked as it should.
You must enable SMTP login for the O365 mailbox or user in the admin settings
If the user has multifactor turned on, then you need to use "app password", normal password won't work if MFA is enabled.
You need to disable security defaults or adjust Conditional Access policies.
Check this answer
I'm trying to send an email from a Cloud Function using the sendmail package.
It works when I host my "send function" locally. And I can deploy the function without problems to my Firebase project.
In the log at Firebase I can see this message:
Error: queryMx ESERVFAIL hotmail.com
at errnoException (dns.js:28:10)
at QueryReqWrap.onresolve [as oncomplete] (dns.js:219:19)
I'm neither familiar with sending emails from servers or Cloud Functions for Firebase. My question is why I got this error and how I can make it work?
Here is an excerpt from my function:
sendmail({
from: body.name + ' ' + '<' + body.email + '>',
to: 'soerensmed#hotmail.com',
subject: 'Henvendelse via kontaktformular',
html: html,
}, function (err, reply) {
if (err) {
console.log(err && err.stack);
response.status(500).end()
}
else {
console.log(reply)
response.status(200).end()
}
});
I'm developing a website where people can contact me through a contact form. The goal is to receive an email with the message... If this approach isn't possible I'm open for suggestions on how I can set this contact-email-thing up using Angular and Firebase.
It will not work with cloud function with free spark account. You should upgrade as it is clearly defined in pricing section in network box. https://firebase.google.com/pricing/
I have a server with static IP in my home, I serve my own web pages with a domain and all works fine.
in my web pages, you can register by email and password. when you register a node module called nodemailer, sends an email from a google account, the problem is that the google account has a limit of the sent emails.
so I need to connect the nodemailer module to a server in my own home.
I search on google but nothing similar has the answer.
how to use postfix with nodejs??
http://www.postfix.org/
or how to use haraka module with nodemailer
https://github.com/baudehlo/Haraka
so I repeat my question, I need to send an email from my server to any email user that register in my web.
for example...
user jose#gmail.com register in my web
nodemailer configuration is...
exports.newRegistration=function(parametros,callback)
{
var mailOptions =
{
from: "<myemailingoogle#gmail.com>",//my email
to: parametros.useremail,//user email
subject: 'Welcome '+parametros.useremail+'.',
html: '<br><b>Hello</b><br>'+ // html
};
var smtpTransport = nodemailer.createTransport("SMTP",
{
service: "Gmail",
secureConnection: true,
auth:
{
user: "myemailingoogle#gmail.com",
pass: "7ftera359c28a",
},
});
smtpTransport.sendMail(mailOptions, function(err, response)
{
if(err)
{
smtpTransport.close();
console.warn(err);
return callback(err,null);
}else{
smtpTransport.close();
return callback(null,response);
}
});
}
the email sends ok, but it has a limit per day.
so I need to use an email server to send my emails with no limit.... tnx
EDIT 2
i install mailutils with apt-get
and now i try
mail mymailin#gmail.com
Cc: // press enter
Subject: Welcome
Hello Mail.
// Ctrl+D
this sends emails to my mailbox and I receive in SPAM an email sent from root#mail.mydomain.com
so, postfix is working, but I still can't send emails with emailjs or nodemailer...
when I try to send emails with emails or nodemailer I get this
smtp: '535 5.7.8 Error: authentication failed: generic failure\n'
I search in google that error and is and auth login error, I can't login to the system.
so I try with telnet
telnet localhost 25
ehlo localhost
250-mydomain.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
mail to: myuserin#gmail.com
501 5.5.4 Syntax: MAIL FROM:<address>
mail from: info#mydomain.com
250 2.1.0 Ok
rcpt to: myuserin#gmail.com
451 4.3.0 <myuserin#gmail.com>: Temporary lookup failure
data
554 5.5.1 Error: no valid recipients
AUTH LOGIN
503 5.5.1 Error: MAIL transaction in progress
I try again
220 mydomain.com ESMTP Postfix (Ubuntu)
ehlo localhost
250-mydomain.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH LOGIN
334 VXNlcm5hbWU6
UbuntuUser
535 5.7.8 Error: authentication failed: another step is needed in authentication
and again with root
220 mydomain.com ESMTP Postfix (Ubuntu)
ehlo localhost
250-mydomain.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth login
334 VXNlcm5hbWU6
root
334 UGFzc3dvcmQ6
rootPassword
535 5.7.8 Error: authentication failed: another step is needed in authentication
this is the log file
Jun 20 15:50:16 myname postfix/smtpd[12528]: warning: localhost[127.0.0.1]: SASL login authentication failed: another step is needed in authentication
and that's it... where is the problem in this???
I just had to do this as well, but I am running my node server on an Azure virtual Ubuntu Linux server. I imagine the same steps would work from your home server if you're running Ubuntu. Here is what I found worked:
I installed the postfix email server using this guide:
https://help.ubuntu.com/community/Postfix
It looked like a lot of work at first, but it worked for me pretty easily.
I found the easiest way to send the outgoing email from node.js was to use emailjs:
http://github.com/eleith/emailjs.git
I found that emails sent often end up being marked as spam. To help avoid this, you can go to wherever you manage your domain name (I use enom) and then configure an SPF record to help make your outgoing email look legit.
Here is my node.js module to send emails using emailjs:
var email = require("emailjs");
postfixSend = function postfixSend(emailInfo, callback) {
var server = email.server.connect({
user: "yourEmailAccountUser",
password: "yourPassword",
host: "localhost",
ssl: false
});
server.send({
text: emailInfo.msg,
from: emailInfo.from,
to: emailInfo.to,
subject: emailInfo.subject
}, function(err, message) {
callback(err);
});
}
exports.postfixSend = postfixSend;
i solve de problem with this...
article using postfix
i add some users in the sasldb2 and the emailjs works pretty well.
first of all install the postfix using the Svbaker tutorial but,
edit /etc/postfix/sasl/smtpd.conf adding the following lines instead:
pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: PLAIN LOGIN
thnx all your help, specially #Svbaker and serve you the solution to this problem.