python email发送销售报表

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)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值