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

文章目录

  • 使用Python实现发送Email电子邮件
    • 实现原理
    • Python实现发送Email电子邮件-基础版
      • 实现源码
      • 源码解析
    • Python实现发送Email电子邮件-完善版
      • 实现源码
      • 源码解析
      • 优化
  • 总结

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

实现原理

使用Python实现发送Email电子邮件【第19篇—python发邮件】_第1张图片

  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电子邮件【第19篇—python发邮件】_第2张图片

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 = '[email protected]'  # 发信人邮箱
    # 定义发件人的邮箱授权码
    emailpass = secretPass  # 邮箱授权码
    # 定义收件人的邮箱地址
    to_email = '[email protected]'  # 收信人邮箱
    # 定义邮件的主题
    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 = "[email protected]"
password = "password"
sender = "[email protected]"
recipients = "[email protected]"
cc = ["[email protected]","[email protected]"]
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 = "[email protected]"
password = "password"
sender = "[email protected]"
recipients = "[email protected]"
cc = ["[email protected]","[email protected]"]
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. 更清晰的代码结构: 第二段代码通过将不同功能块划分为函数,使得代码结构更清晰。这有助于提高代码的可读性和维护性,使每个功能单元更容易理解和修改。

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

你可能感兴趣的:(python,github,开发语言,python发邮件,Python脚本)