How to send email to multiple recipients using python smtplib?
Solution 1
This really works, I spent a lot of time trying multiple variants.
import smtplib
from email.mime.text import MIMEText
s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = '[email protected]'
recipients = ['[email protected]', '[email protected]']
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = ", ".join(recipients)
s.sendmail(sender, recipients, msg.as_string())
Solution 2
The msg['To']
needs to be a string:
msg['To'] = "[email protected], [email protected], [email protected]"
While the recipients
in sendmail(sender, recipients, message)
needs to be a list:
sendmail("[email protected]", ["[email protected]", "[email protected]", "[email protected]"], "Howdy")
Solution 3
You need to understand the difference between the visible address of an email, and the delivery.
msg["To"]
is essentially what is printed on the letter. It doesn't actually have any effect. Except that your email client, just like the regular post officer, will assume that this is who you want to send the email to.
The actual delivery however can work quite different. So you can drop the email (or a copy) into the post box of someone completely different.
There are various reasons for this. For example forwarding. The To:
header field doesn't change on forwarding, however the email is dropped into a different mailbox.
The smtp.sendmail
command now takes care of the actual delivery. email.Message
is the contents of the letter only, not the delivery.
In low-level SMTP
, you need to give the receipients one-by-one, which is why a list of adresses (not including names!) is the sensible API.
For the header, it can also contain for example the name, e.g. To: First Last <[email protected]>, Other User <[email protected]>
. Your code example therefore is not recommended, as it will fail delivering this mail, since just by splitting it on ,
you still not not have the valid adresses!
Solution 4
It works for me.
import smtplib
from email.mime.text import MIMEText
s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = '[email protected]'
recipients = '[email protected],[email protected]'
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = recipients
s.sendmail(sender, recipients.split(','), msg.as_string())
Solution 5
The solution below worked for me. It successfully sends an email to multiple recipients, including "CC" and "BCC."
toaddr = ['mailid_1','mailid_2']
cc = ['mailid_3','mailid_4']
bcc = ['mailid_5','mailid_6']
subject = 'Email from Python Code'
fromaddr = 'sender_mailid'
message = "\n !! Hello... !!"
msg['From'] = fromaddr
msg['To'] = ', '.join(toaddr)
msg['Cc'] = ', '.join(cc)
msg['Bcc'] = ', '.join(bcc)
msg['Subject'] = subject
s.sendmail(fromaddr, (toaddr+cc+bcc) , message)
Related videos on Youtube
user1148320
Updated on July 08, 2022Comments
-
user1148320 almost 2 years
After much searching I couldn't find out how to use smtplib.sendmail to send to multiple recipients. The problem was every time the mail would be sent the mail headers would appear to contain multiple addresses, but in fact only the first recipient would receive the email.
The problem seems to be that the
email.Message
module expects something different than thesmtplib.sendmail()
function.In short, to send to multiple recipients you should set the header to be a string of comma delimited email addresses. The
sendmail()
parameterto_addrs
however should be a list of email addresses.from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText import smtplib msg = MIMEMultipart() msg["Subject"] = "Example" msg["From"] = "[email protected]" msg["To"] = "[email protected],[email protected],[email protected]" msg["Cc"] = "[email protected],[email protected]" body = MIMEText("example email body") msg.attach(body) smtp = smtplib.SMTP("mailhost.example.com", 25) smtp.sendmail(msg["From"], msg["To"].split(",") + msg["Cc"].split(","), msg.as_string()) smtp.quit()
-
Cees Timmerman almost 9 yearsIt appears OP answered his own question:
sendmail
needs a list. -
Cees Timmerman almost 9 yearspossible duplicate of Is there any way to add multiple receivers in Python SMTPlib?
-
krethika over 5 yearsUsing Python3 I had to loop through recipients;
for addr in recipients: msg['To'] = addr
and then it worked. Multiple assignments actually appends a new 'To' header for each one. This is a very bizarre interface, I can't even explain how I thought to try it. I was even considering usingsubprocess
to call the unixsendmail
package to save my sanity before I figured this out.
-
-
chug2k over 10 yearsthe documentation does have the example:
tolist =["[email protected]","[email protected]","[email protected]","[email protected]rg"]
-
Steve Hunt almost 10 yearsRFC 2822 imposes a maximum width of 988 characters for a given header and a recommended width of 78 characters. You will need to ensure you "fold" the header if you have too many addresses.
-
fear_matrix almost 9 yearsthank you @sorin for this script. I was having a problem to send an email from a python script and with this piece of code, i can now send the email.
-
Adam Matan almost 9 yearsThis is one strange design decision for
smtplib.
-
Suzana over 8 years
recipients
does not have to be a list - if a string is given, it is treated as a list with one element. Themsg['To']
string can simply be omitted. -
Serrano over 7 yearsThis should be the accepted answer, as it actually explains the why and the how.
-
antonavy over 7 yearsI don't really understand, how '[email protected], [email protected]' is parsed so only the first address gets the email. But, thanks! This is the answer, had to put list in there.
-
Rodrigo Laguna about 7 yearsworked for me, and it is consistent with documentation in docs.python.org/2/library/email-examples.html
-
Tagar almost 7 yearsGreat answer. What about CC and BCC email fields? I assume we also have to include CC and BCC email in smtp.send. And only CC list (and not BCC list) in the msg fields?
-
Has QUIT--Anony-Mousse almost 7 yearsYes, that is how it works. Mail servers will likely drop the BCC field (to prevent this from being visible, and I don't think they all do), but they won't parse it.
-
cardamom almost 7 yearsThis will not send to multiple recipients if you are using Python 3 you need
send_message
instead ofsendmail
as per Antoine's comment below and the Python docs docs.python.org/3/library/email.examples.html -
Johnny over 6 yearsYou have to use for each traverse that recipients for sendmail, otherwise only first element will receive the mail.
-
David over 6 yearscorrection to the url mentioned above: docs.python.org/3/library/email.examples.html
-
panofish over 6 yearswhat version of python are you using? I get the same problem as the original poster and I am using python 2.7.9
-
MasterMind over 6 yearsFYR whole simple code below:
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText sender = '[email protected]' rec_list = ['[email protected]', '[email protected]'] rec = ', '.join(rec_list) msg = MIMEMultipart('alternative') msg['Subject'] = 'The required subject' msg['From'] = sender msg['To'] = rec html = ('whatever html code') htm_part = MIMEText(html, 'html') msg.attach(htm_part) send_out = smtplib.SMTP('localhost') send_out.sendmail(sender, rec_list, msg.as_string()) send_out.quit()
-
Guillaume Algis about 6 yearsSince Python 3.3 you should use the new API email.message
-
Wojciech Jakubas over 5 yearsPython 3.7 throws an exception with message: Exception has occurred: ValueError There may be at most 1 To headers in a message
-
WoJ about 5 yearsWhy not simply
recipients = ['[email protected]','[email protected]']
instead of making it a string, and then split it to make a list? -
Wil almost 5 yearsThis works partly, to realy hide the BCC you must omit the BCC line bcc = ['mailid_5','mailid_6'] otherwise this will show in the header defeating the purpose of bcc. Tested with gmail and other mail server.
-
3pitt over 4 years@Wil how would you implement BCC in that case?
-
lobi over 4 yearsNote, using s.sendmail(sender, recipients, msg.as_string()) works fine for me on 3.7, and s.send_message(msg) also works.
-
Pascal Louis-Marie about 4 yearsto Woj, because msg['To'] should be a string and s.sendmail should have a list : (sender,>>>LIST HERE<<<,msg.as_string()). That's means,as annoying as it looks,that you can not use one same type [ string or list ] for both fields
-
Anadyn about 4 yearsWorks like a charm for me. Python 3.7.3.
-
Orhan Solak almost 3 yearsIt looks like send to all, but only the first address receives the mail. You should use list format in s.sendmail function
-
bfontaine almost 3 years@3pitt a bit late, but you just send them the same email using
s.sendmail(fromaddr, bcc, message)
. -
Chandra Shekhar over 2 yearsThanks, it works for me as well! Could you please suggest how to attach a pdf file along with the mail that we are sending here? Do we have some option for providing the file path as well??
-
tripleee about 2 yearsAs an aside, your code seems to be written for Python 3.5 or earlier. The
email
library was overhauled in 3.6 and is now quite a bit more versatile and logical. Probably throw away what you have and start over with the examples from theemail
documentation. -
tripleee about 2 yearsSome MTAs will strip the
Bcc:
header before sending, others won't. SMTP doesn't really care what's in the headers; it will actually attempt to deliver to the list you provide in the envelope (here, thesendmail
method ofsmtplib
) and completely ignore what's in the headers. -
tripleee about 2 yearsSeveral of the examples here needlessly create a multipart with only a single body part. Obviously, there is no need for a multipart container when there are not multiple body parts. However, this also suffers from using the legacy pre-3.6 API in fairly recent code; you should probably throw away what you have and start over with the new API.
-
tripleee about 2 yearsYour
message
is not a valid RFC822 message, so this should fail spectacularly. -
tripleee about 2 yearsMany of the adornments here were useful with the legacy
email.message.message
/MIMEText
API, but no longer necessary with the modern Python 3.6+email.message.EmailMessage
API. -
tripleee about 2 yearsWithout details, this is rather dubious, but it seems that you managed to use the modern
EmailMessage
API before it was official. (It was introduced already in 3.3, but became the official and documented one in 3.6.) -
tripleee about 2 yearsThe string
"Howdy"
is not a valid RFC822 message. Some mail servers will simply reject it, others will probably guess what the missing parts are, and probably find surprising things to put there. Ultimately, if something actually ends up being delivered somewhere, it will probably not be useful. -
tripleee about 2 yearsAs long as the input strings are simple short ASCII only text fragments, assembling an email message by pasting them together like this will actually work; but unless you know exactly what you are doing, you will be better off using the
email
library, which knows what the corner cases are and how to handle content types which are not completely plain text. -
tripleee about 2 years@ChandraShekhar My answer coincidentally shows how to add an attachment, but really, probably search for other questions before asking here.
-
Chandra Shekhar about 2 years@tripleee Sure, Thanks.