确认一个 Email 地址是否存在


前些天做销售的同事给我出了个题目: 她的客户数据里有很多的 Email 地址都是过期的或者错误的, 因此群发发邮件时会收到很多退信. 但是由于数量较大, 又不好手工去一一找出哪些地址是无效的. 有没有可能用程序解决呢?

当然是可能的啦, 思路: 首先肯定不能通过发邮件来测试, 因为, 乱发垃圾邮件那是违法的. 于是我采取三个步骤:

  1. 利用 regex 从 Email 地址的格式上先淘汰一些, 例如连 @ 都没有的那肯定不是合格的 Email 地址.
  2. 再从 DNS MX 记录上淘汰一些. 如果某域名没有有效的 MX 记录, 那该域名结尾的任何 Email 地址都是无效的.
  3. 最后使用 SMTP 协议”假装”发邮件, 只查询收件人是否存在, 便挂断.

基本能够达到目的, 但不保证 100% 准确. 因为… 很多发垃圾邮件的专业户也是这么做的, 所以一些邮件服务器对此是提防的. 程序如下.

require 'net/smtp'
require 'dnsruby'
class EmailValidator
 def check_format(email)
   m =  /^[A-Za-z0-9._%+-]+@([A-Za-z0-9.-]+\.[A-Za-z]{2,4})$/.match email
   if m
     @domain = m[1]
     @email = email
   else
     puts "Invalid Email address for '#{email}'."
     return false
   end
 end

 def mx_lookup
   res = Dnsruby::Resolver.new
   ret = res.query(@domain, Dnsruby::Types.mx)

   return ret.answer[0].exchange.to_s if ret && ret.answer && ret.answer[0]
 end

 def validate(email)
   return false unless check_format(email)

   mx = mx_lookup()
   if mx
     Net::SMTP.start(mx, 25) do |smtp|
       smtp.helo 'the.domain.name'
       smtp.mailfrom 'sender.email.address'
       smtp.rcptto @email
       smtp.finish
     end
     puts "Account exists for '#{@email}'."
     return true
   else
     puts "No MX available for '#{@domain}'."
     return false
   end
 rescue => err
   puts "Account may not exist for '#{@email}'."
   puts err
   return false
 end
end

🙂


3 responses to “确认一个 Email 地址是否存在”

  1. You design a small program for your company and decided to help them,you solving a big problems for them. You are so great! I envy you.

  2. 我认为群发邮件就是这么个问题,无论是否垃圾,要是能让每个客户都感觉是在享受单独服务就更好了。