2

Please, in python3 and sendgrid I need to send an email to multiple addresses in BCC way. I have these emails on a list. I'm trying like this with Personalization:

import os
import json
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, Personalization, From, To, Cc, Bcc

recips = ['email1@gmail.com', 'email2@gmail.com', 'email2@gmail.com']

new_email = Mail(from_email='emailsender@gmail.com', 
              to_emails = 'one_valid_email@gmail.com',
              subject= "email subject", 
              html_content="Hi<br><br>This is a test")

personalization = Personalization()
for bcc_addr in recips:
    personalization.add_bcc(Bcc(bcc_addr))

new_email.add_personalization(personalization)

try:
    sg = SendGridAPIClient('API_KEY')
    response = sg.send(new_email)
    print(response.status_code)
    print(response.body)
    print(response.headers)
except Exception as e:
    print(e.to_dict)

In a test with real email addresses an error appears: HTTP Error 400: Bad Request, with dictionary: {'errors': [{'message': 'The to array is required for all personalization objects, and must have at least one email object with a valid email address.', 'field': 'personalizations.0.to', 'help': 'http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.personalizations.to'}]}

Please does anyone know why?

Reinaldo Chaves
  • 965
  • 4
  • 16
  • 43

2 Answers2

4

Twilio SendGrid developer evangelist here.

When adding multiple bccs to your personalization object, you need to loop through the email addresses and add them each individually.

import os
import json
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, Personalization, Bcc, To

recips = ['email1@gmail.com', 'email2@gmail.com', 'email2@gmail.com']

new_email = Mail(
  from_email='emailsender@gmail.com', 
  subject= "email subject", 
  html_content="Hi<br><br>This is a test"
)

personalization = Personalization()

personalization.add_to(To('emailsender@gmail.com'))

for bcc_addr in recips:
    personalization.add_bcc(Bcc(bcc_addr))

new_email.add_personalization(personalization)

try:
    sg = SendGridAPIClient('API_KEY')
    response = sg.send(new_email)
    print(response.status_code)
    print(response.body)
    print(response.headers)
except Exception as e:
    print(e.to_dict)

Check out this mail example for how to use the various parts of personalizations.

philnash
  • 70,667
  • 10
  • 60
  • 88
  • Hello thank you so much. I tried like this, but it gave an error: mock_personalization = Personalization() for bcc_addr in recips: mock_personalization.add_bcc(bcc_addr) -> AttributeError: 'str' object has no attribute 'get' Actually I need to send a simple email. For regular email it works, but for BCC I'm finding it very difficult – Reinaldo Chaves Feb 17 '22 at 14:21
  • 1
    It looks like you have copied the code from the example and not from my answer above. Perhaps you can share your current code by editing your question and I can take a look? – philnash Feb 18 '22 at 02:27
  • Thanks. I changed the code above for you to see. Well, for the example of Github I'll have to change the entire code - even the format of my email. I learned to use Sendgrid a few days ago, I will try to read and learn in the next few days – Reinaldo Chaves Feb 18 '22 at 10:44
  • 1
    I've updated my answer with more code, have another look. Notice how, when I `add_bcc` I pass a new `Bcc` object initialized with the email from the list. I also add the personalization to the mail object. – philnash Feb 20 '22 at 06:37
  • Thank you again. Now the error appears in the send block in the try, showing the Exception - HTTP Error 400: Bad Request, i.e. maybe the request was somehow incorrect. Do you know what it could be? I tested sending without the BCC part and it worked normal, with the same code – Reinaldo Chaves Feb 20 '22 at 19:30
  • 1
    Error messages from the API actually come with more information about what went wrong within the body of the response. You can [see this in python by calling `to_dict` on the error message](https://github.com/sendgrid/sendgrid-python/blob/main/TROUBLESHOOTING.md#error-messages). Try `print(e.to_dict)` and see what the API is telling you. – philnash Feb 21 '22 at 00:17
  • Thanks. The dictionary shows this: {'errors': [{'message': 'The to array is required for all personalization objects, and must have at least one email object with a valid email address.', 'field': 'personalizations.0.to', 'help': 'http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.personalizations.to'}]} – Reinaldo Chaves Feb 21 '22 at 02:22
  • 1
    So, you need at least one To address to send the email to. If you are trying to keep all recipients in the bcc private from each other then you could set the To address to an email address on your own domain. Or, you could just send an email to each recipient rather than sending it all as one email. What are you trying to achieve here? – philnash Feb 21 '22 at 02:27
  • Thanks. Got it, I changed the code and include a valid email in new_email (to_emails), with address to appear. But the same error appeared – Reinaldo Chaves Feb 21 '22 at 11:21
  • I created a free service to verify legislative proposals, so every day I send it to anyone who fills out a form. It's the same email for everyone, so I only need to send one - but I don't want to show people's email addresses – Reinaldo Chaves Feb 21 '22 at 11:24
  • 1
    Ah, I wasn't reading the error clearly enough. The to address must be added to the personalization, not to the constructor. I've updated the code in the answer, try it now. – philnash Feb 21 '22 at 23:09
  • Thanks. With a real email, the command (personalization.add_to('emailsender@gmail.com')) show this error: AttributeError: 'str' object has no attribute 'substitutions' – Reinaldo Chaves Feb 22 '22 at 12:12
  • 1
    Bah, import To from SendGrid helpers and wrap the string email in it. Sorry. I’ll update my answer again. – philnash Feb 22 '22 at 12:21
0

Without using Personalization, we can pass a list of BCC objects to .bcc method.

Ex:

sg = SendGridAPIClient(api_key=self.__api_key)
mailObj = Mail(self.from_mail, self.to_mail, self.subject)
bcc_list = ['email1@gmail.com', 'email2@gmail.com', 'email2@gmail.com']
for bcc_addr in bcc_list:
    li.append(Bcc(bcc_addr))
        mailObj.bcc = li
mail_settings = MailSettings()
mail_settings.bcc_settings = BccSettings(False)
mail_settings.sandbox_mode = SandBoxMode(False)
mailObj.mail_settings = mail_settings
sg.send(mailObj)
PAC
  • 1,664
  • 1
  • 18
  • 24