SMTP发送邮件

使用smtplibemail发送邮件

smtplib库是python自带的库,专门用于发送邮件。使用smtplib,我们可以通过SMTP协议与邮件服务器进行通信,从而发送邮件。

email库也是python自带的库,提供了构造和解析电子邮件消息的API,我们可以用它来创建包含文本、HTML、附件等内容的复杂邮件消息,也可以解析来自文件、字符串或网络的邮件消息

smtplib的使用

导入smtplib模块

1
import smtplib

连接到SMTP服务器

使用smtplib.SMTP()smtplib.SMTP_SSL()方法连接到SMTP服务器。SMTP_SSL()用于加密连接

1
server = smtplib.SMPT( [host [, port [, local_hostname]]])
  • host:SMTP服务器主机。我们可以指定主机的IP地址或者域名,可选参数
  • port:如果提供了host参数,需要指定SMTP服务使用的端口号,如果是默认的端口号,则无需指定。端口通常为587(非加密)或465(加密)
  • local_hostname:如果SMTP在本机上,只需要指定服务器地址为localhost即可

比如:

1
2
3
4
5
6
7
8
# 不加密的连接
server = smtp.SMTP('smtp.example.com', 587)

# 加密的连接
server = smtp.SMTP_SSL('smtp.example.com', 465)

# 默认端口号不指定
server = smtp.SMTP_SSL('smtp.qq.com')

使用connect()方法可以显示地控制何时建立到SMTP服务器的连接,还可以设置超时时间等参数。在大多数情况下,直接使用smtplib.SMPT()smtplib.SMTP_SSL()就可以直接建立连接:

1
2
3
4
5
6
7
8
9
import smtplib

server = smtplib.SMTP() # 不加入任何参数

# 显示连接到SMTP服务器
server.connect('smtp.example.com', 587)

# 也可以设置超时时间:
# server.connect('smtp.example.com', 587, timeout=10)

对于一些旧的SMTP服务器,可能无法直接建立加密连接,我们可以先建立非加密连接,然后调用starttls()方法来升级为加密连接:

1
2
3
4
5
6
7
8
9
10
import smtplib

server = smtplib.SMTP()
server.connect('smtp.example.com', 587)

# 启用加密连接
server.starttls()

# 登录
server.login('abc@example.com', 'abcd')

登录到SMTP服务器

使用login()方法登录到SMTP服务器

1
server.login('邮箱地址', '邮箱密码')

发送邮件

使用email库构造邮件内容后,使用sendmail()方法发送邮件:

1
server.sendmail('发件人地址', ['收件人地址列表'], 邮件内容)

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import smtplib
from email.mime.text import MIMEText

# 邮件内容
msg = MIMEText('This is the body of the email', 'plain')
msg['From'] = 'youremail@example.com'
msg['To'] = 'receiveremail@example.com'
msg['Subject'] = 'Subject of the email'

server = smtplib.SMTP('smtp.example.com', 587)
server.login('youremail@example.com', 'password')
server.sendmail('youremail@example.com', ['receiveremail@example.com'], msg.as_string())

# 关闭连接
server.quit()

关闭连接

发送邮件后,使用quit()方法关闭与服务器的连接:

1
server.quit()

email的使用

email.mime模块

email.mime模块用于创建不同类型的MIME(多用途互联网邮件扩展)消息。MIME是扩展电子邮件标准,支持文本、图像、音频、视频以及应用程序数据等多媒体类型。

常用的MIME类型:

  • email.mime.text.MIMEText:用于创建文本邮件
  • email.mime.multipart.MIMEMultipart:用于创建多部分邮件,可以包含文本和附件
  • email.mime.image.MIMEImage:用于创建包含图像的邮件
  • email.mime.audio.MIMEAudio:用于创建包含音频的邮件
  • email.mime.application.MIMEApplication:用于创建包含应用程序数据的邮件

email.mime.text.MIMEText

email.mime.text中引入MIMEText

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from email.mime.text import MIMEText
import smtp

sender = 'from@example.com'
receivers = ['to_1@example.com', 'to_2@example.com']

# 设置邮件的三个参数,第一个为文本内容,第二个 plain 设置文本格式,第三个 utf-8 设置编码
message = MIMEText('内容', 'plain', 'utf-8')

# 标准邮件需要三个头部信息:From、To和Subject
message['From'] = sender # 发送者
message['To'] = f'{receivers[0]}, {receivers[1]}' # 多个接收者之间用逗号隔开,也可以用join()方法
message['Subject'] = 'Test' # 邮件主题

try:
server = smtplib.SMTP('smtp.example.com', 587)
server.login(sender, 'password')
server.sendmail(sender, receivers, message.as_string())
print("邮件发送成功")
except smtplib.SMTPException:
print("Error: 无法发送邮件")
finally:
server.quit()

MIMEText()的文本格式:

  1. plain:纯文本格式,这是最基本的文本格式,不包含任何格式化信息,如字体、颜色或链接等。纯文本邮件在各种设备和客户端上都有很好的兼容性
  2. html:表示HTML格式的文本,可以包含格式化信息,如字体、颜色、链接、图片等

MIMEText()默认的编码格式是us-ascii,如果使用非ASCII字符,需要显示指定一个更通用的编码格式,比如utf-8

1
mime_text = MIMEText(text, _subtype='plain', _charset='utf-8')

也可以直接写成:

1
mime_text = MIMEText(text, 'plain', 'utf-8')

email.mime.multipart.MIMEMultipart

使用MIMEMultipart时,我们使用attach()方法将一个MIME(多用途互联网邮件扩展)对象附加到MIMEMultipart对象中。

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib

sender = 'from@example.com'
receiver = ['to@example.com']

message = MIMEMultipart()
message['From'] = sender
message['To'] = receiver[0]
message['Subject'] = '邮件主题'

text = "Hello, this is a test email."

# 将文本内容加入MIMEMultipart对象中
message.attach(MIMEText(text, "plain"))

html = '<html><body><h1>Hello</h1><p>This is an HTML part of the email.</p></body></html>'
# 添加HTML
message.attach(MIMEText(html, "html"))

# 邮件发送...

email.mime.image.MIMEImage

MIMEImage类用于创建包含图像的MIME对象

1
2
3
4
5
6
7
8
9
10
11
12
13
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import smtplib

message = MIMEMultipart()

with open("image.jpg", "rb") as image_file:
image_data = image_file.read()

# 图片内容和图片名
mime_image = MIMEImage(image_data, name="image.jpg")

message.attach(mime_image)

email.mime.audio.MIMEAudio

MIMEAudio类用于创建包含音频的MIME对象

1
2
3
4
5
6
7
8
9
10
11
from email.mime.audio import MIMEAudio
from email.mime.multipart import MIMEMultipart
import smtplib

message = MIMEMultipart()

with open("audio.mp3", "rb") as audio_file:
audio_data = audio_file.read()

# 音频内容和文件名
mime_audio = MIMEAudio(audio_data, name="audio.mp3")

email.mime.application.MIMEApplication

MIMEAppication类用于创建包含应用程序数据的MIME对象(比如PDF文件等),通常用于附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
import smtplib

message = MIMEMultipart()

with open("document.pdf", "rb") as attachment_file:
attachment_data = attachment_file.read()

# 创建MIMEApplication对象
mime_applicaiton = MIMEApplication(attachment_data, name="document.pdf")
mime_application.add_header("Content-Disposition", "attachment", filename="document.pdf")

message.attach(mime_application)

与其他几个不同的是,MIMEApplication对象创建后使用了add_header()方法,用于为附件添加额外的头部信息,这些信息对于邮件客户端正确处理附件至关重要。具体来说,add_header()在这个上下文中用于设置Content-Disposition头部,它指示邮件客户端如何显示附件以及附件的文件名。

  • Content-Disposition:这个头部信息告诉邮件客户端该部分为attachment(附件),并且应该作为文件提供给用户下载或查看
  • filename:这个参数设置了附件的文件名,这样接收者在查看邮件时可以看到一个有意义的文件名,而不是一个默认的或无名的附件

filename和前面设置的name不同的是,在创建MIMEApplication对象时,name参数也是用来设置文件名的,但它主要是为了内部使用,而filename是为了在邮件客户端中显示。

不是所有的邮件客户端都默认使用MIMEApplicationname参数来显示文件名的,通过显示设置Content-Dispositionfilename,可以确保大多数邮件客户端能够正确显示附件的文件名。

通过明确指定Content-Dispositionattachment,可以清楚地表明这部分内容是作为一个附件,而不是邮件正文的一部分

email.header模块

email.header模块中的Header类可以用于创建带有复杂字符集的邮件头,比如包含非ASCII码字符的邮件主题。然而,对于大多数情况,我们不需要直接使用Header类,因为email.mime.MIMETextemail.mime.MIMEMultipart等类在设置邮件头时会自动处理字符串编码

如果我们需要手动处理邮件头的编码,或者遇到了编码问题,那么可以使用Header类,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from email.header import Header
from email.mime.text import MIMEText
import smtplib

sender = 'from@examole.com'
receivers = ['to_1@example.com', 'to_2@example.com']

text = '邮件内容'
message = MIMEText(text, 'plain', 'utf-8')
message['From'] = sender
message['To'] = ', '.join(receivers)

# 使用Header('邮件主题', '编码格式')设置邮件的主体
message['Subject'] = Header('邮件标题', 'utf-8')

try:
server = smtplib.SMTP('smtp.example.com', 587)
server.login(sender, 'password')
server.sendmail(sender, receivers, message.as_string())
except Exception as e:
print(f"Error: {e}")
finally:
server.quit()

SMTP发送邮件
https://blog.shinebook.net/2025/03/17/编程/Python/发送邮件/SMTP发送邮件/
作者
X
发布于
2025年3月17日
许可协议