我正在尝试通过libsmtp和gmail将具有不同消息的电子邮件发送到不同的收件人。
我尝试在不关闭smtp连接的情况下发送邮件。它只是将所有消息发送到同一接收者,但我想与接收者发送消息。 我尝试为每个循环打开和退出连接,但是在执行第一次迭代并退出连接后,第二次迭代会给出错误消息“ smtplib.SMTPServerDisconnected:请先运行connect()”,即使它应该再次连接。
class Mail:
msg = MIMEMultipart()
def __init__(self, addr_from, addr_to):
self.msg['From'] = addr_from
self.msg['To'] = addr_to
def set_subject(self, subject):
self.msg['Subject'] = subject
def set_message(self, message):
self.msg.attach(MIMEText(message, 'plain'))
def attach_image(self, image_location, image_name):
fp = open(image_location, 'rb')
img = MIMEImage(fp.read())
img.add_header('Content-Disposition', "attachment; filename= %s" % image_name)
fp.close()
self.msg.attach(img)
def get_mail(self):
return self.msg
class EmailServer:
server = smtplib.SMTP('smtp.gmail.com', 587)
def __init__(self, sender_mail, password):
self.sender_mail = sender_mail
self.password = password
self.server.ehlo()
self.server.starttls()
self.server.login(sender_mail, password)
def send_mail(self, mail):
self.server.sendmail(mail['From'], mail['To'], mail.as_string())
def quit_server(self):
self.server.quit()
for row in range(0,x):
name = sheet.cell_value(row, 0)
mail_adress = sheet.cell_value(row, 1)
print(name, mail_adress)
mail = Mail('xxxxxxxx@gmail.com', mail_adress)
mail.set_subject("subject")
mail.set_message('message')
server = EmailServer('xxxxxxxx@gmail.com', 'xxxxxxxxx')
mail.attach_image('/Users/xxxx/xxxx/xxxx.jpg', 'title')
server.send_mail(mail.get_mail())
server.quit_server()
答案 0 :(得分:0)
您定义Mail
,msg
的方式是一个类属性,因此Mail
的每个实例都包含相同的msg
。
import email
from email.mime.multipart import MIMEMultipart
class Mail:
msg = MIMEMultipart()
def __init__(self, addr_from, addr_to):
self.msg['From'] = addr_from
self.msg['To'] = addr_to
for afrom, ato in zip(list('abcd'),list('wert')):
mail = Mail(afrom, ato)
print(id(mail.msg))
In [60]:
160675264
160675264
160675264
160675264
MIMEMultipart是email.message
对象;其__setitem__
文档字符串状态:...does not overwrite an existing header with the same field name. Use __delitem__() first to delete any existing headers.
...
In [61]: help(mail.msg.__setitem__)
Help on method __setitem__ in module email.message:
__setitem__(name, val) method of email.mime.multipart.MIMEMultipart instance
Set the value of a header.
Note: this does not overwrite an existing header with the same field
name. Use __delitem__() first to delete any existing headers.
在for循环之后,From
和To
标头是具有多个值的列表:
mail.msg.get_all('From'), mail.msg.get_all('To')
Out[62]: (['a', 'b', 'c', 'd'], ['w', 'e', 'r', 't'])
您的问题的一种解决方案是在循环中分配新值之前删除From
和To
标头。
In [63]: del mail.msg['From']
In [64]: del mail.msg['To']
In [65]: mail.msg.get_all('From'), mail.msg.get_all('To')
Out[65]: (None, None)
In [66]: mail.msg['From'] = 'z'
In [67]: mail.msg['To'] = 'y'
In [68]: mail.msg.get_all('From'), mail.msg.get_all('To')
Out[68]: (['z'], ['y'])
另一种选择可能是为每个msg
实例创建一个新的Mail
。
class Mail:
def __init__(self, addr_from, addr_to):
self.msg = MIMEMultipart()
self.msg['From'] = addr_from
self.msg['To'] = addr_to
另一种选择是在循环之后发送邮件。 SMTP.sendmail
的{{3}}接受列表,因此需要修改EmailServer.sendmail
class EmailServer:
...
...
def send_mail(self, mail):
self.server.sendmail(mail['From'], mail.get_all('To'), mail.as_string())
然后在添加多个'To'
地址的循环之后
server.send_mail(mail.get_mail())
server.quit_server()
我无法对此进行测试,但应该可以。您可能应该只创建一个Mail
实例,并且所有 stuff 都不会改变;然后,一个EmailServer
实例使用循环将多个地址添加到Mail
实例。然后发送邮件。