为了避免每次发送邮件都需要登录账号的问题,制作一个邮件发送程序。项目目标:使用python发送邮件。
SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。
1.首先,构造一个简单的纯文本邮件
from email.mime.text import MIMEText msg = MIMEText('hello, send by Python...', 'plain', 'utf-8') ''' 第一个参数就是邮件正文, 第二个参数是MIME的subtype,传入’plain’表示纯文本,最终的MIME就是’text/plain’, 最后一定要用utf-8编码保证多语言兼容性。 '''
MIMEText对象中, 有三个参数
造MIMEText对象时,第一个参数就是邮件正文,第二个参数是MIME的subtype,传入’plain’表示纯文本,最终的MIME就是’text/plain’,最后一定要用utf-8编码保证多语言兼容性。
2.用SMTP发送:
(1)发送邮件代码格式
# 输入Email地址和口令: from_addr = input('From: ') password = input('Password: ') # 输入SMTP服务器地址: smtp_server = input('SMTP server: ') # 输入收件人地址: to_addr = input('To: ')
SMTP服务器地址,实际上就是代收发服务器地址,是由邮箱服务商提供的。说白了,你用哪家公司的邮箱, 就是哪家公司收发邮件服务器的地址。
本程序以QQ邮箱来测试. 我们使用QQ邮箱的收发邮件服务器的地址。
QQ邮箱SMTP服务器地址:smtp.qq.com, 端口465, QQ邮箱默认的端口是25, 我们这里使用的是加密端口465
server = smtplib.SMTP_SSL(smtp_server, 465) # SMTP协议加密端口是465 server.set_debuglevel(1) #调试级别
用set_debuglevel(1)就可以打印出和SMTP服务器交互的所有信息。
server.login(from_addr, password) server.sendmail(from_addr, [to_addr], msg.as_string())
login()方法用来登录SMTP服务器,参数有两个, from_addr是用户输入的发件邮箱, password是发件邮箱的密码。
sendmail()方法就是发邮件,需要引入三个参数:
第一个参数:from_addr是发件人的邮箱地址
第二个参数:[to_addr] 是收件人的邮箱地址, 是列表形式。因为邮件可能一次发给多个人,使用列表,如果发送多个人,就写多个邮箱,中间使用逗号隔开。
第三个参数:msg.as_string()把邮件内容MIMEText对象变成str。
server.quit()
server.quit()语句,是邮件发送结束后,停止服务的意思.
(2)发送纯文本邮件代码
import smtplib from email.mime.text import MIMEText # 构造一个纯文本邮件 msg = MIMEText("hello world","plain","utf-8") ''' 第一个参数就是邮件正文, 第二个参数是MIME的subtype,传入’plain’表示纯文本,最终的MIME就是’text/plain’, 最后一定要用utf-8编码保证多语言兼容性。 ''' # 使用SMTP发送邮件 # 输入发件人Email地址课口令 from_addr = input("请输入发件人邮箱号码From:") from_pwd = input("请输入发件人邮箱口令Password::") # 收件人Email地址 to_addr = input("请输入收件人邮箱地址To:") # 输入SMTP服务器地址: smtp_server = input('请输入邮箱服务器地址SMTP server: ') server = smtplib.SMTP_SSL(smtp_server, 465) # SMTP协议加密端口是25 server.set_debuglevel(1) server.login(from_addr, from_pwd) server.sendmail(from_addr, [to_addr], msg.as_string()) # 停止服务 server.quit()
如果出现以下错误:
出现这种错误, 就说明邮箱出现授权问题. 也就是邮箱的SMTP服务没有开启。
接下来,我们开启邮箱SMTP服务。不要慌,这个开启服务只在QQ邮箱客户端里设置即可。
打开QQ邮箱客户端, 输入账号,密码进去. 在QQ邮箱页面, 点击【设置】
点进【设置】页面进去,点击第二个选项,【账户】,往下滑动, 滑动在下方的时候, 出现如图内容:
这里, 我们的SMTP服务还是关闭状态, 我们点击【开启】按钮, 开启SMTP服务。然后验证短信。
验证结束后, 会出现一个弹框:
这个授权码, 就是以后我们运行代码,在输入密码的地方进行输入。
发送成功
# 导包 import smtplib from email import encoders from email.header import Header from email.mime.text import MIMEText from email.utils import parseaddr,formataddr ''' 1、encoders模块负责编码 2、Header模块负责处理邮件头 3、MIMEText模块负责处理文本 4、parseaddr模块与formataddr模块 负责将输入的内容格式化 ''' def _format_addr(s): name,addr = parseaddr(s) return formataddr((Header(name,"utf-8").encode(),addr)) # 发件人Email地址和口令 from_addr = input("From:") from_pwd = input("pwd:") # 收件人Email地址 to_addr = input("To:") # 输入SMTP服务器地址: smtp_server = input("SMTP server:") # 邮件内容 content = ''' 桃之夭夭,灼灼其华。之子于归,宜其室家。 桃之夭夭,有蕡其实。之子于归,宜其家室。 桃之夭夭,其叶蓁蓁。之子于归,宜其家人。 ''' # 实例化MIMEText对象 msg = MIMEText(content,"plain","utf-8") # 发件人 msg['From'] = _format_addr(u'python爱好者<%s>'%from_addr) # 收件人 msg["To"] = _format_addr(u'管理员<%s>'%to_addr) # 主题 msg["Subject"] = Header(u'来自xxx的问候。。。。','utf-8').encode() server = smtplib.SMTP(smtp_server,465) server.set_debuglevel(1) server.login(from_addr,to_addr) server.sendmail(from_addr,[to_addr],msg.as_string()) # 结束服务 server.quit()
收到的邮件是:
发送HTML邮件,而不是普通的纯文本文件怎么办?方法很简单,在构造MIMEText对象时,把HTML字符串传进去,再把第二个参数由plain变为html就可以了:
msg = MIMEText('<html><body><h1>Hello</h1>' + '<p>send by <a href="http://www.python.org">Python</a>...</p>' + '</body></html>', 'html', 'utf-8')
如果Email中要加上附件怎么办?带附件的邮件可以看做包含若干部分的邮件:文本和各个附件本身,所以,可以构造一个MIMEMultipart对象代表邮件本身,然后往里面加上一个MIMEText作为邮件正文,再继续往里面加上表示附件的MIMEBase对象即可:
from email.mime.multipart import MIMEMultipart from email.header import Header from email.mime.text import MIMEText from email import encoders import smtplib from email.mime.base import MIMEBase from email.utils import formataddr,parseaddr # 发件人邮箱和口令 from_addr = input("From:") from_pwd = input("Password:") # 收件人邮箱吧地址 to_addr = input("To:") # 服务器地址 smtp_server = input("smtp_server:") def _from_addr(s): name,addr = parseaddr(s) return formataddr((Header(name,"utf-8").encode(),addr)) # # 邮件对象: msg = MIMEMultipart() msg["From"] = _from_addr("python爱好者<%s>"%from_addr) msg["To"] = _from_addr("管理员<%s>"%to_addr) msg['Subject'] = Header("来自SMTP的问候","utf-8").encode() # 邮件正文是MIMEText: msg.attach(MIMEText("send with file","plain","utf-8")) # 添加附件就是加上一个MIMEBase,从本地读取一个图片: with open('./1.jpg',"rb") as fp: # 设置附件的MIME和文件名,这里是jpg类型: mime = MIMEBase("image","jpg",filename="1.jpg") mime.add_header('Content-Disposition', 'attachment', filename='1.jpg') mime.add_header('Content-ID', '<0>') mime.add_header('X-Attachment-Id', '0') # 把附件的内容读进来: mime.set_payload(fp.read()) # 用Base64编码: encoders.encode_base64(mime) # 添加到MIMEMultipart: msg.attach(mime) server = smtplib.SMTP_SSL(smtp_server,465) server.set_debuglevel(1) server.login(from_addr,from_pwd) server.sendmail(from_addr,[to_addr],msg.as_string()) server.quit()
msg.attach(MIMEText('<html><body><h1>Hello</h1>' + '<p><img src="cid:0"></p>' + '</body></html>', 'html', 'utf-8'))
同时支持HTML和Plain格式
如果收件人使用的设备太古老,我们发送HTML邮件,收件人通过浏览器或者Outlook之类的软件是可以正常浏览邮件内容的,但是,查看不了HTML邮件怎么办?
办法是在发送HTML的同时再附加一个纯文本,如果收件人无法查看HTML格式的邮件,就可以自动降级查看纯文本邮件。
利用MIMEMultipart就可以组合一个HTML和Plain,要注意指定subtype是alternative:
msg = MIMEMultipart('alternative') msg['From'] = ... msg['To'] = ... msg['Subject'] = ... msg.attach(MIMEText('hello', 'plain', 'utf-8')) msg.attach(MIMEText('<html><body><h1>Hello</h1></body></html>', 'html', 'utf-8')) # 正常发送msg对象...
使用标准的25端口连接SMTP服务器时,使用的是明文传输,发送邮件的整个过程可能会被窃听。要更安全地发送邮件,可以加密SMTP会话,实际上就是先创建SSL安全连接,然后再使用SMTP协议发送邮件。
某些邮件服务商,例如Gmail,提供的SMTP服务必须要加密传输。我们来看看如何通过Gmail提供的安全SMTP发送邮件。
必须知道,Gmail的SMTP端口是587,因此,修改代码如下:
smtp_server = 'smtp.gmail.com' smtp_port = 587 server = smtplib.SMTP(smtp_server, smtp_port) server.starttls() # 剩下的代码和前面的一模一样: server.set_debuglevel(1) ...
小结
使用Python的smtplib发送邮件十分简单,只要掌握了各种邮件类型的构造方法,正确设置好邮件头,就可以顺利发出。
构造一个邮件对象就是一个Messag对象,如果构造一个MIMEText对象,就表示一个文本邮件对象,如果构造一个MIMEImage对象,就表示一个作为附件的图片,要把多个对象组合起来,就用MIMEMultipart对象,而MIMEBase可以表示任何对象。它们的继承关系如下:
Message +- MIMEBase +- MIMEMultipart +- MIMENonMultipart +- MIMEMessage +- MIMEText +- MIMEImage
本文属于作者原创,转载请注明出处,不足之处,希望大家能过给予宝贵的意见,如有侵权,请私信。每天一个knowledge point,一起学python,让技术无限发散