收到一個需求,要檢查用戶的 email 是否存在避免寄信時被退信,要檢查 Email 是否存在可以簡單的使用 telnet 驗證
以作者的 Gmail 信箱為例:shazi7804@gmail.com
telnet 檢查信箱存在
先找到使用者網域的 SMTP Server,可以從 DNS MX record 找到
$ dig mx gmail.com
;; ANSWER SECTION:
gmail.com. 2771 IN MX 20 alt2.gmail-smtp-in.l.google.com.
gmail.com. 2771 IN MX 5 gmail-smtp-in.l.google.com.
gmail.com. 2771 IN MX 40 alt4.gmail-smtp-in.l.google.com.
gmail.com. 2771 IN MX 10 alt1.gmail-smtp-in.l.google.com.
gmail.com. 2771 IN MX 30 alt3.gmail-smtp-in.l.google.com.
以 MX 的權重來說,最優先的是 gmail-smtp-in.l.google.com.
這台主機
透過 telnet 與 SMTP Server 溝通
$ telnet gmail-smtp-in.l.google.com 25
Trying 74.125.203.27...
Connected to gmail-smtp-in.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP 4si3424472ple.242 - gsmtp
HELO localhost
250 mx.google.com at your service
MAIL FROM: <shazi7804@gmail.com>
250 2.1.0 OK 4si3424472ple.242 - gsmtp
RCPT TO:<shazi7804@gmail.com>
250 2.1.5 OK 4si3424472ple.242 - gsmtp
telnet
若是成功 SMTP 會回覆 220HELO localhost
告訴 SMTP 來的人是誰,也能先以 localhost 代替MAIL FROM
設定一個 Mail Sender,但在驗證的步驟中不具意義,因為實際上並沒有要發信,只是為了走到RCPT TO
這一步驗證使用者是否能收信RCPT TO
這邊指定要收信的 Email,也是要驗證的信箱,如果用戶的位址存在則會回覆 250
如果用戶不存在的話,則會回覆 550
RCPT TO:<shazi78044@gmail.com>
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 4si3424472ple.242 - gsmtp
python 檢查信箱存在
Python 的實作就簡單很多了,除了 smtplib 去呼叫 SMTP 以外 py3-validate-email 更是簡單的驗證方式
以 python 3.x 版本為例,若用戶存在則為 True
from validate_email import validate_email
validate_email(email_address='shazi7804@gmail.com', check_regex=True, check_mx=True, helo_host='localhost')
# True
反之會回覆 550
validate_email(email_address='shazi78204@gmail.com', check_regex=True, check_mx=True, helo_host='localhost')
Validation for 'shazi78204@gmail.com' failed: Email address undeliverable:
gmail-smtp-in.l.google.com.: 550 5.1.1 The email account that you tried to reach does not exist. Please try