使用smtplib
、email
发送邮件
smtplib
库是python自带的库,专门用于发送邮件。使用smtplib
,我们可以通过SMTP协议与邮件服务器进行通信,从而发送邮件。
email
库也是python自带的库,提供了构造和解析电子邮件消息的API,我们可以用它来创建包含文本、HTML、附件等内容的复杂邮件消息,也可以解析来自文件、字符串或网络的邮件消息
smtplib
的使用
导入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() server.connect('smtp.example.com' , 587 )
对于一些旧的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 smtplibfrom 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()
方法关闭与服务器的连接:
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 MIMETextimport smtp sender = 'from@example.com' receivers = ['to_1@example.com' , 'to_2@example.com' ] message = MIMEText('内容' , 'plain' , 'utf-8' ) message['From' ] = sender message['To' ] = f'{receivers[0 ]} , {receivers[1 ]} ' 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()
的文本格式:
plain
:纯文本格式,这是最基本的文本格式,不包含任何格式化信息,如字体、颜色或链接等。纯文本邮件在各种设备和客户端上都有很好的兼容性
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 MIMETextfrom email.mime.multipart import MIMEMultipartimport 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." message.attach(MIMEText(text, "plain" )) html = '<html><body><h1>Hello</h1><p>This is an HTML part of the email.</p></body></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 MIMEImagefrom email.mime.multipart import MIMEMultipartimport 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 MIMEAudiofrom email.mime.multipart import MIMEMultipartimport 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 MIMEApplicationfrom email.mime.multipart import MIMEMultipartimport smtplib message = MIMEMultipart()with open ("document.pdf" , "rb" ) as attachment_file: attachment_data = attachment_file.read() 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
是为了在邮件客户端中显示。
不是所有的邮件客户端都默认使用MIMEApplication
的name
参数来显示文件名的,通过显示设置Content-Disposition
的filename
,可以确保大多数邮件客户端能够正确显示附件的文件名。
通过明确指定Content-Disposition
为attachment
,可以清楚地表明这部分内容是作为一个附件,而不是邮件正文的一部分
email.header
模块中的Header
类可以用于创建带有复杂字符集的邮件头,比如包含非ASCII码字符的邮件主题。然而,对于大多数情况,我们不需要直接使用Header
类,因为email.mime.MIMEText
和email.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 Headerfrom email.mime.text import MIMETextimport 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) 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()