nodemailer occasional ETIMEDOUT while alternate method is successful - node.js

Context
Windows Server 2012 R2 Standard, not behind a network proxy
NodeJS 6.11.3
Nodemailer 4.1.0
This snippet tries to send email to an in-house SMTP server on the same network that does not require authentication:
var transporter = nodemailer.createTransport({
host: "smtp.example.com",
port: 25,
secure: false
});
var mailOptions = {
'from': 'noreply#example.com',
'to': 'someone#example.com',
'subject': 'test email',
'text': 'some text for a body',
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
// do something
} else {
// do something else
}
});
The following is an alternate script (VBScript) that we're executing ad hoc just for testing.
Set objMail=CreateObject("CDO.Message")
objMail.From="noreply#example.com"
objMail.To="someone#example.com"
objMail.Subject="Test from new server"
objMail.TextBody = "This is a message."
objMail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing")=2
objMail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver")="smtp.example.com"
objMail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport")=25
objMail.Configuration.Fields.Update
objMail.Send
Set objMail=nothing
Problem
Set up a setInterval() to try to send email with Nodemailer once per minute.
Sometimes the email is sent but more often we get the following error.
{ Error: connect ETIMEDOUT XXX.XXX.XX.XX:25
at Object.exports._errnoException (util.js:1020:11)
at exports._exceptionWithHostPort (util.js:1043:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1086:14)
code: 'ECONNECTION',
errno: 'ETIMEDOUT',
syscall: 'connect',
address: 'XXX.XXX.XX.XX',
port: 25,
command: 'CONN' }
No apparent correlation to restarting the server, frequency of calls to the script, etc.
What's most strange (to me) is that right in the middle of, say, 40 failed Nodemailer attempts, executing the VBScript sends an email through just fine. It never fails.
Resolution Attempts
I've looked at dozens of nodemailer usage examples and read the nodemailer documentation. I can't tell that I'm doing anything wrong; the firewall isn't blocking us, we're not behind a network proxy, the SMTP server doesn't require authentication.
I don't see any files named util.js or net.js that I could investigate.
I've read every Stack Overflow post mentioning the ETIMEDOUT error.
Questions
Am I doing anything wrong? If so, what?
If I'm not, then what could cause this behaviour? What should I ask my system / network admins to investigate?

This turned out to be caused by a problem outside my application. Thus, I'm answering the following portion of my original question set, in case someone else gets that same error message / experiences the same intermittent behaviour and is looking for possible causes outside her/his app: "[w]hat could cause this behaviour? What should I ask my system / network admins to investigate?"
In my example, the host parameter was set to "smtp.example.com" (which is, of course, not the real hostname). On our network, the hostname I was given can resolve to either of two IP addresses. When it resolved to one IP address, the SMTP server was reached and the message was accepted for queueing. When it resolved to the other IP address, the SMTP server was not reached and the timedout error was the result.
Until the network admins figure out the problem, I'm skipping the hostname and sending directly to the IP address that works.

Related

Nodemailer: My frontend website can't send emails through node mailer from a different IP address

My frontend portfolio has an emailing option which sends a post req to nodemailer in the backend.
My portfolio is already deployed in firebase and I'm currently running the backend on the localhost server.
I face no issues when I send emails on my laptop, same IP address, while I receive an error whenever I try sending emails on a different device.
I have searched around for a day now and I can't find an available solution. Any idea on how I can solve this issue?
My nodemailer configuration:
const transporter = nodemailer.createTransport(smtpTransport({
name: 'domainname',
host: 'domainname.com',
port: 443,
secure: true,
service: 'gmail',
auth: {
user: '*****#gmail.com',
pass: '******' //Google's less secure apps option enabled.
},
tls: {
// do not fail on invalid certs
rejectUnauthorized: false,
}
}))
The following error is logged into the console when sending email fails:
POST http://localhost:4000/api/email/ net::ERR_CONNECTION_REFUSED
TypeError: Failed to fetch
at main.1ec56b92.js:2:347746
at c (main.1ec56b92.js:2:168378)
at Generator._invoke (main.1ec56b92.js:2:168166)
at Generator.next (main.1ec56b92.js:2:168807)
at Ft (main.1ec56b92.js:2:332714)
at i (main.1ec56b92.js:2:347506)
at main.1ec56b92.js:2:347567
at new Promise (<anonymous>)
at main.1ec56b92.js:2:347446
at main.1ec56b92.js:2:348157
Thank you
As Derpirscher pointed out, the host of the backend was hardcoded as localhost:4000 hence why it worked on my laptop and failed on my phone.
The solution for me was to deploy the code to a server -like Heroku- and use its address to connect to the nodemailer API, eg: https://project.herokuapp.com/api/email instead of https://localhost:4000/api/email

nodemailer SMTP server connection issue (Error: connect ETIMEDOUT) but it works for another system not in mine

Iam trying to send node mailer using webmail instead of GMail using smtp sever as follows..
// config connections
"nodemailer" : {
"host": "smtp.in-sciencelabs.com",
"port": 587,
"auth": {
"user": "myuser.com",
"pass": "myp#ssword"
}
// in nodemailer.js code iam importing the config details....
const transporter=
nodemailer.createTransport(smtpTransport((config["nodemailer"])));
var mailOptions = {
from: `${config["nodemailer"]["user"]}`,
to: tomail,
subject: subject ,
text: data
};
transporter.verify(function(error, success) {
if (error) {
console.log(error,"17");
} else {
console.log("Server is ready to take our messages");
}
});
i tried to verify the connections so its shows an error like this
(Error: connect ETIMEDOUT)***.**.***.***:587
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1146:16) {
errno: -4039,
code: 'ECONNECTION',
syscall: 'connect',
address: 'xxx.xx.xxx.xxx',
port: 587,
command: 'CONN'
}
here iam trying this but its not workout for me but in another system emails are sending so i dont know which setting is going to change in system for sending an email could you please help me out from this problem and i also changed the node version to 12.18.3
Have you looked at this answer.
It turns out that in order for Google to authorize a third party server to access your account via SMTP now, you have to enable “Less Secure Apps” on your gmail account, if you want to use username/password (more info here).
So you have two option:
use OAuth
make your account less secure
you also need to check your server firewall setting,
This may be firewall problem, Problem can be solved by enabling TCP inbound and outbound in firewall settings on your server, if you are using digital ocean then you can find it in firewall settings in panel

Openssl issue when sending email through AWS SES

Update:
If I follow the instructions from Using the Command Line to Send Email Using the Amazon SES SMTP Interface, I can get the email to send perfectly from my local and my ec2 instance.
We're using nodemailer to send email through SMTP. When we configure everything using Gmail's SMTP user/pass, everything works fine.
We're trying to move to AWS SES. Everything is seemingly set up fine (domains are verified, we're out of SANDBOX mode, and we're using the SMTP user/pass credentials).
We're using the exact same code, and just swapping out the smtp user/pass/host in our credentials file. When sending the mail with the SES credentials, we're getting this error:
Email was not send due to the following error: [Error: 62024:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:c:\ws\deps\openssl\openssl\ssl\record\ssl3_record.c:332:
] {
library: 'SSL routines',
function: 'ssl3_get_record',
reason: 'wrong version number',
code: 'ESOCKET',
command: 'CONN'
}
According to this GitHub issue, the problem seems to be:
You are either trying to use TLS on a non-TLS port or the openssl
version you use is not compatible with the server.
I'm not quite sure what to do with that information. Our SSL cert is on ELB.
Here's the code that's responsible for sending the actual email:
"use strict";
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
secure: process.env.SMTP_SECURE,
auth: {
user: process.env.SMTP_AUTH_USER,
pass: process.env.SMTP_AUTH_PASS
}
});
module.exports = {
sendMail: (to, subject, html, callback) => {
const mailOptions = {
from: "no-reply#xyz.com",
to,
subject,
html
};
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return callback(err);
}
return callback(null, info);
});
}
};
TLDR;
Use port 465 when the secure option is true.
What I Did
I went by the comment of #moulder on the question and it worked.
To be clear, you should use 465, true to use SSL to connect, or 587, false to connect without SSL and upgrade via STARTTLS. Any other combination won't work. The code was buggy, fixing it here:
Source: Fabien Potencier at symfony/symfony#34846
See also symfony/symfony/34067
What Amazon Says
Just like there are HTTP and HTTPS ("s" for secure), there is SMTP and SMTPS (kinda)... As for the secure version of the communication, there are to ways to establish that security.
STARTTLS - The client connects with no security. The server says it supports security. Then, the client negotiates security contracts with the SMTP server and migrate from insecure to secure communication.
TLS Wrapper - The client goes secure from the beginning.
Source: Amazon SES Docs - Connecting to an SMTP endpoint

aws ec2 getaddrinfo ENOTFOUND error code

My aim is to get the instanceId when my script is started. (Cause I want to connect my webserver as backend with the aws elb. This even works when I hardcode the id) So now I try to code a function wich gives me the id.
So what I know is that I need the AWS.metadataService but I don't know how to use it. I found this documentation (metaDataService) an command-line tool. I guess I need to combine it like this:
var meta = new AWS.MetadataService();
meta.request("http://169.254.169.254/latest/meta-data/", function(err, data){
if(err){
console.log(err);
}
console.log(data);
});
But it produces this error:
{ [Error: getaddrinfo ENOTFOUND 169.254.169.254http 169.254.169.254http:80]
code: 'ENOTFOUND',
errno: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: '169.254.169.254http',
host: '169.254.169.254http',
port: 80 }
Any ideas what could fix this? Or at least what causes this error.
Hope it helps.
var meta = new AWS.MetadataService({
host: '169.254.169.254'
});
meta.request('/latest/meta-data/', function(err, data){
if(err){
console.log(err);
}
console.log(data);
});
As the error message rather clearly tells you, you somehow ended up passing in 169.254.169.254http as the host name, and 169.254.169.254http:80 as the host. Just to spell this out completely, you probably wanted the host to be 169.254.169.254. You need to figure out why your request was botched like this, and correct the code or your configuration files so you send what you wanted to send.
ENOTFOUND in response to getaddrinfo simply means that you wanted to obtain the address of something which doesn't exist or is unknown. Very often this means that you have a typo, or that the information you used to configure your service is obsolete or otherwise out of whack (attempting to reach a private corporate server when you are outside the corporate firewall, for example).

Accessing SMTP server with AUTH NTLM from Node.js

I'm trying to access a SMTP server with AUTH type of NTLM.
I'm using nodemailer and nodemailer-smtp-transport as such:
var config = require('./config.json');
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var transporter = nodemailer.createTransport(smtpTransport({
host : config.mailer.host,
port: config.mailer.port,
auth: {
user: config.mailer.username,
pass: config.mailer.password
},
authMethod: 'PLAIN'
}));
But it doesn't work. The error I get is:
{ [Error: Invalid login: 504 5.7.4 Unrecognized authentication type]
code: 'EAUTH',
response: '504 5.7.4 Unrecognized authentication type',
responseCode: 504 }
Which makes sense, because if I telnet into the SMTP server
ehlo server.domain.net
250-server.domin.net Hello [10.100.10.100]
250-SIZE
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-X-ANONYMOUSTLS
250-AUTH NTLM
250-X-EXPS GSSAPI NTLM
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250-XEXCH50
250 XRDST
And enter
AUTH PLAIN
I get
504 5.7.4 Unrecognized authentication type
But inside Node, if I change the authMethod to 'NTLM', I get an error that says
{ [Error: Unknown authentication method "NTLM"] code: 'EAUTH' }
I'm suspecting that nodemailer just doesn't support NTLM. If that's the case, how do I connect to a SMTP server that requires NTLM authentication type?
Thanks
My company ran into the same problem a few days ago. The options we considered were:
Ask the exchange server admins to enable PLAIN auth under STARTTLS (it is secure and appears to only involve ticking a couple of checkboxes)
Set up a local relay (e.g. postfix) that relays to Exchange, and use the postfix relay from nodemailer
Fork nodemailer and add NTLM support
Unfortunately we hit political issues on the easy options (1) and (2), so had to fork nodemailer.
I didn't send a pull request yet, but the fork is here. For the time being the easiest way to use it is via npm by referring directly to the github project in your package json, e.g.:
"dependences": {
"nodemailer": "steveliles/nodemailer"
}
If you're interested, most of the change was actually in a sub-sub-project (smtp-connection), and the forks of nodemailer, nodemailer-smtp-pool, and nodemailer-smtp-transport are only necessary to get my smtp-connection fork to be picked up.
We didn't need to implement the NTLM protocol, as SamDecrock's httpntlm already did the hard work.
It has only been tested against Exchange 2007 over TLS (with STARTTLS) and no domain or workstation.
If you do need domain + workstation in the credentials, just add them to nodemailer's options.auth and they will be passed through, e.g.
var smtpConfig = {
host: 'ntlm.boo.hoo',
port: 25,
auth: {
domain: 'windows-domain',
workstation: 'windows-workstation',
user: 'user#somedomain.com',
pass: 'pass'
}
};
We were even more unlucky in that the exchange server we're connecting to doesn't have a valid SSL certificate, but luckily nodemailer can handle that by setting tls: {rejectUnauthorized: false} in the options.
From version 6.x.x, you can use custom auth:
https://github.com/nodemailer/nodemailer-ntlm-auth
Refs: https://nodemailer.com/smtp/#authentication
If this is an internal/service type application and your server admin doesn't mind, you can ask them to create a host without authorization and just get rid of
auth: {
user: '-----------',
pass: '-----------'
}
Since I'm just creating a service type app just to send emails on a schedule, my server admin allowed this for me.
Worked for me but I'm sure this solution is not for everyone!

Resources