为什么dns.resolveMx在多次调用时总是返回错误?

时间:2014-01-17 09:10:21

标签: node.js dns

我正在尝试通过使用Node.JS查找MX记录来验证电子邮件地址列表(以摆脱垃圾邮件地址,例如asdasdas@waqwqasd.com)

我的代码适用于一个电子邮件地址,但是当我多次调用它时,我从dns.resolveMx收到ETIMEOUT或ECONNREFUSED的错误。

以下是相关位:

此测试代码有效:

(function() {
  var dns = require('dns'); 
  var email = "test@yahoo.co.uk"
   var emailDomain;
    try
    {
      emailDomain = email.split('@')[1];

      console.log('Checking Domain ' + emailDomain);
    }
    catch(e)
    {
      return false;
    }
  dns.resolveMx("yahoo.co.uk", function (err, addresses) {
      if(err)
      {
        console.log(err);
      }
      else
      {
        console.log('Found addresses ' + JSON.stringify(addresses));  
        return true;
      }
    }
  );
})();

此代码不会:

(function() {

  var dns = require('dns');
  var fs = require('fs');
  var Sync = require('sync');

  var validEmails = [];
  var invalidEmails = [];
  var validDomains = [];

  var checkEmails = function()
  {
    var fileData = fs.readFileSync('emails_only-full.txt').toString().split('\n');

    console.log(fileData.length);
    testValidEmailDomains(fileData);
  }

  var finished = function()
  {
    console.log('Finished parsing database');
    console.log('Found ' + validEmails.length + ' valid emails');
    console.log('Found ' + invalidEmails.length + ' invalid emails');    
  };

  var testValidEmailDomains = function(emails, index)
  {
    if(emails.length == 0)
    {
      finished();
      return;
    }

    var email = emails.pop();
    var emailDomain;
    try
    {
      emailDomain = email.split('@')[1];
      if(validDomains.indexOf(emailDomain) != -1)
      {
        validEmails.push(email);
        return;
      }
    }
    catch(e)
    {
      invalidEmails.push(email);
      return;
    }
    console.log('Checking Domain ' + emailDomain);    
    dns.resolveMx(emailDomain, function (err, addresses) {
      if(err)
      {
        console.log(err);
        invalidEmails.push(email);
      }
      else
      {
        validDomains.push(emailDomain);
        validEmails.push(email);
        console.log('Found addresses ' + JSON.stringify(addresses));  
      }
      testValidEmailDomains(emails.slice(index), index + 1);
    });
  }
  checkEmails();
})();

我当时认为这是同时调用太多次,但使用Sync /光纤来休眠线程似乎也不起作用。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

编辑:出现稳定分支(0.10.x)不支持dns.setServers。在这种情况下,请使用https://github.com/tjfontaine/node-dns代替dns请求。请参阅dns.Request方法。它允许您在每个请求中手动设置DNS服务器。

如果快速连续发出太多请求以避免DNS放大攻击,DNS服务器通常会阻止客户端。最好的方法是:

  • 速率限制DNS请求
  • 使用多台服务器并循环使用它们(可能仍被ISP或其他中介机构阻止)
  • 缓存已经过检查以避免重复请求的域

这里有一个很好的DNS服务器列表:http://pcsupport.about.com/od/tipstricks/a/free-public-dns-servers.htm

循环访问多台服务器的示例代码:

// static list of DNS servers to use from the list above
var SERVERS = ['8.8.8.8', ...];
var SERVERS_LENGTH = servers.length;

var dns = require('dns');

// function to resolve mx records   
// loops through emails and launches parallel requests - rate limit as required
function resolve(emails, fn) {
   emails.forEach(function(email, index) {
       var nextServer = SERVERS[index % SERVERS_LENGTH];
       dns.setServers([nextServer]);
       dns.resolveMx(email, fn);
   });
}