python: how to send mail with TO, CC and BCC?
Question:
I need for testing purposes to populate few hundred email boxes with various messages, and was going to use smtplib for that. But among other things I need to be able to send messages not only TO specific mailboxes, but CC and BCC them as well. It does not look like smtplib supports CC-ing and BCC-ing while sending emails.
Looking for suggestions how to do CC or BCC sending messages from the python script.
(And — no, I’m not creating a script to spam anyone outside of my testing environment.)
Answers:
The distinction between TO, CC and BCC occurs only in the text headers. At the SMTP level, everybody is a recipient.
TO – There is a TO: header with this recipient’s address
CC – There is a CC: header with this recipient’s address
BCC – This recipient isn’t mentioned in the headers at all, but is still a recipient.
If you have
TO: [email protected]
CC: [email protected]
BCC: [email protected]
You have three recipients. The headers in the email body will include only the TO: and CC:
You can try MIMEText
msg = MIMEText('text')
msg['to'] =
msg['cc'] =
then send msg.as_string()
Email headers don’t matter to the smtp server. Just add CC and BCC recipients to toaddrs
when sending emails. For CC, add them to the CC header.
toaddr = '[email protected]'
cc = ['[email protected]','[email protected]']
bcc = ['[email protected]']
fromaddr = '[email protected]'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %srn" % fromaddr
+ "To: %srn" % toaddr
+ "CC: %srn" % ",".join(cc)
+ "Subject: %srn" % message_subject
+ "rn"
+ message_text
toaddrs = [toaddr] + cc + bcc
server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, message)
server.quit()
Don’t add the bcc header.
See this: http://mail.python.org/pipermail/email-sig/2004-September/000151.html
And this: “””Notice that the second argument to sendmail(), the recipients, is passed as a list. You can include any number of addresses in the list to have the message delivered to each of them in turn. Since the envelope information is separate from the message headers, you can even BCC someone by including them in the method argument but not in the message header.””” from http://pymotw.com/2/smtplib
toaddr = '[email protected]'
cc = ['[email protected]','[email protected]']
bcc = ['[email protected]']
fromaddr = '[email protected]'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %srn" % fromaddr
+ "To: %srn" % toaddr
+ "CC: %srn" % ",".join(cc)
# don't add this, otherwise "to and cc" receivers will know who are the bcc receivers
# + "BCC: %srn" % ",".join(bcc)
+ "Subject: %srn" % message_subject
+ "rn"
+ message_text
toaddrs = [toaddr] + cc + bcc
server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, message)
server.quit()
Key thing is to add the recipients as a list of email ids in your sendmail call.
import smtplib
from email.mime.multipart import MIMEMultipart
me = "[email protected]"
to = "[email protected]"
cc = "[email protected],[email protected]"
bcc = "[email protected],[email protected]"
rcpt = cc.split(",") + bcc.split(",") + [to]
msg = MIMEMultipart('alternative')
msg['Subject'] = "my subject"
msg['To'] = to
msg['Cc'] = cc
msg.attach(my_msg_body)
server = smtplib.SMTP("localhost") # or your smtp server
server.sendmail(me, rcpt, msg.as_string())
server.quit()
It did not worked for me until i created:
#created cc string
cc = ""[email protected];
#added cc to header
msg['Cc'] = cc
and than added cc in recipient [list] like:
s.sendmail(me, [you,cc], msg.as_string())
As of Python 3.2, released Nov 2011, the smtplib has a new function send_message
instead of just sendmail
, which makes dealing with To/CC/BCC easier. Pulling from the Python official email examples, with some slight modifications, we get:
# Import smtplib for the actual sending function
import smtplib
# Import the email modules we'll need
from email.message import EmailMessage
# Open the plain text file whose name is in textfile for reading.
with open(textfile) as fp:
# Create a text/plain message
msg = EmailMessage()
msg.set_content(fp.read())
# me == the sender's email address
# you == the recipient's email address
# them == the cc's email address
# they == the bcc's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you
msg['Cc'] = them
msg['Bcc'] = they
# Send the message via our own SMTP server.
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
Using the headers work fine, because send_message respects BCC as outlined in the documentation:
send_message does not transmit any Bcc or Resent-Bcc headers that may appear in msg
With sendmail
it was common to add the CC headers to the message, doing something such as:
msg['Bcc'] = [email protected]
Or
msg = "From: [email protected]" +
"To: [email protected]" +
"BCC: [email protected]" +
"Subject: You've got mail!" +
"This is the message body"
The problem is, the sendmail function treats all those headers the same, meaning they’ll get sent (visibly) to all To: and BCC: users, defeating the purposes of BCC. The solution, as shown in many of the other answers here, was to not include BCC in the headers, and instead only in the list of emails passed to sendmail
.
The caveat is that send_message
requires a Message object, meaning you’ll need to import a class from email.message
instead of merely passing strings into sendmail
.
None of the above things worked for me as I had multiple recipients both in ‘to’ and ‘cc’. So I tried like below:
recipients = ['[email protected]', '[email protected]']
cc_recipients = ['[email protected]', '[email protected]']
MESSAGE['To'] = ", ".join(recipients)
MESSAGE['Cc'] = ", ".join(cc_recipients)
and extend the ‘recipients’ with ‘cc_recipients’ and send mail in trivial way
recipients.extend(cc_recipients)
server.sendmail(FROM,recipients,MESSAGE.as_string())
I need for testing purposes to populate few hundred email boxes with various messages, and was going to use smtplib for that. But among other things I need to be able to send messages not only TO specific mailboxes, but CC and BCC them as well. It does not look like smtplib supports CC-ing and BCC-ing while sending emails.
Looking for suggestions how to do CC or BCC sending messages from the python script.
(And — no, I’m not creating a script to spam anyone outside of my testing environment.)
The distinction between TO, CC and BCC occurs only in the text headers. At the SMTP level, everybody is a recipient.
TO – There is a TO: header with this recipient’s address
CC – There is a CC: header with this recipient’s address
BCC – This recipient isn’t mentioned in the headers at all, but is still a recipient.
If you have
TO: [email protected]
CC: [email protected]
BCC: [email protected]
You have three recipients. The headers in the email body will include only the TO: and CC:
You can try MIMEText
msg = MIMEText('text')
msg['to'] =
msg['cc'] =
then send msg.as_string()
Email headers don’t matter to the smtp server. Just add CC and BCC recipients to toaddrs
when sending emails. For CC, add them to the CC header.
toaddr = '[email protected]'
cc = ['[email protected]','[email protected]']
bcc = ['[email protected]']
fromaddr = '[email protected]'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %srn" % fromaddr
+ "To: %srn" % toaddr
+ "CC: %srn" % ",".join(cc)
+ "Subject: %srn" % message_subject
+ "rn"
+ message_text
toaddrs = [toaddr] + cc + bcc
server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, message)
server.quit()
Don’t add the bcc header.
See this: http://mail.python.org/pipermail/email-sig/2004-September/000151.html
And this: “””Notice that the second argument to sendmail(), the recipients, is passed as a list. You can include any number of addresses in the list to have the message delivered to each of them in turn. Since the envelope information is separate from the message headers, you can even BCC someone by including them in the method argument but not in the message header.””” from http://pymotw.com/2/smtplib
toaddr = '[email protected]'
cc = ['[email protected]','[email protected]']
bcc = ['[email protected]']
fromaddr = '[email protected]'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %srn" % fromaddr
+ "To: %srn" % toaddr
+ "CC: %srn" % ",".join(cc)
# don't add this, otherwise "to and cc" receivers will know who are the bcc receivers
# + "BCC: %srn" % ",".join(bcc)
+ "Subject: %srn" % message_subject
+ "rn"
+ message_text
toaddrs = [toaddr] + cc + bcc
server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, message)
server.quit()
Key thing is to add the recipients as a list of email ids in your sendmail call.
import smtplib
from email.mime.multipart import MIMEMultipart
me = "[email protected]"
to = "[email protected]"
cc = "[email protected],[email protected]"
bcc = "[email protected],[email protected]"
rcpt = cc.split(",") + bcc.split(",") + [to]
msg = MIMEMultipart('alternative')
msg['Subject'] = "my subject"
msg['To'] = to
msg['Cc'] = cc
msg.attach(my_msg_body)
server = smtplib.SMTP("localhost") # or your smtp server
server.sendmail(me, rcpt, msg.as_string())
server.quit()
It did not worked for me until i created:
#created cc string
cc = ""[email protected];
#added cc to header
msg['Cc'] = cc
and than added cc in recipient [list] like:
s.sendmail(me, [you,cc], msg.as_string())
As of Python 3.2, released Nov 2011, the smtplib has a new function send_message
instead of just sendmail
, which makes dealing with To/CC/BCC easier. Pulling from the Python official email examples, with some slight modifications, we get:
# Import smtplib for the actual sending function
import smtplib
# Import the email modules we'll need
from email.message import EmailMessage
# Open the plain text file whose name is in textfile for reading.
with open(textfile) as fp:
# Create a text/plain message
msg = EmailMessage()
msg.set_content(fp.read())
# me == the sender's email address
# you == the recipient's email address
# them == the cc's email address
# they == the bcc's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you
msg['Cc'] = them
msg['Bcc'] = they
# Send the message via our own SMTP server.
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
Using the headers work fine, because send_message respects BCC as outlined in the documentation:
send_message does not transmit any Bcc or Resent-Bcc headers that may appear in msg
With sendmail
it was common to add the CC headers to the message, doing something such as:
msg['Bcc'] = [email protected]
Or
msg = "From: [email protected]" +
"To: [email protected]" +
"BCC: [email protected]" +
"Subject: You've got mail!" +
"This is the message body"
The problem is, the sendmail function treats all those headers the same, meaning they’ll get sent (visibly) to all To: and BCC: users, defeating the purposes of BCC. The solution, as shown in many of the other answers here, was to not include BCC in the headers, and instead only in the list of emails passed to sendmail
.
The caveat is that send_message
requires a Message object, meaning you’ll need to import a class from email.message
instead of merely passing strings into sendmail
.
None of the above things worked for me as I had multiple recipients both in ‘to’ and ‘cc’. So I tried like below:
recipients = ['[email protected]', '[email protected]']
cc_recipients = ['[email protected]', '[email protected]']
MESSAGE['To'] = ", ".join(recipients)
MESSAGE['Cc'] = ", ".join(cc_recipients)
and extend the ‘recipients’ with ‘cc_recipients’ and send mail in trivial way
recipients.extend(cc_recipients)
server.sendmail(FROM,recipients,MESSAGE.as_string())