I am using Docusign SDK for NodeJS and below is sample code that I followed from nodejs github example.
let taxYear = docusign.Text.constructFromObject({
customTabId:"taxYear",
tabLabel: "taxYear",
value:"2018"
})
let signer1Tabs = docusign.Tabs.constructFromObject({
textTabs: [taxYear]
})
// Create a signer recipient for the signer role of the server template
let signer1 = docusign.Signer.constructFromObject({
email: args.signerEmail,
name: args.signerName,
roleName: "signer",
recipientId: "1",
// Adding clientUserId transforms the template recipient
// into an embedded recipient:
clientUserId: "1",
tabs: signer1Tabs
});
// Create the cc recipient
let cc1 = docusign.CarbonCopy.constructFromObject({
email: args.ccEmail,
name: args.ccName,
roleName: "cc",
recipientId: "2"
});
// Recipients object:
let recipientsServerTemplate = docusign.Recipients.constructFromObject({
carbonCopies: [cc1], signers: [signer1], });
// create a composite template for the Server Template
let compTemplate1 = docusign.CompositeTemplate.constructFromObject({
compositeTemplateId: "1",
serverTemplates: [
docusign.ServerTemplate.constructFromObject({
sequence: "1",
templateId: args.templateId
})
],
// Add the roles via an inlineTemplate
inlineTemplates: [
docusign.InlineTemplate.constructFromObject({
sequence: "1",
recipients: recipientsServerTemplate
})
]
})
// create the envelope definition
let env = docusign.EnvelopeDefinition.constructFromObject({
status: "sent",
compositeTemplates: [compTemplate1]
})
return env;
I have custom text field with tab label as taxYear but I am not seeing it getting posted in the form when envelop is sent out.
Here is the out put I am receiving
Not sure what I am missing!!!!!!
The Taxfield that you're using does not appear to have an X/Y location or anchor string attached to it -- so our system would not know where to place it.
For these fields to be added, you need to supply the documentId (if using x/y coordinates), recipientId, tabLabel, and either the x/y position or an anchor string to place it.
If adding those doesn't seem to do it, please edit your comment with the parameters specifically for the taxYear tab and we can have another look at it.
Related
I was trying to create a Docusign envelope using docusign-esign package.
What I need is to force the signer to draw his/her signature and I found out that setting the property "signInEachLocation" to true will do the trick.
Now my question is how or where should I set the property?
Is it here? Because when I try to execute the code, no error returned but it is not working.
let signer = docusign.TemplateRole.constructFromObject({
email: 'test#email.com',
name: 'Signer Name',
roleName: 'signer',
signInEachLocation: true, //this property
tabs: tabs
});
Need help.
The signInEachLocation property is part of the Signer object, not the TemplateRole. When you add the parameter to TemplateRole, the API is just ignoring the extra parameter instead of flagging it with an error.
This code example shows how you can add a Signer to a Template and you can add the signInEachLocation property there. See the API reference for more info.
This feature was added to all new developer accounts created in 2021.
If your account was created prior to 2021, create a new one and you'll have this feature.
Sample Node code:
let signer1 = docusign.Signer.constructFromObject({
email: 'test#sample.com',
name: 'some name',
clientUserId: '1',
recipientId: 1,
signInEachLocation: 'true' // signer must draw their signature in each tab
});
let signHere1 = docusign.SignHere.constructFromObject({
YPosition: '200',
XPosition: '200',
documentId: '1',
pageNumber: '1'
});
let signHere2 = docusign.SignHere.constructFromObject({
YPosition: '100',
XPosition: '100',
documentId: '1',
pageNumber: '1'
});
let signer1Tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere1, signHere2]});
signer1.tabs = signer1Tabs;
let recipients = docusign.Recipients.constructFromObject({
signers: [signer1]});
I have a user and a supervisor.
The user will submit some information, which will be used to generate a document, create an envelope and send it to the user to sign. I add 2 signing fields, one for the user and one for the supervisor.
What I would like to do is instead of sending it on to the supervisor after a user signs, I would like to get all the documents for each user and create a new envelope and send that one to the supervisor. This will then only have one email to the supervisor instead of no: users.
Is there a way this can be done? I have been unable to find a way to complete this.
Below is what I am doing at the current moment. For the first signer they are redirected.
const doc1 = new docusign.Document();
doc1.documentBase64 = Buffer.from(htmlPage(args.htmlArgs)).toString('base64');
doc1.name = args.documentName;
doc1.fileExtension = 'html';
doc1.documentId = '1';
env.documents = [doc1];
const signer1 = docusign.Signer.constructFromObject({
email: args.htmlArgs.submitterEmail,
name: args.htmlArgs.submitterName,
clientUserId: 1,
recipientId: 1,
routingOrder: 1 });
// Signer 2 is the supervisor. Gets sent the document after signer 1 signs
const signer2 = docusign.Signer.constructFromObject({
email: args.htmlArgs.supervisorEmail,
name: args.htmlArgs.supervisorName,
recipientId: 2,
routingOrder: 2 });
const signHere1 = docusign.SignHere.constructFromObject({
anchorString: '**signature_1**',
anchorYOffset: '10', anchorUnits: 'pixels',
anchorXOffset: '20'});
const signHere2 = docusign.SignHere.constructFromObject({
anchorString: '**signature_2**',
anchorYOffset: '10', anchorUnits: 'pixels',
anchorXOffset: '20'});
// Tabs are set per recipient / signer
signer1.tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere1]});
signer2.tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere2]});
env.recipients = docusign.Recipients.constructFromObject({
signers: [signer1, signer2],
});
env.status = args.status;
This can be done.
There are multiple things to consider here:
RoutingOrder - you can use that to have users sign in the order you choose and the suprevisor last.
Document Visibly feature enables you to prevent user 1 from seeing user 2 documents if that's what you want.
Merge fields. the ability to get data into a document.
Using a template to nicely capture the repeatable process for all the above.
Would suggest to first do all of this without the API using the web app to understand the capabilities. If you can do it via web app - you can use the API to do the same. So that's a good way to know what can or cannot be done.
I have a script which is working OK to send emails, but I have a requirement to attach the email to:
Multiple Entities (incl Projects)
Support Case
Multiple Custom records (mail merge is active)
My current script is as follows:
var emaildata = {body: field.fld_message+'<br />'+attachmentList+signature,
author: sender.entityid,
recipients: primary.email,
subject: field.fld_subject,
cc : cc_entities,
bcc : bcc_entities,
relatedRecords: {
entityId: entities,
activityId: field.claimid,
}
};
sendemail.send(emaildata);
The array variable entities contains the employees/partners I want to attach the email too, but it is not attaching to the records.
For the custom records, i have tried including this in the email data object:
customRecord: [
{id: field.submitid, recordType: 267},
{id: field.scopeid, recordType: 73 },
{id: field.assessid, recordType: 83 },
],
But sadly it is not working...
What am I doing wrong?
The email is being sent (sometimes) but not attaching.
When i tried with just ONE custom record, but was getting an Unexpected Suitescript error:
customRecord: {id: field.submitid, recordType: 267 }
I have confirmed the "id" fields are populated corrected.
var records = new Array();
records['record'] = '11'; // internal id of the record
records['recordtype'] = '250'; // record type id
nlapiSendEmail ( from,to,subject,body,cc,bcc,records,files);
It is working.`enter code here`
Note: I'm using the 'classic' experience because the new interface doesn't have a way for a template to set up required fields for future signers.
The workflow:
have a template with a bunch of fields
using the api:
create an envelope/document from the template, and assign a new user to sign (this document is going to be an agreement for signing up for a service)
create new role
set roleName to fake signer on template (because I can't configure fields without at least one signer on the template)
add textTabs to try to perfill some of the fields.
retrieve the recipients
create a recipient view so that I get the URL to put in an iframe
This is kind of obnoxious, because I don't care about having a first signer that isn't the user signing up for the service. I would however, like to have the the document be copied to someone after signing, but docusign doesn't appear to support this (that I've found anyway).
Here is the node.js code for the creation of the envelope (where I think my API usage is going wrong):
function createEnvelopeDefinition(templateId, userData) {
var envDef = new docusign.EnvelopeDefinition();
envDef.setEmailSubject('Signup Agreement');
envDef.setTemplateId(templateId);
var tRole = new docusign.TemplateRole();
tRole.setRoleName('RoleOne');
tRole.setName(userData.fullName);
tRole.setEmail(userData.email);
tRole.setClientUserId('2');
tRole.setTabs(new docusign.Tabs());
tRole.getTabs().setTextTabs([]);
const fieldsToPreFill = [
'field1',
'field2',
'field3',
'field4'];
fieldsToPreFill.forEach(fieldName => {
let textTab = new docusign.Text();
let value = userData[fieldName];
if (value === null || value === undefined) { value = 'not null'; }
textTab.setTabLabel(fieldName);
textTab.setValue(value);
tRole.getTabs().getTextTabs().push(textTab);
});
tRole = removeNulls(tRole);
envDef.setTemplateRoles([tRole]);
// send the envelope by setting |status| to 'sent'.
// To save as a draft set to 'created'
// sent is required for getting view URLs
envDef.setStatus('sent');
return envDef;
}
In the template editor on docusign, the Data Field Tag Properties show the label of each of the corresponding fields as field1, field2, etc.
These fields are now filled out with the provided values when I throw the new envelope in an iframe.
just for reference here is the rest of the code that creates the api connection, and gets the view URL
import ENV from 'environment/backend';
const accountId = ENV.docusign.accountId;
var Promise = require('bluebird');
var docusign = require('docusign-esign');
export function newApiClient() {
let apiClient = new docusign.ApiClient();
apiClient.setBasePath(ENV.docusign.endpoint);
// create JSON formatted auth header
let creds = JSON.stringify({
Username: ENV.docusign.email,
Password: ENV.docusign.password,
IntegratorKey: ENV.docusign.integratorKey
});
apiClient.addDefaultHeader('X-DocuSign-Authentication', creds);
// assign api client to the Configuration object
// this probably doesn't need to be set every time...
docusign.Configuration.default.setDefaultApiClient(apiClient);
return apiClient;
}
const defaultApiClient = newApiClient();
const envelopesApi = new docusign.EnvelopesApi();
const createEnvelope = Promise.promisify(envelopesApi.createEnvelope, { context: envelopesApi });
const listRecipients = Promise.promisify(envelopesApi.listRecipients, { context: envelopesApi });
const createRecipientView = Promise.promisify(envelopesApi.createRecipientView, { context: envelopesApi });
export default defaultApiClient;
// promise resolves to the view URL, envelopeId for the user.
// returns a recipientView
export function setupDocumentForEmbeddedSigning(templateId, userData) {
let envDefinition = createEnvelopeDefinition(templateId, userData);
return createEnvelope(accountId, envDefinition, null)
.then(envelopeSummary => {
const envelopeId = envelopeSummary.envelopeId;
return createViewFromEnvelope(envelopeId);
});
}
export function createViewFromEnvelope(envelopeId) {
return getRecipients(envelopeId).then(recipients => {
// the last signer is the one we added in the
// createEnvelopeDefinition step
let signers = recipients.signers;
let lastSigner = signers[signers.length - 1];
return createView(envelopeId, lastSigner)
.then(recipientView => [recipientView.url, envelopeId]);
});
}
function getRecipients(envelopeId) {
return listRecipients(accountId, envelopeId);
}
function createView(envelopeId, signerData) {
var viewRequest = new docusign.RecipientViewRequest();
viewRequest.setReturnUrl(ENV.host);
viewRequest.setAuthenticationMethod('email');
// recipient information must match embedded recipient info
// from the createEnvelopeDefinition method
viewRequest.setEmail(signerData.email);
viewRequest.setUserName(signerData.name);
viewRequest.setRecipientId('2');
viewRequest.setClientUserId('2');
return createRecipientView(accountId, envelopeId, viewRequest);
}
// bug with the api wrapper
// https://github.com/docusign/docusign-node-client/issues/47
const removeNulls = function(obj) {
var isArray = obj instanceof Array;
for (var k in obj) {
if (obj[k] === null) isArray ? obj.splice(k, 1) : delete obj[k];
else if (typeof obj[k] == 'object') removeNulls(obj[k]);
if (isArray && obj.length == k) removeNulls(obj);
}
return obj;
};
So, I may not fully understand where you're stuck, but I'll take a crack at this anyway...
Let's say I create a Template using the DocuSign UI and define two Recipient roles:
Signer1 (which will be the person who is signing up for your service) -- Action = "Sign"
CarbonCopy1 (which will be the person who gets a copy of the completed/signed documents once Signer1 signs) -- Action = "Receive a Copy"
(Note: these roles can be named whatever you want to name them -- I named them "Signer1" and "CarbonCopy1" so it'd be clear who each role represents.)
Assuming the above scenario, your Template's Recipient Roles (in the DocuSign UI) will look like this:
Next, let's assume that you define some fields (tabs) in the Template's document(s) (i.e., using the DocuSign UI) that the Signer1 recipient will need to populate when they sign the document(s). For this example, let's assume that the label (name) of one of those Text tabs is field1. Notice that the field is assigned to the Signer1 recipient:
Now, if I want to create an Envelope via the API that uses this Template, and pre-fill fields for one or more of the recipients, the key to doing that is using the "Composite Templates" structure in the API request. (See the Composite Templates section of this page for details.) In the example described above, your compositeTemplates object in the API request would contain a single serverTemplate object (which specifies the templateId and sequence=1), and a single inlineTemplate object (which specifies sequence=2 and the recipient info, including values for any tabs (fields) that you want to pre-fill).
In the example described above, the JSON API request to create the Envelope would look like this (assuming we're just pre-filling a single field for Signer1 -- obviously you could pre-fill additional fields by simply including them in the tabs object of the request along with field1):
POST https://{{env}}.docusign.net/restapi//v2/accounts/{{accountId}}/envelopes
{
"emailSubject": "Test Pre-fill Tabs",
"emailBlurb": "This is a test.",
"compositeTemplates": [{
"serverTemplates": [{
"sequence": "1",
"templateId": "CD0E6D53-3447-4A9E-BBAF-0EB2C78E8310"
}],
"inlineTemplates":[{
"sequence": "2",
"recipients": {
"signers": [
{
"roleName": "Signer1",
"recipientId": "1",
"name": "John Doe",
"email": "johndoe#test.com",
"clientUserId": "1234",
"tabs": {
"textTabs": [
{
"tabLabel": "field1",
"value": "TEST-123"
}
]
}
},
{
"roleName": "CarbonCopy1",
"recipientId": "2",
"name": "Jane Doe",
"email": "janedoe#test.com"
}
]
}
}]
}],
"status": "sent"
}
Once I create the Envelope using the above request, I execute a "POST Recipient View" request to get the signing URL for the first recipient (https://{{env}}.docusign.net/restapi//v2/accounts/{{accountId}}/envelopes/{{envelopeId/views/recipient).
Then, when I subsequently use the URL that's returned in that response to launch the signing session for Signer1 (John Doe), I see that the field1 tab is indeed pre-filled with the value that I specified in the "Create Envelope" API request (TEST-123):
Furthermore, once John Doe (Signer1) finishes signing and submits the completed documents, Jane Doe (CarbonCopy1) will be sent a copy.
I'm not familiar with the DocuSign Node SDK, but imagine you can figure out the syntax to use composite templates as shown in the above example. Hope this helps!
I am having issue in sending mails to multiple recipients.
My script is
var SendGrid = require('sendgrid').SendGrid;
var sendgrid = new SendGrid('<<username>>', '<<password>>');
sendgrid.send({
to: 'nabababa#gmail.com',
from: 'sengupta.nabarun#gmail.com',
bcc: ["sengupta.nabarun#gmail.com","sengupta_nabarun#rediffmail.com"],
I have two questions here
Can I have an array of recipients in to list?
How can I get an array of recipients in bcc list?
Solutions related to above two queries will be indeed helpful
Thanks
Nabarun
You may use an array of recipients in both the to and bcc fields.
For example:
var SendGrid = require('sendgrid').SendGrid;
var sendgrid = new SendGrid('{{sendgrid username}}', '{{sendgrid password}}');
sendgrid.send({
to: ['one#example.com', 'two#example.com'],
from: 'nick#sendgrid.com',
bcc: ['three#example.com', 'four#example.com'],
subject: 'This is a demonstration of SendGrid sending email to mulitple recipients.',
html: '<img src="http://3.bp.blogspot.com/-P6jNF5dU_UI/TTgpp3K4vSI/AAAAAAAAD2I/V4JC33e6sPM/s1600/happy2.jpg" style="width: 100%" />'
});
If this isn't working for you and Node isn't spitting out any errors, check to see if the emails are being sent, by logging into SendGrid's website and looking at the Email Activity Log.
One thing I came across while testing your code sample is if you're sending the to and bcc to the same gmail address, gmail will combine it all into one email (so it appears it didn't work). Make sure when testing you're sending email to entirely different accounts.
If you need some email accounts to test with Guerrilla Mail is an excellent option for creating temporary test accounts.
This is the solution that I ended up with and thought it was more straightforward and could be helpful for folks.
Note the difference in the shape of the personalizations object.
Recipients can see each other:
const sgMail = require('#sendgrid/mail')
sgMail.setApiKey(process.env.SENDGRID_API_KEY)
// Declare the content we'll use for the email
const FROM_EMAIL = 'example#example.io' // <-- Replace with your email
const subject = 'Test Email Subject'
const body = '<p>Hello HTML world!</p>'
const recipients = ['alice#example.com', 'bob#example.com'] // <-- Add your email(s) here to test
// Create the personalizations object that will be passed to our message object
let personalizations = [{
to: [],
subject
}]
// Iterate over our recipients and add them to the personalizations object
for (let index in recipients) {
personalizations[0].to[index] = { email: recipients[index] }
}
const msg = {
personalizations,
from: FROM_EMAIL,
html: body,
}
// Log to see what our message object looks like
console.log(msg)
// Send the email, if success log it, else log the error message
sgMail.send(msg)
.then(() => console.log('Mail sent successfully'))
.catch(error => console.error(error.toString()))
Personalizations Object:
{
personalizations: [{
to: [
{email: "alice#example.com"},
{email: "bob#example.com"},
],
subject: "Test Email Subject"
}]
}
Recipients can not see each other:
// Create the personalizations object that will be passed to our message object
personalizations = []
// Iterate over our recipients and add them to the personalizations object
for (let index in recipients) {
personalizations[index] = { to: recipients[index], subject}
}
Personalizations Object:
{
personalizations: [
{
to: "alice#example.com",
subject: "Test Email Subject"
},
{
to: "bob#example.com",
subject: "Test Email Subject"
}
]
}
I created a RunKit with the full solution and where you can test it out.
For Sendgrid's v3 API, I found their "kitchen sink" example helpful. Here is a relevant bit from it:
var helper = require('sendgrid').mail
mail = new helper.Mail()
email = new helper.Email("test#example.com", "Example User")
mail.setFrom(email)
mail.setSubject("Hello World from the SendGrid Node.js Library")
personalization = new helper.Personalization()
email = new helper.Email("test1#example.com", "Example User")
personalization.addTo(email)
email = new helper.Email("test2#example.com", "Example User")
personalization.addTo(email)
// ...
mail.addPersonalization(personalization)
The new sendgrid-nodejs update has scrapped previous implementation methods and therefore the accepted answer wont help you now.
So... just an update in case anyone lands to this thread with specific search result.
to: [
{
email: 'email1#email.com',
},
{
email: 'email2#email.com',
},
],
A solution for TypeScript (written in ts version 3.4.3 and sendGrid 7.1.1) where you don't want recipients to be able to see each other.
import * as sendGrid from '#sendgrid/mail'
type UserEmail = {
to: string
subject: string
}
// Add as many recipients as you want
recipients = ['email1#global.com', 'email2#gmail.com']
const personalizations: UserEmail[] = recipients.map(admin => ({
to: admin,
subject: 'Inject Subject Here',
}))
try {
await sendGrid.send({
from, // Inject
personalizations,
html, // Inject
})
} catch (err) {
console.log(err)
}
const personalizations looks like this
[{ to: 'email1#global.com',
subject: 'Inject Subject Here' },
{ to: 'email2#global.com',
subject: 'Inject Subject Here' }]