Python3实现向指定邮箱发送邮件(支持附件文件、图片等)

Background

最近业务需求需要把生成的月报定时发送到指定邮箱,直接在网上找了相关经验改巴改巴给实现了,测试可以直接使用,生产是我从MySQL数据库获取文件信息和邮箱等使用的,程序中的注释相当清楚了。定时是通过shell脚本实现的。

获取邮件服务器和授权码

在这里插入图片描述
在这里插入图片描述

源码

from datetime import datetime
from pymysql import connect
import smtplib
from email.header import Header
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart


# 【mysql 基本信息】
class MysqlUtil:
    # 定义基本属性【测试】
    host = '110.110.110.110'
    username = 'wlf'
    password = 'wlf'
    database = 'wlf'
    charset = 'utf8'

    # 定义基本属性【生产】
    # host = '192.168.110.110'
    # username = 'wlf'
    # password = 'wlf'
    # database = 'wlf'
    # charset = 'utf8'

    # 定义构造方法
    def __init__(self):
        self.connection = None
        self.cursor = None
        # 初始化 MySQL 连接配置
        try:
            self.connection = connect(host=self.host, user=self.username, password=self.password,
                                      database=self.database, charset=self.charset)
            self.cursor = self.connection.cursor()
        except():
            print("mysql connect failed, please check the config")

    # 获取所有需要发送月报的项目以及对应的邮箱,返回字典结构,key为项目id,value为list,存储邮箱
    def get_projects_with_emails(self):
        table = 'cft_report_email'
        pid_email_dict = {}
        sql_projects = "SELECT `project_id`, `email` FROM %s" % table
        self.cursor.execute(sql_projects)
        res_pid_email = self.cursor.fetchall()
        for pe in res_pid_email:
            pid = pe[0]
            email = pe[1]
            if pid in pid_email_dict:
                pid_email_dict[pid].append(email)
            else:
                email_list = [email]
                pid_email_dict[pid] = email_list
        return pid_email_dict

    # 根据项目id和月报时间获取月报路径
    def get_filepath(self, pid):
        table = 'report_month'
        last_month_date = get_last_month_date()
        sql = "SELECT `path` FROM %s WHERE project_id = '%s' AND `report_date` = '%s'" % (table, pid, last_month_date)
        self.cursor.execute(sql)
        res_path = self.cursor.fetchone()[0]
        return res_path


# 获取上月日期 年份和月份 例子:2020年10月
def get_last_month_date():
    now_month = datetime.now()
    year = now_month.year
    month = now_month.month
    if month == 1:
        month = 12
        year -= 1
    else:
        month -= 1
    return str(year) + "年" + str(month) + "月"


# 向指定邮箱发送文件
def send_email(file, emails):
    """
    发送邮件的脚本,在邮件中可添加text文本,图片和附件
    :return:
    """
    # 设置服务器(这里是163的服务器,这里需要用户名和密码,host网上查对应的smtp服务器)
    mail_host = "smtp.163.com"
    mail_user = "yunluwlf@163.com"
    # 密码(这里的密码不是登录邮箱密码,而是授权码)
    mail_auth_code = "IXMHKCCISDRJGVJW"
    # 邮件发送和接收人
    sender = mail_user
    reciever = emails
    # 邮件头信息
    message = MIMEMultipart('related')
    message['From'] = sender
    message['To'] = ','.join(reciever)
    message['Subject'] = Header('数据简报【输电铁塔】')
    # ③图片 形式的内容添加到邮件(包含在②中,否咋上传的是图片附件)
    # fp = open(r'D:/wkspc/pycharm-wkspc/wind_rose/imgs/2020-10/ybj/wind-rose.jpg', 'rb')
    # content_image = MIMEImage(fp.read())
    # fp.close()
    # content_image.add_header('content-disposition', 'attachment', filename='wind-rose.jpg')
    # message.attach(content_image)
    # ④ 附件 形式的内容添加到邮件
    attach_table = MIMEApplication(open(file, 'rb').read())
    attach_table.add_header('content-disposition', 'attachment', filename=get_file_name(file))
    # 这样的话,附件名称就可以是中文的了,不会出现乱码
    attach_table.set_charset('utf-8')
    message.attach(attach_table)
    # 发送邮件,测试成功,流程都是固定的:创建客户端,登陆,发送,关闭
    try:
        # 实例化
        smtpObj = smtplib.SMTP()
        # 25为 SMTP 端口号
        smtpObj.connect(mail_host, 25)
        smtpObj.login(mail_user, mail_auth_code)
        print('登录成功!')
        smtpObj.sendmail(mail_user, reciever, message.as_string())
        smtpObj.quit()
        print("恭喜:邮件发送成功!")
    except smtplib.SMTPException:
        print("错误:邮件发送失败!")


# 根据文件路径获取文件名
def get_file_name(file_path):
    splits = file_path.split("/")
    return splits[len(splits) - 1]


if __name__ == '__main__':
    # 【测试】
    file_send = 'docs/results/2020年10月/羊八井测点2020年10月风场实测数据简报.docx'
    emails_to_send = ['1147314023@qq.com', 'longfei.wang@cloudansys.com']
    send_email(file_send, emails_to_send)

    # 【生产】
    # 获取MySQL工具类对象
    # mysql_util = MysqlUtil()
    # # 获取所有需要发送月报的项目id以及对应的邮箱
    # dict_pid_with_email = mysql_util.get_projects_with_emails()
    # # 获取所有需要发送月报的项目id
    # dict_keys = dict_pid_with_email.keys()
    # for project_id in dict_keys:
    #     # 根据项目id获取获取发送的月报路径
    #     the_filepath = mysql_util.get_filepath(project_id)
    #     # 获取项目id对应的邮箱
    #     the_email_list = dict_pid_with_email[project_id]
    #     # 向对应的邮箱发送邮件
    #     send_email(the_filepath, the_email_list)

效果

在这里插入图片描述
在这里插入图片描述

注意

经测试:支持网易邮箱和qq邮箱;不支持搜狐邮箱。
ps:其实搜狐邮箱也能发送成功,但是发过去的时候文件不知怎么被改名改后缀了,变成了`投递状态.txt`,当然,如果手动把txt改成docx还是可以打开文件的,内容也没变。

在这里插入图片描述

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WaiSaa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值