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

2023-11-06

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还是可以打开文件的,内容也没变。

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 工作日重新订购 Pandas 系列

    使用 Pandas 我提取了一个 CSV 文件 然后创建了一系列数据来找出一周中哪几天崩溃最多 crashes by day bc DAY OF WEEK value counts 然后我将其绘制出来 但当然它按照与该系列相同的排名顺序绘制
  • sklearn 中的 pca.inverse_transform

    将我的数据拟合后 X 我的数据 pca PCA n components 1 pca fit X X pca pca fit transform X 现在 X pca 具有一维 当我根据定义执行逆变换时 它不是应该返回原始数据 即 X 二维
  • Python3.0 - 标记化和取消标记化

    我正在使用类似于以下简化脚本的内容来解析较大文件中的 python 片段 import io import tokenize src foo bar src bytes src encode src io BytesIO src src l
  • 如果未引发异常,则通过 Python 单元测试

    在Python中unittest框架 是否有一种方法可以在未引发异常的情况下通过单元测试 否则会因 AssertRaise 而失败 如果我正确理解你的问题 你could做这样的事情 def test does not raise on va
  • 我如何知道 C 程序的可执行文件是在前台还是后台运行?

    在我的 C 程序中 我想知道我的可执行文件是否像这样在前台运行 a out 或者像这样 a out 如果你是前台工作 getpgrp tcgetpgrp STDOUT FILENO or STDIN FILENO or STDERR FIL
  • 监视目录的更改

    很像一个类似的问题 https stackoverflow com questions 112276 directory modification monitoring 我正在尝试监视 Linux 机器上的目录以添加新文件 并希望在这些新文
  • Gspread如何复制sheet

    在 Stackoverflow 上进行谷歌搜索和搜索后 我想我找不到有关如何复制现有工作表 现有模板工作表 并将其保存到另一个工作表中的指南 根据文档 有重复表 https gspread readthedocs io en latest
  • ODBC 链接表中突然开始出现写入冲突消息

    我有一个 mySQL 数据库 用于跟踪我们的项目并驱动我们的网站显示其信息 为了方便更新数据库 我设置了一个使用 ODBC 连接 MySQL ODBC 5 1 来编辑数据的访问数据库 过去几个月一直运行良好 没有出现任何问题 然而 昨晚用户
  • Python新式类和__subclasses__函数

    有人可以向我解释为什么这有效 在 Python 2 5 中 class Foo object pass class Bar Foo pass print Foo subclasses 但这不是 class Foo pass class Ba
  • Tensorflow 与 Keras 的兼容性

    我正在使用 Python 3 6 和 Tensorflow 2 0 并且有一些 Keras 代码 import keras from keras models import Sequential from keras layers impo
  • 数据读取过程中遇到致命错误

    我正在进行定期更新表扫描 Using connect1 As New MySqlConnection ConnectLocalhost serverString connect1 Open Dim cmd New MySqlCommand
  • SMTP_SSL SSLError: [SSL: UNKNOWN_PROTOCOL] 未知协议 (_ssl.c:590)

    此问题与 smtplib 的 SMTP SSL 连接有关 当与 SMTP 无 ssl 连接时 它正在工作 在 SMTP SSL 中尝试相同的主机和端口时 出现错误 该错误仅基于主机 gmail 设置也工作正常 请检查下面的示例 如果 Out
  • 您可以使用 MySQL 查询来完整创建数据库的副本吗

    我有一个包含 5 个表的 MySQL 数据库的实时版本和一个测试版本 我不断使用 phpMyAdmin 将实时版本中的每个表复制到测试版本 有谁有mysql查询语句来制作数据库的完整副本吗 查询字符串需要考虑结构 数据 自动增量值以及与需要
  • 在 keras 中保存和加载权重

    我试图从我训练过的模型中保存和加载权重 我用来保存模型的代码是 TensorBoard log dir output model fit generator image a b gen batch size steps per epoch
  • 根据最大值连接表

    这是我正在谈论的内容的一个简化示例 Table students exam results id name id student id score date 1 Jim 1 1 73 8 1 09 2 Joe 2 1 67 9 2 09 3
  • MYSQL 按喜欢/不喜欢和受欢迎程度排序

    我有评论表 其中包括喜欢和不喜欢的内容 现在我在正确的顺序上遇到了问题 实际上 我的系统在顶部显示了最多点赞的评论 我正在 youtube 上寻找类似系统的东西 这意味着 100like 100dislikes 的评论的顺序高于 1 1 我
  • 混淆矩阵不支持多标签指示符

    multilabel indicator is not supported是我在尝试运行时收到的错误消息 confusion matrix y test predictions y test is a DataFrame其形状为 Horse
  • Django 与谷歌图表

    我试图让谷歌图表显示在我的页面上 但我不知道如何将值从 django 视图传递到 javascript 以便我可以绘制图表 姜戈代码 array Year Sales Expenses 2004 1000 400 2005 1170 460
  • 双击打开 ipython 笔记本

    相关文章 通过双击 osx 打开 ipython 笔记本 https stackoverflow com questions 16158893 open an ipython notebook via double click on osx
  • python 线程安全可变对象复制

    Is 蟒蛇的copy http docs python org 2 library copy html模块线程安全吗 如果不是 我应该如何在 python 中以线程安全的方式复制 deepcopy 可变对象 蟒蛇的GIL http en w

随机推荐

  • 为什么Centos装上以后,执行apt-get命令提示没有该命令

    CentOS的软件安装工具不是apt get 是yum yum y install 你要安装的文件
  • java最大堆空间会自动扩增吗_最大化Java堆空间

    我试图在 Java中使用非常大的方阵 n 1e6或更大的数量级 矩阵不是稀疏的 所以我没有看到很多方法将它们表示为2D数组 这需要n 2 sizeof int 位的内存 显然 我正在获得堆溢出错误 即使添加编译器标志来使用我的机器将允许的大
  • 二十九.刷题.19

    输入两点坐标 X1 Y1 X2 Y2 0 lt x1 x2 y1 y2 lt 1000 计算并输出两点间的距离 include
  • centos7.3 32位 安装ssh实现远程登陆

    centos7 3 32位 安装ssh实现远程登陆 安装ssh sudo yum install openssh 关闭防火墙 永久禁用 sudo systemctl disable firewalld 重启ssh sudo systemct
  • 流动的数据——使用 RxJS 构造复杂单页应用的数据逻辑

    感谢作者徐飞的授权发布 作者 徐飞 网名民工精髓V 曾任Teambition前端架构师 苏宁云计算中心前端架构师 有十年以上大型企业应用前端架构及开发经验 熟悉AngularJS等框架 对Web组件化有一些思考 博客地址 https git
  • 微软server2012服务器端客户端,windows server 2012 datacenter配置iSCSI目标服务器和客户端配置...

    您好 1 在添加角色时 添加 文件和存储服务 文件和iSCSI服务 iSCSI目标存储提供程序 VDS和VSS硬件提供程序 这项主要的作用是什么 在配置iSCSI目标服务器时 有没有必要安装 这个应该 是 让 iscsi 卷 支持 VSS
  • gitee配置SSH公钥

    第一步 找个地方打开 git bash 然后输入生成ssh公钥的命令 ssh keygen t rsa C your email 然后敲四次回车生成公钥 第二步 输入查看公钥的命令 cat ssh id rsa pub 结果如下 第三步 将
  • 如何在微信小程序中优雅地发送异步请求

    一 微信小程序运行环境 微信小程序的 javascript 运行环境和浏览器不同 页面的脚本逻辑是在JsCore中运行 JsCore是一个没有窗口对象的环境 所以不能在脚本中使用window 也无法在脚本中操作组件 JsCore中也没有 X
  • ProtoBuf(Google Protocol Buffers)—— C++开发具体教程

    ProtoBuf C 开发 教程 C 开发 教程 1 定义你的 protocol 格式 1 1 protocol 字段格式 1 2 指定字段规则 1 3 proto文件 2 编译你的 Protocol Buffers 3 The Proto
  • 【华为OJ】【在字符串中找出连续最长的数字串】

    题目描述 请一个在字符串中找出连续最长的数字串 并把这个串的长度返回 如果存在长度相同的连续数字串 返回最后一个连续数字串 注意 数字串只需要是数字组成的就可以 并不要求顺序 比如数字串 1234 的长度就小于数字串 1359055 如果没
  • 模板类的特化和类型萃取

    模板类的特化 有时为了需要 针对特定的类型 需要对模板进行特化 也就是所谓的特殊处理 全特化 对传入的数据类型都做了限制 偏特化 半特化 偏特化并不仅仅是指特殊部分参数 而是针对模板参数更进一步的条件限制所设计出来的一个特化版本 模板的全特
  • Linux vim的常见基本操作

    目录 vim是一款多模式的编辑器 命令模式下 用小写英文字母 h j k l 分别控制光标左 下 上 右移一格 gg 定位到代码第一行 n shift g 定位到任意一行 最后一行 移动到光标所在行的结尾 移动到光标所在行的开头 w 以单词
  • Linux之 Shell分析日志文件

    文章目录 前言 1 查看有多少个IP访问及某一个页面被访问的次数 2 查看每一个IP访问了多少个页面及个IP访问的页面数进行从小到大排序 3 查看某一个IP访问了哪些页面及去掉搜索引擎统计的页面 4 查看2015年8月16日14时这一个小时
  • React Hook的用法: Ref + useMemo + 自定义Hook(三)

    React Hook的用法 Ref Hook 这个Hook的作用是可以通过他来获取到Dom元素节点 使用起来非常方便 关键代码如下 const xxxEle useRef initialValue 1 useRef返回一个ref变量 并接受
  • U盘怎么重装系统到电脑上

    当今社会 电脑可以说是融入了我们的生活 每个工作职能都需要使用到电脑来录入信息 电脑既然这么重要 但还是偶然出现些小故障 我们都可以通过u盘来重装系统拯救电脑 更多系统教程尽在小白系统重装官网 1 注 准备好一个8g以上u盘 一台能上网的电
  • Blender里的三种绑定:(一)主从绑定

    文章目录 Blender里的三种绑定 主从绑定 进行物体绑定 进行顶点绑定 解除绑定 保持变换 无反向 进行晶格绑定 Blender里的三种绑定 1 Blender中一共有三种绑定模式 分别是 主从绑定 约束 骨骼 主从绑定 1 主从绑定即
  • python下载安装过程——超详细!

    Python 下载安装 文末附python全套学习资料 安装python分三个步骤 1 下载python 2 安装python 3 检查是否安装成功 1 下载Python 1 python下载地址https www python org d
  • python使用pycrawlers批量下载huggingface上的模型与数据文件

    文章目录 前言 一 git下载的例子 二 pycrawlers的使用 1 安装 2 批量下载 3 单个下载 4 示例 5 后台下载 6 断点续传 总结 前言 现在从下载huggingface的文件一般使用git 下载单个小型模型的文件使用g
  • Linux系统管理:虚拟机Alpine Linux安装

    目录 一 理论 1 Alpine Linux 二 实验 1 Alpine Linux安装 三 问题 1 Alpine Linux 缺少VIM命令 2 Alpine Linux SSH连接不上 3 Alpine Linux IP配置 四 总结
  • Python3实现向指定邮箱发送邮件(支持附件文件、图片等)

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