使用Python 通过SMTP协议发送邮件

内容导读

  1. smtp协议介绍
  2. 使用的模块(对应介绍)
  3. 代码片段解读
  4. 源码展示(有基础的可以直接看这里)
  5. 相关资料

1.smtp协议介绍

SMTP(simple mail transfer protocol)简单邮件传输协议,SMTP 协议属于 TCP/IP 协议簇,用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式,帮助每台计算机在发送或中转信件时找到下一个目的地。SMTP是一个“推”(发送)的协议,它不允许根据需要从远程服务器上“拉”(获取)来消息。而SMTP 服务器就是使用SMTP 协议来发送邮件的服务器。

2.使用的模块

# 以下三个模块都是python自带的基础模块不需要下载
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
smtplib(点击展开)

smtplib 是 Python 的一个标准库,用于提供与 SMTP(简单邮件传输协议)服务器交互的功能。这个库允许你发送邮件,通过 SMTP 协议与邮件服务器进行通信。

  • 功能:支持邮件的发送,包括纯文本邮件、HTML 邮件以及带附件的邮件。
  • 安全性:可以与支持 SSL(SMTP_SSL)或 TLS(通过 starttls() 方法)的 SMTP 服务器进行安全连接。
  • 默认端口:25(推荐使用默认端口的TLS协议会更安全源码里有写,我这里使用SSL协议所以下面端口设置为465)
  • 本代码中使用的方法:
    • smtplib.SMTP_SSL() 是 Python 标准库 smtplib 模块中的一个方法,用于创建一个预设为使用 SSL(Secure Sockets Layer)加密的 SMTP(Simple MailTransfer Protocol)连接。这个连接允许你安全地发送邮件,因为 SSL 会在邮件发送过程中加密数据传输。
    • 语法
      smtplib.SMTP_SSL(host, port)
    • host:SMTP 服务器的地址,通常是一个字符串,表示服务器的域名或 IP 地址。
    • port:SMTP 服务器的端口号,SSL 通常使用 465 或 994 作为默认端口。
email.mime.text.MIMEText(点击展开)

MIMEText 是 email 模块中的一个类,用于创建 MIME(多用途互联网邮件扩展)格式的纯文本消息。

  • 用途:通常用于创建邮件的正文内容。
  • 语法:
    MIMEText(_text, _subtype='plain', _charset='us-ascii')
  • 具体参数:
    • _text:这是要包含在邮件正文中的文本内容。
    • _subtype:这个参数指定了邮件正文的类型。常见的值有:
      • 'plain':表示纯文本邮件正文(默认值)。
      • 'html':表示 HTML 格式的邮件正文。
    • _charset:指定文本内容使用的字符编码。通常设置为 'utf-8' 以支持国际化文本。
  • 返回值:MIMEText 返回一个 MIMEText 对象,该对象是 email.mime.text.MIMEText 类的一个实例,可以作为构建更复杂邮件结构的一部分。
email.mime.multipart.MIMEMultipart(点击展开)

MIMEMultipart 类也是 email 模块的一部分,用于创建包含多个部分(如文本和附件)的邮件。

  • 用途:当你需要发送包含多种内容类型的邮件时使用,例如同时包含文本正文和附件(我这里只使用了正文)
  • 构造函数:在创建 MIMEMultipart 对象时,可以指定一个子类型(默认为 mixed),用于指示邮件包含多个部分。
  • 功能:可以添加多个 MIMEText 或 MIMEBase 对象作为邮件的一部分,支持构建复杂的邮件结构。
  • 本代码中使用的方法:.attach() 方法是 MIMEMultipart 类的一个成员函数,用于将一个邮件内容部分附加到一个多部分邮件消息中。当你创建一个 MIMEMultipart 对象时,你可以使用 .attach() 方法来添加文本内容、HTML 内容或附件等;;.as_string() 方法是 email 模块中 EmailMessage 类的一个方法用于将邮件消息对象转换为字符串形式的邮件内容。这个字符串包含了邮件的头部(headers)和正文(body),遵循 MIME(多用途互联网邮件扩展)的格式规范。当你使用 email 模块的类(如 MIMETextMIMEMultipart 等)构建了一个邮件消息后,你需要将这个对象转换成字符串形式,以便能够发送。as_string() 方法就承担了这一转换任务。
TLS与SSL协议的区别(点击展开)

TLS是传输层安全的缩写,SSL是安全套接字层的缩写,都是加密数据和在Internet上移动数据时验证连接的加密协议。TLS 实际上只是SSL的更新版本。它修复了早期SSL协议中的一些安全漏洞。SSL 2.0于1995年2月首次发布(由于安全缺陷,SSL 1.0从未公开发布)。尽管SSL 2.0已公开发布,但它也包含安全漏洞,并在1996年迅速被SSL 3.0取代。然后,在1999 年,TLS (1.0) 的第一个版本作为对SSL 3.0的升级发布。从那以后,又发布了三个TLS版本,最新版本是2018年8月的TLS 1.3。

至于SSL协议与SSL证书则是顺延关系,SSL证书使用了SSL的名字但实际上并不是直接指代SSL协议,大多数人仍然将它们称为SSL证书的原因基本上是品牌问题。大多数主要的证书提供商仍然将证书称为SSL证书,但实际上都是SSL/TLS 证书

3.代码片段解读

3.1首先使用变量将SMTP协议需要的基本参数准备好(部分smtp服务器地址在后的相关资料里有,而授权码不知道搞的同志可以参考这里的示例1  示例2  kimi(问AI)

# smtp服务器(依服务商而定)
server_host = 'smtp.126.com'

# 端口(依据使用的协议而定,我这里使用的是ssl协议,服务商指定为465端口)
server_port = 465

# 发件人
server_user = 'rongxinyu2003@126.com'

# 收件人(使用列表可以表示多个收件人['rong@qq.com', 'xin@126.com', 'yu@163.com'])
addressee = 'rongxinyu2003@163.com'

# 授权码(在邮箱的服务商哪里开通SMTP服务获得)/密码
server_key = 'XGIDXXXBMGDECXXX'

3.2准备要发送的邮件,创建一个邮件格式的对象mgs,将发件人和收件人分别写入到mgs['From']mgs['To']中,主题/标题写入到mgs['Subject'],邮件正文先使用MIMEText()类进行一下转换,再使用attach()方法加入到对象mgs中。

# 创建邮件对象
mgs = MIMEMultipart()

# 发件人&收件人的信息
mgs['From'] = server_user
mgs['To'] = addressee

# 主题(标题)
sub = input('主题:')
mgs['Subject'] = sub

# 正文
text = input('正文:')
body = MIMEText(_text=text)
mgs.attach(body)

3.3使用smtplib.SMTP_SSL()方法与SMTP服务器连接,并使用login()方法进行验证登陆。

# 使用SSL协议连接STMP服务器
server = smtplib.SMTP_SSL(host=server_host, port=server_port)


# 下面是使用TLS协议连接STMP服务器,比SSL要安全的多,用的时候把上面的注释掉,使用下面的代码就行
# server_port = 25
# server = smtplib.SMTP(host=server_host, port=server_port)
# # 不要使用链式调用,.starttls()方法返回的是None不是对象
# server.starttls()


# 使用发件人和密钥/密码登陆STMP服务器
server.login(user=server_user, password=server_key)

3.4使用sendmail()方法发送邮件(发送成功该方法会返回一个空字典,反之为具体的错误信息),同时使用as_string()方法将对象mgs里的数据转化成符合MIME(多用途互联网邮件扩展)的格式规范。

# 发送邮件并检查是否成功(成功state会被赋值为空字典,反之则为各收件人的错误信息)
state = server.sendmail(from_addr=server_user, to_addrs=addressee, msg=mgs.as_string())

3.5使用quit()方法if安全的关闭与SMTP服务器的连接并打印相应信息。

if(not state):
    print('---成功发送---\n')

    # 关闭连接
    server.quit()

else:
    print('---发送失败---\n')
    print(f'错误信息:-->{state}')

    # 关闭连接
    server.quit()

4.源码展示

'''
# Author: 荣鑫宇
# Update: 2024-08-25
# Content: 邮件的基本实现原理
# Version: 0.0.0
'''
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart


# smtp服务器(依服务商而定)
server_host = 'smtp.126.com'

# 端口(依据使用的协议而定,我这里使用的是ssl协议,服务商指定为465端口,TLS协议使用默认的25端口)
server_port = 465

# 发件人
server_user = 'rongxinyu2003@126.com'

# 收件人(使用列表可以表示多个收件人['rong@qq.com', 'xin@126.com', 'yu@163.com'])
addressee = 'rongxinyu2003@163.com'

# 授权码(在邮箱的服务商哪里开通SMTP服务获得)/密码
server_key = 'XGIDXXXBMGDECXXX'

# 创建邮件对象
mgs = MIMEMultipart()

# 发件人&收件人的信息
mgs['From'] = server_user
mgs['To'] = addressee

# 主题(标题)
sub = input('主题:')
mgs['Subject'] = sub

# 正文
text = input('正文:')
body = MIMEText(_text=text)
mgs.attach(body)


# 使用SSL协议连接STMP服务器
server = smtplib.SMTP_SSL(host=server_host, port=server_port)


# 下面是使用TLS协议连接STMP服务器,比SSL要安全的多,用的时候把上面的注释掉,使用下面的代码就行
# server_port = 25
# server = smtplib.SMTP(host=server_host, port=server_port)
# # 不要使用链式调用,.starttls()方法返回的是None不是对象
# server.starttls()


# 使用发件人和密钥/密码登陆STMP服务器
server.login(user=server_user, password=server_key)

# 发送邮件并检查是否成功(成功state会被赋值为空字典,反之则为各收件人的错误信息)
state = server.sendmail(from_addr=server_user, to_addrs=addressee, msg=mgs.as_string())
if(not state):
    print('---成功发送---\n')

    # 关闭连接
    server.quit()

else:
    print('---发送失败---\n')
    print(f'错误信息:-->{state}')

    # 关闭连接
    server.quit()

 

5.相关资料

1.SMTP服务申请的操作

如何获取126邮箱授权码 | 华为官网 (huawei.com)

网易邮箱(126/163):授权码获取攻略-腾讯云开发者社区-腾讯云 (tencent.com)

2.相关的文章

Python smtplib的详细介绍 - Sitin - SegmentFault 思否

C# 使用网易126邮箱发件和收件 - shihao316558512 - 博客园 (cnblogs.com)

TLS与SSL有什么区别?你应该使用哪一个? - 闪电博 (wbolt.com)

3.部分邮箱的SMTP服务器地址及端口

请注意,下表中列出的端口号是标准的服务端口号,但实际的端口号可能根据服务提供商的配置有所不同。某些服务可能会使用STARTTLS扩展来升级连接的安全性,表格中注明为“STARTTLS”。在使用这些设置时,请自行查阅电子邮件服务提供商的指南和策略。("STARTTLS"表示服务器支持通过明文连接开始后切换到加密连接的能力。也就是客户端可以首先与服务器建立一个普通的非加密连接,然后通过发送一个特定的命令(例如“STARTTLS”)来请求服务器升级到安全的加密连接。一旦服务器同意并确认,它们将使用TLS或SSL协议对后续的通信进行加密,以确保数据的安全性和隐私性。)

国内

邮箱服务提供商 SMTP服务器地址 SMTP默认端口 SMTP SSL端口 IMAP服务器地址 IMAP默认端口 IMAP SSL端口
阿里云邮箱 smtp.aliyun.com 25 465 imap.aliyun.com 143 993
网易163邮箱 smtp.163.com 25 465/994 imap.163.com 143 993
网易126邮箱 smtp.126.com 25 465/994 imap.126.com 143 993
QQ邮箱 smtp.qq.com 25 465/587 imap.qq.com 143 993
新浪邮箱 smtp.sina.com.cn 25 465 imap.sina.com.cn 143 993
搜狐邮箱 smtp.sohu.com 25 465 imap.sohu.com 143 993

国外

邮箱服务提供商 SMTP服务器地址 SMTP默认端口 SMTP SSL端口 IMAP服务器地址 IMAP默认端口 IMAP SSL端口
Gmail smtp.gmail.com 587 465 imap.gmail.com 993 993
Outlook.com smtp-mail.outlook.com 587 STARTTLS imap-mail.outlook.com 993 STARTTLS
Yahoo smtp.mail.yahoo.com 587 465 imap.mail.yahoo.com 993 993
Apple iCloud smtp.mail.me.com 587 STARTTLS mail.me.com 993 STARTTLS
ProtonMail smtp.protonmail.ch 587 STARTTLS protonmail.ch 993 STARTTLS
Zoho Mail smtp.zoho.com 587 STARTTLS mail.zoho.com 993 STARTTLS
GMX smtp.gmx.com 587 465 pop.gmx.com 110 995
Mail.com smtp.mail.com 587 STARTTLS mail.com 993 STARTTLS
FastMail mx1.fastmail.com 587 STARTTLS mx1.fastmail.com 993 STARTTLS
Tutanota mail.tutanota.com 465 465 mail.tutanota.com 993 993
AOL smtp.aol.com 587 465 imap.aol.com 993 993
Hotmail/Outlook smtp-mail.outlook.com 587 STARTTLS imap-mail.outlook.com 993 STARTTLS
Mail.ru smtp.mail.ru 465 465 imap.mail.ru 993 993
Yandex smtp.yandex.com 465 465 imap.yandex.com 993 993
Qwant qwant.com 465 465 qwant.com 993 993
点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注