javascript - Node.js 网络模块,从回调函数中获取数据
问题描述
所以我尝试自己解决它并搜索了很多,但我无法真正解决问题,尽管我认为它不应该那么困难。所以我正在做(或试图做)的是,我建立一个到服务器的简单 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();
它在第二个和第三个命令得到响应之前结束连接。我试图用“await client.write ...”来“等待”响应,但这显然是行不通的,因为不确定是什么原因。
我希望你能大致了解我正在努力完成的工作,如果你不问的话。谢谢!
解决方案
所以我想我自己已经完成了,或者至少得到了一个在大多数情况下都可以正常工作的解决方案。我正在做的是在第三个写命令的回调中结束套接字,如下所示:
client.write("rcpt to:<" + senderEmail + ">\r\n","utf-8",()=>{
console.log("third command written");
client.end();
});
通过这样做,服务器“应该有足够的时间”来回答所有命令。
较早的解决方案是计算“数据”事件的回调函数中的响应数,如下所示:
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 语句来检查响应的数量。但问题是,有时多个响应可能会作为一个响应发送。例如,响应可能如下所示:
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 个响应作为一个发送。这使得很难评估我是否得到了我需要得到的所有回复。这就是为什么我只是在最后一个写命令之后结束套接字。
然后在 client.on('end') 函数中,我将 completeData 发送回客户端。
client.on('end', function () {
console.log('Requested an end to the TCP connection');
console.log(completeData);
res.status(200).json(completeData);
});
唯一仍然困扰我的是我的数组(我用每个发出的“数据”事件推送数据)的长度是可变的。如果找到电子邮件,这将使验证变得有点困难。但是由于这应该始终是最后一个响应,所以如果我只是测试数组的最后一个条目是否包含状态码“250”或“550”,它应该在大多数情况下工作。
我希望这至少对某人有所帮助。让我知道它是否对您有所帮助,或者您对此有任何疑问。也仍然开放以获得更好的解决方案,因为我相信有更好的方法来做到这一点。
推荐阅读
- java - JavaParser 读取 src 目录
- python - Python 正则表达式性能:使用数千个正则表达式迭代文本的最佳方法
- spring-boot - @Lookup 不工作 - 抛出空指针异常
- c++ - 'int*' 和 'int*' 类型的无效操作数到二进制 'operator+'
- google-bigquery - BQ 脚本 - 声明:使用现有表的模式类型
- c++ - MFC CEdit 控件在添加到加速器后不处理 Key Pressed
- php - WordPress 如何添加重写 url 永久链接
- json - Vaadin 8 通信问题,来自服务器 1|X 的 JSON 无效
- go - 如何在 Google Cloud Run 中运行 go-cloud-debug-agent,以便我可以在 Stackdriver Debug 中调试我的 go 应用
- javascript - 将 API 派生值映射到 React.js 状态的问题