Can't send mails using deno (SmtpClient module) - javascript

i just started learning deno and tried to send mails with it.
import { SmtpClient } from "./deps.js";
await client.connectTLS({
host: "smtp.163.com",
port: 465,
username: "my email",
password: "my password",
});
await client.send({
from: "mailaddress#163.com",
to: "t32n5nr#prowerl.com",
subject: "Mail Title",
content: "Mail Content,maybe HTML",
});
I did everything as said in SmtpClient docs
But i get an error
error: Uncaught ConnectionRefused: No connection could be made because the target machine actively refused it. (os error 10061)
at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
at Object.sendAsync ($deno$/ops/dispatch_json.ts:98:10)
at async Object.connectTls ($deno$/tls.ts:20:15)
at async SmtpClient.connectTLS (https://deno.land/x/smtp/smtp.ts:36:18)
at async file:///C:/.../controller.js:28:1

The "connection refused" message almost always resolve to one these two possibilities:
1. The server or service is unstable or unavailable.
In this situation there might be a few things going on the server:
Options 1.1 - Incorrect port / listener is down
The port you are using is correct but the listener (process on the servers) is down, meaning that you are connecting to the correct port, but there's no process to listen for your requests.
Possible solution is to try running telnet <address> <port> and check if the service is up. Example: telnet google.com 443.
Option 1.2 - Threshold limit
The port and the service are up, but you've reached the threshold that limits the configured TCP connectivity.
That might occur due to high traffic (peaks) to the endpoint. That is not something you can solve yourself. TCP listeners might reject the caller connection if the traffic is too high.
One way of testing these is to implement a load testing script that tests the connectivity over time. If you prove that the server is limiting the requests you can then report and ask them to increase the load capabilities (allow for a higher capacity for simultaneous requests).
2. The client cannot communicate with the server
Option 2.1 - Proxy
If you are connection from an enterprise network and there is a proxy in between, that might be why you are having such difficulties.
Solution: run your code from home or an external network to prove that you are able to connect from outside the corporate network.
Option 2.2 - Firewall
Just like the proxy, you're running your code behind a firewall that is either blocking or interfering with your communication with the external network.
I was able to run your code and connect to Google using my personal credentials. I had to perform a slight change due to a problem to the Deno library due to type definitions but it worked fine.
I strongly suspect that your problem is related to the infrastructure (local or remote), not to the Deno runtime or library.
import { SmtpClient } from "https://deno.land/x/smtp/mod.ts";
import { ConnectConfigWithAuthentication } from "https://raw.githubusercontent.com/manyuanrong/deno-smtp/master/config.ts";
const client = new SmtpClient();
const params = <ConnectConfigWithAuthentication>{
hostname: "smtp.google.com",
port: 465,
username: "<google mail>",
password: "<password>"
}
await client.connectTLS(params);
await client.send({
from: "<from_email>", // Your Email address
to: "<to_email>", // Email address of the destination
subject: "Mail Title",
content: "Mail Content,maybe HTML",
});
await client.close();
I tried to create a user on the smtp.163.com website but I couldn't understand the language, if you give me test credentials I try myself.

Related

How to use proxy and ignore specific request ssl errors

Good day, I am trying to connect to a third party rest API which is kinda old and has its certificate expired. I am using NodeJS and axios for sending request which at the moment looks something like this.
agent = new HttpsProxyAgent({ host, port, auth: `${uname}:${pass}` });
this.client = axios.create({
baseURL: this.baseUrl,
headers: this.headers,
httpsAgent: agent,
});
the agent above creates a proxy agent so my request would tunnel through that host which i am later mounting on axios, i am using this package https-proxy-agent. Now the proxy works fine and all, but it throws an error certificate has expired. I have tried to use rejectUnauthorized: false but that didn't work at all, however i found one more solution and that is to use NODE_TLS_REJECT_UNAUTHORIZED=0. But it is widely described as dangerous to use on the server, i also wonder if i will use this environment variable would it make client requests visible when intercepting?
What i need here is to just connect to the proxy and reject certificate errors only for this axios client, if there are solutions for other http clients feel free to share, thank you very very much.
Managed to solve the issue with a different package.
import { getProxyHttpAgent } from 'proxy-http-agent';
const proxyUrl = `http://${host}:${port}`;
agent = getProxyHttpAgent({
proxy: proxyUrl,
endServerProtocol: 'https:',
rejectUnauthorized: false,
});
setting agent with this package works great, except for some reason i have to use non authentication based proxy otherwise it would throw some weird ssl error which looks like this
tunneling socket could not be established, cause=write EPROTO 20920:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:c:\ws\deps\openssl\openssl\ssl\record\ssl3_record.c:332:.

MQTT TLS connection

I would like to connect a test MQTT-Client to my Node.js application as a MQTT-Broker. I am using the aedes library from moscajs
My MQTT-Client is the tool "MQTT-Explorer" and here is my Node.js application:
const fs = require('fs');
const aedes = require('aedes')();
const options = {
key: fs.readFileSync('certs/server_key.pem'),
cert: fs.readFileSync('certs/server_cert.pem'),
};
// const server = require('net').createServer(aedes.handle);
const server = require('tls').createServer(options, aedes.handle);
const PORT = 8881;
server.listen(PORT, () => {
console.log(`server is up and running: PORT [${PORT}] - ID [${aedes.id}]`);
});
I can connect without any problems to PORT=1881 with const server = require('net').createServer(aedes.handle) and I also can connect to PORT=8881 with const server = require('tls').createServer(options, aedes.handle)
With the Tool xca-2.4.0.msi XCA 2.4.0 I have created a ca.pem CERTIFICATE File and a CERTIFICATE server_cert.pem and a server_key.pem PRIVATE KEY (signed from ca.pem) as a Server. The key for CA and the Server are different:
For my MQTT-Client, under ADVANCED, CERTIFICATES, SERVER CERTIFICAT (CA) I selected the ca.pem File. If I select "Encryption", it works. But if select "validate certificate", error: Hostname/IP does not match certificate's altnames: IP: 127.0.0.1 is not in the certs list
Unfortunately I don't know what I'm doing wrong, thanks in advance :(
MQTT Explorer is built using Node.js and the MQTT library MQTT.js. As per this issue:
Node.js requires the IP address to be in the subjectAltNames for the cert and not in the CN. Maybe MQTT.fx isn't requiring that, but it should.
and:
If your server's certificate says CN=localhost in the Subject field, connect using localhost and not 127.0.0.1 and it should work. If it says CN=127.0.0.1, you have to make a new one because Node.js won't validate the IP address unless it's in the SAN extension. There is a way to work around it in code (I think it's an option called checkServerIdentity), but I would prefer to fix my certificate if I had this problem.
A rationale for the approach taken in Node is set out in this answer which includes the following quote from RFC2818: HTTP Over TLS
:
In some cases, the URI is specified as an IP address rather than a hostname. In this case, the iPAddress subjectAltName must be present in the certificate and must exactly match the IP in the URI.
As you are using MQTT over TLS (as opposed to HTTP Over TLS) you could argue that the above does not apply but, given that the main use of the TLS library is for HTTP traffic, it makes sense that it confirms to the RFC by default.
You have a few options including:
Use a hostname (e.g. localhost) rather then an IP when creating the certificate/connecting.
Add the IP as a subjectAltName
Modify the library to use a noop checkServerIdentity (see this answer).
Use another application for testing (not really recommended as some applications will work and others will not). The issue quoted above mentions that MQTT.fx works.

Node.js Soap Client outgoing network interface

I'm using Node.js' Soap Client (https://github.com/vpulim/node-soap) for some extensive integration with other service. However, this is not the only integration running on my server, and I would like to make my calls from another network interface (i.e. "external IP")
My software layer is pretty much complete, but this is something that I've not predicted. Can I possibly do this with some setting, or maybe some Node.js' launch argument?
I was thinking about a locally running proxy server (even in the same thread as the app), but - if possible - I'd welcome some more elegant option.
OK, i've managed to achieve this by using request module (https://github.com/request/request) and simply changing one line of code:
soap.createClientAsync('https://example.com/service.php?wsdl', {
'request': request.defaults({
localAddress: 'xxx.xxx.xxx.xxx',
connection: 'keep-alive'
})
})

Websocket Server, based on socketo.me not accepting connections from shared internet

I managed to configure a simple websocket server according to this tutorial in AWS EC2 instance and its working fine.
But only from my home internet connection which has a real IP and told as a dedicated internet line.
I tried with a very simple javascript example code from client side (using a HTML page) and it works perfectly if I use that dedicated internet connection from my PC/Mac. (I used autobahn.min.js) above the following script.
var conn = new ab.Session('ws://X.X.X.X:8080',
function() {
console.log("Connection established!");
// To Do: Subscribe with client ID
},
function() {
console.warn('Connection closed!');
},
{'skipSubprotocolCheck': false}
);
but it fails if I run the same simple file/script from under another shared internet connection such as cellular data or something like that. I get the following error in browser console.
WebSocket connection to 'ws://X.X.X.X:8080/ws' failed: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT example.com Connection closed!
The server is in AWS EC2 instance. Yes, 8080 is enabled under security group. Actually all works fine except client connection goes from some specific types of internet connection based computer.
Thanks in advance for any help!

event stream request not firing close event under passenger apache

So I have an event stream in my express js node application. Here's an overview:
app.get('/eventstream', function(req, res){
req.socket.setTimeout(Infinity);
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
res.write('/n');
req.on('close', function(){
console.log('connection closed');
});
}
On my local dev box, running from the command line with
node app.js
it works fine, and prints out 'connection closed' when i close my tab in my browser.
However, when running on my server, under Apache with Passenger, it doesn't print out any message - the server seems to not fire the 'close' event. I'm using this event to remove from my count of active users. Any ideas?
Cheers,
Dan
Phusion Passenger author here. The short answer is: technically, the connection hasn't closed yet.
Here's the long answer. If the client connects directly to your Node.js process, then yes, the connection is closed. But with Phusion Passenger there's a proxy in between the client and Node.js. The thing about sockets is that there are two ways to find out whether a socket has been closed: either 1) by reading end-of-file from it, or 2) by writing to it and getting an error. Phusion Passenger stops reading from the client as soon as it has determined that the request body has ended. And in case of GET requests, that is immediately after header. Thus, the only way Phusion Passenger can notice that the client has closed to the connection, is by sending data to it. But your application never sends any data after that newline, and so Phusion Passenger doesn't do that either and never notices that the connection is closed.
This issue is not limited to Phusion Passenger. If you put your Node.js app behind a load balancer or any other kind of reverse proxy, then you could also run into the same issue.
The standard solution is to regularly send "ping" messages, with the purpose of checking whether the connection is alive.
A similar issue also applies to WebSockets. It is the reason why the WebSocket supports ping frames.
UPDATE February 28, 2016:
We have found a solution, and Passenger 5.0.26 and later supports forwarding half-close events which fixes the problem described by #coffeedougnuts. Just use 5.0.26 and later and it'll work as expected.

Categories

Resources