从DataFrame多邮箱地址发送邮件仅成功首个地址的问题排查
解决多收件人邮件发送问题
你的代码核心问题在于没有正确拆分逗号分隔的邮箱地址,同时函数调用和参数传递存在错误,导致SMTP服务器实际只收到一个格式错误的收件人地址(包含逗号的单个字符串)。以下是具体修复方案:
问题点分析
- 收件人地址未拆分:
emailto = [str(row[3])]仅将整行的邮箱字符串包装成列表,未把逗号分隔的多个邮箱拆分成独立元素,SMTP服务器会把这个带逗号的字符串当作单个收件人,自然无法投递到第二个邮箱。 - 函数参数传递错误:循环中
sendemail(df.to_html(index=False), df['email'])传递的是整个DataFrame的email列,而非当前行的邮箱地址。 - 函数内变量未定义:sendemail函数直接使用
row变量,但该变量是循环的局部变量,函数无法正确获取,会引发逻辑错误。
修改后的完整代码
import psycopg2 import csv import pandas import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.utils import formatdate from datetime import date from dateutil.relativedelta import relativedelta try: conn = psycopg2.connect("dbname='' user='' host='' port='' password='' sslmode=''") except psycopg2.Error as e: print ("Unable to connect to database: " + str(e)) cursor = conn.cursor() cursor.execute(open("query.sql","r").read()) with open('file.csv', mode='w', newline='') as csv_file: writer = csv.writer(csv_file, delimiter=',') writer.writerow([ i[0] for i in cursor.description ]) writer.writerows(cursor.fetchall()) conn.close() df = pandas.read_csv('file.csv') def sendemail(first_name, middle_name, last_name, exp_date, to_emails): emailhost = '' emailport = '' emailfrom= '' emailsubject = 'Subject' # 拆分逗号分隔的邮箱,去除空格并过滤空值 email_list = [email.strip() for email in to_emails.split(',') if email.strip()] text = '''Dear {} {} {}, something happened and I want to tell you about it: {}. Thank You.'''.format( str(first_name), str(middle_name), str(last_name), str(exp_date) ) msg = MIMEMultipart('alternative') part1 = MIMEText(text,'plain') msg['From'] = emailfrom msg['To'] = ', '.join(email_list) msg['Date'] = formatdate(localtime = True) msg['Subject'] = emailsubject msg.attach(part1) server = smtplib.SMTP(emailhost, emailport) # sendmail第二个参数必须是拆分后的独立邮箱列表 server.sendmail(emailfrom, email_list, msg.as_string()) server.quit() for row in df.itertuples(index=False): # 传递当前行的具体字段给发送函数 sendemail(row[0], row[1], row[2], row[5], row[3])
关键修改说明
- 拆分邮箱地址:用
split(',')拆分字符串,再通过strip()去除每个邮箱前后的空格,避免因空格导致地址无效。 - 明确函数参数:将姓名、过期日期、邮箱等需要的字段作为参数传入函数,避免依赖外部变量,逻辑更清晰。
- 符合SMTP协议要求:
server.sendmail()的第二个参数必须是独立邮箱地址组成的列表,而非逗号分隔的字符串,这是服务器识别多收件人的关键。 - 修复循环调用:循环中传递当前行的
row[3](邮箱字段),而非整个DataFrame的email列。
修改后,SMTP服务器会正确识别每个收件人地址,实现向同一行的多个邮箱发送邮件。
内容的提问来源于stack exchange,提问作者vwalden
相关产品推荐
相关产品推荐

