boto / boto3

AWS SDK for Python
https://aws.amazon.com/sdk-for-python/
Apache License 2.0
9.06k stars 1.87k forks source link

SES send_raw_email, adding recipients leads to accumlation of To: (or Cc: or Bcc:) in the MultiPartMessage #4332

Open agrawald opened 1 week ago

agrawald commented 1 week ago

Describe the bug

Using boto3 SES send_raw_email method to email to more than 50 recipient. The Bcc (same with To and CC) field is getting accumulated as new entry every time we initialize it.

Regression Issue

Expected Behavior

The msg[Bcc] should be overridden instead of accumulating new Bcc entries as shown in Current ebhaviour.

Current Behavior

The above code will try to send the

Bcc: 1@email.com, ..., 20@email.com

- Second email with another 20 recipient, but the above code will create another Bcc entry with the new 20 recipient email retaining the previous 20 recipient, as shown below,  SES will send 40 emails here but will report 20 emails sent in AWS SES metrics (not sure why)
Bcc: 1@email.com, ..., 20@email.com Bcc: 21@email.com, ..., 40@email.com ``` - Third email with another 20 recipient, but this time again it will add another Bcc entry without overriding the previous Bcc leading to 3 Bcc entries, SES will error out as the recipient list has exceeded the 50 recipient count hard limit ``` Bcc: 1@email.com, ..., 20@email.com Bcc: 21@email.com, ..., 40@email.com Bcc: 41@email.com, ..., 60@email.com ``` ### Reproduction Steps For the below code snippet please assume we have 60 recipient email addresses. We break the recipient list of 60 into 3 chucks of 20 recipients each. And then use the following function send email ```python def send_email_to_20_recipient(self, msg: MIMEMultipart, recipients: []): msg['Bcc'] = ', '.join(recipients) response = self._client.send_raw_email( Source=get_email_from(), RawMessage={ 'Data': msg.as_string(), } ) logger.info(f"Email sent! Message ID {msg.as_string()}") return response.get("MessageId") ``` ### Possible Solution We should not have to delete the `msg['Bcc']` but it should get reinitialized without creating a new entry. **NOT A POSSIBLE SOLUTION BUT A WORKAROUND** Delete the `msg['Bcc']` entry before initializing the recipients. ```python def send_email_to_20_recipient(self, msg: MIMEMultipart, recipients: []): # we must delete msg['Bcc'] every time otherwise it will lead to appending recipients **del msg['Bcc']** msg['Bcc'] = ', '.join(recipients) response = self._client.send_raw_email( Source=get_email_from(), RawMessage={ 'Data': msg.as_string(), } ) logger.info(f"Email sent! Message ID {msg.as_string()}") return response.get("MessageId") ``` ### Additional Information/Context _No response_ ### SDK version used 1.34.154 ### Environment details (OS name and version, etc.) Ubuntu 22.04.5 LTS
tim-finnigan commented 1 week ago

Thanks for reaching out. The Boto3 send_raw_email command calls the SendRawEmail API, so this issue involves the SES service API rather than Boto3 directly.

The issue with your current approach may be with the MIME headers — have you tried creating a new MIMEMultipart object before sending each email?

Have you also tried using the sesv2 client and send_email command? In the SES Developer Guide there is a Boto3 snippet which may help with your use case: https://docs.aws.amazon.com/ses/latest/dg/send-email-raw.html#send-email-raw-api

If still seeing an issue, can you provide a complete code snippet for reproducing this? And can you also share your debug logs (with any sensitive info redacted) which you can get by adding boto3.set_stream_logger('') to your script?