检查 domain.com 是否有 MX 记录(即是否能接收邮件)

  • 合法邮箱格式(例如:abc@domain.com)
  • 检查 domain.com 是否有 MX 记录(即是否能接收邮件)
  • 若无 MX 记录,则该邮箱无法收邮件
import re
import dns.resolver
import csv
import time
import os

# 校验邮箱格式
def is_valid_format(email):
    return re.match(r"[^@]+@[^@]+\.[^@]+", email)

# 检查域名是否有 MX 记录
def has_mx_record(domain):
    try:
        answers = dns.resolver.resolve(domain, 'MX', lifetime=5.0)
        return len(answers) > 0
    except:
        return False

# 检查邮箱格式 + 接收能力
def check_email(email):
    if not is_valid_format(email):
        return '❌ 格式非法'
    domain = email.split('@')[1]
    if has_mx_record(domain):
        return '✅ 可接收邮件(有MX)'
    else:
        return '❌ 无MX记录(无法接收邮件)'

# 主程序
def batch_check_emails(file_path):
    # 加载输入邮箱并去重
    with open(file_path, 'r', encoding='utf-8') as f:
        all_emails = list(set([line.strip() for line in f if line.strip()]))

    # 加载已检测过的邮箱(如果结果文件已存在)
    processed_emails = set()
    if os.path.exists('email_check_results.csv'):
        with open('email_check_results.csv', 'r', encoding='utf-8') as csvfile:
            reader = csv.reader(csvfile)
            next(reader, None)  # 跳过表头
            for row in reader:
                if row and row[0]:
                    processed_emails.add(row[0].strip())

    # 筛选出未检测的邮箱
    emails_to_check = [email for email in all_emails if email not in processed_emails]
    print(f"\n📬 待检测邮箱数量:{len(emails_to_check)} / 总共:{len(all_emails)}\n", flush=True)

    # 打开文件(追加写入)
    with open('email_check_results.csv', 'a', newline='', encoding='utf-8') as csvfile, \
         open('valid_mx_emails.txt', 'a', encoding='utf-8') as valid_file:

        writer = csv.writer(csvfile)
        if not processed_emails:  # 如果是首次运行,写入表头
            writer.writerow(['邮箱地址', '检测结果'])

        existing_valids = set()
        if os.path.exists('valid_mx_emails.txt'):
            with open('valid_mx_emails.txt', 'r', encoding='utf-8') as f:
                existing_valids = set(line.strip() for line in f if line.strip())

        for idx, email in enumerate(emails_to_check, start=1):
            result = check_email(email)
            print(f"{idx:04d}. {email} → {result}", flush=True)
            writer.writerow([email, result])
            if result.startswith('✅') and email not in existing_valids:
                valid_file.write(email + '\n')
                existing_valids.add(email)
            time.sleep(0.1)

    print("\n✅ 检测完成!结果保存至:email_check_results.csv 和 valid_mx_emails.txt\n", flush=True)

# 程序入口
if __name__ == '__main__':
    batch_check_emails('emails.txt')

:open_file_folder: 输出文件说明:

文件名 内容说明
email_check_results.csv 所有邮箱 + 是否有 MX 记录
valid_mx_emails.txt 只包含“有 MX 记录”的邮箱