How to replace body text in MIME message?

75
April 07, 2022, at 11:30 PM

I am trying to send an automated email to various users with the lake that they are subscribed to changing:

message = MIMEMultipart()
message['From'] = email  # Sender
message['Subject'] = "Algae Bloom Alert\n"  # Subject
for user in subscriber_dict:
    sms_gateway = subscriber_dict[user]['email']
    message['To'] = subscriber_dict[user]['email']
    body = (
        f"This is an algae alert for Lake {subscriber_dict[user]['lake']}.\n\n"
        f"Sent at {sent_time_date} {sent_time_time}"
    )
    message.attach(MIMEText(body, 'plain'))  # Attaching body to email
    sms = message.as_string()
    server.sendmail(email, sms_gateway, sms)
        
    # Reset body here ideally
    print(f"Email sent at {formatted_time}")

However, when the emails are sent, each successive email contains the contents from the emails prior to it. Does anyone know how I can reset the body so that I am not attaching to the previous bodies but rather writing new ones?

Answer 1

Don't reuse the same message. Create a new one inside the loop.

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.

from email.message import EmailMessage
...
for user in subscriber_dict:
    message = EmailMessage()
    message['From'] = email
    message['Subject'] = "Algae Bloom Alert"  # no \n
    message['To'] = subscriber_dict[user]['email']
    message.set_content(
        f"This is an algae alert for Lake {subscriber_dict[user]['lake']}.\n\n"
        f"Sent at {sent_time_date} {sent_time_time}"
    )
    server.send_message(message)
    print(f"Email sent at {formatted_time}")

You might want to avoid calling your sender variable email to avoid shadowing the email library, although in this example it doesn't really matter.

With .set_content() you could actually reuse the same message over and over but there is no actual benefit from that, and the problems if you fail to replace some part of an earlier message by mistake could be ugly. (For example, a typo could cause you to send the same message to the same recipient as many times as you have users!)

Answer 2

Righto - there's no need to keep digging back into subscriber_dict. Instead of:

for user in subscriber_dict:
    sms_gateway = subscriber_dict[user]['email']

You can do:

for user in subscriber_dict.values():
    sms_gateway = user['email']

Your for loop is reusing the same message. It should probably create a new one on each loop:

FROM_ADDR = "jake@lakefacts.gov.au"
for user in subscriber_dict.values():
    message = MIMEMultipart()
    message['From'] = FROM_ADDR
    message['To'] = user['email']
    message['Subject'] = "Algae Bloom Alert\n"
    body = (
        f"This is an algae alert for Lake {user['lake']}.\n\n"
        f"Sent at {sent_time_date} {sent_time_time}"
    )
    message.attach(MIMEText(body, 'plain'))
    sms_gateway = user['email']
    sms = message.as_string()
    server.sendmail(email, sms_gateway, sms)
    print(f"Email sent at {formatted_time}")
Rent Charter Buses Company
READ ALSO
MongoMock Python function that inserts list of dictionaries and returns a response

MongoMock Python function that inserts list of dictionaries and returns a response

I am pretty new to mongomock and having some trouble with some examples of it on the internetI am trying to mock a python function that gets passed the db_name and a list of dictionaries to be inserted into a collection

99
Text Comparing Program

Text Comparing Program

I'm making a program where I am supposed to compare text files by returning a list of all the words that come up in the file, and the number of times they come upI have to disregard a list of words called stopwords so they won't be checked for the number...

111
Why won't my Django template display the correct date listed in the database?

Why won't my Django template display the correct date listed in the database?

My model contains a datefield, 'valid_until'Even though an entry contains the date '12/25/2022', the update template literally displays as its contents 'mm/dd/yyyy' when the user tries to modify the date

75
Best way to import custom packages [duplicate]

Best way to import custom packages [duplicate]

I use python for data analysisA lot of pandas

121