基于Python3版本的学习。
学习知识来源:风变编程
要用python群发邮件,需用到两个python的内置模块。
smtplib模块 是用来发送邮件用的。
email模块 是用来构建邮件内容的。
官网教程:https://docs.python.org/3/library/smtplib.html
SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。
python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。
Python创建 SMTP 对象语法如下:
import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
参数说明:
host: SMTP 服务器主机。 你可以指定主机的ip地址或者域名,这个是可选参数。
port: 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号,一般情况下 SMTP 端口号为25。
local_hostname: 如果 SMTP 在你的本机上,你只需要指定服务器地址为 localhost 即可。
Python SMTP 对象使用 sendmail 方法发送邮件,语法如下:
SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
参数说明:
from_addr: 邮件发送者地址。
to_addrs: 字符串列表,邮件发送地址。
msg: 发送消息
这里要注意一下第三个参数,msg 是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意 msg 的格式。这个格式就是 smtp 协议中定义的格式。
总结方法:
要发送邮件,就需要用到smtplib模块的以下方法:
import smtplib
server = smtplib.SMTP()
server.connect(host, port)
server.login(username, password)
server.sendmail(sender, to_addr, msg.as_string())
server.quit()
解释:
第一行: 引入smtplib模块
第三行: SMTP 是一个类(class),要想调用 smtplib 模块下、SMTP 类下的方法,应该这样写:smtplib.SMTP.方法。
SMTP 协议是由源服务器到目的地服务器传送邮件的一组规则。
可以简单理解为:我们需要通过SMTP指定一个服务器,这样才能把邮件送到另一个服务器。
第四行: 连接(connect)指定的服务器。
host是指定连接的邮箱服务器,你可以指定服务器的域名。
port 是“端口”的意思。一般情况下SMTP默认端口号为25。
以QQ邮箱为例:
SMTP服务器地址是:smtp.qq.com
端口是:465或587
有两种写法:
第一种是使用默认端口:25。
import smtplib
server = smtplib.SMTP()
server.connect('smtp.qq.com', 25)
第二种是其他端口,比如465。
由于QQ邮箱采用的加密方式是SSL,我们需要写成这样:
import smtplib
server = smtplib.SMTP_SSL()
#如果端口是用SSL加密,请这样写代码。其中server是变量名
server.connect('smtp.qq.com', 465)
#如果出现编码错误UnicodeDecodeError,你可以这样写:server.connect('smtp.qq.com', 465,'utf-8')
提醒:QQ邮箱的 POP3/SMTP服务 一般默认关闭SMTP服务,我们得先去开启它。
如果你打算用QQ邮箱自动发邮件,请保存好这个授权码。在你使用SMTP服务登录邮箱时,要输入这个授权码作为密码登录
第五行: login是登录的意思,也就是登录你指定的服务器用的。
需要输入两个参数:
username:登录邮箱的用户名
password:授权码
username = '[email protected]'
password = '你的授权码数字'
server.login(username, password)
#username:登录邮箱的用户名
#password:登录密码/授权码
第六行: sendmail是“发送邮件”的意思,是发送邮件用的。
sendmail()方法需要三个参数:发件人,收件人和邮件内容。
from_addr = '[email protected]'
to_addr = '[email protected]'
server.sendmail(from_addr, to_addr, msg.as_string())
#from_addr:邮件发送地址,就是上面的username
#to_addr:邮件收件人地址
#msg.as_string():为一个字符串类型,as_string()是将发送的信息msg变为字符串类型。
最后一行: quit是“退出”的意思,就是退出服务器。
将上述的内容整合在一起:
# smtplib 用于邮件的发信动作
import smtplib
# 发信方的信息:发信邮箱,QQ邮箱授权码
from_addr = '[email protected]'
password = '你的授权码数字'
# 收信方邮箱
to_addr = '[email protected]'
# 发信服务器
smtp_server = 'smtp.qq.com'
# 开启发信服务,这里使用的是加密传输
server = smtplib.SMTP_SSL()
server.connect(smtp_server,465)
# 登录发信邮箱
server.login(from_addr, password)
# 发送邮件
server.sendmail(from_addr, to_addr, msg.as_string())
# 关闭服务器
server.quit()
用email模块构建邮件的正文内容。
内容可以是纯文本、HTML内容、图片、附件等多种形式。
MIMEText: 内容形式为纯文本、HTML页面。
MIMEImage: 内容形式为图片。
MIMEMultipart: 多形式组合,可包含文本和附件。
email是一个包 。
模块(module)一般是一个文件,而包(package)是一个目录,一个包中可以包含很多个模块,可以说包是“模块打包”组成的。
与直接导入整个 smtplib 模块(import smtplib)不同,需要使用 from … import … 语句,从email包目录下的 某个文件 引入 需要的对象 。
每种形式对应的导入方式是这样的:
from email.mime.text import MIMEText # 引入email包中构建文本内容的方法
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
构建纯文本的邮件内容
MIMEText()方法需要输入三个参数: 文本内容,文本类型和文本编码。
MIMEText(msg,type,chartset)
# msg:文本内容,可自定义
# type:文本类型,默认为plain(纯文本)
# chartset:文本编码,中文为“utf-8”
文本类型和文本编码,我们默认用’plain’和’utf-8’。文本内容,可以写自己想写的话。
from email.mime.text import MIMEText
msg = MIMEText('send by python','plain','utf-8')
最后整合在一起形成完整的代码:
# smtplib 用于邮件的发信动作
import smtplib
from email.mime.text import MIMEText
# email 用于构建邮件内容
# 发信方的信息:发信邮箱,QQ 邮箱授权码
from_addr = '[email protected]'
password = '你的授权码数字'
# 收信方邮箱
to_addr = '[email protected]'
# 发信服务器
smtp_server = 'smtp.qq.com'
# 邮箱正文内容,第一个参数为内容,第二个参数为格式(plain 为纯文本),第三个参数为编码
msg = MIMEText('send by python','plain','utf-8')
# 开启发信服务,这里使用的是加密传输
server = smtplib.SMTP_SSL()
server.connect(smtp_server,465)
# 登录发信邮箱
server.login(from_addr, password)
# 发送邮件
server.sendmail(from_addr, to_addr, msg.as_string())
# 关闭服务器
server.quit()
注意:
如果报错信息:ValueError: server_hostname cannot be an empty string or start with a leading dot.
如果你的Python版本是3.7,很可能发生这种报错。因为Python 3.7修改了ssl.py,导致smtplib.SMTP_SSL也连带产生了问题。
而解决方法也很简单:
# 改动这句代码
server = smtplib.SMTP_SSL()
# 在括号内加入host参数
server = smtplib.SMTP_SSL(smtp_server)
上述代码还不算完善,没有发件人信息,没有主题,正文内容太简单。
丰富邮件头:
邮件头(header)是这一块区域,包括主题、发件人、收件人等信息:
from email.header import Header
msg['From'] = Header(from_addr)
msg['To'] = Header(to_addr)
msg['Subject'] = Header('python test')
第一行: 从email包引入Header()方法。Header()是用来构建邮件头的。
第三到五行: 提供了标准邮件需要的三个头部信息:From , To 和 Subject。
丰富邮件内容:
原本邮件内容是写在这里:
msg = MIMEText('send by python','plain','utf-8')
如果内容很多很长,可以先定义一个变量,用来存放你想说的内容。
text = '''如何让我遇见你,
在这最美的时刻。
为这,我在佛前求了几千年,
求佛让我们结一段缘。
'''
msg = MIMEText(text,'plain','utf-8')
此外,可以把收发件人,和授权码这些信息用input()变成需要输入的模式。
# 发信方的信息:发信邮箱,QQ邮箱授权码)
from_addr = input('请输入登录邮箱:')
password = input('请输入邮箱授权码:')
# 收信方邮箱
to_addr = input('请输入收件邮箱:')
将代码整合在一起就可以得到一封完整的邮件啦!
三种群发的方式:
1、设置一个列表形式的变量,将所有收件人的邮箱地址存放在里面。(不深究)
to_addrs = ['[email protected]','[email protected]']
--snip--
msg['To'] = Header(",".join(to_addrs))
2、采用询问“是否继续输入邮箱地址”的方式,并用while循环来实现多个收件人的功能。
to_addrs = []
while True:
a=input('请输入收件人邮箱:')
#输入收件人邮箱
to_addrs.append(a)
#写入列表
b=input('是否继续输入,n退出,任意键继续:')
#询问是否继续输入
if b == 'n':
break
print(to_addrs)
3、调用csv模块,将收件人邮箱写入csv文件,在发邮件时读取csv文件。
完整代码如下:
import smtplib
# smtplib 用于邮件的发信动作
from email.mime.text import MIMEText
# email 用于构建邮件内容
from email.header import Header
# 用于构建邮件头
import csv
# 引用csv模块,用于读取邮箱信息
# 发信方的信息:发信邮箱,QQ邮箱授权码
# 方便起见,你也可以直接赋值
from_addr = input('请输入登录邮箱:')
password = input('请输入邮箱授权码:')
# 发信服务器
smtp_server = 'smtp.qq.com'
# 邮件内容
text='''如何让我遇见你,
在这最美的时刻。
为这,我在佛前求了几千年,
求佛让我们结一段缘。
'''
# 待写入csv文件的收件人数据:人名+邮箱
# 记得替换成你要发送的名字和邮箱
data = [['xxx ', '[email protected]'],['yyy', '[email protected]']]
# 写入收件人数据
with open('to_addrs.csv', 'w', newline='') as f:
writer = csv.writer(f)
for row in data:
writer.writerow(row)
# 读取收件人数据,并启动写信和发信流程
with open('to_addrs.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
to_addrs=row[1]
msg = MIMEText(text,'plain','utf-8')
msg['From'] = Header(from_addr)
msg['To'] = Header(to_addrs)
msg['Subject'] = Header('python test')
server = smtplib.SMTP_SSL()
server.connect(smtp_server,465)
server.login(from_addr, password)
server.sendmail(from_addr, to_addrs, msg.as_string())
# 关闭服务器
server.quit()
此外,你还可以为这个程序加一段异常处理代码,也就是try…except…语句来帮助你更好地处理你遇到的问题。
try:
server.sendmail(from_addr, to_addrs, msg.as_string())
print('恭喜,发送成功')
except:
print('发送失败,请重试')