How to send email to multiple recipients using python smtplib?

337,090

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)
Share:
337,090

Related videos on Youtube

user1148320
Author by

user1148320

Updated on July 08, 2022

Comments

  • user1148320
    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 the smtplib.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() parameter to_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
      Cees Timmerman almost 9 years
      It appears OP answered his own question: sendmail needs a list.
    • Cees Timmerman
      Cees Timmerman almost 9 years
    • krethika
      krethika over 5 years
      Using 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 using subprocess to call the unix sendmail package to save my sanity before I figured this out.
  • chug2k
    chug2k over 10 years
    the documentation does have the example: tolist =["[email protected]","[email protected]","[email protected]","[email protected]‌​rg"]
  • Steve Hunt
    Steve Hunt almost 10 years
    RFC 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
    fear_matrix almost 9 years
    thank 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
    Adam Matan almost 9 years
    This is one strange design decision for smtplib.
  • Suzana
    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
    Serrano over 7 years
    This should be the accepted answer, as it actually explains the why and the how.
  • antonavy
    antonavy over 7 years
    I 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
    Rodrigo Laguna about 7 years
    worked for me, and it is consistent with documentation in docs.python.org/2/library/email-examples.html
  • Tagar
    Tagar almost 7 years
    Great 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
    Has QUIT--Anony-Mousse almost 7 years
    Yes, 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
    cardamom almost 7 years
    This will not send to multiple recipients if you are using Python 3 you need send_message instead of sendmail as per Antoine's comment below and the Python docs docs.python.org/3/library/email.examples.html
  • Johnny
    Johnny over 6 years
    You have to use for each traverse that recipients for sendmail, otherwise only first element will receive the mail.
  • David
    David over 6 years
    correction to the url mentioned above: docs.python.org/3/library/email.examples.html
  • panofish
    panofish over 6 years
    what version of python are you using? I get the same problem as the original poster and I am using python 2.7.9
  • MasterMind
    MasterMind over 6 years
    FYR 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
    Guillaume Algis about 6 years
    Since Python 3.3 you should use the new API email.message
  • Wojciech Jakubas
    Wojciech Jakubas over 5 years
    Python 3.7 throws an exception with message: Exception has occurred: ValueError There may be at most 1 To headers in a message
  • WoJ
    WoJ about 5 years
    Why not simply recipients = ['[email protected]','[email protected]'] instead of making it a string, and then split it to make a list?
  • Wil
    Wil almost 5 years
    This 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
    3pitt over 4 years
    @Wil how would you implement BCC in that case?
  • lobi
    lobi over 4 years
    Note, 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
    Pascal Louis-Marie about 4 years
    to 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
    Anadyn about 4 years
    Works like a charm for me. Python 3.7.3.
  • Orhan Solak
    Orhan Solak almost 3 years
    It looks like send to all, but only the first address receives the mail. You should use list format in s.sendmail function
  • bfontaine
    bfontaine almost 3 years
    @3pitt a bit late, but you just send them the same email using s.sendmail(fromaddr, bcc, message).
  • Chandra Shekhar
    Chandra Shekhar over 2 years
    Thanks, 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
    tripleee about 2 years
    As 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 the email documentation.
  • tripleee
    tripleee about 2 years
    Some 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, the sendmail method of smtplib) and completely ignore what's in the headers.
  • tripleee
    tripleee about 2 years
    Several 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
    tripleee about 2 years
    Your message is not a valid RFC822 message, so this should fail spectacularly.
  • tripleee
    tripleee about 2 years
    Many 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
    tripleee about 2 years
    Without 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
    tripleee about 2 years
    The 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
    tripleee about 2 years
    As 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
    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
    Chandra Shekhar about 2 years
    @tripleee Sure, Thanks.