MIMEMultipart edit msg['To'] recipients - python

I have a loop that iterates through a list of addresses and sends mail to each.
def send_mail(self, user_name, smtp_host, smtp_user, smtp_pass, smtp_port):
s = smtplib.SMTP_SSL(smtp_host[0],smtp_port[0])
s.login(smtp_user[0],smtp_pass[0])
msg = MIMEMultipart()
msg.attach(MIMEText(self.message))
msg['From'] = user_name[0]
msg['Subject'] = self.subject
for f in self.attachment_list:
part = MIMEBase('application', "octet-stream")
part.set_payload(open('temp/'+f,"rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(f)))
msg.attach(part)
for i,address in enumerate(Sheet.email_list):
print("Send email: " + address)
msg['To'] = address
s.sendmail(smtp_user[0], address, msg.as_string())
s.quit()
print("SMTP connection closed")
The code runs fine and sends an email to each address. However, when I view the email in Mail Application it lists: "To: " with each address. I intend for it to only list the recipient who is receiving the emails address. I played around with the code and I have determined that the issue is coming from msg['To']. I have tried to adjust it many ways, but I do not know how to make it send with only the one recipients address displayed.
msg['To'] addresses

I found the answer. I needed to replace the To header with each iteration.
if 'To' in msg:
msg.replace_header('To', address)
else:
msg['To'] = address

Related

Email sending without attachment - Python 3.8

I want to send a .txt file attached to the mail in Python.
Currently the mail is received but without any attachment.
Code bellow
I've sent emails in PHP but Python is completely new to me
The code doesn't return any errors, it simply doesn't send the attachment with the email
with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
server = smtplib.SMTP('smtp.gmail.com', 587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
msg = MIMEMultipart()
smtp.login(EMAIL_ADRESS, EMAIL_PASSWORD)
subject = 'Log Register'
filename = 'logs-to-h4wtsh0wt.txt'
attachment = open(filename, 'rb')
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= "+filename)
msg.attach(part)
msg = f'Subject: {subject}\n\n{Body}'
smtp.sendmail(EMAIL_ADRESS,EMAIL_ADRESS, msg)
snakecharmerb is right. You are indeed overriding the message object and therefore losing everything you add before that point.
You can instead set the subject like this:
msg['Subject'] = "Subject of the Mail"
# string to store the body of the mail
body = "Body_of_the_mail"
# attach the body with the msg instance
msg.attach(MIMEText(body, 'plain'))
Because you are attaching a file you will also need to convert the multipart message into a string before sending:
text = msg.as_string()
smtp.sendmail(fromaddr, toaddr, text)
When you created msg with MIMEMultipart() it generated the message object structure for you as per RFC2822 which also gives you FROM, TO, etc.
The msg object also has a bunch of functions you can run outlined in its docs

how to send bcc without showing the bcc in the e-mail header? [duplicate]

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.)
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 = 'buffy#sunnydale.k12.ca.us'
cc = ['alexander#sunydale.k12.ca.us','willow#sunnydale.k12.ca.us']
bcc = ['chairman#slayerscouncil.uk']
fromaddr = 'giles#sunnydale.k12.ca.us'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %s\r\n" % fromaddr
+ "To: %s\r\n" % toaddr
+ "CC: %s\r\n" % ",".join(cc)
+ "Subject: %s\r\n" % message_subject
+ "\r\n"
+ 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 = "user63503#gmail.com"
to = "someone#gmail.com"
cc = "anotherperson#gmail.com,someone#yahoo.com"
bcc = "bccperson1#gmail.com,bccperson2#yahoo.com"
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()
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'] = blind.email#adrress.com
Or
msg = "From: from.email#address.com" +
"To: to.email#adress.com" +
"BCC: hidden.email#address.com" +
"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.
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 = 'buffy#sunnydale.k12.ca.us'
cc = ['alexander#sunydale.k12.ca.us','willow#sunnydale.k12.ca.us']
bcc = ['chairman#slayerscouncil.uk']
fromaddr = 'giles#sunnydale.k12.ca.us'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %s\r\n" % fromaddr
+ "To: %s\r\n" % toaddr
+ "CC: %s\r\n" % ",".join(cc)
# don't add this, otherwise "to and cc" receivers will know who are the bcc receivers
# + "BCC: %s\r\n" % ",".join(bcc)
+ "Subject: %s\r\n" % message_subject
+ "\r\n"
+ 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()
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: abc#company.com
CC: xyz#company.com
BCC: boss#company.com
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()
https://docs.python.org/3.6/library/email.examples.html
It did not worked for me until i created:
#created cc string
cc = ""someone#domain.com;
#added cc to header
msg['Cc'] = cc
and than added cc in recipient [list] like:
s.sendmail(me, [you,cc], msg.as_string())
None of the above things worked for me as I had multiple recipients both in 'to' and 'cc'. So I tried like below:
recipients = ['abc#gmail.com', 'xyz#gmail.com']
cc_recipients = ['lmn#gmail.com', 'pqr#gmail.com']
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())

Python2.7 sending mail, why msg['To'] stay empty?

I am sending multiple recipients mail with a python script, and it works, but in the "To" in the mail, the field is empty. On every mail provider I tried.
Here is my code :
def send_mail(self, server, send_from, subject, attach, foo=None, bar=None)
msg = MIMEMultipart()
msg['From'] = send_from
msg['Subject'] = subject
body = u"""<html> My Body </html>"""
#Attach file pdf
msg.attach(MIMEText(body, 'html', 'utf-8'))
filename = 'fname.pdf'
attachment = open(attach, "rb")
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename = %s" % filename)
msg.attach(part)
text = msg.as_string()
if foo != None and bar != None:
recipients = ["a#b.fr", "b#b.fr"]
msg['To'] = ", ".join(recipients)
server.sendmail(send_from, recipients, text)
else:
msg['To'] = "c#b.fr"
server.sendmail(send_from, msg['To'], text)
sleep(1)
msg['To'] should be the "To" in my mail but it stays empty. (Even in the "else" with only one recipient). I can't find any help about it on existing question, so I come to ask for your help about that.
As per the documentation, the second parameter is a LIST of recipients. You need to change your line
server.sendmail(send_from, msg['To'], text)
to
server.sendmail(send_from, [msg['To']], text)
Finally found out:
text = msg.as_string() should be done after the assignement to msg['To'] So it will appear in my if and else block juste before the server.sendmail(send_from, msg['To'], text) since all information written in the mail, even 'To', and 'From' are in the third argument text .

How to send email to multiple recipients using python smtplib?

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"] = "me#example.com"
msg["To"] = "malcom#example.com,reynolds#example.com,firefly#example.com"
msg["Cc"] = "serenity#example.com,inara#example.com"
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()
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 = 'me#example.com'
recipients = ['john.doe#example.com', 'john.smith#example.co.uk']
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = ", ".join(recipients)
s.sendmail(sender, recipients, msg.as_string())
The msg['To'] needs to be a string:
msg['To'] = "a#b.com, b#b.com, c#b.com"
While the recipients in sendmail(sender, recipients, message) needs to be a list:
sendmail("a#a.com", ["a#b.com", "b#b.com", "c#b.com"], "Howdy")
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#addr.tld>, Other User <other#mail.tld>. 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!
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 = 'me#example.com'
recipients = 'john.doe#example.com,john.smith#example.co.uk'
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = recipients
s.sendmail(sender, recipients.split(','), msg.as_string())
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)
So actually the problem is that SMTP.sendmail and email.MIMEText need two different things.
email.MIMEText sets up the "To:" header for the body of the e-mail. It is ONLY used for displaying a result to the human being at the other end, and like all e-mail headers, must be a single string. (Note that it does not actually have to have anything to do with the people who actually receive the message.)
SMTP.sendmail, on the other hand, sets up the "envelope" of the message for the SMTP protocol. It needs a Python list of strings, each of which has a single address.
So, what you need to do is COMBINE the two replies you received. Set msg['To'] to a single string, but pass the raw list to sendmail:
emails = ['a.com','b.com', 'c.com']
msg['To'] = ', '.join( emails )
....
s.sendmail( msg['From'], emails, msg.as_string())
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def sender(recipients):
body = 'Your email content here'
msg = MIMEMultipart()
msg['Subject'] = 'Email Subject'
msg['From'] = 'your.email#gmail.com'
msg['To'] = (', ').join(recipients.split(','))
msg.attach(MIMEText(body,'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login('your.email#gmail.com', 'yourpassword')
server.send_message(msg)
server.quit()
if __name__ == '__main__':
sender('email_1#domain.com,email_2#domain.com')
It only worked for me with send_message function and using the join function in the list whith recipients, python 3.6.
I tried the below and it worked like a charm :)
rec_list = ['first#example.com', 'second#example.com']
rec = ', '.join(rec_list)
msg['To'] = rec
send_out = smtplib.SMTP('localhost')
send_out.sendmail(me, rec_list, msg.as_string())
I came up with this importable module function. It uses the gmail email server in this example. Its split into header and message so you can clearly see whats going on:
import smtplib
def send_alert(subject=""):
to = ['email#one.com', 'email2#another_email.com', 'a3rd#email.com']
gmail_user = 'me#gmail.com'
gmail_pwd = 'my_pass'
smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(gmail_user, gmail_pwd)
header = 'To:' + ", ".join(to) + '\n' + 'From: ' + gmail_user + '\n' + 'Subject: ' + subject + '\n'
msg = header + '\n' + subject + '\n\n'
smtpserver.sendmail(gmail_user, to, msg)
smtpserver.close()
I use python 3.6 and the following code works for me
email_send = 'xxxxx#xxx.xxx,xxxx#xxx.xxx'
server.sendmail(email_user,email_send.split(','),text)
I figured this out a few months back and blogged about it. The summary is:
If you want to use smtplib to send email to multiple recipients, use email.Message.add_header('To', eachRecipientAsString) to add them, and then when you invoke the sendmail method, use email.Message.get_all('To') send the message to all of them. Ditto for Cc and Bcc recipients.
Well, the method in this asnwer method did not work for me. I don't know, maybe this is a Python3 (I am using the 3.4 version) or gmail related issue, but after some tries, the solution that worked for me, was the line
s.send_message(msg)
instead of
s.sendmail(sender, recipients, msg.as_string())
This is an old question. My main reason to post a new answer is to explain how to solve the problem with the modern email library in Python 3.6+ and how it differs from the old version; but first, let's recap what Anony-Mousse wrote in their answer from 2012.
SMTP doesn't care at all what's in the headers. The list of recipients you pass in to the sendmail method are what actually determine where the message will be delivered.
In SMTP parlance, this is called the message's envelope. On the protocol level, you connect to the server, then tell it who the message is from (MAIL FROM: SMTP verb) and who to send it to (RCPT TO:), then separately transmit the message itself (DATA) with headers and body as one oblique string blob.
The modern smtplib simplifies the Python side of this by providing a send_message method which actually sends to the recipients specified in the message's headers.
The modern email library provides an EmailMessage object which replaces all the various individual MIME types which you had to use in the past to assemble a message from smaller parts. You can add attachments without separately constructing them, and build various more complex multipart structures if you need to, but you normally don't have to. Just create a message and populate the parts you want.
Notice that the following is heavily commented; on the whole, the new EmailMessage API is more succinct and more versatile than the old API.
from email.message import EmailMessage
msg = EmailMessage()
# This example uses explicit strings to emphasize that
# that's what these header eventually get turned into
msg["From"] = "me#example.org"
msg["To"] = "main.recipient#example.net, other.main.recipient#example.org"
msg["Cc"] = "secondary#example.com, tertiary#example.eu"
msg["Bcc"] = "invisible#example.int, undisclosed#example.org.au"
msg["Subject"] = "Hello from the other side"
msg.set_content("This is the main text/plain message.")
# You can put an HTML body instead by adding a subtype string argument "html"
# msg.set_content("<p>This is the main text/html message.</p>", "html")
# You can add attachments of various types as you see fit;
# if there are no other parts, the message will be a simple
# text/plain or text/html, but Python will change it into a
# suitable multipart/related or etc if you add more parts
with open("image.png", "rb") as picture:
msg.add_attachment(picture.read(), maintype="image", subtype="png")
# Which port to use etc depends on the mail server.
# Traditionally, port 25 is SMTP, but modern SMTP MSA submission uses 587.
# Some servers accept encrypted SMTP_SSL on port 465.
# Here, we use SMTP instead of SMTP_SSL, but pivot to encrypted
# traffic with STARTTLS after the initial handshake.
with smtplib.SMTP("smtp.example.org", 587) as server:
# Some servers insist on this, others are more lenient ...
# It is technically required by ESMTP, so let's do it
# (If you use server.login() Python will perform an EHLO first
# if you haven't done that already, but let's cover all bases)
server.ehlo()
# Whether or not to use STARTTLS depends on the mail server
server.starttls()
# Bewilderingly, some servers require a second EHLO after STARTTLS!
server.ehlo()
# Login is the norm rather than the exception these days
# but if you are connecting to a local mail server which is
# not on the public internet, this might not be useful or even possible
server.login("me.myself#example.org", "xyzzy")
# Finally, send the message
server.send_message(msg)
The ultimate visibility of the Bcc: header depends on the mail server. If you want to be really sure that the recipients are not visible to each other, perhaps don't put a Bcc: header at all, and separately enumerate the envelope recipients in the envelope like you used to have to with sendmail (send_message lets you do that too, but you don't have to if you just want to send to the recipients named in the headers).
This obviously sends a single message to all recipients in one go. That is generally what you should be doing if you are sending the same message to a lot of people. However, if each message is unique, you will need to loop over the recipients and create and send a new message for each. (Merely wishing to put the recipient's name and address in the To: header is probably not enough to warrant sending many more messages than required, but of course, sometimes you have unique content for each recipient in the body, too.)
you can try this when you write the recpient emails on a text file
from email.mime.text import MIMEText
from email.header import Header
import smtplib
f = open('emails.txt', 'r').readlines()
for n in f:
emails = n.rstrip()
server = smtplib.SMTP('smtp.uk.xensource.com')
server.ehlo()
server.starttls()
body = "Test Email"
subject = "Test"
from = "me#example.com"
to = emails
msg = MIMEText(body,'plain','utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = Header(from, 'utf-8')
msg['To'] = Header(to, 'utf-8')
text = msg.as_string()
try:
server.send(from, emails, text)
print('Message Sent Succesfully')
except:
print('There Was An Error While Sending The Message')
There are a lot of answers on here that are technically or partially correct. After reading everyone's answers, I came up with this as a more solid/universal email function. I have confirmed it works and you can pass HTML or plain text for the body. Note that this code does not include attachment code:
import smtplib
import socket
# Import the email modules we'll need
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
#
# #param [String] email_list
# #param [String] subject_line
# #param [String] error_message
def sendEmailAlert(email_list="default#email.com", subject_line="Default Subject", error_message="Default Error Message"):
hostname = socket.gethostname()
# Create message
msg = MIMEMultipart()
msg['Subject'] = subject_line
msg['From'] = f'no-reply#{hostname}'
msg['To'] = email_list
msg.attach(MIMEText(error_message, 'html'))
# Send the message via SMTP server
s = smtplib.SMTP('localhost') # Change for remote mail server!
# Verbose debugging
s.set_debuglevel(2)
try:
s.sendmail(msg['From'], msg['To'].split(","), msg.as_string())
except Exception as e:
print(f'EMAIL ISSUE: {e}')
s.quit()
This can obviously be modified to use native Python logging. I am just providing a solid core function. I also can't stress this enough, sendmail() wants a List and NOT a String! Function is for Python3.6+
Try declaring a list variable with all recipients and cc_recipients as strings than looping over them, like this:
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
import smtplib
recipients = ["malcom#example.com","reynolds#example.com", "firefly#example.com"]
cc_recipients=["serenity#example.com", "inara#example.com"]
msg = MIMEMultipart()
msg["Subject"] = "Example"
msg["From"] = "me#example.com"
msg["To"] = ', '.join(recipients)
msg["Cc"] = ', '.join(cc_recipients)
body = MIMEText("example email body")
msg.attach(body)
smtp = smtplib.SMTP("mailhost.example.com", 25)
for recipient in recipients:
smtp.sendmail(msg["From"], recipient, msg.as_string())
for cc_recipient in cc_recipients:
smtp.sendmail(msg["From"], cc_recipient, msg.as_string())
smtp.quit()
For those who wish to send the message with only one 'To' header, the code below solves it. Ensure that your receivers variable is a list of strings.
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = title
msg['From'] = f'support#{config("domain_base")}'
msg['To'] = "me"
message_content += f"""
<br /><br />
Regards,<br />
Company Name<br />
The {config("domain_base")} team
"""
body = MIMEText(message_content, 'html')
msg.attach(body)
try:
smtpObj = smtplib.SMTP('localhost')
for r in receivers:
del msg['To']
msg['To'] = r #"Customer /n" + r
smtpObj.sendmail(f"support#{config('domain_base')}", r, msg.as_string())
smtpObj.quit()
return {"message": "Successfully sent email"}
except smtplib.SMTPException:
return {"message": "Error: unable to send email"}
To send email to multiple recipients add receivers as list of email id.
receivers = ['user1#email.com', 'user2#email.com', 'user3#email.com']
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
smtp_server = 'smtp-example.com'
port = 26
sender = 'user#email.com'
debuglevel = 0
# add receivers as list of email id string
receivers = ['user1#email.com', 'user2#email.com', 'user3#email.com']
message = MIMEMultipart(
"mixed", None, [MIMEImage(img_data, 'png'), MIMEText(html,'html')])
message['Subject'] = "Token Data"
message['From'] = sender
message['To'] = ", ".join(receivers)
try:
server = smtplib.SMTP('smtp-example.com')
server.set_debuglevel(1)
server.sendmail(sender, receivers, message.as_string())
server.quit()
# print(response)
except BaseException:
print('Error: unable to send email')

python: how to send mail with TO, CC and BCC?

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.)
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 = 'buffy#sunnydale.k12.ca.us'
cc = ['alexander#sunydale.k12.ca.us','willow#sunnydale.k12.ca.us']
bcc = ['chairman#slayerscouncil.uk']
fromaddr = 'giles#sunnydale.k12.ca.us'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %s\r\n" % fromaddr
+ "To: %s\r\n" % toaddr
+ "CC: %s\r\n" % ",".join(cc)
+ "Subject: %s\r\n" % message_subject
+ "\r\n"
+ 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 = "user63503#gmail.com"
to = "someone#gmail.com"
cc = "anotherperson#gmail.com,someone#yahoo.com"
bcc = "bccperson1#gmail.com,bccperson2#yahoo.com"
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()
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'] = blind.email#adrress.com
Or
msg = "From: from.email#address.com" +
"To: to.email#adress.com" +
"BCC: hidden.email#address.com" +
"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.
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 = 'buffy#sunnydale.k12.ca.us'
cc = ['alexander#sunydale.k12.ca.us','willow#sunnydale.k12.ca.us']
bcc = ['chairman#slayerscouncil.uk']
fromaddr = 'giles#sunnydale.k12.ca.us'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %s\r\n" % fromaddr
+ "To: %s\r\n" % toaddr
+ "CC: %s\r\n" % ",".join(cc)
# don't add this, otherwise "to and cc" receivers will know who are the bcc receivers
# + "BCC: %s\r\n" % ",".join(bcc)
+ "Subject: %s\r\n" % message_subject
+ "\r\n"
+ 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()
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: abc#company.com
CC: xyz#company.com
BCC: boss#company.com
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()
https://docs.python.org/3.6/library/email.examples.html
It did not worked for me until i created:
#created cc string
cc = ""someone#domain.com;
#added cc to header
msg['Cc'] = cc
and than added cc in recipient [list] like:
s.sendmail(me, [you,cc], msg.as_string())
None of the above things worked for me as I had multiple recipients both in 'to' and 'cc'. So I tried like below:
recipients = ['abc#gmail.com', 'xyz#gmail.com']
cc_recipients = ['lmn#gmail.com', 'pqr#gmail.com']
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())

Categories

Resources