Sendgrid Substitutions Tags - node.js

I want to send a notification email in my application and I am trying to use sendgrid. My application is writtin in CoffeeScript.
enter code here
from_address = 'noreply#example.co'
subject = 'This Is The Subject'
html_body = '<table style="font-family: verdana, tahoma, sans-serif; color: #000;">
<tr> <td>
<h2>Hello,</h2> <p>Hello!!</p>
<p>%%name%% %%surname%% send you a message</p>
</table>'
sendgrid = require('sendgrid')(api_key)
Email = sendgrid.Email
email = new Email(
to: to_address
from: from_address
subject: subject
text: text_body
html: html_body)
recipients = [
'example1#example.com'
'example2#example.com'
]
i = 0
while i < recipients.length
email.addTo recipients[i]
i++
substitutions = {
"%%name%%": [
"name1",
"name2"
],
"%%surname%%": [
"surname1",
"surname2"
]
}
for tag in substitutions
email.addSubstitution(tag, substitutions[tag])
email.setFilters({
"templates": {
"settings": {
"enable": "1",
"template_id": "XXXXXX-XXX-XXXX-XXXX-XXXXXXXXXX"
}
}
})
sendgrid.send email, (err, json) ->
if err
return console.log(err)
console.log json
return
When I execute the code send my the email to the emails address. But the message is:
Hello!!
%%name%% %%surname%% send you a message.
The substitution doesn't work. I try changing %% for %,- and #. But any ot those seems to work. Also I try using setSections.
Update
This is the sendgrid object i am sending.
{ to: [ 'example1#example.com', 'example2#example.com' ],
from: 'noreply#example.co',
smtpapi:
{ version: '1.2.0',
header:
{ to: [],
sub: {},
unique_args: {},
category: [Object],
section: {},
filters: [Object],
send_at: '',
send_each_at: [],
asm_group_id: {},
ip_pool: '' } },
subject: 'This Is The Subject',
text: 'Hello!\n\nThis is a test message from SendGrid. We have sent this to you because you requested a test message be sent from your account.\n\n This is a link to google.com: http://www.google.com\n This is a link to apple.com: http://www.apple.com\n This is a link to sendgrid.com: http://www.sendgrid.com\n\n Thank you for reading this test message.\n\nLove,\nYour friends at SendGrid',
html: '<table style="font-family: verdana, tahoma, sans-serif; color: #000;"> <tr> <td> <h2>Hello,</h2> <p>Hello!!</p> <p>%%name%% %%surname%% send you a message</p> </table>',
bcc: [],
cc: [],
replyto: '',
date: '',
headers: {},
toname: undefined,
fromname: undefined,
files: [] }
What am I doing wrong?
Thank you in advance.

I answer my own question because already found the problem.
The problem was not related with Sendgrid but with coffeeScript. In one of my statement I use this:
for tag in substitutions
email.addSubstitution(tag, substitutions[tag])
I try here to add to the email object the substitutions tag. But the debuging my code I found that the loop was not iterating over the substitution variable. So any tag was added to the email object.
I've changed the previous code for this one:
Object.keys(substitutions).forEach((tag)->
email.addSubstitution(tag, sub[tag])
return
And with this change the substitutions tags was added to the email object.

Related

Docusign pre-filled tabs

We are trying to pre-fill PDF forms in Docusign so that clients only need to sign the template as we already have all the data needed to complete the form.
We are able to send the template via Docusign programmatically but when we test, the Text fields that we place on the form do not show for the signer. They are not pre-filled and do not even show up as fields. They are blank and the signer has to drag a field onto the form.
We are using Node.js
As an example, we have created a Text Field named "client-fullname" on the PDF form within the template.
Programatically, we are doing this:
const tabClientFullName = docusign.Text.constructFromObject({ tabLabel: 'client-fullname', value: 'John Q Smith' });
const dsTabs = docusign.Tabs.constructFromObject({
textTabs: [
tabClientFullName
]
});
const signer1 = docusign.TemplateRole.constructFromObject({
email: signerEmail,
name: signerName,
roleName: 'signer',
tabs: dsTabs
});
env.templateRoles = [signer1];
env.status = 'sent'; // We want the envelope to be sent
What are we missing?
So, first of all, you can put the tabs on the template directly. Not filled out, but just place them there, so that all you have to do in the API is fill them.
{This code below shows different types of tabs, not just text.}
So, when the template has tabs, the code to fill them is like this:
(note each tabs has a tabLabel property)
// create the envelope definition with the template id
let envelopeDefinition = docusign.EnvelopeDefinition.constructFromObject({
templateId: args.templateId,
status: "sent",
});
// Set the values for the fields in the template
// List item
let list1 = docusign.List.constructFromObject({
value: "green",
documentId: "1",
pageNumber: "1",
tabLabel: "list",
});
// Checkboxes
let check1 = docusign.Checkbox.constructFromObject({
tabLabel: "ckAuthorization",
selected: "true",
}),
check3 = docusign.Checkbox.constructFromObject({
tabLabel: "ckAgreement",
selected: "true",
});
// The NOde.js SDK has a bug so it cannot create a Number tab at this time.
//number1 = docusign.Number.constructFromObject({
// tabLabel: "numbersOnly", value: '54321'});
let radioGroup = docusign.RadioGroup.constructFromObject({
groupName: "radio1",
// You only need to provide the radio entry for the entry you're selecting
radios: [
docusign.Radio.constructFromObject({ value: "white", selected: "true" }),
],
});
let text = docusign.Text.constructFromObject({
tabLabel: "text",
value: "Jabberwocky!",
});
// We can also add a new tab (field) to the ones already in the template:
let textExtra = docusign.Text.constructFromObject({
document_id: "1",
page_number: "1",
x_position: "280",
y_position: "172",
font: "helvetica",
font_size: "size14",
tab_label: "added text field",
height: "23",
width: "84",
required: "false",
bold: "true",
value: args.signerName,
locked: "false",
tab_id: "name",
});
// Pull together the existing and new tabs in a Tabs object:
let tabs = docusign.Tabs.constructFromObject({
checkboxTabs: [check1, check3], // numberTabs: [number1],
radioGroupTabs: [radioGroup],
textTabs: [text, textExtra],
listTabs: [list1],
});
// Create the template role elements to connect the signer and cc recipients
// to the template
let signer = docusign.TemplateRole.constructFromObject({
email: args.signerEmail,
name: args.signerName,
roleName: "signer",
clientUserId: args.signerClientId, // change the signer to be embedded
tabs: tabs, // Set tab values
});
// Create a cc template role.
let cc = docusign.TemplateRole.constructFromObject({
email: args.ccEmail,
name: args.ccName,
roleName: "cc",
});
// Add the TemplateRole objects to the envelope object
envelopeDefinition.templateRoles = [signer, cc];
// Create an envelope custom field to save the our application's
// data about the envelope
let customField = docusign.TextCustomField.constructFromObject({
name: "app metadata item",
required: "false",
show: "true", // Yes, include in the CoC
value: "1234567",
}),
customFields = docusign.CustomFields.constructFromObject({
textCustomFields: [customField],
});
envelopeDefinition.customFields = customFields;
return envelopeDefinition;
https://github.com/docusign/code-examples-node/blob/master/lib/eSignature/examples/setTemplateTabValues.js
We figured it out. The role 'signer' must match the role used to place forms on the template PDF. Once we changed the role name, everything worked correctly.

How to send email using sendgrid in Nodejs using dynamicTemplateData?

This my first time I use sendgrid for mail. I have problem with dynamic data passed from database. Actually HTML content passed in object and display as it is in mail. For more detail check below object.
{
to: "to Email"
from: "from email",
templateId: "Template ID",
dynamicTemplateData: {
subject: "Testing Templates",
name: "Some One",
city: "Denver",
week: "August 24 2020",
job0: {
header: "Test",
body: "<table border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td class="
snip ">We are looking for physically fit individuals to fill general labour requirements by partnering with a truck driver. Your help is needed to load/unload the truck at the various job sites. <b>Skills required: </b> - comfortable with physical exertion and lifting minimum of 50lbs - works well on a team but trusted to work independently - reliable, self-motivated and committed to high standards of quality - able to read and understand work instructions <b>Specific requirements: </b> - in good physical condition - must have own safety footwear - reliable transportation to ensure punctual and consistent attendance If you meet the qualifications listed above, submit your resume in MS Word format via the link below. <i>Previously employed with The Staffing Connection? Please contact our office to confirm your continued availability for these upcoming positions.</i></td> </tr> </tbody> </table>",
cta: "Apply now",
url: "My URL"
},
}
}
Code
getJobs().then((jobs) => {
var mailPayload = {
to: emails,
from: "",
templateId: "",
dynamicTemplateData: {
subject: "Testing Templates",
name: "Some One",
city: "Denver",
week: "August 24 2020",
},
};
for (let i = 0; i < jobs.length; i++) {
mailPayload.dynamicTemplateData["job" + i] = {
header: jobs[i].job_title,
body: jobs[i].job_description,
cta: "Apply now",
url: jobs[i].company_url,
};
}
mail(mailPayload);
res.send("Mail sent Successfully").status(200);
});
});
Here is the Output
Please help me to solve this issue.

Adaptive Cards and Microsoft Bot Framework: will only permit 'openUrl' action?

EDIT 2: The following schema (provided by a colleague) works. I removed the quotation marks from the schema in the examples from Microsoft, but that still didn't work. I'm not sure what the issue is. I leave the question open in case someone else wants to provide an answer, but I've got it working.
const card = {
contentType: 'application/vnd.microsoft.card.adaptive',
content: {
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
type: 'AdaptiveCard',
version: '1.0',
{
type: 'Input.Text',
placeholder: 'Name',
style: 'text',
maxLength: 50,
id: 'defaultInput'
},
actions: [
{
type: 'Action.Submit',
title: 'Siguiente',
data: {} // will be populated with form input values
}
]
}
};
I'm trying to make a form in my MS Bot using Adaptive Cards. I took the sample form from the MS site (https://blog.botframework.com/2019/07/02/using-adaptive-cards-with-the-microsoft-bot-framework/) but get the following error
The error seems to be thinking that my action type is Action.openUrl but I don't see that in my code, which is below. Any help much appreciated. Using Microsoft Bot Framework 3, Node 12.13.0.
function askPolicyNumber(session) {
const card = {
'$schema': 'https://adaptivecards.io/schemas/adaptive-card.json',
'type': 'AdaptiveCard',
'version': '1.1',
'body': [
{
'type': 'Input.Text',
'id': 'id_text'
},
{
'type': 'Input.Number',
'id': 'id_number'
}
],
'actions': [
{
'type': 'Action.messageBack',
'title': 'Submit',
'data': {
'prop1': true,
'prop2': []
}
}
]
};
const msg = new builder.Message(session).attachments([card]);
return session.send(msg);
}
EDIT:
It seems that no matter what I set the action to it keeps thinking it's an openUrl action. In fact, if I set it to openUrl and give it a url property, it works fine.
I looked at this page -- https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-actions#adaptive-cards-actions -- and followed the instructions there for 'Adaptive Cards with messageBack action', but it didn't change anything
"actions": [
{
"type": "Action.Submit",
"title": "Click me for messageBack",
"data": {
"msteams": {
"type": "messageBack",
"displayText": "I clicked this button",
"text": "text to bots",
"value": "{\"bfKey\": \"bfVal\", \"conflictKey\": \"from value\"}"
}
}
}
]
}
There are a lot of problems with what you're doing. It is recommended that everyone use Bot Builder v4 instead of v3. The main problem that your colleague solved was that you were trying to use an Adaptive Card object as though it was an Attachment object.
The blog post you linked to explains that Adaptive Cards must follow the Adaptive Cards schema. There is no Action.messageBack in the Adaptive Cards schema. Please continue referring to the documentation for more information.

Gmail email markup not working with invoices and script.google.com

I'm testing this markup https://developers.google.com/gmail/markup/reference/invoice on https://script.google.com/, so I discard all the SPF problems.
This is the JS:
function testSchemas() {
var htmlBody = HtmlService.createHtmlOutputFromFile('mail_template').getContent();
MailApp.sendEmail({
to: Session.getActiveUser().getEmail(),
subject: 'Test Email markup - ' + new Date(),
htmlBody: htmlBody,
});
}
And this is the HTML
<html>
<head>
<script type='application/ld+json'>
{
"#context": "http://schema.org",
"#type": "Invoice",
"accountId": "123-456-789",
"minimumPaymentDue": {
"#type": "PriceSpecification",
"price": "$70.00"
},
"paymentDue": "2015-11-22T08:00:00+00:00",
"paymentStatus": "PaymentAutomaticallyApplied",
"provider": {
"#type": "Organization",
"name": "Mountain View Utilities"
},
"totalPaymentDue": {
"#type": "PriceSpecification",
"price": "$70.00"
}
}
</script>
</head>
<body>
<p>
This a test for a Go-To action in Gmail.
</p>
</body>
</html>
As you may see, the code should be fine. Ok, I execute the code and I receive this (please, add "h" at beggining, stackoverflow dont let me add more than 2 links):
https://i.stack.imgur.com/bg8S2.png
https://i.stack.imgur.com/ituM0.png
What I'm doing wrong? one-click actions on http://gmail-actions.appspot.com/ works fine, but I can't get working invoices.

#docusignapi frequent event=ttl_expired when using inline signing

When using docusign inline signing api, I get event=ttl_expired frequently. I even tried using the Docusign API Explorer and the same thing happens. For every two out of three URLs that I get, I get the ttl_expired error. I checked the possible reasons given in DocuSign getRecipientView ttl_expired error but to no avail.
Is there something that I am missing here?
The truncated sample json is below. I have replaced the mail IDs & name field.
{
signers: [{
name: 'Name',
email: 'mail#example.com',
text_tabs: [
{
label: 'Name Field',
anchor_string: 'Name:',
anchor_x_offset: '100',
anchor_y_offset: '-10',
document_id: '1',
page_number: '10',
required: true,
width: 200,
height: 10
}
],
sign_here_tabs: [
{
label: 'Signature',
anchor_string: 'Signature',
anchor_x_offset: '100',
anchor_y_offset: '-20',
document_id: '1',
page_number: '10',
}
],
routing_order: 1,
embedded: true,
role_name: 'FirstRole',
clientUserId: 1
},
{
name: 'Another Name',
email: 'Anothermail#example.com',
sign_here_tabs: [
{
anchor_string: 'COMPANY:',
anchor_x_offset: '-20',
anchor_y_offset: '-20'
}
],
routing_order: 2,
embedded: false,
role_name: 'SecondRole'
}],
status: 'sent',
return_url: 'http://www.google.com',
email_subject: 'Agreement from Document',
email_body: 'Please sign the Agreement',
files: [
{
path: File.join('/', 'docusign_docs', 'Agreement.pdf'),
name: 'Agreement.pdf'
}
]
}
1) Per the other article you reference, the URL that is returned must be opened/used within 300 seconds
2) These are one time use URL's only. If you try to re-use the same URL a second+ time, it will automatically re-direct you to the landing page w/ttl_expired event.
Your design pattern must be to request the signing url from DocuSign immediately before re-directing the human to the signing url. Anything else will not be reliable.
If you need a longer lasting url for the signing ceremony, then use your own url, to your own application. When the user clicks on that url, your application should:
Verify the url
Obtain a signing url from DocuSign
Redirect the user to the signing url

Resources