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?
Related
I'm mounting an API in Google Cloud Run that connects to an MySQL DB server using Sequelize.
This is the standard setup:
index.js file
const DB_CONFIG = require('../db/db.config');
const Sequelize = require('sequelize')
let sequelize = new Sequelize(
DB_CONFIG.NAME,
DB_CONFIG.USER,
DB_CONFIG.PASSWORD,
{ host: DB_CONFIG.HOST, dialect: DB_CONFIG.DIALECT, pool: DB_CONFIG.POOL }
)
db.config.js file
module.exports = {
NAME: process.env.DB_NAME,
HOST: process.env.DB_HOST,
USER: process.env.DB_USER,
PASSWORD: process.env.DB_PASSWORD,
DIALECT: process.env.DB_DIALECT,
POOL: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
};
The problem comes when I start the project, it fails with an error that shows it is trying to connect to the same IP as the local machine public IP:
{
code: 'ER_ACCESS_DENIED_ERROR',
errno: 1045,
sqlState: '28000',
sqlMessage: "Access denied for user 'DB_USER'#'LOCAL_MACHINE_IP' (using password: YES)",
sql: undefined
}
The problem happens either if I write the final values directly in the db.config file or the values are read from process.env.
It is important to not that I'm using the Google Cloud Secret Manager to inject this values to process.env.
Also, the execution logs in Google Cloud Run shows that the API is trying to connect using the local IP.
What could be happening, and how can I search the cause of this error?
There is nothing wrong with that IP address as the host name in a mysql user account indicates the client you are connecting from, not the mysql server's IP address you are connecting to.
See mysql manual on account names for details.
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'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.
I consistently get a SequelizeConnectionRefusedError when trying to connect to a MySQL database on my server.
The login credentials are correct, the port is open, everything seems good (and works like a charm in the dev environment).
Sorry for the scarce background information, but I'm dumbfounded here - I really don't know what could be causing this problem.
This is my output from mysql --version
mysql Ver 14.14 Distrib 5.5.43, for debian-linux-gnu (x86_64) using readline 6.3
And this is the code I'm using to initialize Sequelize. The table I want it to use doesn't exist yet, but I'm fairly sure that hasn't got anything to do with this problem. I've tried logging in with the root user as well, but no dice - I still get the same error.
var sequelize = new Sequelize("database", username, password, {
host: "localhost",
dialect: "mysql",
port: 3306,
define: {
paranoid: true
}
});
var Model = sequelize.define("Model", {
md5: {type: Sequelize.STRING(128)},
ip: {type: Sequelize.STRING(256)},
url: {type: Sequelize.STRING(1024)}
});
sequelize.sync();
This is running on Ubuntu 14.04, where node is being run behind Passenger (although the error appears if I run the application with node directly as well). I'm running nginx and PHP on the same server, where another PHP application is connecting to the database, if that's of any relevance.
What could be causing this problem?
I tried to connect to the database directly with the MySQL module as well, but that gave me the same error. When looking for solutions to the same problem, but related to the MySQL module rather than Sequelize, I found this: connect ECONNREFUSED - node js , sql.
What I needed was to supply the mysql module with a socketPath key. Here's how I changed my code to make it work:
var sequelize = new Sequelize("database", username, password, {
host: "localhost",
dialect: "mysql",
logging: function () {},
pool: {
max: 5,
min: 0,
idle: 10000
},
dialectOptions: {
socketPath: "/var/run/mysqld/mysqld.sock"
},
define: {
paranoid: true
}
});
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.