将 .eml 格式的文件批量发送给指定用户

本文介绍如何使用Python脚本处理.eml格式的邮件文件,并将其批量发送给多个指定的电子邮件接收者。内容包括解析.eml文件、构建SMTP连接、设置发件人和收件人、以及发送邮件的详细步骤。
摘要由CSDN通过智能技术生成
# -*- coding:utf-8 -*-

import email
import smtplib
import os
import sys
import time
import shutil
from email.mime.text import MIMEText
from email.header import Header
import imp


'''
批量发邮件 5.0
CN
;运行系统Windows
;运行程序Python+pycharm
;适配环境内网测试批量发信

所用的框架库,确保自己安装的pycharm装有第三方支持库:email、smtplib、os、time、shutil。
运行脚本的 rootdir 指定发送样本库,确保样本库中全是eml文件,不能有文件夹、txt文件、ffs_db文件等。
运行环境确保发送服务器和接收服务器连通正常,配置完整,因为脚本针对的是内网服务器批量发信测试,所以运行环境确保网络的正常。
eml文件乱码问题,部分文件有可能会出现 from、to、正文、附件名的乱码问题,需要更换,代码中没有针对名称乱码的解决方案

行注意事项:
读取文件源码操作:根据实况而定,一般情况下eml文件定义统一,代码在运行时,若出现文件乱码,或者报错,请查看该eml文件的from、to、正文、附件、和源码(是否有:Content-Type: text/plain; charset=utf-8)
判断附件操作:附件可以根据自己的需求是否读取分析,一般情况下不建议读取附件,防止发送结果有影响,仅读取附件名称即可。
时间操作:时间获取分别有两种方式,可以根据自己的喜好而定。
                        第一是大概时间,精确到日 timed = time.strftime('%Y.%m.%d',time.localtime(time.time()))  (2021.03.15)
                        第二是完整标准时间,精确到秒 timed = time.asctime(time.localtime(time.time()))   (Mon Mar 15 10:56:07 2021)
定位from和to: receive 是接收端的 用户名@域名,其他的是发送端用户名,密码、IP
判断 charset字符串:eml文件编码格式和解析编码格式相同,以防发送的时候出现乱码现象,目前仅针对gbk特殊标注,若出现文件乱码,或者报错,请查看该eml文件的from、to、正文、附件、和源码(是否有:Content-Type: text/plain; charset=utf-8)
发送邮件成功备份操作:发送成功的eml邮件需要 copy 到自定义的绝对目录中,目录需要自己定义( ok_eml ),因为,如果出现代码error,或者乱码现象,需要在eml文件夹里替换掉问题邮件,然后运行 4_Remove_Emlfile.py(删除文件),将备份目录文件保存,删除eml文件夹发送成功的文件,结束后再重新运行批量发送邮件脚本

字符集统计:
        "gbk"、"GBK"、"gb2312"、"GB2312"、"iso-8859-1"、"gib5"、"GIB5"、"us-ascii"、"utf-8"、"UTF-8"、"ascii"、"ASCII"
        gbk、GBK、gb2312、GB2312、iso-8859-1、gib5、GIB5、us-ascii、utf-8、UTF-8、ascii、ASCII

版本更新:
    5.0
        1、兼容了Python3
        2、重置了代码规制
        3、增加了ASCII编码格式
        4、增加了 AttributeError 异常捕获
		5、增加了文件保存形式的编码查询(通过将原文保存至指定文件,然后查询文件内的编码格式,按照非1跳2的形式


'''

'''遍历搜索查找文件内子父目录的文件'''
def getAllMail(rootdir, dirlist=[], filelist=[]):
    lists = os.listdir(rootdir)
    for filename in lists:
        file_name = os.path.join(rootdir, filename)
        if os.path.isdir(file_name):
            dirlist.append(file_name)
            getAllMail(rootdir, dirlist, filelist)
        if os.path.isfile(file_name):
            filelist.append(file_name)
    return dirlist, filelist


'''最后方案的字符集指定'''
def the_final_solution(file_names , w_character, r_character, msg):
    character_test = []  # 主要针对字符集的提取做列表
    character_test_txt = ""  # # 主要针对字符集的提取做唯一保存
    # 将文件存入指定文件内
    eml_character = str(msg)
    w_character.writelines(eml_character)
    # reload(sys)
    imp.reload(sys)
    # sys.setdefaultencoding('utf8')
    sample = r_character.readlines()
    for line in sample:
        line = line.strip()
        if 'charset' in line:
            print("line:  ", line)
            try:
                lines = line.split("=")[1]
            except IndexError:
                print("\033[43m 下标越界异常,请检查该文件原件内容是否符合操作")
                print(file_names , "\033[0m")
                continue
            print("line:  ", line)
            character_test.append(lines)
            # print(character_test)
            print(character_test[0])
            character_test_txt = character_test[0]
    return character_test_txt

if __name__ in '__main__':
    rootdir = "eml_dir"  # 需要发送的eml 文件存放目录
    abc = "dir"  # 预留存放 eml 文件解析目录
    ok_eml = "eml_ok_dir"  # 发送成功的 eml 文件目录
    w_character = open("写入的临时文件", "w")
    r_character = open("读取的临时文件", "r")


    x = 0   # 第一字符集累加
    y = 0   # 第二字符集累加
    z = 0   # 最后字符集累加
    c = 0
    c_txt = []   # # 解析到乱码内容的邮件
    d = 0   # 没有字符集或者是不能解析字符集的邮件累加
    d_txt = []   # 没有字符集或者是不能解析字符集的邮件
    e = 0   # 主要针对的是严重的邮件解析异常的累加
    e_txt = []   # 主要针对的是严重的邮件解析异常
    g = 0   #针对不能识别到编码格式的邮件累加
    g_txt = []  #针对不能识别到编码格式的邮件
    error_eml = 0   # 针对最后的字符集,选择跳出
    error_eml_txt = []
    attError = []  # 针对附件文件提取时格式的问题或是提取失败做捕获

    Dirlist, Filelist = getAllMail(rootdir)
    for i in range(len(Filelist)):
        print("文件路径::  ", Filelist[i])
        paths = Filelist[i]
        if os.path.isfile(paths):
            # 读取文件源码操作:
            eml_txt = paths.split('\\')[::-1]  # 切变操作
            eml_name = eml_txt[0]
            print("eml文件名::  ", eml_name)
            new_dir = ok_eml + eml_name
            fp = open(paths, "r")
            try:
                msg = email.message_from_file(fp)
            except UnicodeDecodeError:
                print("\033[31m \n codec can't decode byte 0xf3 in position 16: ordinal not in range(128)\n邮件中包含乱码,跳出继续》》》》》》》》》》》》\033[0m")
                c = c + 1
                c_txt.append(eml_name)
                continue
            subject = msg.get("subject")
            content_type = msg.get("Content-Type")
            print("content_type::  ", content_type)

            # content_types = content_type.rsplit("=", 1)[::-1][0]
            try:
                content_types = content_type.rsplit("=", 1)[::-1][0]
            except AttributeError:
                print("\033[31m \n'NoneType' object has no attribute 'rsplit'\n不能解析字符集或者没有字符集标识,跳出继续》》》》》》》》》》》》》》》》\033[0m")
                d = d + 1
                d_txt.append(eml_name)
                continue
            # h = email.Header.Header(subject)
            try:
                # h = email.Header.Header(subject)
                h = email.header.Header(subject)
            except UnicodeDecodeError:
                print("\033[31m \n'ascii' codec can't decode byte 0xf3 in position 16: ordinal not in range(128)\n邮件中包含乱码,跳出继续》》》》》》》》》》》》\033[0m")
                c = c + 1
                c_txt.append(eml_name)
                continue
            # dh = email.Header.decode_header(h)
            try:
                # dh = email.Header.decode_header(h)
                dh = email.header.decode_header(h)
            except email.errors.HeaderParseError:
                print("\033[31m 严重的邮件异常(email.errors.HeaderParseError),已经记录\n\t\tpython的base64的编码和本邮件的字符集出现冲突或者是无法解析报错!!! \033[0m")
                e = e + 1
                e_txt.append(eml_name)
                continue

            try:
                subject = dh[0][0]
            except IndexError:
                print("\033[31m 针对不能识别到编码格式的邮件,已经记录\n\t\t  \033[0m")
                g = g + 1
                g_txt.append(eml_name)
                continue
            # print("subject::  ", subject)
            print("字符集:1:  ", content_types)

            # 第二个解决方案
            content_types_2 = the_final_solution(eml_name , w_character , r_character , msg)
            print("字符集:2:  ", content_types_2)
            print('='*10)
            content_types_2 = the_final_solution(eml_name , w_character , r_character , msg)
            print("字符集:2:  ", content_types_2)

            from_name = email.utils.parseaddr(msg.get("from"))[1]
            # print"from: ", email.utils.parseaddr(msg.get("from"))[1] #  取from)
            to_name = email.utils.parseaddr(msg.get("to"))[1]
            # print"to: ", email.utils.parseaddr(msg.get("to"))[1] # 取to)

            # 判断附件操作:
            for par in msg.walk():
                if not par.is_multipart():
                    name = par.get_param("name")
                    if name:
                        # h = email.Header.Header(name)
                        try:
                            h = email.header.Header(name)
                        except UnicodeDecodeError:
                            print("\033[31m\n'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)\n解析邮件内容出现乱码情况,跳出继续》》》》》》》》》》》》》》》》\033[0m")
                            c = c + 1
                            c_txt.append(eml_name)
                            continue
                        except AttributeError:
                            print("\033[31m \n AttributeError: 'tuple' object has no attribute 'decode'   解析过程中提取附件为空,格式有误提取失败")
                            attError.append(eml_name + " ***  'tuple' object has no attribute 'decode'")
                            continue

                        dh = email.header.decode_header(h)
                        fname = dh[0][0]
                        # print('附件名::  ', fname)
                        data = par.get_payload(decode=True)
                        try:
                            f = open(fname, 'wb')  # 注意一定要用wb来打开文件,因为附件一般都是二进制文件
                            print("fname::  ", fname)
                        except:
                            f = open('zzzzzzzz', 'wb')
                        f.write(data)
                        f.close()
            #         else:
            #             print
            # 时间操作:
            timed = time.asctime(time.localtime(time.time()))
            # timed = time.strftime('%Y.%m.%d',time.localtime(time.time()))
        # a = a + 1
        # print('+' * 30 , a , '+' * 30)

        # def send():
        # 定位from和to
        smtpserver = '发信IP地址'
        user = '发信用户@域名'
        password = 'eyouadmin'
        sender = '发信用户@域名'
        receive = '收信用户@域名'
        subject = eml_name + " *** " + timed
        content = par.get_payload(decode=True)

        # 判断文件是否存在
        if not os.path.exists(ok_eml):
            os.mkdir(ok_eml)
            # 判断 charset字符串:
            if content_types == "gbk" or content_types == "GBK" or content_types == "\"gbk\"" or content_types == "\"GBK\"":
                print("start  \n\t\t\t >>  第一次定位字符集:", content_types_2, " <<")
                msg = MIMEText(content, 'html', 'gbk')
                msg['Subject'] = Header(subject, 'gbk')
                msg['From'] = '发信用户@域名t'
                msg['To'] = '发信用户@域名t'
                smtp = smtplib.SMTP_SSL(smtpserver, 465)  #  可更改端口号,465属于加密端口
                smtp.ehlo(smtpserver)
                smtp.login(user, password)
                smtp.sendmail(sender, receive, msg.as_string())
                smtp.quit()
                content_txt = abc + eml_name[0] + ".txt"
                print("文件内容结果:", content_txt)
                # 解析后的内容以txt格式存进指定文件夹
                # with open(content_txt , 'w') as f :
                #     f.write(content)s
                print("eml文件原路径:", paths)
                print("发送成功eml:", ok_eml + eml_txt[0])
                shutil.copyfile(paths, new_dir)
                time.sleep(1)
                x = x + 1
                print("\033[7m", '+' * 20, "end", '+' * 20, x + y + z, '+' * 20, "\033[0m")
                time.sleep(1)
            elif content_types == "gb2312" or content_types == "GB2312" or content_types == "\"GB2312\"":
                print("start  \n\t\t\t >>  第一次定位字符集:", content_types_2, " <<")
                msg = MIMEText(content, 'html', 'gb2312')
                msg['Subject'] = Header(subject, 'gbk')
                msg['From'] = '发信用户@域名t'
                msg['To'] = '发信用户@域名t'
                smtp = smtplib.SMTP_SSL(smtpserver, 465)  #  可更改端口号,465属于加密端口
                smtp.ehlo(smtpserver)
                smtp.login(user, password)
                smtp.sendmail(sender, receive, msg.as_string())
                smtp.quit()
                content_txt = abc + eml_name[0] + ".txt"
                print("文件内容结果:", content_txt)
                # 解析后的内容以txt格式存进指定文件夹
                # with open(content_txt , 'w') as f :
                #     f.write(content)s
                print("eml文件原路径:", paths)
                print("发送成功eml:", ok_eml + eml_txt[0])
                shutil.copyfile(paths, new_dir)
                time.sleep(1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值