https://blog.csdn.net/yfreedomliTHU/article/details/88196631
需求背景:最近同學(xué)需要收集一些調(diào)研問卷,立馬想到了群發(fā)郵件這一方式,機(jī)智地用excel按照郵件格式造了一堆學(xué)校郵箱,打算一個(gè)一個(gè)復(fù)制粘貼群發(fā)。好家伙,這么多郵箱得粘貼到猴年馬月啊,極其精污。作為略懂點(diǎn)python的弱雞,當(dāng)然要在這個(gè)問題上裝個(gè)逼了,一口答應(yīng)了同學(xué)用python給他寫個(gè)腳本,當(dāng)然就踩到了各種坑了。網(wǎng)上各種python群發(fā)郵件的教程都有,沒錯(cuò),就是用smtplib這個(gè)包基本可以實(shí)現(xiàn),但是寫完之后卻發(fā)現(xiàn)遇到無(wú)效的郵箱程序自動(dòng)拋出錯(cuò)誤就停止了,郵件倒是一個(gè)都沒發(fā)出去。在網(wǎng)上找了很久,都沒找到啥教程。最后我貌似陰差陽(yáng)錯(cuò)找到了可能有效的替代方法,因此記錄一下,供大家討論學(xué)習(xí)。
步驟:使用python中的smtplib群發(fā)郵件主要可以分為以下幾個(gè)步驟:
1.開通郵箱的第三方授權(quán),注意記下授權(quán)碼;
2.創(chuàng)建smpt對(duì)象,連接smpt服務(wù)器(注意不通郵箱的端口不同);
3.登錄自己的郵箱賬號(hào)(注意密碼是1中開通第三方授權(quán)的授權(quán)碼,而不是登錄密碼);
4.通過發(fā)送消息函數(shù)發(fā)送郵件,需要設(shè)置發(fā)件人、收件人(群發(fā)為多個(gè)收件人),內(nèi)容,標(biāo)題等參數(shù);
5.發(fā)送成功,關(guān)閉連接。
為了比較清楚地了解具體的流程,下面我將以QQ郵箱為例。進(jìn)行簡(jiǎn)單的說明。
一、開通郵箱的第三方授權(quán)
QQ郵箱開通授權(quán)的步驟可以參考這篇博客:https://blog.csdn.net/SpiderManSun/article/details/84964171
簡(jiǎn)單來說就是:登入你的QQ郵箱,點(diǎn)擊設(shè)置–賬戶,然后找到POP3/SMTP或者IMAP/SMTP服務(wù),二者選其一就行,這里我們只需要SMTP,然后會(huì)通知你給騰訊科技的電話發(fā)郵件,之后會(huì)告訴你一個(gè)授權(quán)碼,這個(gè)授權(quán)碼需要記住,后面需要用。
二、創(chuàng)建對(duì)象,設(shè)置參數(shù)
這一部分網(wǎng)上的教程比較多,就不過多贅述了,只說幾個(gè)需要注意的點(diǎn):
1.smpt server的host:這個(gè)不同郵箱有所不同,例如QQ郵箱就是:smpt.qq.com
2.mail_user和sender均為發(fā)件人郵箱,mail_pass為授權(quán)碼,并非郵箱登錄密碼
3.群發(fā)郵件有多個(gè)收件人,需要用.join()函數(shù)添加,即:message[‘To’] = “,”.join(receiver)
import smtplib
from email.header import Header
from email.mime.text import MIMEText
import csv
import pandas as pd
# SMTP Service
mail_host = "smtp.qq.com" # SMTP server, take QQ for example
mail_user = "xxx@qq.com" # user
mail_pass = "xxxxxxxxxx" # note:Authorization Code,not password
sender = "xxx@qq.com" # sender email
#get receiver email from cvs file
def get_email():
with open('test.csv','r') as csvfile:
reader = csv.reader(csvfile)
row1 = [row for row in reader]
data = row1[0]
print(data)
print(len(data))
return data
#write the content and title of your email here!
def email_content():
title = 'python_email_test' # title
content = 'Test success!' # content of your email
return title,content
def sendEmail():
title,content = email_content()
#receiver = get_email()
bcc = get_email() # 接收郵件,可設(shè)置為你的QQ郵箱或者其他郵箱,加入bcc實(shí)現(xiàn)密送
message = MIMEText(content, 'plain', 'utf-8') # content, format, encoding
message['From'] = "{}".format(sender)
#message['To'] = ",".join(receiver) #To:收件人,Cc:抄送,Bcc:密送,不顯示地址
message['Bcc'] = ",".join(bcc)
message['Subject'] = title
try:
smtp_Obj = smtplib.SMTP_SSL(mail_host, 465) # 啟用SSL發(fā)信, 端口一般是465
smtp_Obj.login(mail_user, mail_pass) # 登錄驗(yàn)證
#smtp_Obj.sendmail(sender, receiver, message.as_string()) # send
smtp_Obj.sendmail(sender, bcc, message.as_string())
print("email send success!")
except smtplib.SMTPException as e:
print(e)
print("error!email send failed!")
if __name__ == '__main__':
sendEmail()
注意這幾點(diǎn)基本就能實(shí)現(xiàn)簡(jiǎn)單的群發(fā)郵件了,但是在實(shí)際運(yùn)行過程中會(huì)發(fā)現(xiàn)如果遇到無(wú)效的郵箱地址,會(huì)導(dǎo)致程序拋出錯(cuò)誤,該批郵箱均無(wú)法成功發(fā)出郵件。
運(yùn)行結(jié)果如下:

輸入正確郵箱和錯(cuò)誤郵箱,但是會(huì)導(dǎo)致兩個(gè)均無(wú)法接受到郵件,這在群發(fā)郵件中是很讓人頭疼的問題。為了解決這個(gè)問題,翻了網(wǎng)上大部分教程都沒有解決,本來就要放棄了,卻因?yàn)槿喊l(fā)郵件的另一個(gè)需求而陰差陽(yáng)錯(cuò)的解決了,下面聽我慢慢道來。
契機(jī):像這種調(diào)研問卷直接讓每個(gè)收件人看到所有的群發(fā)收件人是不合適的,容易引起反感,也無(wú)法營(yíng)造出被問卷調(diào)查人是被偶然抽中的(廢話!當(dāng)然是怕被罵啊?。虼讼雽?shí)現(xiàn)類似手動(dòng)群發(fā)中的群發(fā)單顯功能,由于時(shí)間有限,當(dāng)然沒有實(shí)現(xiàn)完整的群發(fā)單顯功能,通過查閱smtplib的說明文檔,我發(fā)現(xiàn)可以通過簡(jiǎn)單設(shè)置一下參數(shù)就可實(shí)現(xiàn)抄送,密送功能,這種發(fā)騷擾問卷,當(dāng)然密送最好了,最后就選了密送。
了解一下什么是抄送、密送,可以參考:https://www.zhihu.com/question/19670232
具體的實(shí)現(xiàn)問題可以參考Stack Overflow的討論:https://stackoverflow.com/questions/1546367/python-how-to-send-mail-with-to-cc-and-bcc
注意:To列表:所有收件人郵箱;Cc列表:抄送;放入Bcc列表:密送,不能看見收件人郵箱,只能看到發(fā)件人郵箱地址。
簡(jiǎn)單總結(jié)一下:只要把收件人的郵箱都添加在 bcc 列表里就可以保證單個(gè)收件人只可以看到自己的郵箱,而無(wú)法看到所有收件人的郵箱。
下面重點(diǎn)來了!在將所有的收件人均放到message[‘Bcc’]后,我發(fā)現(xiàn)不但成功解決了顯示郵箱的隱私泄露問題,還成功解決了錯(cuò)誤郵箱不能跳過的問題。采用密送形式群發(fā)郵件,smtplib就能自動(dòng)跳過無(wú)效郵箱,只發(fā)送給有效郵箱,成功解決了兩大問題,也成功發(fā)完了所有的問卷,避免了人工篩選的繁雜工作。
當(dāng)然,這里的無(wú)效郵箱也不是完全非法形式,主要是針對(duì)正確郵箱形式的無(wú)效郵箱。其實(shí)在用QQ郵箱測(cè)試的時(shí)候發(fā)現(xiàn)QQ會(huì)自動(dòng)退訂,這種情況下不會(huì)出現(xiàn)有錯(cuò)誤郵箱發(fā)不出的因素。本文針對(duì)的更多是學(xué)校的教育郵箱或者公司郵箱不能對(duì)錯(cuò)誤郵箱作出自動(dòng)退回的郵箱,這種情況下一有報(bào)錯(cuò)就可能會(huì)導(dǎo)致全部發(fā)送失敗,這時(shí)候可以試著采用密送的形式,就能跳過無(wú)效郵箱了。
簡(jiǎn)單總結(jié)一下,實(shí)現(xiàn)python群發(fā)郵件可能會(huì)出現(xiàn)錯(cuò)誤郵箱導(dǎo)致全部發(fā)送失敗,可以嘗試改為密送方式,這時(shí)候可以自動(dòng)跳過這些錯(cuò)誤郵箱,當(dāng)然還有前提條件:沒有自動(dòng)退回功能的自建郵箱,如學(xué)校郵箱等。當(dāng)然不同郵箱的差別很大,這種方法可能也不一定完全適用,如果不適用,本文也可以提供密送郵件的解決辦法嘛。
參考:
1.QQ郵箱SMTP授權(quán):https://blog.csdn.net/SpiderManSun/article/details/84964171
2.知乎:什么是抄送、密送:https://www.zhihu.com/question/19670232
3.Stack Overflow的實(shí)現(xiàn):https://stackoverflow.com/questions/1546367/python-how-to-send-mail-with-to-cc-and-bcc