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

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.

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.

Emails to recipients are not being sent using docusign sender view api where status is changed to sent

This is my sender view from where i create envelope as draft and open it in edit sender view and send it but recipients are not getting emails
#app.route('/sender', methods = ['POST'])
def sender1():
if request.method == 'POST':
name = request.form['name']
email = request.form['email']
filename1 = pdf2.save(request.files['file'])
subject = request.form['subject']
body = request.form['body']
path1 = pdf2.path(filename1)
url1 = pdf2.url(filename1)
remoteFile1 = urllib.request.urlopen(url1).read()
login_information = client.login_information()
signers = [
models.Signer(
email=email,
name=name,
recipientId=1,
clientUserId=str(uuid.uuid4()), # Something unique in your database.
emailSubject=subject,
emailBody=body,
supportedLanguage='en')]
session['email']=email
session['name']=name
session['subject']=subject
session['body']=body
with open(path1, 'rb') as pdf:
envelope = models.Envelope(
documents=[
models.Document(
name='document.pdf',
documentId=1,
data=pdf,
)
],
emailSubject=subject,
emailBlurb='request for signing',
status=models.Envelope.STATUS_CREATED,
recipients=signers,
)
client.create_envelope_from_documents(envelope)
url = client.sender_edit_view(envelope.envelopeId)
models.Envelope(status=models.Envelope.STATUS_SENT)
data=url['url']
#data = data.replace('send=1','send=0')
#print(data)
return redirect(data)
This is the sender edit view to call api
def sender_edit_view(self,envelopeId=''):
"""POST to {account}/envelopes/{envelopeId}/views/recipient.
This is the method to start embedded signing for recipient.
Return JSON from DocuSign response.
"""
authenticationMethod=None
returnUrl='http://127.0.0.1:5000/callback'
if not self.account_url:
self.login_information()
url = '/accounts/{accountId}/envelopes/{envelopeId}/views/correct' \
.format(accountId=self.account_id,envelopeId=envelopeId,
)
if authenticationMethod is None:
authenticationMethod = 'email'
data = {
'authenticationMethod': authenticationMethod,
'returnUrl': returnUrl,
}
return self.post(url, data=data, expected_status_code=201)
How can i send email to recipients using the api. i have tried using the create correct api also and tried to update recipients but emails are still not being sent.
The problem isn't the sender view, the problem is that the signer is being marked as an embedded signer (no email invite to the signing ceremony is sent).
Your recipients aren't receiving email invitations because you are setting the clientUserId attribute for them.
Setting clientUserId causes a number of effects:
The signer becomes an embedded signer.
An email invitation to a signing ceremony is not sent.
The signer will sign via an embedded signing ceremony after you create one for them.
The metadata of the value of the clientUserId setting is maintained with the signer for your app's purposes.
To solve the problem:
Don't set the clientUserId attribute
If you want to maintain metadata between the receipient record in DocuSign and your own app, use the recipient's customFields attribute.
(This doesn't apply in your use case since you're using a uuid. But it may apply to other readers of this answer.)

django sending email (delivery report)

I'm a beginner who is trying to use "Django" to send mail to multiple recipients.
How could I get a delivery report that tells me that: "the mail delivered to recipients a,b,c and d".
"The delivery failed to recipient (e) because his mail box is full".
The delivery failed to recipient (f) because your message considered as spam".
The return value of send_mail() is a boolean that tells whether or not the message was successfully sent.
You can write a function that iterates through the list of recipients, calls send_mail(), appends the successful deliveries to one list, and appends the unsuccessful recipients to another. Then you can write messages using that information. Something like this:
recipients = [ ... ] # list of people you're sending the email to
successful_recipients = []
unsuccessful_recipients = []
for recipient in recipients:
if send_mail( ... ):
successful_recipients.append(recipient)
else:
unsuccessful_recipients.append(recipient)
It may be difficult/impossible to get the cause of failure, because Django isn't providing you with that information.
https://docs.djangoproject.com/en/1.11/topics/email/

sendgrid how to track an individual email

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

How to receive mail using python

I would like to receive email using python. So far I have been able to get the subject but not the body. Here is the code I have been using:
import poplib
from email import parser
pop_conn = poplib.POP3_SSL('pop.gmail.com')
pop_conn.user('myusername')
pop_conn.pass_('mypassword')
#Get messages from server:
messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
# Concat message pieces:
messages = ["\n".join(mssg[1]) for mssg in messages]
#Parse message intom an email object:
messages = [parser.Parser().parsestr(mssg) for mssg in messages]
for message in messages:
print message['subject']
print message['body']
pop_conn.quit()
My issue is that when I run this code it properly returns the Subject but not the body. So if I send an email with the subject "Tester" and the body "This is a test message" it looks like this in IDLE.
>>>>Tester >>>>None
So it appears to be accurately assessing the subject but not the body, I think it is in the parsing method right? The issue is that I don't know enough about these libraries to figure out how to change it so that it returns both a subject and a body.
The object message does not have a body, you will need to parse the multiple parts, like this:
for part in message.walk():
if part.get_content_type():
body = part.get_payload(decode=True)
The walk() function iterates depth-first through the parts of the email, and you are looking for the parts that have a content-type. The content types can be either text/plain or text/html, and sometimes one e-mail can contain both (if the message content_type is set to multipart/alternative).
The email parser returns an email.message.Message object, which does not contain a body key, as you'll see if you run
print message.keys()
What you want is the get_payload() method:
for message in messages:
print message['subject']
print message.get_payload()
pop_conn.quit()
But this gets complicated when it comes to multi-part messages; get_payload() returns a list of parts, each of which is a Message object. You can get a particular part of the multipart message by using get_payload(i), which returns the ith part, raises an IndexError if i is out of range, or raises a TypeError if the message is not multipart.
As Gustavo Costa De Oliveir points out, you can use the walk() method to get the parts in order -- it does a depth-first traversal of the parts and subparts of the message.
There's more about the email.parser module at http://docs.python.org/library/email.message.html#email.message.Message.
it also good return data in correct encoding in message contains some multilingual content
charset = part.get_content_charset()
content = part.get_payload(decode=True)
content = content.decode(charset).encode('utf-8')
Here is how I solved the problem using python 3 new capabilities:
import imaplib
import email
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(username, password)
mail.select(readonly=True) # refresh inbox
status, message_ids = mail.search(None, 'ALL') # get all emails
for message_id in message_ids[0].split(): # returns all message ids
# for every id get the actual email
status, message_data = mail.fetch(message_id, '(RFC822)')
actual_message = email.message_from_bytes(message_data[0][1])
# extract the needed fields
email_date = actual_message["Date"]
subject = actual_message["Subject"]
message_body = get_message_body(actual_message)
Now get_message_body is actually pretty tricky due to MIME format. I used the function suggested in this answer.
This particular example works with Gmail, but IMAP is a standard protocol, so it should work for other email providers as well, possibly with minor changes.
if u want to use IMAP4. Use outlook python library, download here : https://github.com/awangga/outlook
to retrieve unread email from your inbox :
import outlook
mail = outlook.Outlook()
mail.login('emailaccount#live.com','yourpassword')
mail.inbox()
print mail.unread()
to retrive email element :
print mail.mailbody()
print mail.mailsubject()
print mail.mailfrom()
print mail.mailto()

Categories