博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

企业应用中的邮件处理

Posted on 2018-08-29 15:01  Yonguos  阅读(209)  评论(0编辑  收藏  举报

邮件发送是一种很常见的应用场景,特别是在企业应用中。

实际开发中,这块宜独立抽取为公共的方法进行实现,将样式、结构统一处理。下面以Python为例进行简单的介绍:

1,邮件内容分析:

一般的邮件,我们可以将展示的内容分为如下5个部分:

subject,greeting,content,list_data和footer。

2,样式常量定义

const.MAIL_FOOTER = (u"<p><span style='font-weight:bold'>P.S. </span><br>"
                         u"本邮件由【堡垒机(CloudSecureMgmt, CSM)】自动发送,如有疑问,"
                         u"请加堡垒机eSpace沟通群:12345678 进行咨询。<br>"
                         u"This mail is sent by CSM system automatically, if any questions, "
                         u"please contact us by joining eSpace group: 12345678 for further learn.</p>")
    const.MAIL_CSM_ADDRESS = u"<p><span style='font-weight:bold'>堡垒机地址:</span>https://csm.demo.com.</p>"
    const.MAIL_TITLE = u"【堡垒机(CSM)知会】"
    const.MAIL_OUTER_TABLE_STYLE = \
        u'align="left" border="0" cellpadding="5" cellspacing="0" width="100%" style="border-collapse: collapse;"'
    const.MAIL_INNER_TABLE_STYLE = \
        u'align="left" border="3" cellpadding="5" cellspacing="0" style="border-collapse: collapse;margin-left:-5px;"'

 

3, 底层邮件发送方法:

def send_mail(mail_title, mail_msg, mail_to):
    """
    发送邮件信息
    :param mail_title: 邮件标题
    :param mail_msg: 邮件内容
    :param mail_to: 收件人
    :return: True or False
    """
    try:
        msg = EmailMessage(mail_title, mail_msg, EMAIL_HOST_USER, mail_to)
        msg.content_subtype = "html"
        msg.send()
        return True
    except Exception as e:
        logger.error(u"邮件发送失败, 错误信息: {}".format(e))
        return False

 

4,列表展示的HTML生成代码:

def build_mail_table(show_name_list, data):
    """
    返回数据展示的HTML表格代码
    :param:
        show_name_list: 对外展示的表头名称列表
        data: 要展示的数据,格式为[tuple]
    """
    show_name_list.insert(0, u"序号")
    for i in range(len(data)):
        temp_data = list(data[i])
        temp_data.insert(0, i + 1)
        data[i] = temp_data
    html_table = u"<table {table_style}> <thead>".format(table_style=const.MAIL_INNER_TABLE_STYLE)
    html_table = u"".join(
        [html_table, u"".join([u"<th>{}</th>".format(name) for name in show_name_list]), u"</thead><tbody>"])
    table_content = u"".join([u"<tr> {row_content} </tr>".format(
        row_content=u"".join([u"<td style='padding:5px 20px;'> {cell_content} </td>".format(
            cell_content=u"{}".format(
                value)) for value in item])) for item in data])
    html_table = u"".join([html_table, table_content, u"</tbody></table>"])
    return html_table

 

5,邮件构建方法:

def build_and_send_mail(**kwargs):
    """
    提供堡垒机统一的邮件发送方法,
    负责邮件的构建、样式渲染和发送
    :param kwargs:
        subject: 邮件主题, 必选, 注明本邮件的目的, 如:权限过期提醒
        content: 邮件的正文内容, 必选, 如:***正在申请以下服务的成员权限,请登录堡垒机(https://www.huaweicloud.com)查看:
        show_name_list: 表格展示的表头列表,可选, 如:[u"姓名", u"工号", u"电话"]
        data: 要表格形式展示的数据,格式为[tuple], 可选, 注意tuple中的数据顺序要和表头保持一致
        mail_to_list: 收件人地址列表, 必选
    :return: True or False
    """
    if not kwargs.get("subject") or not kwargs.get("content") or not kwargs.get("mail_to_list"):
        logger.error(u"邮件发送失败:必选参数缺失!")
        return False
    mail_title = "{}{}".format(const.MAIL_TITLE, kwargs.get("subject"))
    mail_to = kwargs.get("mail_to_list")
    mail_msg = (u"<table {table_style}><thead>"
                u"<th style='text-align:left; font-size: 25px'>{greeting}</th></thead><tbody>").format(
        table_style=const.MAIL_OUTER_TABLE_STYLE,
        greeting=u"Hi 亲爱的堡垒机用户, " if len(mail_to) > 1 else (u"Hi {}, ".format(
            User.objects.filter(email=mail_to[0]).first().name
        ))
    )
    mail_msg = u"".join([mail_msg, u"<tr><td><hr /></td></tr>",
                         u"<tr><td>{content}</td></tr>".format(content=kwargs.get("content"))])
    if kwargs.get("show_name_list") and kwargs.get("data"):
        html_table = build_mail_table(kwargs.get("show_name_list"), kwargs.get("data"))
        if html_table:
            mail_msg = u"".join([mail_msg, u"<tr><td>", html_table, u"</td></tr>"])
    mail_msg = u"".join([mail_msg, u"<tr><td><br>", const.MAIL_CSM_ADDRESS, u"</td></tr>",
                         u"<tr><td><hr /></td></tr>", u"<tr><td>",
                         const.MAIL_FOOTER, u"</td></tr></tbody></table>"])

    return send_mail(mail_title, mail_msg, mail_to)

6,调用示范:

subject = u"用户信息公示"
content = u"您所需的堡垒机用户信息如下,请查阅:"
users = models.User.objects.all()[:10]
show_name_list = [u"姓名", u"工号", u"电话", u"Mail"]
data = [(user.name, user.username, user.phone, user.email) for user in users]
mail_to_list = ["demo1@demo.com", "demo2@demo.com"]

if utils.build_and_send_mail(subject=subject, content=content, show_name_list=show_name_list,
                             data=data, mail_to_list=mail_to_list):
    print("Send mail to {} successfully.".format("yonguo"))
else:
    print("Failed")

7,如此便实现了内容和样式的分离。后续如需要改动邮件的结构和样式,只需要维护构建函数即可。