def get_view(): """Obtains a sending view from DocuSign. The user will then be redirected to the view url Uses the information stored in the session to request the view. Query parameter: send = 0 or 1. See https://goo.gl/aLNjJH RETURNS {err, redirect_url} """ err = False # No problems so far! auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} if not embedded_tagging_key in session: return { "err": "Embedded signing information missing from session! Please re-send." } embedding_info = session[embedded_tagging_key] # Obtain the "sender's view" # See https://docs.docusign.com/esign/restapi/Envelopes/EnvelopeViews/createSender/ return_url = ds_recipe_lib.get_base_url(2) + return_uri data = {"returnUrl": return_url} send = request.args.get('send') # append "/envelopes/{envelopeId}/views/sender" to the baseUrl and use in the request url = auth["base_url"] + '/envelopes/{}/views/sender?send={}'.format( embedding_info["envelopeId"], send) ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling EnvelopeViews:createSender: " + str(e)} status = r.status_code if (status != 201): return ({ 'err': "Error calling DocuSign EnvelopeViews:createSender<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) data = r.json() redirect_url = data['url'] # Update the send parameter in the url # An example url: # https://demo.docusign.net/Member/StartInSession.aspx?StartConsole=1&t=2fABCXYZ6197&DocuEnvelope=2dABCXYZ&send=1 # We search for send=0|1 and replace it per our incoming "send" parameter send_re = re.compile("(\&send=[01])") redirect_url = send_re.sub("&send={}".format(request.args.get('send')), redirect_url) return {"err": err, "redirect_url": redirect_url}
def get_doc(): """Get a document from DocuSign query parameters: url, fn Returns {err, pdf, filename} """ err = False # No problems so far! auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} uri = request.args.get("url") fn = request.args.get("fn") if not uri: return {"err": "query parameter url is missing!"} # Retrieve file # append the uri parameter to the baseUrl and use in the request url = auth["base_url"] + uri ds_headers = {'Accept': 'Accept: application/pdf', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling EnvelopeViews:createRecipient: " + str(e)} status = r.status_code if (status != 200): return ({'err': "Error retrieving document.<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) # Success! return {"err": err, "pdf": r.content, "filename": fn}
def logs_list(): """Returns log_entries for all current logs that were previously downloaded {"err": an error or false "entries": Array of log_entry log_entry: {file_name: the filename of the entry url: for retrieving the file head: first 1500 bytes of the entry, base64 encoded} } Strategy: parse the log files on the clients. """ global auth auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} entries = [] log_path = get_log_path() log_path_url = ds_recipe_lib.get_base_url( 1) + "/" + log_storage_uri + "/" + account_id_to_dir( auth["account_id"]) + "/" # Walk the dir for i in os.listdir(log_path): if i.endswith(".txt"): entries.append( api_log_item(os.path.join(log_path, i), i, log_path_url)) return {"err": False, "entries": entries}
def get_view(): """Obtains a view from DocuSign. The user will then be redirected to the view url Uses the information stored in the session to request the view. RETURNS {err, redirect_url} """ err = False # No problems so far! auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} if not embedded_signing_key in session: return { "err": "Embedded signing information missing from session! Please re-send." } embedding_info = session[embedded_signing_key] # Obtain the "recipient's view" (In this case, its the signer's view) # See https://docs.docusign.com/esign/restapi/Envelopes/EnvelopeViews/createRecipient/ return_url = ds_recipe_lib.get_base_url(2) + return_uri data = { "authenticationMethod": "Password", # How was this recipient authenticated. Pick from list of values "clientUserId": embedding_info["clientUserId"], "email": embedding_info["email"], "userName": embedding_info["name"], "returnUrl": return_url } # append "/envelopes/{envelopeId}/views/recipient" to the baseUrl and use in the request url = auth["base_url"] + '/envelopes/{}/views/recipient'.format( embedding_info["envelopeId"]) ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return { 'err': "Error calling EnvelopeViews:createRecipient: " + str(e) } status = r.status_code if (status != 201): return ({ 'err': "Error calling DocuSign EnvelopeViews:createRecipient<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) data = r.json() redirect_url = data['url'] return {"err": err, "redirect_url": redirect_url}
def start(): """Sends EnvelopeRecipients: list method Returns r: { err: False, or an error message intro: html introduction to the page url: the url used for the request response: the response body } """ # Ready... # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} if not 'latest_envelope_id' in session: return { "err": "Problem, no envelope ID is available. Please send an envelope with a different recipe, then retry the Envelope Recipient Status recipe." } envelope_id = session['latest_envelope_id'] # # STEP 2 - Create and send the request # # See the docs, https://docs.docusign.com/esign/restapi/Envelopes/EnvelopeRecipients/list # create the url from the baseUrl url = auth[ "base_url"] + "/envelopes/{}/recipients/?include_tabs=true".format( envelope_id) ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling EnvelopeRecipients:list: " + str(e)} status = r.status_code if (status != 200): return ({ 'err': "Error calling DocuSign EnvelopeRecipients:list<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) response = r.json() return { "err": False, "url": url, "intro": intro, "response": json.dumps(response, indent=4, sort_keys=True) }
def get_status(envelope_id): """Fetch the envelope status from DocuSign See https://docs.docusign.com/esign/restapi/Envelopes/Envelopes/get/ Returns {false or the result of the call} """ # Sample data returned from the Envelopes: Get method # { # "status": "completed", # "documentsUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/documents", # "recipientsUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/recipients", # "envelopeUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d", # "emailSubject": "Please sign the NDA package", # "envelopeId": "ed400d38-7765-4ce5-9f50-8652a8c4486d", # "customFieldsUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/custom_fields", # "autoNavigation": "true", # "envelopeIdStamping": "true", # "notificationUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/notification", # "enableWetSign": "true", # "allowMarkup": "false", # "createdDateTime": "2016-06-28T15:57:07.1800000Z", # "lastModifiedDateTime": "2016-06-28T15:57:07.1800000Z", # "deliveredDateTime": "2016-06-28T15:57:33.6270000Z", # "initialSentDateTime": "2016-06-28T15:57:07.7430000Z", # "sentDateTime": "2016-06-28T15:57:33.6270000Z", # "completedDateTime": "2016-06-28T15:57:33.6270000Z", # "statusChangedDateTime": "2016-06-28T15:57:33.6270000Z", # "documentsCombinedUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/documents/combined", # "certificateUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/documents/certificate", # "templatesUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/templates", # "brandId": "3774f432-9d31-40e6-bc6b-6ae30cce334c", # "purgeState": "unpurged", # "is21CFRPart11": "false", # "isSignatureProviderEnvelope": "false" # } auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # append "/envelopes/{envelopeId}" to the baseUrl and use in the request url = auth["base_url"] + '/envelopes/{}'.format(envelope_id) + "?cache_buster={}".format(time.time()) ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return False status = r.status_code if (status != 200): return False result = r.json() result["err"] = False return result
def start(): """Sends Envelopes: listStatusChanges method Returns r: { err: False, or an error message intro: html introduction to the page url: the url used for the request response: the response body } """ # Ready... # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # # STEP 2 - Create and send the request # # See the docs, https://docs.docusign.com/esign/restapi/Envelopes/Envelopes/listStatusChanges/ # We need to set one or more of the following parameters: from_date, envelopeIds and/or transactionIds. # We will set from_date to be yesterday. # # If you're using this method to poll for changes, see "Polling for Current Status" section of # page https://docs.docusign.com/esign/guide/usage/status_and_events.html for a strategy that won't # violate the platform's polling policy. # construct the body of the request yesterday = datetime.date.today() - datetime.timedelta(days=1) yesterday_s = yesterday.strftime ("%Y-%m-%d") # '2016-07-25' # create the url from the baseUrl url = auth["base_url"] + "/envelopes?from_date={}".format(yesterday_s) ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling Envelopes:listStatusChanges: " + str(e)} status = r.status_code if (status != 200): return ({'err': "Error calling DocuSign Envelopes:listStatusChanges<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) response = r.json() return { "err": False, "url": url, "intro": intro, "response": json.dumps(response, indent=4, sort_keys=True) }
def start(): """Sends EnvelopeRecipients: list method Returns r: { err: False, or an error message intro: html introduction to the page url: the url used for the request response: the response body } """ # Ready... # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} if not 'latest_envelope_id' in session: return {"err": "Problem, no envelope ID is available. Please send an envelope with a different recipe, then retry the Envelope Recipient Status recipe."} envelope_id = session['latest_envelope_id'] # # STEP 2 - Create and send the request # # See the docs, https://docs.docusign.com/esign/restapi/Envelopes/EnvelopeRecipients/list # create the url from the baseUrl url = auth["base_url"] + "/envelopes/{}/recipients/?include_tabs=true".format(envelope_id) ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling EnvelopeRecipients:list: " + str(e)} status = r.status_code if (status != 200): return ({'err': "Error calling DocuSign EnvelopeRecipients:list<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) response = r.json() return { "err": False, "url": url, "intro": intro, "response": json.dumps(response, indent=4, sort_keys=True) }
def get_view(): """Obtains a sending view from DocuSign. The user will then be redirected to the view url Uses the information stored in the session to request the view. Query parameter: send = 0 or 1. See https://goo.gl/aLNjJH RETURNS {err, redirect_url} """ err = False # No problems so far! auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} if not embedded_tagging_key in session: return {"err": "Embedded signing information missing from session! Please re-send."} embedding_info = session[embedded_tagging_key] # Obtain the "sender's view" # See https://docs.docusign.com/esign/restapi/Envelopes/EnvelopeViews/createSender/ return_url = ds_recipe_lib.get_base_url(2) + return_uri data = {"returnUrl": return_url} send = request.args.get('send') # append "/envelopes/{envelopeId}/views/sender" to the baseUrl and use in the request url = auth["base_url"] + '/envelopes/{}/views/sender?send={}'.format( embedding_info["envelopeId"], send) ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling EnvelopeViews:createSender: " + str(e)} status = r.status_code if (status != 201): return ({'err': "Error calling DocuSign EnvelopeViews:createSender<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) data = r.json() redirect_url = data['url'] # Update the send parameter in the url # An example url: # https://demo.docusign.net/Member/StartInSession.aspx?StartConsole=1&t=2fABCXYZ6197&DocuEnvelope=2dABCXYZ&send=1 # We search for send=0|1 and replace it per our incoming "send" parameter send_re = re.compile("(\&send=[01])") redirect_url = send_re.sub("&send={}".format(request.args.get('send')), redirect_url) return {"err": err, "redirect_url": redirect_url}
def get_view(): """Obtains a view from DocuSign. The user will then be redirected to the view url Uses the information stored in the session to request the view. RETURNS {err, redirect_url} """ err = False # No problems so far! auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} if not embedded_signing_key in session: return {"err": "Embedded signing information missing from session! Please re-send."} embedding_info = session[embedded_signing_key] # Obtain the "recipient's view" (In this case, its the signer's view) # See https://docs.docusign.com/esign/restapi/Envelopes/EnvelopeViews/createRecipient/ return_url = ds_recipe_lib.get_base_url(2) + return_uri data = {"authenticationMethod": "Password", # How was this recipient authenticated. Pick from list of values "clientUserId": embedding_info["clientUserId"], "email": embedding_info["email"], "userName": embedding_info["name"], "returnUrl": return_url } # append "/envelopes/{envelopeId}/views/recipient" to the baseUrl and use in the request url = auth["base_url"] + '/envelopes/{}/views/recipient'.format(embedding_info["envelopeId"]) ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling EnvelopeViews:createRecipient: " + str(e)} status = r.status_code if (status != 201): return ({'err': "Error calling DocuSign EnvelopeViews:createRecipient<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) data = r.json() redirect_url = data['url'] return {"err": err, "redirect_url": redirect_url}
def get_doc(): """Get a document from DocuSign query parameters: url, fn Returns {err, pdf, filename} """ err = False # No problems so far! auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} uri = request.args.get("url") fn = request.args.get("fn") if not uri: return {"err": "query parameter url is missing!"} # Retrieve file # append the uri parameter to the baseUrl and use in the request url = auth["base_url"] + uri ds_headers = { 'Accept': 'Accept: application/pdf', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return { 'err': "Error calling EnvelopeViews:createRecipient: " + str(e) } status = r.status_code if (status != 200): return ({ 'err': "Error retrieving document.<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) # Success! return {"err": err, "pdf": r.content, "filename": fn}
def get_logging_status(): """Returns the logging status of the account Side-effect: initializes logging if it isn't already active Returns: logging_status = { err: False or a problem string. err_code: False or codes eg 'GENERIC', 'PLEASE_AUTHENTICATE', status: string description of the status logging: True / False remaining_entries: integer from the platform, max_entries: integer from the platform } """ global auth auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} logging = logging_updateSettings( ) # returns {err, max_entries, remaining_entries, err_code} if logging['err']: return {"err": logging["err"]} # No API error... if logging["logging"]: logging_activated = "Logging is activated. " else: logging_activated = "Logging is <b>not</b> activated! " status = logging_activated + "{} logging spaces are available out of {} total.".format( logging["remaining_entries"], logging["max_entries"]) return { 'err': False, 'status': status, 'logging': logging["logging"], 'remaining_entries': logging["remaining_entries"], 'max_entries': logging["max_entries"] }
def logs_download(): """Download (and then delete) the logs from DocuSign The logs are stored in files/log/<account_id>/log_<timestamp>_<orig_name> <orig_name> is the original name of the file from the platform. Eg: 00_OK_GetAccountSharedAccess.txt 01_OK_GetFolderList.txt 02_OK_ExecuteLoggedApiBusinessLogic.txt 03_Created_RequestRecipientToken.txt 04_OK_GetEnvelope.txt 05_OK_GetEnvelope.txt 06_OK_SendEnvelope.txt Returns {err: False or a problem string, entries: log_entries, err_code } returns an array of just the new log_entries """ global auth auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} r = logging_do_download() # returns {err, new_entries} return r
def send(): """Creates the envelope as a draft Returns r: { err: False, or an error message html: html output, to be displayed envelope_id: } """ # Ready... # Possibly create some fake people ds_signer1_email = ds_recipe_lib.get_signer_email(ds_signer1_email_orig) ds_signer1_name = ds_recipe_lib.get_signer_name(ds_signer1_name_orig) ds_cc1_email = ds_recipe_lib.get_signer_email(ds_cc1_email_orig) ds_cc1_name = ds_recipe_lib.get_signer_name(ds_cc1_name_orig) # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # # STEP 2 - Create the draft envelope # # construct the body of the request file_contents = open(doc_document_path, "rb").read() # Please use the most accurate and relevant subject line. subject = "Please sign the NDA package" # File contents are provided here # The documents array can include multiple documents, of differing types. # All documents are converted to pdf prior to signing. # The fileExtension field defaults to "pdf". documents = [{ "documentId": "1", "name": doc_document_name, "fileExtension": os.path.splitext(doc_document_path)[1][1:], "documentBase64": base64.b64encode(file_contents) }] # The signing fields # # Invisible (white) Anchor field names for the NDA.pdf document: # * signer1sig # * signer1name # * signer1company # * signer1date # fields = { "signHereTabs": [{ "anchorString": "signer1sig", # Anchored for doc 1 "anchorXOffset": "0", "anchorYOffset": "0", "anchorUnits": "mms", "recipientId": "1", "name": "Please sign here", "optional": "false", "scaleValue": 1, "tabLabel": "signer1sig" }], "fullNameTabs": [{ "anchorString": "signer1name", # Anchored for doc 1 "anchorYOffset": "-6", "fontSize": "Size12", "recipientId": "1", "tabLabel": "Full Name", "name": "Full Name" }] } signers = [{ "email": ds_signer1_email, "name": ds_signer1_name, "recipientId": "1", "routingOrder": "1", "tabs": fields }] ccs = [{ "email": ds_cc1_email, "name": ds_cc1_name, "recipientId": "2", "routingOrder": "2" }] data = { "emailSubject": subject, "documents": documents, "recipients": { "signers": signers, "carbonCopies": ccs }, "status": "created" ### "created" status means we'll get a draft envelope } eventNotification = ds_webhook.get_eventNotification_object() if eventNotification: data["eventNotification"] = eventNotification # append "/envelopes" to the baseUrl and use in the request url = auth["base_url"] + "/envelopes" ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling Envelopes:create: " + str(e)} status = r.status_code if (status != 201): return ({ 'err': "Error calling DocuSign Envelopes:create<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) data = r.json() envelope_id = data['envelopeId'] session['latest_envelope_id'] = envelope_id # Save for other recipe's use # Save the information that we will need for the embedded tagging # in our "database" (for this example, we're using the session) session[embedded_tagging_key] = {"envelopeId": envelope_id} # Instructions for tagging and sending the envelope html = ( "<h2>A draft envelope was created, ready to be tagged and sent!</h2>" + "<p>Envelope ID: " + envelope_id + "</p>" + "<p>Signer: " + ds_signer1_name + "</p>" + "<p>CC: " + ds_cc1_name + "</p>") html += ( "<h2>Next step:</h2>" + "<form action='get_view'>" + "<p><select name='send'>" + "<option value='0'>Start with the prepare page</option>" + "<option value='1' selected='selected'>Start with the tagging page</option>" + "</select></p>" + "<button type='submit' class='btn btn-primary'>Tag and Send the envelope</button>" + "</form>") return { "err": False, "envelope_id": envelope_id, "ds_signer1_email": ds_signer1_email, "ds_signer1_name": ds_signer1_name, "ds_signer1_qr": ds_signer1_email, "ds_cc1_email": ds_cc1_email, "ds_cc1_name": ds_cc1_name, "html": html }
def get_status(envelope_id): """Fetch the envelope status from DocuSign See https://docs.docusign.com/esign/restapi/Envelopes/Envelopes/get/ Returns {false or the result of the call} """ # Sample data returned from the Envelopes: Get method # { # "status": "completed", # "documentsUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/documents", # "recipientsUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/recipients", # "envelopeUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d", # "emailSubject": "Please sign the NDA package", # "envelopeId": "ed400d38-7765-4ce5-9f50-8652a8c4486d", # "customFieldsUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/custom_fields", # "autoNavigation": "true", # "envelopeIdStamping": "true", # "notificationUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/notification", # "enableWetSign": "true", # "allowMarkup": "false", # "createdDateTime": "2016-06-28T15:57:07.1800000Z", # "lastModifiedDateTime": "2016-06-28T15:57:07.1800000Z", # "deliveredDateTime": "2016-06-28T15:57:33.6270000Z", # "initialSentDateTime": "2016-06-28T15:57:07.7430000Z", # "sentDateTime": "2016-06-28T15:57:33.6270000Z", # "completedDateTime": "2016-06-28T15:57:33.6270000Z", # "statusChangedDateTime": "2016-06-28T15:57:33.6270000Z", # "documentsCombinedUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/documents/combined", # "certificateUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/documents/certificate", # "templatesUri": "/envelopes/ed400d38-7765-4ce5-9f50-8652a8c4486d/templates", # "brandId": "3774f432-9d31-40e6-bc6b-6ae30cce334c", # "purgeState": "unpurged", # "is21CFRPart11": "false", # "isSignatureProviderEnvelope": "false" # } auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # append "/envelopes/{envelopeId}" to the baseUrl and use in the request url = auth["base_url"] + '/envelopes/{}'.format( envelope_id) + "?cache_buster={}".format(time.time()) ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return False status = r.status_code if (status != 200): return False result = r.json() result["err"] = False return result
def send(): """Sends the envelope Returns r: { err: False, or an error message html: html output, to be displayed envelope_id: } """ # Ready... # Possibly create some fake people ds_signer1_email = ds_recipe_lib.get_signer_email(ds_signer1_email_orig) ds_signer1_name = ds_recipe_lib.get_signer_name(ds_signer1_name_orig) ds_cc1_email = ds_recipe_lib.get_signer_email(ds_cc1_email_orig) ds_cc1_name = ds_recipe_lib.get_signer_name(ds_cc1_name_orig) ds_cc2_email = ds_recipe_lib.get_signer_email(ds_cc2_email_orig) ds_cc2_name = ds_recipe_lib.get_signer_name(ds_cc2_name_orig) # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # # STEP 2 - Create and send envelope # # construct the body of the request file_contents = open(doc_document_path, "rb").read() # Please use the most accurate and relevant subject line. subject = "Please sign the NDA package" # File contents are provided here # The documents array can include multiple documents, of differing types. # All documents are converted to pdf prior to signing. # The fileExtension field defaults to "pdf". documents = [{"documentId": "1", "name": doc_document_name, "fileExtension": os.path.splitext(doc_document_path)[1][1:], "documentBase64": base64.b64encode(file_contents)} ] # The signing fields # # Invisible (white) Anchor field names for the NDA.pdf document: # * signer1sig # * signer1name # * signer1company # * signer1date # fields = { "signHereTabs": [{ "anchorString": "signer1sig", # Anchored for doc 1 "anchorXOffset": "0", "anchorYOffset": "0", "anchorUnits": "mms", "recipientId": "1", "name": "Please sign here", "optional": "false", "scaleValue": 1, "tabLabel": "signer1sig"}], "fullNameTabs": [{ "anchorString": "signer1name", # Anchored for doc 1 "anchorYOffset": "-6", "fontSize": "Size12", "recipientId": "1", "tabLabel": "Full Name", "name": "Full Name"}], "textTabs": [{ "anchorString": "signer1company", # Anchored for doc 1 "anchorYOffset": "-8", "fontSize": "Size12", "recipientId": "1", "tabLabel": "Company", "name": "Company", "required": "false"}], "signerAttachmentTabs": [{ "anchorString": "signer1company", # Anchored for doc 1 "anchorYOffset": "110", "fontSize": "Size12", "recipientId": "1", "tabLabel": "Optional attachment", "name": "NDA_attachment", "optional": "true"}], "dateSignedTabs": [{ "anchorString": "signer1date", # Anchored for doc 1 "anchorYOffset": "-6", "fontSize": "Size12", "recipientId": "1", "name": "Date Signed", "tabLabel": "date_signed"}] } signers = [{"email": ds_signer1_email, "name": ds_signer1_name, "clientUserId": ds_signer1_clientUserId, # this signer is an embedded signer "recipientId": "1", "routingOrder": "1", "tabs": fields}] ccs = [{"email": ds_cc1_email, "name": ds_cc1_name, "recipientId": "2", "routingOrder": "2"}, {"email": ds_cc2_email, "name": ds_cc2_name, "recipientId": "3", "routingOrder": "3"}] data = { "emailSubject": subject, "documents": documents, "recipients": {"signers": signers, "carbonCopies": ccs}, "status": "sent" } eventNotification = ds_webhook.get_eventNotification_object() if eventNotification: data["eventNotification"] = eventNotification # append "/envelopes" to the baseUrl and use in the request url = auth["base_url"] + "/envelopes" ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling Envelopes:create: " + str(e)} status = r.status_code if (status != 201): return ({'err': "Error calling DocuSign Envelopes:create<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) data = r.json() envelope_id = data['envelopeId'] session['latest_envelope_id'] = envelope_id # Save for other recipe's use # Save the information that we will need for the embedded signing # in our "database" (for this example, we're using the session) session[embedded_signing_key] = { "email": ds_signer1_email, "name": ds_signer1_name, "clientUserId": ds_signer1_clientUserId, "envelopeId": envelope_id} # Instructions for signing the email webhook_instructions = ds_webhook.webhook_instructions(envelope_id) html = ("<h2>Envelope created, ready to be signed!</h2>" + "<p>Envelope ID: " + envelope_id + "</p>" + "<p>Signer: " + ds_signer1_name + "</p>" + "<p>CC: " + ds_cc1_name + ", " + ds_cc2_name + "</p>") if webhook_instructions: html += ( "<h2>Next steps:</h2>" + webhook_instructions + "<h3>2. Sign the envelope</h3>" + "<form action='get_view'>" + "<button type='submit' class='btn btn-primary'>" + sign_button_text + "</button>" + "</form>") else: html += ( "<h2>Next step:</h2>" + "<form action='get_view'>" + "<button type='submit' class='btn btn-primary'>" + sign_button_text + "</button>" + "</form>") return { "err": False, "envelope_id": envelope_id, "ds_signer1_email": ds_signer1_email, "ds_signer1_name": ds_signer1_name, "ds_signer1_clientUserId": ds_signer1_clientUserId, "ds_signer1_qr": ds_signer1_email, "ds_cc1_email": ds_cc1_email, "ds_cc1_name": ds_cc1_name, "html": html }
def send(): """Sends the envelope from a template Parameters: template_name company_name Returns r: { err: False, or an error message html: html output, to be displayed envelope_id: } """ # Ready... # Possibly create some fake people ds_signer1_email = ds_recipe_lib.get_signer_email(ds_signer1_email_orig) ds_signer1_name = ds_recipe_lib.get_signer_name(ds_signer1_name_orig) ds_cc1_email = ds_recipe_lib.get_signer_email(ds_cc1_email_orig) ds_cc1_name = ds_recipe_lib.get_signer_name(ds_cc1_name_orig) # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # # STEP 2 - lookup the template # template_name = request.form.get('template_name') company_name = request.form.get('company_name') if not template_name: return {"err": "Please fill in a template name"} if not company_name: return {"err": "Please fill in a company name"} # Templates: list. See https://docs.docusign.com/esign/restapi/Templates/Templates/list/ url = auth["base_url"] + "/templates?" + "search_text={}".format(urllib.quote(template_name)) ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling Templates:list: " + str(e)} status = r.status_code if (status != 200): return ({'err': "Error calling DocuSign Templates:list<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) data = r.json() if data["resultSetSize"] == "0": return {"err": "No Templates with title {} were found.".format(template_name)} # Use the first template_id in the results template_id = data["envelopeTemplates"][0]["templateId"] # When we create the envelope, we want to set the text tag with the company name value. # To set a value, we need the tab's "tabLabel". If it were an agreed value with the person # who created the tab, that'd be fine. For the purpose of this example, we'll be more # flexible: we'll get the details on the template, and then assume that the first text tab # is the company tab. You wouldn't want to do this in production since someone might add # an additional text tab to the template, which would break the integration. # Use the Templates: get method to retrieve full info about the template. # See https://docs.docusign.com/esign/restapi/Templates/Templates/get/ url = auth["base_url"] + "/templates/{}".format(urllib.quote(template_id)) ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling Templates:list: " + str(e)} status = r.status_code if (status != 200): return ({'err': "Error calling DocuSign Templates:list<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) data = r.json() company_tabLabel = data["recipients"]["signers"][0]["tabs"]["textTabs"][0]["tabLabel"] # # STEP 3 - Create and send envelope # # Since we're using a template, this request is relatively small # The signer and cc role names must be in agreement with the template's settings template_role_signer_1 = { "roleName": signer1_role, "email": ds_signer1_email, "name": ds_signer1_name, "tabs": { "textTabs": [ {"tabLabel": company_tabLabel, "value": company_name} ] } } template_role_cc = { "roleName": cc_role, "email": ds_cc1_email, "name": ds_cc1_name } data = { "templateId": template_id, "templateRoles": [template_role_signer_1, template_role_cc], "status": "sent" } eventNotification = ds_webhook.get_eventNotification_object() if eventNotification: data["eventNotification"] = eventNotification # append "/envelopes" to the baseUrl and use in the request url = auth["base_url"] + "/envelopes" ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling Envelopes:create: " + str(e)} status = r.status_code if (status != 201): return ({'err': "Error calling DocuSign Envelopes:create<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) data = r.json() envelope_id = data['envelopeId'] session['latest_envelope_id'] = envelope_id # Save for other recipe's use # Instructions for reading the email webhook_instructions = ds_webhook.webhook_instructions(envelope_id) html = ("<h2>Envelope created, Signature request sent!</h2>" + "<p>Envelope ID: " + envelope_id + "</p>" + "<p>Signer: " + ds_signer1_name + "</p>" + "<p>CC: " + ds_cc1_name + "</p>") if webhook_instructions: html += ( "<h2>Next steps:</h2>" + webhook_instructions + "<h3>2. Sign the envelope</h3>") else: html += "<h2>Next step:</h2>" ds_signer1_email_access = ds_recipe_lib.get_temp_email_access(ds_signer1_email) if (ds_signer1_email_access): # A temp account was used for the email html += "<p>Respond to the request via your mobile phone by using the QR code: </p>" + \ "<p>" + ds_recipe_lib.get_temp_email_access_qrcode(ds_signer1_email_access) + "</p>" + \ "<p> or via <a target='_blank' href='" + ds_signer1_email_access + "'>your web browser.</a></p>" #html += ("<p>View and respond to the request by opening " + # "<a target='_blank' href='http://mailinator.com'>mailinator.com</a></p>" + # "<p>Then enter mailbox id " + ds_recipe_lib.get_temp_email_access_id(ds_signer1_email) + "</p>") else: # A regular email account was used html += "<p>Respond to the request via your mobile phone or other mail tool.</p>" + \ "<p>The email was sent to " + ds_signer1_name + " <" + ds_signer1_email + "></p>" return { "err": False, "envelope_id": envelope_id, "ds_signer1_email": ds_signer1_email, "ds_signer1_name": ds_signer1_name, "ds_signer1_access": ds_signer1_email_access, "ds_signer1_qr": ds_signer1_email, "ds_cc1_email": ds_cc1_email, "ds_cc1_name": ds_cc1_name, "html": html }
def send(): """Sends the envelope Returns r: { err: False, or an error message html: html output, to be displayed envelope_id: } """ # Ready... # Possibly create some fake people ds_signer1_email = ds_recipe_lib.get_signer_email(ds_signer1_email_orig) ds_signer1_name = ds_recipe_lib.get_signer_name(ds_signer1_name_orig) ds_cc1_email = ds_recipe_lib.get_signer_email(ds_cc1_email_orig) ds_cc1_name = ds_recipe_lib.get_signer_name(ds_cc1_name_orig) # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # # STEP 2 - Create and send envelope # # construct the body of the request file_contents = open(doc_document_path, "rb").read() # Please use the most accurate and relevant subject line. subject = "Please sign the NDA package" # File contents are provided here # The documents array can include multiple documents, of differing types. # All documents are converted to pdf prior to signing. # The fileExtension field defaults to "pdf". documents = [{"documentId": "1", "name": doc_document_name, "fileExtension": os.path.splitext(doc_document_path)[1][1:], "documentBase64": base64.b64encode(file_contents)} ] # The signing fields # # Invisible (white) Anchor field names for the NDA.pdf document: # * signer1sig # * signer1name # * signer1company # * signer1date # fields = { "signHereTabs": [{ "anchorString": "signer1sig", # Anchored for doc 1 "anchorXOffset": "0", "anchorYOffset": "0", "anchorUnits": "mms", "recipientId": "1", "name": "Please sign here", "optional": "false", "scaleValue": 1, "tabLabel": "signer1sig"}], "fullNameTabs": [{ "anchorString": "signer1name", # Anchored for doc 1 "anchorYOffset": "-6", "fontSize": "Size12", "recipientId": "1", "tabLabel": "Full Name", "name": "Full Name"}], "textTabs": [{ "anchorString": "signer1company", # Anchored for doc 1 "anchorYOffset": "-8", "fontSize": "Size12", "recipientId": "1", "tabLabel": "Company", "name": "Company", "required": "true"}], "dateSignedTabs": [{ "anchorString": "signer1date", # Anchored for doc 1 "anchorYOffset": "-6", "fontSize": "Size12", "recipientId": "1", "name": "Date Signed", "tabLabel": "date_signed"}] } signers = [{"email": ds_signer1_email, "name": ds_signer1_name, "recipientId": "1", "routingOrder": "1", "tabs": fields}] ccs = [{"email": ds_cc1_email, "name": ds_cc1_name, "recipientId": "2", "routingOrder": "2"}] data = {"emailSubject": subject, "documents": documents, "recipients": {"signers": signers, "carbonCopies": ccs}, "status": "sent" } eventNotification = ds_webhook.get_eventNotification_object() if eventNotification: data["eventNotification"] = eventNotification # append "/envelopes" to the baseUrl and use in the request url = auth["base_url"] + "/envelopes" ds_headers = {'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value} try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling Envelopes:create: " + str(e)} status = r.status_code if (status != 201): return ({'err': "Error calling DocuSign Envelopes:create<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>"}) data = r.json() envelope_id = data['envelopeId'] session['latest_envelope_id'] = envelope_id # Save for other recipe's use # Instructions for reading the email webhook_instructions = ds_webhook.webhook_instructions(envelope_id) html = ("<h2>Envelope created, Signature request sent!</h2>" + "<p>Envelope ID: " + envelope_id + "</p>" + "<p>Signer: " + ds_signer1_name + "</p>" + "<p>CC: " + ds_cc1_name + "</p>") if webhook_instructions: html += ( "<h2>Next steps:</h2>" + webhook_instructions + "<h3>2. Sign the envelope</h3>") else: html += "<h2>Next step:</h2>" ds_signer1_email_access = ds_recipe_lib.get_temp_email_access(ds_signer1_email) if (ds_signer1_email_access): # A temp account was used for the email html += "<p>Respond to the request via your mobile phone by using the QR code: </p>" + \ "<p>" + ds_recipe_lib.get_temp_email_access_qrcode(ds_signer1_email_access) + "</p>" + \ "<p> or via <a target='_blank' href='" + ds_signer1_email_access + "'>your web browser.</a></p>" #html += ("<p>View and respond to the request by opening " + # "<a target='_blank' href='http://mailinator.com'>mailinator.com</a></p>" + # "<p>Then enter mailbox id " + ds_recipe_lib.get_temp_email_access_id(ds_signer1_email) + "</p>") else: # A regular email account was used html += "<p>Respond to the request via your mobile phone or other mail tool.</p>" + \ "<p>The email was sent to " + ds_signer1_name + " <" + ds_signer1_email + "></p>" return { "err": False, "envelope_id": envelope_id, "ds_signer1_email": ds_signer1_email, "ds_signer1_name": ds_signer1_name, "ds_signer1_access": ds_signer1_email_access, "ds_signer1_qr": ds_signer1_email, "ds_cc1_email": ds_cc1_email, "ds_cc1_name": ds_cc1_name, "html": html }
def start(): """Sends Envelopes: listStatusChanges method Returns r: { err: False, or an error message intro: html introduction to the page url: the url used for the request response: the response body } """ # Ready... # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # # STEP 2 - Create and send the request # # See the docs, https://docs.docusign.com/esign/restapi/Envelopes/Envelopes/listStatusChanges/ # We need to set one or more of the following parameters: from_date, envelopeIds and/or transactionIds. # We will set from_date to be yesterday. # # If you're using this method to poll for changes, see "Polling for Current Status" section of # page https://docs.docusign.com/esign/guide/usage/status_and_events.html for a strategy that won't # violate the platform's polling policy. # construct the body of the request yesterday = datetime.date.today() - datetime.timedelta(days=1) yesterday_s = yesterday.strftime("%Y-%m-%d") # '2016-07-25' # create the url from the baseUrl url = auth["base_url"] + "/envelopes?from_date={}".format(yesterday_s) ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling Envelopes:listStatusChanges: " + str(e)} status = r.status_code if (status != 200): return ({ 'err': "Error calling DocuSign Envelopes:listStatusChanges<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) response = r.json() return { "err": False, "url": url, "intro": intro, "response": json.dumps(response, indent=4, sort_keys=True) }
def send(): """Sends the envelope from a template Parameters: template_name company_name Returns r: { err: False, or an error message html: html output, to be displayed envelope_id: } """ # Ready... # Possibly create some fake people ds_signer1_email = ds_recipe_lib.get_signer_email(ds_signer1_email_orig) ds_signer1_name = ds_recipe_lib.get_signer_name(ds_signer1_name_orig) ds_cc1_email = ds_recipe_lib.get_signer_email(ds_cc1_email_orig) ds_cc1_name = ds_recipe_lib.get_signer_name(ds_cc1_name_orig) # STEP 1 - Fetch Authentication information from session auth = ds_authentication.get_auth() if auth["err"]: return {"err": auth["err"], "err_code": auth["err_code"]} # # STEP 2 - lookup the template # template_name = request.form.get('template_name') company_name = request.form.get('company_name') if not template_name: return {"err": "Please fill in a template name"} if not company_name: return {"err": "Please fill in a company name"} # Templates: list. See https://docs.docusign.com/esign/restapi/Templates/Templates/list/ url = auth["base_url"] + "/templates?" + "search_text={}".format( urllib.quote(template_name)) ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling Templates:list: " + str(e)} status = r.status_code if (status != 200): return ({ 'err': "Error calling DocuSign Templates:list<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) data = r.json() if data["resultSetSize"] == "0": return { "err": "No Templates with title {} were found.".format(template_name) } # Use the first template_id in the results template_id = data["envelopeTemplates"][0]["templateId"] # When we create the envelope, we want to set the text tag with the company name value. # To set a value, we need the tab's "tabLabel". If it were an agreed value with the person # who created the tab, that'd be fine. For the purpose of this example, we'll be more # flexible: we'll get the details on the template, and then assume that the first text tab # is the company tab. You wouldn't want to do this in production since someone might add # an additional text tab to the template, which would break the integration. # Use the Templates: get method to retrieve full info about the template. # See https://docs.docusign.com/esign/restapi/Templates/Templates/get/ url = auth["base_url"] + "/templates/{}".format(urllib.quote(template_id)) ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.get(url, headers=ds_headers) except requests.exceptions.RequestException as e: return {'err': "Error calling Templates:list: " + str(e)} status = r.status_code if (status != 200): return ({ 'err': "Error calling DocuSign Templates:list<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) data = r.json() company_tabLabel = data["recipients"]["signers"][0]["tabs"]["textTabs"][0][ "tabLabel"] # # STEP 3 - Create and send envelope # # Since we're using a template, this request is relatively small # The signer and cc role names must be in agreement with the template's settings template_role_signer_1 = { "roleName": signer1_role, "email": ds_signer1_email, "name": ds_signer1_name, "tabs": { "textTabs": [{ "tabLabel": company_tabLabel, "value": company_name }] } } template_role_cc = { "roleName": cc_role, "email": ds_cc1_email, "name": ds_cc1_name } data = { "templateId": template_id, "templateRoles": [template_role_signer_1, template_role_cc], "status": "sent" } eventNotification = ds_webhook.get_eventNotification_object() if eventNotification: data["eventNotification"] = eventNotification # append "/envelopes" to the baseUrl and use in the request url = auth["base_url"] + "/envelopes" ds_headers = { 'Accept': 'application/json', auth["auth_header_key"]: auth["auth_header_value"], trace_key: trace_value } try: r = requests.post(url, headers=ds_headers, json=data) except requests.exceptions.RequestException as e: return {'err': "Error calling Envelopes:create: " + str(e)} status = r.status_code if (status != 201): return ({ 'err': "Error calling DocuSign Envelopes:create<br/>Status is: " + str(status) + ". Response: <pre><code>" + r.text + "</code></pre>" }) data = r.json() envelope_id = data['envelopeId'] session['latest_envelope_id'] = envelope_id # Save for other recipe's use # Instructions for reading the email webhook_instructions = ds_webhook.webhook_instructions(envelope_id) html = ("<h2>Envelope created, Signature request sent!</h2>" + "<p>Envelope ID: " + envelope_id + "</p>" + "<p>Signer: " + ds_signer1_name + "</p>" + "<p>CC: " + ds_cc1_name + "</p>") if webhook_instructions: html += ("<h2>Next steps:</h2>" + webhook_instructions + "<h3>2. Sign the envelope</h3>") else: html += "<h2>Next step:</h2>" ds_signer1_email_access = ds_recipe_lib.get_temp_email_access( ds_signer1_email) if (ds_signer1_email_access): # A temp account was used for the email html += "<p>Respond to the request via your mobile phone by using the QR code: </p>" + \ "<p>" + ds_recipe_lib.get_temp_email_access_qrcode(ds_signer1_email_access) + "</p>" + \ "<p> or via <a target='_blank' href='" + ds_signer1_email_access + "'>your web browser.</a></p>" #html += ("<p>View and respond to the request by opening " + # "<a target='_blank' href='http://mailinator.com'>mailinator.com</a></p>" + # "<p>Then enter mailbox id " + ds_recipe_lib.get_temp_email_access_id(ds_signer1_email) + "</p>") else: # A regular email account was used html += "<p>Respond to the request via your mobile phone or other mail tool.</p>" + \ "<p>The email was sent to " + ds_signer1_name + " <" + ds_signer1_email + "></p>" return { "err": False, "envelope_id": envelope_id, "ds_signer1_email": ds_signer1_email, "ds_signer1_name": ds_signer1_name, "ds_signer1_access": ds_signer1_email_access, "ds_signer1_qr": ds_signer1_email, "ds_cc1_email": ds_cc1_email, "ds_cc1_name": ds_cc1_name, "html": html }