运行Bulk-Mailer项目 账密正确仍报smtplib.SMTPAuthenticationError
问题说明
运行Bulk-Mailer项目的Main.py脚本批量发信时,触发SMTP鉴权报错:smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted'),确认账号登录密码填写正确仍无法解决。
原项目核心代码(已隐去隐私信息)如下:
import smtplib import imghdr import os import pandas as pd from email.message import EmailMessage # your account credentials maildid = "EMAIL" # enter your email id here password = "PASSWORD" # enter your password here files = [] # path of the folder which will be attached path = "attachments" attachments = os.listdir(path) # creating a new list to store files along with path for file in range(len(attachments)): files.append(f'{path}/{attachments[file]}') # reading mail id's from excel sheet cont = pd.read_excel("contacts.xlsx") contacts = cont['mail id'].values # storing all the mail id's in contacts list for contact in contacts: message = EmailMessage() message['From'] = maildid message['To'] = contact message['Subject'] = 'Enter the Subject here' # replace the subject """ Note: if you want to send mail with content then use option 1 and delete the option 2 or if you want to send HTML mail then use option 2 and delete option 1 """ # option 1 message.set_content( 'Enter the content here ') # this is optional. if you are using web mails then this is not necessary. # option 2 message.add_alternative("""\ <!DOCTYPPE html> <html> <body> //Insert you html code here </body> </html> """, subtype='html') # attaching files to the mail for file in files: with open(file, 'rb') as f: file_data = f.read() file_type = imghdr.what(f.name) file_name = f.name message.add_attachment(file_data, maintype='application', subtype='octect-stream', filename=file_name) # Sending mails with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp: smtp.login(maildid, password) smtp.send_message(message) # if the mail is Successfully sent then this statement will be printed print("Mail sent Successfully to {}".format(contact)) print("\nSuccessfully sent!!!")
报错原因
- Gmail在2022年5月后正式下线了「低安全性应用访问」功能,直接使用账号登录密码走SMTP协议鉴权的方式已经被官方完全禁止,和密码输入正确与否没有关系。
- 原代码存在3处会影响正常运行的拼写/逻辑问题:
- HTML文档声明多打了一个字母P,写为
<!DOCTYPPE html>,会导致部分邮箱客户端无法正常识别HTML格式邮件 - 附件MIME类型拼写错误,写为
octect-stream,正确值为octet-stream,会导致附件无法被正常识别 - 每发送一封邮件就重新建立一次SMTP连接,极易触发Gmail的发信限流规则,导致发送中途被拦截
- HTML文档声明多打了一个字母P,写为
修复方案
- 先给用来发信的Gmail账号开启两步验证,这是生成应用专用密码的前置条件,未开启两步验证的账号不会显示应用密码生成入口。
- 在Gmail账号的安全设置页生成应用专用密码,应用类型选择「邮件」,设备选择当前运行脚本的设备即可,将生成的16位应用密码妥善保存。
- 将代码中
password字段原本填写的Gmail账号登录密码,替换为刚才生成的16位应用专用密码,maildid字段仍填写完整的Gmail邮箱地址即可。 - 修正代码中的拼写错误,同时把SMTP连接初始化逻辑移到收件人遍历循环的外侧,复用同一个连接发送所有邮件,避免触发限流。
修正后的核心代码片段参考:
# 账号配置 maildid = "你的完整Gmail邮箱地址" password = "你生成的16位应用专用密码" # 不要填账号日常登录的密码 # ... 省略附件加载、联系人读取的原有逻辑 ... # SMTP连接移到循环外,只登录一次 with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp: smtp.login(maildid, password) for contact in contacts: message = EmailMessage() message['From'] = maildid message['To'] = contact message['Subject'] = '你的邮件主题' # 纯文本内容配置 message.set_content('你的纯文本邮件内容') # HTML内容配置,修正DOCTYPE拼写错误 message.add_alternative("""\ <!DOCTYPE html> <html> <body> <!-- 你的HTML邮件代码写在这里 --> </body> </html> """, subtype='html') # 添加附件,修正MIME类型拼写 for file in files: with open(file, 'rb') as f: file_data = f.read() file_type = imghdr.what(f.name) file_name = f.name message.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name) smtp.send_message(message) print("Mail sent Successfully to {}".format(contact)) print("\nSuccessfully sent!!!")
内容的提问来源于stack exchange,提问作者Andy Thompson
相关产品推荐
相关产品推荐

