Node.js 网络模块,从回调函数中获取数据
Node.js Net Module, Getting data out of the callback function
所以我试着自己解决它并用谷歌搜索了很多但我无法真正解决问题,虽然我认为它不应该那么困难。所以我正在做的(或试图做的)是,我建立一个简单的 telnet 连接到服务器并模拟 SMTP 会话的开始以验证电子邮件是否存在(如果这给我正确的结果是另一个问题)
我的代码如下所示:
const net = require('net');
async function TCPConnection(smtpServer, emailDomain, senderEmail) {
const client = new net.Socket();
client.setEncoding("utf-8");
let completeData = '';
client.connect({port: 25, host: smtpServer}, () => {
console.log("TCP Connection established with the Server.");
})
client.write("ehlo " + emailDomain + "\r\n");
client.write("mail from:<" + senderEmail + ">\r\n");
client.write("rcpt to:<" + senderEmail + ">\r\n");
client.on('data', function (data) {
console.log(data);
});
function dataReceived(data){
completeData += data;
}
client.on('end', function () {
console.log('Requested an end to the TCP connection');
});
}
TCPConnection('aspmx.l.google.com', 'mailtrap.io', 'new-recipient@mailtrap.io');
记录到控制台的服务器响应如下所示:
TCP Connection established with the Server.
220 mx.google.com ESMTP m17si1129948edf.309 - gsmtp
250-mx.google.com at your service, [217.84.87.66]
250-SIZE 157286400
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
250 2.1.0 OK m17si1129948edf.309 - gsmtp
550-5.1.1 The email account that you tried to reach does not exist. Please try
550-5.1.1 double-checking the recipient's email address for typos or
550-5.1.1 unnecessary spaces. Learn more at
550 5.1.1 https://support.google.com/mail/?p=NoSuchUser m17si1129948edf.309 - gsmtp
所以我想要实现的是从回调或 TCPConnection 函数中获取完整的数据(即现在记录到控制台)。例如“return completeData;”在 TCPConnection 函数的末尾。
我想这样做的原因是,这个函数 (TCPConnection) 是通过 HTTP 请求调用的。我想将此结果发送回客户端。完整的功能可能看起来像这样(但显然到目前为止还没有工作):
app.post('/tcpConnection', (req, res) => {
let smtpServer = req.body.smptServer;
let domain = req.body.domain;
let senderEmail = req.body.senderEmail;
async function sendResponse(){
let response = await TCPConnection(smtpServer,domain,senderEmail);
await res.status(200).json(result);
}
})
我读到的解决方案可能是在发出“结束”事件后对我的数据执行我想执行的操作。但我的问题是,在我的三个“写入命令”之后,服务器不会立即结束连接。如果我这样写:
client.write("ehlo " + emailDomain + "\r\n");
client.write("mail from:<" + senderEmail + ">\r\n");
client.write("rcpt to:<" + senderEmail + ">\r\n");
client.end();
在第二个和第三个命令得到响应之前结束连接。我试图用“等待 client.write...”来“等待”响应,但由于不确定原因,这显然行不通。
如果您不方便提问,我希望您能大致了解我要完成的工作。谢谢!
所以我想我已经自己完成了,或者至少得到了一个在大多数情况下都能正常工作的解决方案。我正在做的是在第三个写命令的回调中结束套接字,如下所示:
client.write("rcpt to:<" + senderEmail + ">\r\n","utf-8",()=>{
console.log("third command written");
client.end();
});
通过这样做,服务器“应该有足够的时间”来回答所有命令。
更简单的解决方案是计算 'data' 事件的回调函数中的响应数,如下所示:
client.on('data', function (data) {
counterResponses++;
console.log("Response Nr: " + counterResponses + '\r\n' + data);
completeData.push(data);
if (counterResponses === 4){
console.log("4 responses received end connection");
client.end();
}
});
因为我想在收到对我的命令的 4 个响应后结束套接字,所以我使用 if-statement 来检查响应的数量。但这样做的问题是,有时多个响应可能会作为一个响应发送。例如,响应可能如下所示:
Response Nr: 1
220 mtaproxy104.free.mail.ir2.yahoo.com ESMTP ready
Response Nr: 2
250-mtaproxy104.free.mail.ir2.yahoo.com
250-PIPELINING
250-SIZE 41943040
250-8BITMIME
250 STARTTLS
但也像这样:
Response Nr: 1
220 mtaproxy104.free.mail.ir2.yahoo.com ESMTP ready
250-mtaproxy104.free.mail.ir2.yahoo.com
250-PIPELINING
250-SIZE 41943040
250-8BITMIME
250 STARTTLS
所以 2 个回复会作为一个回复发送。这使得很难评估我是否得到了我需要得到的所有答复。这就是为什么我在最后一个 write-command.
之后结束套接字的原因
在 client.on('end') 函数中,我将完整数据发送回客户端。
client.on('end', function () {
console.log('Requested an end to the TCP connection');
console.log(completeData);
res.status(200).json(completeData);
});
唯一仍然困扰我的是我的数组(我在其中推送每个发出的 'data' 事件的数据)的长度是可变的。如果找到电子邮件,这将使验证变得有点困难。但是由于这应该始终是最后一个响应,所以如果我只测试数组的最后一个条目是否包含状态码“250”或“550”,它应该在大多数情况下都有效。
我希望这至少对某些人有所帮助。如果它对您有帮助或者您对此有任何疑问,请告诉我。也仍然对更好的解决方案持开放态度,因为我确信有更好的方法可以做到这一点。
所以我试着自己解决它并用谷歌搜索了很多但我无法真正解决问题,虽然我认为它不应该那么困难。所以我正在做的(或试图做的)是,我建立一个简单的 telnet 连接到服务器并模拟 SMTP 会话的开始以验证电子邮件是否存在(如果这给我正确的结果是另一个问题)
我的代码如下所示:
const net = require('net');
async function TCPConnection(smtpServer, emailDomain, senderEmail) {
const client = new net.Socket();
client.setEncoding("utf-8");
let completeData = '';
client.connect({port: 25, host: smtpServer}, () => {
console.log("TCP Connection established with the Server.");
})
client.write("ehlo " + emailDomain + "\r\n");
client.write("mail from:<" + senderEmail + ">\r\n");
client.write("rcpt to:<" + senderEmail + ">\r\n");
client.on('data', function (data) {
console.log(data);
});
function dataReceived(data){
completeData += data;
}
client.on('end', function () {
console.log('Requested an end to the TCP connection');
});
}
TCPConnection('aspmx.l.google.com', 'mailtrap.io', 'new-recipient@mailtrap.io');
记录到控制台的服务器响应如下所示:
TCP Connection established with the Server.
220 mx.google.com ESMTP m17si1129948edf.309 - gsmtp
250-mx.google.com at your service, [217.84.87.66]
250-SIZE 157286400
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
250 2.1.0 OK m17si1129948edf.309 - gsmtp
550-5.1.1 The email account that you tried to reach does not exist. Please try
550-5.1.1 double-checking the recipient's email address for typos or
550-5.1.1 unnecessary spaces. Learn more at
550 5.1.1 https://support.google.com/mail/?p=NoSuchUser m17si1129948edf.309 - gsmtp
所以我想要实现的是从回调或 TCPConnection 函数中获取完整的数据(即现在记录到控制台)。例如“return completeData;”在 TCPConnection 函数的末尾。
我想这样做的原因是,这个函数 (TCPConnection) 是通过 HTTP 请求调用的。我想将此结果发送回客户端。完整的功能可能看起来像这样(但显然到目前为止还没有工作):
app.post('/tcpConnection', (req, res) => {
let smtpServer = req.body.smptServer;
let domain = req.body.domain;
let senderEmail = req.body.senderEmail;
async function sendResponse(){
let response = await TCPConnection(smtpServer,domain,senderEmail);
await res.status(200).json(result);
}
})
我读到的解决方案可能是在发出“结束”事件后对我的数据执行我想执行的操作。但我的问题是,在我的三个“写入命令”之后,服务器不会立即结束连接。如果我这样写:
client.write("ehlo " + emailDomain + "\r\n");
client.write("mail from:<" + senderEmail + ">\r\n");
client.write("rcpt to:<" + senderEmail + ">\r\n");
client.end();
在第二个和第三个命令得到响应之前结束连接。我试图用“等待 client.write...”来“等待”响应,但由于不确定原因,这显然行不通。
如果您不方便提问,我希望您能大致了解我要完成的工作。谢谢!
所以我想我已经自己完成了,或者至少得到了一个在大多数情况下都能正常工作的解决方案。我正在做的是在第三个写命令的回调中结束套接字,如下所示:
client.write("rcpt to:<" + senderEmail + ">\r\n","utf-8",()=>{
console.log("third command written");
client.end();
});
通过这样做,服务器“应该有足够的时间”来回答所有命令。
更简单的解决方案是计算 'data' 事件的回调函数中的响应数,如下所示:
client.on('data', function (data) {
counterResponses++;
console.log("Response Nr: " + counterResponses + '\r\n' + data);
completeData.push(data);
if (counterResponses === 4){
console.log("4 responses received end connection");
client.end();
}
});
因为我想在收到对我的命令的 4 个响应后结束套接字,所以我使用 if-statement 来检查响应的数量。但这样做的问题是,有时多个响应可能会作为一个响应发送。例如,响应可能如下所示:
Response Nr: 1
220 mtaproxy104.free.mail.ir2.yahoo.com ESMTP ready
Response Nr: 2
250-mtaproxy104.free.mail.ir2.yahoo.com
250-PIPELINING
250-SIZE 41943040
250-8BITMIME
250 STARTTLS
但也像这样:
Response Nr: 1
220 mtaproxy104.free.mail.ir2.yahoo.com ESMTP ready
250-mtaproxy104.free.mail.ir2.yahoo.com
250-PIPELINING
250-SIZE 41943040
250-8BITMIME
250 STARTTLS
所以 2 个回复会作为一个回复发送。这使得很难评估我是否得到了我需要得到的所有答复。这就是为什么我在最后一个 write-command.
之后结束套接字的原因在 client.on('end') 函数中,我将完整数据发送回客户端。
client.on('end', function () {
console.log('Requested an end to the TCP connection');
console.log(completeData);
res.status(200).json(completeData);
});
唯一仍然困扰我的是我的数组(我在其中推送每个发出的 'data' 事件的数据)的长度是可变的。如果找到电子邮件,这将使验证变得有点困难。但是由于这应该始终是最后一个响应,所以如果我只测试数组的最后一个条目是否包含状态码“250”或“550”,它应该在大多数情况下都有效。
我希望这至少对某些人有所帮助。如果它对您有帮助或者您对此有任何疑问,请告诉我。也仍然对更好的解决方案持开放态度,因为我确信有更好的方法可以做到这一点。