Python pandas筛选VIP联系人发送Gmail时变量调用异常问题
问题根因
你的代码存在4个核心错误,直接导致匹配关系错乱、附件异常:
- 遍历逻辑错误:仅循环遍历
df2.Email列,没有同步读取对应行的姓名字段,循环结束后content["to"]只会保留最后一个VIP的邮箱,不会逐个给VIP发件;你打印的i实际是邮箱值,根本没有关联到Name列。 - MIMEText参数传错:
MIMEText的第二个参数是正文类型(纯文本传plain,HTML传html),你把"Demo python send email"传到了类型参数位,会被邮件客户端识别为无效附件,正文也无法正常展示。 - 缩进语法错误:原代码里
try/except块、print语句缩进不符合Python语法要求,运行会直接报错。 - 邮件对象复用错误:在循环外只初始化了一次邮件对象,多次发件时会叠加之前的收件人、正文内容,导致收件人泄露、内容错乱。
修正后代码
import pandas as pd from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import smtplib # 读取并筛选数据 df = pd.read_excel('s1.xlsx') print('RAW_DATA') print(df) print('========================================') df1 = df.loc[df.VIP.str.startswith('Y', na=False)] # 增加na=False避免空值报错 df0 = df.loc[df.VIP.str.startswith('N', na=False)] df2 = pd.DataFrame(df1,columns=['Name','VIP','Email']) df00 = pd.DataFrame(df0, columns=['Name','VIP','Email']) print('VIP LIST') print(df2) print('========================================') print('Non-VIP LIST') print(df00) print('========================================') # 配置发件人信息 sender_addr = "*****@gmail.com" # 替换为你的发件邮箱 sender_pwd = "******" # 替换为Gmail应用专用密码 # 建立SMTP连接(整个发件流程只需要连接登录一次) with smtplib.SMTP(host="smtp.gmail.com", port=587) as smtp: smtp.ehlo() smtp.starttls() smtp.login(sender_addr, sender_pwd) # 逐行遍历VIP列表,保证姓名和邮箱一一匹配 for _, row in df2.iterrows(): name = row['Name'] receiver_addr = row['Email'] # 每个收件人单独初始化邮件对象,避免内容残留 content = MIMEMultipart() content["subject"] = "Learn Code With Mike" content["from"] = sender_addr content["to"] = receiver_addr # 构造定制化正文,修正MIMEText参数 mail_body = f"您好 {name}:\n这是给您发送的VIP专属邮件。" content.attach(MIMEText(mail_body, "plain", "utf-8")) # 发送邮件 try: smtp.send_message(content) print(f"已成功给{name}({receiver_addr})发送邮件") except Exception as s: print(f"给{name}发件失败,错误信息: ", s) print("所有VIP邮件发送流程执行完毕")
关键修改说明
- 用
df2.iterrows()逐行遍历VIP数据,每一行同时提取姓名、邮箱字段,从根源上保证两个字段的匹配关系不会错位。 - 每封邮件单独初始化
MIMEMultipart对象,不会出现上一封邮件的收件人、正文残留到下一封的问题。 - 修正
MIMEText传参顺序:第一个参数传入拼接了联系人姓名的正文,第二个参数传plain标识纯文本格式,第三个参数指定utf-8编码避免乱码,彻底解决异常无名称附件的问题。 - 优化SMTP连接逻辑:整个发件流程只建立一次连接、登录一次,在连接上下文内循环发件,减少不必要的网络开销,同时修正了原代码的缩进语法错误。
- 给
str.startswith()增加na=False参数,避免Excel里VIP字段为空时运行报错。
注意:Gmail现在已经不支持普通密码登录SMTP服务,需要先在谷歌账号里开启两步验证,再生成16位应用专用密码填到
sender_pwd位置才能正常发件。
内容的提问来源于stack exchange,提问作者Pang Felix
相关产品推荐
相关产品推荐

