Python案例笔记 | 用python群发邮件

基于Python3版本的学习。
学习知识来源:风变编程

要用python群发邮件,需用到两个python的内置模块。

smtplib模块 是用来发送邮件用的。

email模块 是用来构建邮件内容的。


smtplib模块

官网教程: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模块

用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)

下面是发送成功的截图。
Python案例笔记 | 用python群发邮件_第1张图片


上述代码还不算完善,没有发件人信息,没有主题,正文内容太简单。

丰富邮件头:
邮件头(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('发送失败,请重试')

你可能感兴趣的:(Python案例笔记)