工资条邮件发错人?一个脚本清洗邮箱列:去空格、统一小写、格式校验、去重

2026-10-06 · 喵窝资源铺

发工资条、发通知,邮箱列往往是各部门 Excel 拼起来的,脏得五花八门:" [email protected] " 前后带空格、[email protected] 大小写不一(同一个人换个写法就成了两个人)、wang#example.com 把 @ 打成了 #、sunba 忘了域名。SMTP 群发对这些毫无抵抗力——格式错的直接报错中断,重复的发两遍。这篇给一个 30 行脚本一遍过:去空格 → 统一小写 → 正则校验 → 按邮箱去重,脏行带行号挑进报告,绝不混进结果。代码实跑验证,真实输出贴在下面。

输出长什么样

构造一份 8 行的联系人流水:正常邮箱、带空格的、大写的、重复的(张三出现两次,一次带空格一次不带)、# 代替 @ 的、邮箱内部含空格的、缺域名的,外加一个空行。跑完:

清洗完成:有效 3 条,剔除 4 条
  - 第4行 张三: 与第2行重复,跳过
  - 第5行 王五: 邮箱「wang#example.com」格式非法
  - 第7行 赵六: 邮箱「zhaoliu@ outlook.com」格式非法
  - 第9行 孙八: 邮箱「sunba」格式非法

姓名,邮箱
张三,[email protected]
李四,[email protected]
钱七,[email protected]

三个全对:张三的 " [email protected] " 和 [email protected] 归一后去重,只留一条;大写的 [email protected] 归一成小写;4 条脏邮箱全部带行号和原因挑出。修完 openpyxl/写出去掉多余时间戳后连跑两次 md5 一致(纯 CSV 写入本来就没有隐藏时间戳,这里顺手验证)。

完整脚本

# -*- coding: utf-8 -*-
"""清洗邮箱列:去空格、统一小写、正则校验、按邮箱去重,脏行挑进报告不混进结果。"""
import sys, csv, re

src, dst = sys.argv[1], sys.argv[2]
EMAIL = re.compile(r'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')

rows, bad = {}, []
with open(src, encoding="utf-8-sig") as f:          # utf-8-sig:兜住Excel导出的BOM
    for i, row in enumerate(csv.reader(f), 1):
        if i == 1 or not any(c.strip() for c in row):   # 跳表头和整行空白
            continue
        name, mail = (row + ["", ""])[:2]           # 短行补空列,不炸
        m = mail.strip().lower()
        if not EMAIL.match(m):
            bad.append(f"第{i}行 {name or '(空姓名)'}: 邮箱「{mail or '(空)'}」格式非法")
            continue
        if m in rows:
            bad.append(f"第{i}行 {name}: 与第{rows[m][0]}行重复,跳过")
            continue
        rows[m] = (i, name.strip())

with open(dst, "w", newline="", encoding="utf-8-sig") as f:
    w = csv.writer(f)
    w.writerow(["姓名", "邮箱"])
    for m, (i, n) in rows.items():
        w.writerow([n, m])

print(f"清洗完成:有效 {len(rows)} 条,剔除 {len(bad)} 条")
for b in bad:
    print("  -", b)

用法:python mail_clean.py 联系人.csv 清洗结果.csv。输入是 Excel 就先另存为 CSV(或用 openpyxl 读,逻辑不变)。

踩到的 3 个真坑

  1. BOM:Excel 导出的 CSV 必须用 utf-8-sig 读。直接 encoding="utf-8" 的话,第一列名会变成 \ufeff姓名,表头判断静默失效;写出侧也用 utf-8-sig,别的程序打开才不带乱码。这是老坑,但每次从 Excel 拿文件都会再中一次。
  2. strip() 救不了邮箱内部的空格。zhaoliu@ outlook.com 是 @ 后面多了个空格——strip 只管两头,正则校验会正确拦下它(因为 [A-Za-z0-9.-] 不含空格)。重点是别试图「帮忙修」,邮箱内部错法千奇百怪,脚本只负责挑出来让人改,替用户猜怎么改反而改错。
  3. 按邮箱去重还是按人去重,先定口径。同一个人有两个邮箱(工作+私人)按邮箱算两条,是对的;但张三/张三 张三 这种同名不同邮箱是不是同一人,脚本不知道。本文默认按邮箱去重(邮箱是发信的键,重复邮箱必然重复发信),姓名只做展示不参与判定。如果你要按「姓名+邮箱」去重,把 rows[m] 的键改成 (n, m) 即可。

口径提醒:[A-Za-z0-9._%+-]+@... 这套正则是「够用版」,能拦住缺域名、@打成#、含空格这些真会被 SMTP 拒收的错误,但不做 RFC 5322 级别的严格校验——那个正则要写一页纸,而且对发邮件没额外收益。

懒得自己跑?把联系人表发我(后台留言),AI 清洗完人工核对后把结果表发回给你,9.9 元/次,虚拟物品交付后不退款、结果不符免费重做。更多现成脚本与代做服务 →

相关阅读:工资条批量发邮件(缺邮箱/格式错自动挑出) · 身份证号批量提取去重 · 打卡记录按关键列去重

← 喵窝资源铺首页 · 全部文章