Python email 实现销售邮件发送
数据来源
项目目录
文件内容
text 文件 为正文数据
attachment 文件 为附件数据
开启邮箱的SMTP服务
以qq邮箱为例
json.dumps()的参数
python 的json模块 提供的dumps函数
参数 | 描述 | 默认值 |
---|---|---|
skipkeys | 是否跳过无法被JSON序列化的key(包括str, int, float, bool, None) | False |
sort_keys | 是否对数据按照key进行排序 | False |
ensure_ascii | 输出保证将所有输入的非 ASCII 字符转义 | True |
allow_nan | 是否允许JSON规范外的float数据(nan, inf, -inf) | True |
default | 是一个函数, 当某个value无法被序列化时, 对其调用该函数 | None |
indent | 是一个正整数, 代表序列化后的缩进 | None |
separator | 是一个格式为 (item_separator, key_separator) 的元组, 默认取值为 (', ', ': ') | None |
check_circular | 是否检查循环引用 | True |
完整代码
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formatdate
import smtplib
import sys
import os
import logging
import csv
# log
logging.getLogger().setLevel(logging.INFO)
# 存放邮件正文数据的csv文件
email_content_data_csv_regenerate = 'source/rg_text'
email_content_data_csv_signal = 'source/sg_text'
# 2.7编码设置
# reload(sys)
# sys.setdefaultencoding("utf-8")
# 发件人服务设置
__smtp_server ='smtp.qq.com'
__smtp_port = '端口号'
__account ='邮箱账户'
__password ='密码'
# 邮件检查
def pre_check():
if __smtp_server is None or __smtp_port is None or __account is None or __password is None:
logging.error("Invaild Email Setting Parameters.")
sys.exit(1)
# 发送邮件
def send_email(_to_address, _cc_address, _subject, _msg_content, _subtype='plain'):
pre_check()
if _to_address is None or _subject is None or _msg_content is None:
logging.error("Invaild Parameters.")
sys.exit(1)
logging.info("Email to %s." % _to_address)
receivers = str.split(_to_address, ',')
MIMEText(_msg_content, 'html', 'utf-8')
message["From"] = Header(__account)
message["To"] = Header(";".join(receivers))
message["Subject"] = Header(_subject)
message["Date"] = formatdate(localtime=True)
try:
smtp = smtplib.SMTP_SSL('%s:%s' % (__smtp_server, __smtp_port))
smtp.login(__account, __password)
smtp.sendmail(__account, receivers, message.as_string())
smtp.quit()
except smtplib.SMTPException as e:
logging.error(e)
logging.error("Try sent email failed.")
sys.exit(-1)
logging.info("Notify Complete.")
# 发送邮件带附件
def send_email_with_attach_file(_to_address, _cc_address, _subject, _msg_content, _subtype='plain', _attach_files=None):
"""
:param _to_address: 收件人,多人用”,“隔开
:param _subject: 主题
:param _msg_content: 正文
:param _subtype: 正文格式,默认'plain'
:param _attach_files: 附件,多个附件用”,“隔开
"""
pre_check()
if _to_address is None or _subject is None or _msg_content is None or _attach_files is None:
logging.error("Invaild Parameters.")
sys.exit(1)
# 检测附件中的文件是否存在
for _attach_file in _attach_files.split(","):
if not os.path.exists(_attach_file):
logging.error("Attach File %s Not Exists in Current Directory, Please Check." % _attach_file)
sys.exit(0)
logging.info("Email to %s." % _to_address)
to_receivers = _to_address.split(",")
cc_receivers = _cc_address.split(",")
receivers = to_receivers + cc_receivers
message = MIMEMultipart()
message["From"] = Header(__account)
message["To"] = Header(";".join(to_receivers))
message["Cc"] = Header(";".join(cc_receivers))
message["Subject"] = Header(_subject)
message["Date"] = formatdate(localtime=True)
# 邮件正文
message.attach(MIMEText(_msg_content, _subtype, 'utf-8'))
# 附件,传送当前目录下的文件,多个附件以”,“隔开
for _attach_file in _attach_files.split(","):
logging.info("attach_file: %s." % _attach_file)
att = MIMEText(open(_attach_file, 'rb').read(), 'base64', 'utf-8')
att["Content-Type"] = 'application/octet-stream'
# 这里的filename,邮件中显示什么名字,考虑到文件可能带路径,取系统目录分隔符后的名字
att.add_header("Content-Disposition", "attachment", filename=("gbk", "", _attach_file.split(os.sep)[-1]))
# att["Content-Disposition"] = 'attachment; filename="%s"' % _attach_file.split(os.sep)[-1]
message.attach(att)
try:
smtp = smtplib.SMTP_SSL('%s:%s' % (__smtp_server, __smtp_port))
smtp.login(__account, __password)
smtp.sendmail(__account, receivers, message.as_string())
smtp.quit()
except smtplib.SMTPException as e:
logging.error(e)
logging.error("Try sent email failed.")
sys.exit(-1)
logging.info("Notify Complete.")
def printArgs():
logging.info("**************************************")
logging.info("len(sys.argv) = " + str(len(sys.argv)))
i = 0
for iargv in sys.argv:
logging.info("sys.argv " + str(i) + " = " + iargv[0:50])
i += 1
logging.info("**************************************")
# 获取邮件正文html
def get_html_content():
html = '''
<html>
<head></head>
<body>
<div style="line-height: 35px;">
Hello all, <br>
Please find the yesterday date daily sales report in the attachment. Thanks
</div>
<div style='width: 800px;height: 150px; margin-top: 20px; font-family: "SimHei";'>
<div id='tm_header'
style="background: rgb(20, 151, 171); color: #fff; font-size: 35px; rg_text-align: center; height: 142px;width: 808px; font-family: SimHei;">
<div style='margin: 0;height: 100%;line-height: 100%; padding-top: 53px; font-weight: bold;letter-spacing:1px'> REGENERATE </div>
</div>
</div>
<div id='data-body' style='padding: 10px 0; width:808px; font-family: Arial;'>
<table border="0" cellspacing="0" cellpadding="5"
style="border-color: #f5f5f5; border-style:solid; width: 100%; margin-bottom: 10px;">
<tr style="background-color: rgb(20, 151, 171); color: #fff;">
<td style="width: 16%;">Channel</td>
<td style="width: 14%;">Sop(pc)</td>
<td style="width: 14%;">MTD(pc)</td>
<td style="width: 14%;">SOP Ach%</td>
<td style="width: 14%;">Tgt TO(CNY)</td>
<td style="width: 14%;">MTD(CNY)</td>
<td style="width: 14%;">Sales Ach%</td>
</tr>
'''
# 读取CSV文件中的数据
files = os.listdir(email_content_data_csv_regenerate)
for i, filename in enumerate(files, start=1):
# print(i, filename)
if '.csv' in filename:
with open(os.path.join(email_content_data_csv_regenerate, filename), 'r', encoding='utf8') as f:
lines = f.readlines()
# print(lines)
for c in lines:
is_total = False
items = c.split('|')
# print(items)
if items[0] == 'Total':
is_total = True
if not is_total: # table body
for cell in items:
html += '<td>' + cell + '</td>'
else:
for cell in items: # table end
html += '<td style="color: rgb(20, 151, 171); font-weight: bold; border-top: 1.5px solid rgb(20, 151, 171); border-bottom: 1.5px solid rgb(20, 151, 171);">' + cell + '</td>\n'
html += '</tr>'
# Signal部分
html += '''
</table>
</div>
<br>
<div style='border: 3px solid rgb(15, 50, 148);width: 802px;height: 150; margin-top: 20px; font-family: "SimHei";'>
<div id = 'tm_header' style="background: rgb(15, 50, 148); color: #fff; font-size: 22px; rg_text-align: center; height: 142px;width: 794px;margin: 4px; font-family: SimHei;">
<div style='margin: 0;height: 50%;line-height: 300%; padding-top: 11px;'>— Signal —</div>
<div style='margin: 0;height: 50%;line-height: 150%;'>以白之名,水光皓齿</div>
</div>
</div>
<div id='data-body' style='padding: 10px 0; width:808px; font-family: Arial;'>
<table border="0" cellspacing="0" cellpadding="5" style="border-color: #f5f5f5; border-style:solid; width: 100%; margin-bottom: 10px;">
<tr style="background-color: rgb(15, 50, 148); color: #fff;">
<td style="width: 16%;">Channel</td>
<td style="width: 14%;">Sop(pc)</td>
<td style="width: 14%;">MTD(pc)</td>
<td style="width: 14%;">SOP Ach%</td>
<td style="width: 14%;">Tgt TO(CNY)</td>
<td style="width: 14%;">MTD(CNY)</td>
<td style="width: 14%;">Sales Ach%</td>
</tr>
'''
# 读取CSV文件中的数据
files = os.listdir(email_content_data_csv_signal)
for i, filename in enumerate(files, start=1):
# print(i, filename)
if '.csv' in filename:
with open(os.path.join(email_content_data_csv_signal, filename), 'r', encoding='utf8') as f:
lines = f.readlines()
# print(lines)
for c in lines:
is_total = False
items = c.split('|')
# print(items)
if items[0] == 'Total':
is_total = True
if not is_total: # table body
for cell in items:
html += '<td>' + cell + '</td>'
else:
for cell in items: # table end
html += '<td style="color: rgb(15, 50, 148); font-weight: bold; border-top: 1.5px solid rgb(15, 50, 148); border-bottom: 1.5px solid rgb(15, 50, 148);">' + cell + '</td>\n'
html += '</tr>'
html += '''
</table>
</div>
</body>
</html>
'''
return html
if __name__ == "__main__":
# 收件人
to_address = '1512118854@qq.com'
# 抄送人
cc_address = '1512118854@qq.com'
# 邮件主题
subject = 'daily sales report'
# 邮件正文
msg_content = get_html_content()
# 邮件类型
subtype = 'html'
# 邮件附件
attach_files = u'source/attachment/attachment_daily_rg.csv,source/attachment/attachment_daily_sg.csv'
# 发送邮件带附件
send_email_with_attach_file(to_address,
cc_address,
subject,
msg_content,
subtype,
attach_files)