前些天做销售的同事给我出了个题目: 她的客户数据里有很多的 Email 地址都是过期的或者错误的, 因此群发发邮件时会收到很多退信. 但是由于数量较大, 又不好手工去一一找出哪些地址是无效的. 有没有可能用程序解决呢?
当然是可能的啦, 思路: 首先肯定不能通过发邮件来测试, 因为, 乱发垃圾邮件那是违法的. 于是我采取三个步骤:
- 利用 regex 从 Email 地址的格式上先淘汰一些, 例如连 @ 都没有的那肯定不是合格的 Email 地址.
- 再从 DNS MX 记录上淘汰一些. 如果某域名没有有效的 MX 记录, 那该域名结尾的任何 Email 地址都是无效的.
- 最后使用 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 地址是否存在”
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.
我们管这个叫数据清洗,使用的方法也差不多
我认为群发邮件就是这么个问题,无论是否垃圾,要是能让每个客户都感觉是在享受单独服务就更好了。