Reputation: 155
Below is a code to send multiple emails to contacts loaded from a text file.
import time
from time import sleep
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
uname = #[email protected]
name = "KTester"
password = #password1
server = smtplib.SMTP('smtp.gmail.com: 587')
server.starttls()
server.login(uname, password)
message="Test"
msg = MIMEMultipart('Alternative')
f= open("list.txt","r")clear
if f.mode == "r":
cont = f.read().splitlines()
for x in cont:
print time.ctime()
msg['Subject'] = "Test Mail - cripted Sample"
msg['To'] = x
msg['From'] = name+"\x0A\x0D"+uname
msg.attach(MIMEText(message, 'html'))
print "successfully sent email to %s:" % (msg['To'])
f.close()
server.quit()
In this case, the first compilation is the expected outcome, which we can get if we use print "successfully sent email to %s:" % (x)
The Variable 'x' changes its value at the end of each iteration.
However, msg['To'] = x does not accept value from second iteration of the loop(The second code run above).
Assignment operation does not work on the message object.
Kindly help with whats going wrong. Thanks!
Upvotes: 2
Views: 1470
Reputation: 55799
This behaviour is by design.
Reassigning to msg['to']
doesn't overwrite the existing mail header, it adds another. To send the existing message to a new address you need to delete the 'to' header before setting it.
del msg['to']
msg['to'] = '[email protected]'
This applies to other headers too. From the docs for Message.__setitem__
:
Note that this does not overwrite or delete any existing header with the same name. If you want to ensure that the new header is the only one present in the message with field name name, delete the field first, e.g.:
del msg['subject']
msg['subject'] = 'Python roolz!'
Upvotes: 2
Reputation: 636
The main problem in your script is that you have defined msg = MIMEMultipart('Alternative') outside for loop. Try defining msg = MIMEMultipart('Alternative') inside for loop.
The solution is same as given by @Daniel Sims but I have turned your script more readable so that everyone can understand
I have edited your code in my own way which worked like a charm for me. Have a try:
[CODE]
import time
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# credentials
uname = 'your email address'
name = "KTester"
password = 'password'
# Connecting to gmail server and logging to your gmail account
server = smtplib.SMTP('smtp.gmail.com: 587')
server.starttls()
server.login(uname, password)
message = "Test" # Your message
with open('list.txt', 'r') as lst:
lines = lst.readlines() # Reading files to get emails
for line in lines: # Getting each email from list of emails
msg = MIMEMultipart('Alternative') # This line is added here(which if you have did outside of the for loop)
msg['Subject'] = "Test Mail - cripted Sample"
msg['To'] = line
msg['From'] = '{}{}{}'.format(name, "\x0A\x0D", uname)
msg.attach(MIMEText(message, 'html'))
print(time.ctime())
print("successfully sent email to {}".format(msg['To']))
server.quit()
Upvotes: 0
Reputation: 1771
(Edit of original answer, after clarification of question's output)
Try moving the following line into the for loop:
msg = MIMEMultipart('Alternative')
To look like this:
for x in cont:
msg = MIMEMultipart('Alternative')
print time.ctime()
msg['Subject'] = "Test Mail - cripted Sample"
msg['To'] = x
msg['From'] = name+"\x0A\x0D"+uname
msg.attach(MIMEText(message, 'html'))
print "successfully sent email to %s:" % (msg['To'])
I think the msg needs to be new in each iteration.
My testing yielded exactly the same results - appearing to send to the same email address over and over. Because the msg headers simply get appended to. The for loop was creating multiple to: headers, but printing was only revealing the first. See below for what it looks like in debug:
Header of To: line in original for loop
After adding the msg instantiation to within the for loop, the output was as expected with different names each iteration.
I think the root of how msg is structured might be that email can have more than one person on the to: line. The above solution presumes that you only wanted one person on each to: line.
Upvotes: 0