0

So I am sending my email using sendgrid personalization something like this:

message = {
            "personalizations": context["personalizations"],
            "from": {"email": context["sender_email"]},
            "subject": context["subject"],
            "content": [{"type": MimeType.html, "value": context["body"]}],
            "reply_to": {"email": context["reply_to"]}
        }
sg = SendGridAPIClient(os.environ.get("SENDGRID_API_KEY"))
sg.send(message)

Here context["personalization"] is an object as below:

{
            "to": [{"email": applicant.email}],
            "custom_args": {
                "email_id": str(correspondance.id),
                "env": settings.ENVIRONMENT
            }
}

Sending and receiving the emails work fine. The problem is that I can't send an email as a reply to some email. Like a user sends me an email which I receive through sendgrid's inbound parse. Now I want to reply to the email I received.

A solution I found on the internet was that I have to add an 'in_reply_to' ID which I receive as Message_ID in inbound parse but that didn't work. I did something like this:

message = {
            "personalizations": context["personalizations"],
            "from": {"email": context["sender_email"]},
            "subject": context["subject"],
            "content": [{"type": MimeType.html, "value": context["body"]}],
            "reply_to": {"email": context["reply_to"]},
            "in_reply_to": message_id
        }
sg = SendGridAPIClient(os.environ.get("SENDGRID_API_KEY"))
sg.send(message)

Here the message_id is Message_ID I received in the inbound email's json.

Ahmad
  • 15
  • 5
  • Does this [previous question and answer help](https://stackoverflow.com/questions/70415956/sendgrid-api-v3-reply-to-a-thread)? – philnash Aug 01 '22 at 07:51
  • @philnash I went through the answer. What I don't get is, how to add headers in my message. I did something like this: message["headers"] = { "In_Reply_To": "<#here comes message id>" } But it doesn't work. Message is an object where I have the from, subject, content, reply_to, etc. – Ahmad Aug 01 '22 at 08:38
  • In [this example](https://github.com/sendgrid/sendgrid-python/blob/main/examples/helpers/mail_example.py) you set a header with `message.header = Header(“Header-Name”, “value”)`. – philnash Aug 01 '22 at 09:19
  • @philnash Saw the code and understood it well. My problem is that I can't use the Mail( ) object for message as I have to do a lot of stuff with my message like adding attachments etc, which I don't know how to do with Mail( ). My message is just an object and not a Mail( ) object. So message.header won't work for me. Do I have another way where I can do something like message["headers"] = {"in_reply_to": "< >" } ???????? – Ahmad Aug 01 '22 at 09:37
  • I would recommend looking into the example, there's a [kitchen sink function](https://github.com/sendgrid/sendgrid-python/blob/main/examples/helpers/mail_example.py#L137) that uses all of the options that you shows you how that works. – philnash Aug 01 '22 at 11:28

1 Answers1

1

What have worked best for me is setting the References header to an outbound mail to instruct email clients to create a thread.

Writers use References to indicate that a message has a parent. The last identifier in References identifies the parent. So the References header is a space separated list of message IDs wrapped by <> in the following format:

"<MESSAGE_ID>"

You should check wether SendGrid already wraps the message you got from your inbound parse endpoint and then append it to the references string.

import sendgrid
import os
from sendgrid.helpers.mail import Mail, Email, To, Content

previously_received_mail_id = "<abc@email.com>"

references = "" + previously_received_mail_id # empty in your case as its the first reply
sg = sendgrid.SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))
from_email = Email("test@example.com")  # Change to your verified sender
to_email = To("test@example.com")  # Change to your recipient
subject = "Sending with SendGrid is Fun"
content = Content("text/plain", "and easy to do anywhere, even with Python")
mail = Mail(from_email, to_email, subject, content)
mail.personalizations[0].add_header(Header("References",references))
# Get a JSON-ready representation of the Mail object
mail_json = mail.get()

# Send an HTTP POST request to /mail/send
response = sg.client.mail.send.post(request_body=mail_json)
print(response.status_code)
print(response.headers)
Karl R. Gharios
  • 153
  • 1
  • 6
  • Saw the code and understood it well. My problem is that I can't use the Mail( ) object for message as I have to do a lot of stuff with my message like adding attachments etc, which I don't know how to do with Mail( ). My message is just an object and not a Mail( ) object. So message.header won't work for me. Do I have another way where I can do something like message["headers"] = {"in_reply_to": "< >" } ???????? – Ahmad Aug 01 '22 at 09:39
  • Yes you should be able to do this in the following way in your case `context["personalizations"][0]['headers'] = {"in_reply_to": "" , "References": ""}` – Karl R. Gharios Aug 01 '22 at 12:04
  • So I did exactly the way you told me. It just never works and the email is always sent as a new thread. I'm stuck at this and can't move forward an inch. Just before the message object in my code, I added this: context["personalizations"][0]['headers'] = { 'in_reply_to': ""} Looks good to me but doesn't work. – Ahmad Aug 03 '22 at 05:16
  • Try using the References header as indicated in the answer: Example: context["personalizations"][0]['headers'] = { 'References': ""} – Karl R. Gharios Aug 03 '22 at 08:07
  • So I did it and added References and In-Reply-To in my headers. Fortunately, when I go to the 'Show Original' in Gmail, the headers really do have the References and In-Reply-To. However, it still never appends like a reply and always becomes a new thread. What am I doing wrong?? Is it about the subject of my reply email? – Ahmad Aug 04 '22 at 06:12