sendgrid how to track an individual email - python

I am sending emails via sendgrid and would like to track the status of an email.
client = sendgrid.SendGridClient(username_or_apikey=my_key)
msg = sendgrid.Mail()
msg.add_to('a#foo.com')
msg.set_html('<div> hello there </div>')
msg.set_from('b#foo.com')
msg.set_subject('test sendgrid subject')
resp = client.send(msg)
The response object I am getting back is simply (200, '{"message":"success"}'). I was hoping to get back some for of email id.
I know sendgrid has webhooks, but how do I associate a sg_message_id with an email that I sent?

You can generate unique arguments on a per mail basis that go into the SMTP API JSON string and are included in status messages to webhooks.
More info at this page: https://sendgrid.com/docs/API_Reference/SMTP_API/unique_arguments.html

Related

How to use Mailgun's recipient-variables with Django SMTP mail backend?

How can I properly send batch/bulk/mass emails using MailGun in Django using SMTP protocol?
What I've tried so far?
I am using django.core.mail.backends.smtp.EmailBackend as my EMAIL_BACKEND
and this is the code snippet that I have tried to send the emails.
from django.core.mail import EmailMultiAlternatives
import json
to_emails = [
"mail_1#example.com",
"mail_2#example.com",
"mail_3#example.com",
"mail_4#example.com",
"jerinpetergeorge#gmail.com",
]
mail = EmailMultiAlternatives(
subject="Hey - %recipient.name%",
body="Hey %recipient.name%,\n\nThis is just a batch email test!!!",
from_email="JPG <me#somehost.com>",
to=to_emails,
)
recipient_variables = {
address: {"name": address} for address in to_emails
}
mail.extra_headers["X-Mailgun-Recipient-Variables"] = json.dumps(recipient_variables)
response = mail.send()
print(response)
and I've got the mail as below,
As we can see, the to attribute is filled with all email addresses, which is not what I am expecting.
So, how can I tell the Mailgun/Django to parse my variables properly in order to make the emails looks more personal?
Notes
I prefer to use SMTP protocol
I've tried the REST APIs of Mailgun and it was a success (but, I prefer SMTP)
I found django-anymail and seems it has the feature. But, It also uses the APIs (correct me if I am wrong)
Update-1
Updated the to argument to to="%recipient%" But, got
TypeError: "to" argument must be a list or tuple
Updated the to argument to to=["%recipient%"] But, got
smtplib.SMTPRecipientsRefused: {'=?utf-8?q?=25recipient=25?=': (501, b'Invalid command or cannot parse to address')}
As we can see, the to attribute is filled with all email addresses, which is not what I am expecting.
It is not properly supported with SMTP by Mailgun.
However, relying on the (unintuitive) implementation of BCC in Mailgun, there is a workaround:
mail = EmailMultiAlternatives(
subject="Hey - %recipient.name%",
body="Hey %recipient.name%,\n\nThis is just a batch email test!!!",
from_email="JPG <me#somehost.com>",
# to=to_emails, # Replace this
bcc=to_emails, # with this
)
recipient_variables = {
address: {"name": address} for address in to_emails
}
mail.extra_headers["To"] = "%recipient%" # Add this
mail.extra_headers["X-Mailgun-Recipient-Variables"] = json.dumps(recipient_variables)
Reference: https://stackoverflow.com/questions/37948729/mailgun-smtp-batch-sending-with-recipient-variables-shows-all-recipients-in-to-field
Why does to=["%recipient%"] not work with SMTP?
It's the standard in the protocol.
From https://documentation.mailgun.com/_/downloads/en/latest/pdf/:
SMTP send will error with “cannot parse to address” or “cannot parse from address” if the provided email address fails syntax checks in accordance with RFC5321, RFC5322, RFC6854.
What to do for proper support of Batch Sending with Mailgun?
Use the API.
From https://stackoverflow.com/questions/30787399/laravel-5-sending-group-emails (multiposted to https://laracasts.com/discuss/channels/laravel/sending-email-to-1000s-of-reciepents):
So far, I have created an array of recipient email addresses, sent the email to a webmaster type address, and included the end recipients in BCC
While this works, it's not ideal.
Rather than using Laravel's built in Mail, I elected to use Mailgun's API (specifically batch sending) directly
This also allows me to access unique recipient variables within my email template
(It's not specific to Laravel/PHP, but to SMTP via Mailgun.)
What do you mean by "unintuitive" implementation of BCC in Mailgun?
Mailgun effectively personalises the email for each BCC recipient using recipient-variables.
From https://github.com/mailgun/mailgun-js-boland/issues/89:
the bcc person is receiving the email as it was addressed to them instead of being part of the bcc
This causes a separate issue when you actually want BCC recipients to get the same content.
From https://stackoverflow.com/questions/48887866/bcc-in-mailgun-batch-send-does-not-include-substitutions:
In the copy sent to the bcc address, the recip_vars substitution has not been made.
According to the good people at Mailgun, this is not possible, at least in the current release of the service.

Get list of emails (Sender's Email, Subject and Body) between given dates through Gmail API in Python

I am working on a project that requires a JSON file response through Gmail API which contains a list of all the emails (Sender's Info, Subject, and Body) between given dates. Then that JSON file will be processed as needed.
I'm not sure how to generate a request that could provide me with the required JSON file using Gmail API through Python.
I'm a beginner, Please help me.
Assuming that you have gone through OAuth and built the service (if not, check the quickstart), you have to do the following:
Call users.messages.list, using the parameter q to filter your messages by date. This q uses the same syntax as in Gmail UI: see Search operators you can use with Gmail. For example, if you wanted to retrieve your messages from the first 9 months in 2020, you would do this:
user_id = "me"
searchFilter = "after:2020/01/01 before:2020/10/01"
messages = service.users().messages().list(userId=user_id, q=searchFilter).execute()
When listing messages, only the id and the threadId are populated. In order to get the full message resource for all these messages, you should loop through them and call users.messages.get for each message, using its id:
for message in messages["messages"]:
messageId = message["id"]
message = service.users().messages().get(userId=user_id, id=messageId).execute()
For each of these retrieved messages, you want to get the subject, body and sender's email. Subject and sender's email can be found on the message headers. You should loop through the headers and look for one named Subject and another one named From. See these answers for more info: Python: how to get the subject of an email from gmail API, Get sender email from gmail-api. Regarding the body, it is to be found at ["payload"]["body"]. See this answer: How to retrieve the whole message body using Gmail API (python).
Reference:
Searching for Messages
REST Resource: users.messages
list(userId=*, labelIds=None, q=None, pageToken=None, maxResults=None, includeSpamTrash=None)
get(userId=, id=, format=None, metadataHeaders=None)

How do I know if a envelope have reach the recipient email?

I am sending envelopes from a template to some recipients, and getting the envelope id like this:
while i < len(excel_signers):
signers = {"signer_name": excel_signers[i][2], "signer_email": excel_signers[i][3], "cc_email": "emailcc#gmail.com", "cc_name": "Responsable prueba"}
# to the template
signer = TemplateRole(email=signers["signer_email"], name=signers["signer_name"], role_name="signer")
# Create a cc template role.
cc = TemplateRole(email=signers["cc_email"], name=signers["cc_name"], role_name="cc")
envelope_definition = EnvelopeDefinition(template_id=args["template_id"], template_roles=[signer, cc])
envelope_definition.status = args["status"]
results = envelope_api.create_envelope(args['account_id'], envelope_definition=envelope_definition)
envelope_id = results.envelope_id
excel_signers[i] = np.append(excel_signers[i], [envelope_id]).tolist()
i += 1
but then I want to know if the envelope was correctly delivered, I tried using list_status_change but it shows me "sent" in all of them which is the status I set when I send the envelope. but in the docusign's dashboard it shows "failure", how can I know when an email is not delivered?
To check the status of the recipients in your envelope use the GetRecipientStatus endpoint of the eSignature API
Since you're using Python, you can use the Python SDK's method list_recipients()
It retrieves a lot of data about the recipients in your envelope, including their status.
https://developers.docusign.com/esign-rest-api/guides/concepts/recipients
delivered status means that the email to that recipient was delivered.

Sendgrid - Sending mails to multiple email recipients stored in a variable in Python

I am trying to send an email using SendGrid API in Python.
The below code works well however I am trying to have emails sent to a list of recipients that are stored in a variable user_list
message = Mail(
from_email=('mail#mail.com'),
to_emails= (user_list),
subject= 'subject,
html_content = 'content')
For example if user_list has three emails stored like mail1#mail.com, mail2#mail.com, mail3#mail.com only mail1#mail.com receives the email while the other recipients do not receive the email.
I see only the first email in the variable receives the email and the other emails do not receive the mail.

Can I get the incoming message by using Mailgun?

A use Mailgun to send b a email, after b receive the email and reply to a.If I want to track the email coming from b, How I can get the email?
Here is the code:
1.sendmail.py
from smtplib import SMTP
import requests
login_name = "postmaster#zzb.mailgun.org"
password = "********"
def send_message_via_smtp():
smtp = SMTP("smtp.mailgun.org", 587)
smtp.login(login_name, password)
smtp.sendmail("zebozhuang#163.com","348284770#qq.com", "Subject:mailgun test \n\n just for test.\n\n")
smtp.quit()
if __name__=="__main__":
send_message_via_smtp()
2.create_route.py
import requests
from werkzeug.datastructures import MultiDict
def create_route():
return requests.post(
"https://api.mailgun.net/v2/routes",
auth=("api", "key-9c4-t2q6fouilngjummvtv1rge7t00f2"),
data=MultiDict([("priority", 1),
("description", "Sample route"),
("expression", "match_recipient('.*#qq.com')"),
("action", "forward('qiyazhuang#gmail.com')"),
("action", "stop()")])
)
I create the route and I run the script sendmail.py.After someone who use email 348284770#qq.com reply to the other who use email zebozhuang#163.com, the Gmail
can not receive the message by using the Mailgun method 'forward'.
Could anyone tell me why?
Your messages are likely being delivered. Check the "Logs" tab of the Mailgun Control Panel.
Do you see any entries that look like this:
Routed: .*#qq.com -> qiyazhuang#gmail.com 'SUBJECT HERE'
The "Routed" prefix means that the message triggered a Route. If you're seeing this, and the next log entry is prefixed with "Delivered", the message is likely being delivered to Gmail without issue. Check your Gmail spam folder if you still don't see the messages in the inbox folder.
Disclaimer: I work for Mailgun Support. :)

Categories