使用Python实现发送Email电子邮件【第19篇—python发邮件】

文章目录

  • 👽使用Python实现发送Email电子邮件
    • 🎶实现原理
    • 🏃Python实现发送Email电子邮件-基础版
      • 👫实现源码
      • 🙆源码解析
    • 💇Python实现发送Email电子邮件-完善版
      • 👫实现源码
      • 🙆源码解析
      • 🙀优化
  • 👥总结

👽使用Python实现发送Email电子邮件

🎶实现原理

在这里插入图片描述

  1. 导入必要的模块

    • 导入 smtplib 用于处理 SMTP 功能的模块,以及从 email 模块导入构建电子邮件消息所需的各个组件。
  2. 定义 send_email 函数

    • 创建一个名为 send_email 的函数,该函数接受 SMTP 服务器详细信息、发件人和收件人信息、主题、内容和附件等参数。
  3. 格式化发件人地址

    • 实现 _format_addr 函数以正确格式化发件人的电子邮件地址,如果提供了显示名称,则包含在内。
  4. 初始化电子邮件消息对象

    • 创建 MIMEMultipart 的实例,它将作为电子邮件消息的容器。
  5. 设置发件人信息

    • 在电子邮件消息中设置发件人的信息,包括如果提供了发件人名称则进行设置。
  6. 设置收件人信息

    • 在电子邮件消息中设置收件人的信息。
  7. 处理抄送(CC)信息

    • 如果在 CC 列表中有收件人,则相应地更新电子邮件消息。
  8. 处理密送(BCC)信息

    • 如果在 BCC 列表中有收件人,则类似于处理 CC 列表。
  9. 设置主题和内容

    • 在电子邮件消息中设置主题和内容。
  10. 处理附件

    • 遍历附件列表,读取每个文件,确定其 MIME 类型,并将其附加到电子邮件消息中。
  11. 尝试连接到 SMTP 服务器并发送电子邮件

    • 尝试使用提供的凭据连接到指定的 SMTP 服务器。
    • 如果连接成功,则使用用户名和密码进行登录。
    • 使用 sendmail 方法将电子邮件发送给指定的收件人。
    • 关闭与 SMTP 服务器的连接。
  12. 处理异常

    • 实现异常处理以处理在过程中可能发生的错误,例如文件未找到、附件读取失败或电子邮件发送失败。

该实现涉及使用 email 模块创建电子邮件消息,处理发件人和收件人信息,添加附件,并使用 smtplib 模块连接到 SMTP 服务器并发送电子邮件。代码被组织成一个函数,以便实现可重用性和清晰度。

在这里插入图片描述

🏃Python实现发送Email电子邮件-基础版

👫实现源码

# 导入smtplib模块,这个模块是Python的标准库,用于发送电子邮件
import smtplib
 
# 从email模块中导入MIMEText类,这个类用于创建文本邮件的MIME消息对象
from email.mime.text import MIMEText
 
# 定义一个变量,存储QQ邮箱的SMTP服务器授权码,此授权码用于登录QQ邮箱SMTP服务器
secretPass = 'xxxxxxxxxxxxxxxxxx'  # SMTP服务器授权码
 
 
# 定义一个函数,用于发送指定邮箱的邮件
def sendqqmail(sender_email, sender_pass, rec_email, subject, message):
    # 使用MIMEText类创建一个邮件消息对象,其中message参数是邮件的内容
    msg = MIMEText(message)
 
    # 设置邮件的主题
    msg['Subject'] = subject
 
    # 设置邮件的发件人邮箱
    msg['From'] = sender_email
 
    # 设置邮件的收件人邮箱
    msg['To'] = rec_email
 
    # 使用smtplib模块的SMTP_SSL类创建一个SSL连接对象,连接到QQ邮箱SMTP服务器,其中'smtp.qq.com'是SMTP服务器地址,465是端口号
    # 在这个类中,有两个方法login和send_message,分别用于登录和发送邮件
    with smtplib.SMTP_SSL('smtp.qq.com', 465) as smtp:
        # 使用login方法登录SMTP服务器,参数sender_email和sender_pass分别是发件人的邮箱地址和授权码
        smtp.login(sender_email, sender_pass)
        # 如果登录成功,打印一条消息
        print('登录邮箱成功!')
        # 使用send_message方法发送邮件,参数msg是要发送的邮件消息对象
        smtp.send_message(msg)
        # 发送成功后,打印一条消息
        print('邮件发送完毕')
        # 关闭SMTP服务连接
        smtp.quit()
 
 
# 定义一个主函数,用于运行整个程序
def main():
    # 定义发件人的邮箱地址
    sender_email = 'xxxxxxxxx@qq.com'  # 发信人邮箱
    # 定义发件人的邮箱授权码
    emailpass = secretPass  # 邮箱授权码
    # 定义收件人的邮箱地址
    to_email = 'xxxxxx@xxx.com'  # 收信人邮箱
    # 定义邮件的主题
    sub_msg = '测试python发送邮件'  # 邮件主题
    # 定义邮件的正文内容
    content = '这是我的第一个python发送邮件测试'  # 邮件正文内容
    # 调用sendqqmail函数,发送邮件
    sendqqmail(sender_email, emailpass, to_email, sub_msg, content)  # 发送邮件
 
 
# 执行main函数,这是Python的标准模式
if __name__ == '__main__':
    main()

🙆源码解析

通过SMTP协议发送邮件。

  1. 导入必要的模块:
    • smtplib: 用于连接SMTP服务器并发送邮件。
    • MIMEText类:用于创建文本邮件的MIME消息对象。
import smtplib
from email.mime.text import MIMEText
  1. 定义了一个QQ邮箱的SMTP服务器授权码:
secretPass = 'xxxxxxxxxxxxxxxxxx'  # SMTP服务器授权码
  1. 定义了一个函数 sendqqmail,用于发送指定邮箱的邮件:
    • 创建MIMEText对象,设置邮件主题、发件人、收件人以及邮件内容。
    • 使用smtplib.SMTP_SSL创建一个SSL连接对象,连接到QQ邮箱SMTP服务器。
    • 使用login方法登录SMTP服务器。
    • 使用send_message方法发送邮件。
    • 打印登录成功和邮件发送完毕的消息,然后关闭SMTP服务连接。
def sendqqmail(sender_email, sender_pass, rec_email, subject, message):
    # ...(略)
  1. 定义了主函数 main
    • 定义发件人、邮箱授权码、收件人、邮件主题和邮件内容。
    • 调用 sendqqmail 函数发送邮件。
def main():
    # ...(略)
  1. 使用 if __name__ == '__main__': 来确保代码在作为脚本直接运行时才会执行 main 函数。
if __name__ == '__main__':
    main()

注意事项:

  • 请谨慎存储和处理邮箱密码或授权码,不要将其硬编码在代码中或分享给其他人。
  • 在使用SMTP服务发送邮件时,需要确保你的邮箱开启了SMTP服务,并使用了正确的SMTP服务器地址和端口号。这些信息可以从你的邮箱服务提供商获取。

💇Python实现发送Email电子邮件-完善版

👫实现源码

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.header import Header
from email.utils import parseaddr, formataddr
import mimetypes
import os 
 
def send_email(smtp_server, username, password, sender, recipients, subject, content, cc, bcc, port=25, sendername=None, attachments=None):
    def _format_addr(s):
        name, addr = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), addr))
    if not attachments:
        attachments = []
    msg = MIMEMultipart()
    if sendername:
        msg['From'] = _format_addr(sendername + ' <%s>' % sender)
    else:
        msg['From'] = sender
    if isinstance(recipients, str):
        recipients = [recipients]
    msg['To'] = ",".join(recipients)
    if cc:
        if isinstance(cc, str):
            cc = [cc]
        cc_list = [addr for addr in cc if addr not in recipients]
        if cc_list:
            msg['Cc'] = ",".join(cc_list)
            recipients += cc_list
    if bcc:
        if isinstance(bcc, str):
            bcc = [bcc]
        bcc_list = [addr for addr in bcc if addr not in recipients]
        if bcc_list:
            msg['Bcc'] = ",".join(bcc_list)
            recipients += bcc_list
    msg['Subject'] = Header(subject, 'utf-8').encode()
    text_part = MIMEText(content, 'html', 'utf-8')
    msg.attach(text_part)
    for attachment in attachments:
        file_path = attachment["path"]
        if not os.path.isfile(file_path):
            print("附件文件不存在:{}".format(file_path))
            continue
        try:
            with open(file_path, "rb") as f:
                mime_type, encoding = mimetypes.guess_type(file_path)
                if mime_type is None:
                    mime_type = 'application/octet-stream'
                part = MIMEApplication(f.read())
                part.add_header('Content-Disposition', 'attachment', filename=attachment["filename"])
                part.add_header('Content-Type', mime_type)
                msg.attach(part)
        except FileNotFoundError as e:
            print("文件未找到:{}".format(e))
        except Exception as e:
            print("附件读取失败:{}".format(e))
    try:
        if str(port) == "25":
            server = smtplib.SMTP(smtp_server, port)
        else:
            server = smtplib.SMTP_SSL(smtp_server, port)
        server.login(username, password)
        server.sendmail(sender, recipients, msg.as_string())
        server.quit()
        print("邮件发送成功!")
    except Exception as e:
        print("邮件发送失败:{}".format(e))
 
 
 
smtp_server = "smtp.aliyun.com"
username = "abc@aliyun.com"
password = "password"
sender = "abc@aliyun.com"
recipients = "abc@abc.cn"
cc = ["abc@126.com","abc@139.com"]
bcc = ""
subject = "title"
content = "content"
n = "name"
port = 25
attachments = [{"filename":"申请单.xlsx","path":"C:/申请单.xlsx"},
               {"filename": "新课标.docx", "path": "D:/新课标.docx"},
                {"filename": "笨笨狗.pdf", "path": "D:/books/笨笨狗.pdf"}]
 
send_email(smtp_server, username, password, sender, recipients, subject, content, cc,bcc,port=port, sendername=n, attachments=attachments)

🙆源码解析

用于发送带附件的邮件的 Python 脚本。

  1. 导入必要的模块:
    • smtplib: 用于连接SMTP服务器并发送邮件。
    • MIMEText:创建文本邮件的MIME消息对象。
    • MIMEMultipart:创建包含附件的MIME消息对象。
    • MIMEApplication:用于处理附件的MIME消息对象。
    • Header:用于对邮件头进行编码。
    • parseaddrformataddr:用于格式化发件人和收件人地址。
    • mimetypes:用于猜测文件的MIME类型。
    • os:用于处理文件路径。
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.header import Header
from email.utils import parseaddr, formataddr
import mimetypes
import os
  1. 定义了一个发送邮件的函数 send_email
    • 使用 MIMEMultipart 创建一个包含附件的邮件消息对象。
    • 格式化发件人和收件人地址。
    • 设置邮件主题、发件人、收件人、抄送、密送。
    • 将文本内容添加到邮件中。
    • 添加附件到邮件中。
    • 使用 smtplib 连接到SMTP服务器,登录,发送邮件,然后关闭连接。
def send_email(smtp_server, username, password, sender, recipients, subject, content, cc, bcc, port=25, sendername=None, attachments=None):
    # ...(略)
  1. 定义了一个辅助函数 _format_addr 用于格式化地址:
def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
  1. 调用 send_email 函数发送邮件,传递了一些必要的参数,包括SMTP服务器、发件人、收件人、邮件主题、文本内容、抄送、密送、发件人姓名、附件等信息。
smtp_server = "smtp.aliyun.com"
username = "abc@aliyun.com"
password = "password"
sender = "abc@aliyun.com"
recipients = "abc@abc.cn"
cc = ["abc@126.com","abc@139.com"]
bcc = ""
subject = "title"
content = "content"
n = "name"
port = 25
attachments = [{"filename":"申请单.xlsx","path":"C:/申请单.xlsx"},
               {"filename": "新课标.docx", "path": "D:/新课标.docx"},
                {"filename": "笨笨狗.pdf", "path": "D:/books/笨笨狗.pdf"}]
 
send_email(smtp_server, username, password, sender, recipients, subject, content, cc,bcc,port=port, sendername=n, attachments=attachments)

🙀优化

第二段代码相对于第一段代码进行了一些优化,主要体现在以下几个方面:

  1. 支持附件:

    • 第二段代码引入了 email.mime.multipartemail.mime.application 模块,允许通过 attachments 参数添加附件。这使得邮件可以携带更多类型的内容。
  2. 更灵活的邮件构建:

    • 第二段代码使用 MIMEMultipart 对象创建邮件消息,可以更灵活地构建邮件内容,包括添加文本部分、HTML部分、以及附件等。
  3. 更友好的发件人地址:

    • 引入了 _format_addr 辅助函数,用于格式化发件人地址,支持设置发件人姓名。
  4. 更丰富的邮件头信息:

    • 使用 Header 对邮件主题进行编码,确保支持非ASCII字符的主题。
    • 设置了 Content-Disposition 头部,用于指定附件的处理方式。
  5. 更全面的错误处理:

    • 添加了对附件文件是否存在的检查,并输出相应的错误信息。
    • 在捕获异常时,输出更详细的错误信息,有助于定位问题。
  6. 端口号处理:

    • 第二段代码通过 str(port) == "25" 的判断来决定使用普通 SMTP 还是 SMTP_SSL,使得端口的设置更加直观。
  7. 更清晰的代码结构:

    • 第二段代码通过将不同的功能块划分为函数,使得代码结构更加清晰,方便维护和阅读。

第二段代码在邮件功能的实现上更为完善,具有更多的灵活性和可读性,并且考虑到了更多的错误处理情况,使得代码更健壮。

👥总结

这两段代码都是用于发送邮件的简单Python脚本,但第二段代码相对于第一段代码进行了一些优化和改进。以下是一些心得总结:

  1. 支持附件的扩展: 第二段代码引入了附件的支持,使用了email.mime.multipartemail.mime.application模块,使得邮件可以携带更多类型的内容,包括文本和附件。

  2. 更友好的发件人地址: 引入了 _format_addr 辅助函数,用于格式化发件人地址,支持设置发件人姓名。这样可以使邮件中的发件人信息更加友好和易读。

  3. 更丰富的邮件头信息: 使用 Header 对邮件主题进行编码,确保支持非ASCII字符的主题。同时,设置了 Content-Disposition 头部,用于指定附件的处理方式,提高邮件的兼容性。

  4. 更全面的错误处理: 第二段代码在处理附件时增加了对附件文件是否存在的检查,并在捕获异常时输出更详细的错误信息。这样的改进有助于提高代码的健壮性,及时发现并处理潜在问题。

  5. 更清晰的代码结构: 第二段代码通过将不同功能块划分为函数,使得代码结构更清晰。这有助于提高代码的可读性和维护性,使每个功能单元更容易理解和修改。

总的来说,第二段代码在功能实现上更为完善,具有更多的灵活性和可读性,并且考虑到了更多的错误处理情况,使得代码更加健壮。在编写邮件发送脚本时,综合考虑邮件内容的复杂性和错误处理的全面性是很重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/267341.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

随机无限采集JK妹妹高清壁纸下载HTML网页源码

源码介绍 美图网站千千万&#xff0c;美图自己说了算&#xff01;本源码由宋佳乐博客 开发&#xff0c;首页图片做了浏览器窗口自适应&#xff0c;最大化占满PC浏览器和移动浏览器的窗口&#xff0c;并且防止出现滚动条。 功能介绍 首页图片设置了4个点击功能区&#xff0c;…

【数据结构入门精讲 | 第十一篇】一文讲清树

在上一篇中我们进行了排序算法的专项练习&#xff0c;现在让我们开始树的知识点讲解。 目录 树二叉搜索树二叉排序树哈夫曼树折半查找判定树kruskal算法、prim算法、最小生成树完全二叉树 树 树是一种非线性的数据结构&#xff0c;也是一种表示一对多关系的数据结构&#xff0…

Flink CDC 1.0至3.0回忆录

Flink CDC 1.0至3.0回忆录 一、引言二、CDC概述三、Flink CDC 1.0&#xff1a;扬帆起航3.1 架构设计3.2 版本痛点 四、Flink CDC 2.0&#xff1a;成长突破4.1 DBlog 无锁算法4.2 FLIP-27 架构实现4.3 整体流程 五、Flink CDC 3.0&#xff1a;应运而生六、Flink CDC 的影响和价值…

Python 数据分析 Matplotlib篇 plot设置线条样式(第2讲)

Python 数据分析 Matplotlib篇 plot设置线条样式(第2讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

算法基础之完全背包问题

完全背包问题 核心思想&#xff1a;集合表示&#xff1a; f[i][j]表示前i种物品 总容量不超过j的最大价值 求f[i][j]时 分为选0、1、2……n个第i种物品 n种情况 每种情况为 f[i][j-kv] (取k个第i种物品) 即f[i][j] max(f[i-1][j] , f[i-1][j-v]w,f[i-1][j-2v]2w….f[i-1][j-k…

【自用】Ubuntu20.4从Vivado到ddr200t运行HelloWorld

【自用】Ubuntu20.4新系统从输入法到ddr200t运行HelloWorld 一、编辑bashrc二、Vivado2022.2安装三、编译蜂鸟E203自测样例1. 环境准备2. 下载e203_hbirdv2工程文件3. 尝试编译自测案例1. 安装RISC-V GNU工具链2. 编译测试样例 4. 用vivado为FPGA生成mcs文件1.准备RTL2.生成bit…

Centos 7.9安装Oracle19c步骤亲测可用有视频

视频介绍了在虚拟机安装centos 7.9并安装数据库软件的全过程 视频链接&#xff1a;https://www.zhihu.com/zvideo/1721267375351996416 下面的文字描述是安装数据库的部分介绍 一.安装环境准备 链接&#xff1a;https://pan.baidu.com/s/1Ogn47UZQ2w7iiHAiVdWDSQ 提取码&am…

贝叶斯球快速检验条件独立

贝叶斯球 定义几个术语&#xff0c;描述贝叶斯球在一个结点上的动作&#xff1a; 通过&#xff08;pass through&#xff09;&#xff1a;从当前结点的父结点方向过来的球&#xff0c;可以访问当前结点的任意子结点&#xff08;父->子&#xff09;。从当前节点的子结点方向…

基于电商场景的高并发RocketMQ实战-NameServer内核原理剖析、Broker 主从架构与集群模式原理分析

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 【11来了】文章导读地址&#xff1a;点击查看文章导读&#xff01; &#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f3…

Prometheus介绍和安装

Prometheus介绍和安装 1. Prometheus介绍 Prometheus&#xff08;普罗米修斯&#xff09;是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目&#xff0c;拥有非常活跃的开发人员和用户社区。为强调开源及独立维护&#xff0c;Prometheus于2016年加入云原生云…

指标体系构建-03-交易型的数据指标体系

参考&#xff1a; 本文参考 1.接地气的陈老师的数据指标系列 2.科普 | 零售行业的数据指标体系及其含义、应用阶段 3.”人货场”模型搞懂没&#xff1f;数据分析大部分场景都能用&#xff01; 4.一分钟读懂广告投放各计费CPM、CPC等&#xff08;公式推导干货&#xff09; 5.AA…

mysql 数据编译安装以及参数说明 安装包下载

目录 MySQL 官网地址官网下载源码包安装步骤修改密码 MySQL 官网地址 https://dev.mysql.com/doc/ 官网下载源码包 安装步骤 # 所需要的依赖及安装mysql的包" [rootmysql_source ~]# yum -y install ncurses ncurses-devel openssl-devel bison libgcrypt gcc gcc-c ma…

前缀和+单调双队列+贪心:LeetCode2945:找到最大非递减数组的长度

本文涉及知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 单调双队列 贪心 题目 给你一个下标从 0 开始的整数数组 nums 。 你可以执行任意次操作。每次操作中&#xff0c;你需要选择一个 子数组 &#xff0c;并将这个子数组用它所…

AcWing 1238. 日志统计(双指针,滑动窗口)

题目&#xff1a; 1238. 日志统计 - AcWing题库 数据范围 输入样例&#xff1a; 7 10 2 0 1 0 10 10 10 10 1 9 1 100 3 100 3输出样例&#xff1a; 1 3 思路&#xff1a;双指针 代码&#xff1a; #include<iostream> #include<cstdio> #include<cmath>…

如何从 Android 手机免费恢复已删除的通话记录/历史记录?

有一个有合作意向的人给我打电话&#xff0c;但我没有接听。更糟糕的是&#xff0c;我错误地将其删除&#xff0c;认为这是一个骚扰电话。那么有没有办法从 Android 手机恢复已删除的通话记录呢&#xff1f;” 塞缪尔问道。如何在 Android 上恢复已删除的通话记录&#xff1f;如…

LeetCode刷题--- 组合总和

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递归递归、搜…

uniapp怎么动态渲染导航栏的title?

直接在接口请求里面写入以下&#xff1a; 自己要什么参数就写什么参数 本人仅供参考&#xff1a; this.name res.data.data[i].name; console.log(名字, res.data.data[i].name); uni.setNavigationBarTitle({title: this.name}) 效果&#xff1a;

[Linux] MySQL数据库之索引

一、索引的相关知识 1.1 索引的简介 索引是一个排序列表&#xff0c;包含索引值和包含该值的数据行的物理地址&#xff08;类似于 c 语言链表&#xff0c;通过指针指向数据记录的内存地址&#xff09;。 使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是先通过索…

Redis-运维

转自 极客时间 Redis 亚风 原文视频&#xff1a;https://u.geekbang.org/lesson/535?article681062 Redis 同步 Redis主从数据同步,主从第⼀次同步是全量同步 replicaof 主机 端口 #当前这个机器做Master的备份master如何判断slave是不是第⼀次来同步数据&#xff1a; Repl…

掌握iText:轻松实现固定pdf模板的动态数据填充

推荐语 如果你在工作中需要处理大量的PDF表单&#xff0c;那么使用iText5实现固定PDF模板的动态数据填充&#xff0c;将是一种非常有效的方法。这篇技术文章详细介绍了如何使用iText5库来读取已有的PDF模板&#xff0c;并动态地填充表单数据&#xff0c;生成最终的表单文件。通…