# -*- 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
将 .eml 格式的文件批量发送给指定用户
最新推荐文章于 2024-03-21 11:28:18 发布
本文介绍如何使用Python脚本处理.eml格式的邮件文件,并将其批量发送给多个指定的电子邮件接收者。内容包括解析.eml文件、构建SMTP连接、设置发件人和收件人、以及发送邮件的详细步骤。
摘要由CSDN通过智能技术生成