Python sends bulk mail from [BCC] insted of [TO], why?

Question:

I am writing a python script that sends every day a bulk email (connected to an outlook.com account) with the body of a news website as an ebook to multiple kindle accounts (that have already whitelisted this outlook account).

This was working so far, but since yesterday the kindle devices couldn’t get the ebooks. I’ve tried a lot and I found out, that the problem is because all the sent emails have the receiver in the BCC part of the email. For some reason since yesterday if the receiver is on BCC, kindle doesn’t receive the email (or process it).

So I am asking, what should I change on my code so I could have the receiver addresses on the [TO] part of the email instead of the [BCC]. I don’t mind if it’s a single email with multiple addresses or multiple single emails, as far as the receiver is not on the BCC.

receiver_email = ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"]

subj = "Issue - "+fullDate
msg = MIMEMultipart('alternative')
msg['Subject'] = subj
msg['From'] = sender_email

msg.attach(MIMEText('Forward this email to your kindle account'))

# Attach the .mobi file
print("Attaching "+epubname)
fp = open(epubname, "rb")
epub_file = MIMEApplication(fp.read())
fp.close()
encoders.encode_base64(epub_file)
epub_file.add_header('Content-Disposition', 'attachment', filename=epubname)
msg.attach(epub_file)

debug = False
if debug:
    print(msg.as_string())
else:
    server = smtplib.SMTP('smtp.office365.com',587)
    server.ehlo()
    server.starttls()
    server.login("##EMAIL##", "##PASSWORD##")
    text = msg.as_string()+ "rn" + message_text
    for x in range(len(receiver_email)):
        email_to = receiver_email[x]
        msg['To'] =  email_to #msg['To'] =  ", ".join(email_to)
        server.sendmail(sender_email, email_to, text.encode('utf-8'))
    server.quit()

I’ve found this question, but with no specific answer unfortunately.

Asked By: MovieAddicted

||

Answers:

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.

The simple and obvious solution is to put all the recipients in msg["to"] instead of msg["bcc"].

Here is a refactoring for Python 3.3+ (the new API was informally introduced already in 3.3).

from email.message import EmailMessage

receiver_email = ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"]

subj = "Issue - "+fullDate
msg = EmailMessage()
msg['Subject'] = subj
msg['From'] = sender_email
msg['To'] =  ", ".join(receiver_email)

msg.set_content('Forward this email to your Kindle account')

with open(epubname, "rb") as fp:
    msg.add_attachment(fp.read())  # XXX TODO: add proper MIME type?

debug = False
if debug:
    print(msg.as_string())
else:
    with smtplib.SMTP('smtp.office365.com',587) as server:
        server.ehlo()
        server.starttls()
        server.login("##EMAIL##", "##PASSWORD##")
        server.send_message(msg)

This sends a single message to all the recipients; this means they can see each others’ email addresses if they view the raw message. You can avoid that by going back to looping over the recipients and sending one message for each, but you really want to avoid that if you can.

As an aside, you don’t need range if you don’t care where you are in the list. The idiomatic way to loop over a list in Python is simply

for email_to in receiver_email:
    ...
Answered By: tripleee