Can't get handlebars to work with dynamic templates - sendgrid

I am very stuck. Tried everything I could think of to solve this issue, but I feel as though it is just something wrong with my JSON. When I build a dynamic template, I'd like to insert some variables for the send. As you can see in the example, simply just adding the first name in the handlebars. However, when I send tests using postman, I can not for the life of me get the first_name to display. I've tried so many different options in the JSON and nothing seems to work. Here is where I am currently at, omitting the first_name obviously. Any help on how to format this I would very much appreciate it.
{
"from": {"email":"example#example.com"},
"template_id":"ID HERE"
"personalizations": [
{
"to": [
{
"email":"recipient#gmail.com"
}
]
}
]
}
I tried 100 different variations of the request.

Twilio developer evangelist here.
I think that using that JSON is mainly for when you're using the API to send an email with a template. You then provide the JSON data as dynamic_template_data and it is populated in the email template.
first_name is a reserved field and substitution tag which lets you use any reserved or custom field data you've added to Marketing Campaigns to dynamically generate unique content for each recipient of your email. One common example is adding a recipient's first name to the body (or even the subject line) of your email.
The data that populates your Substitution Tags will come from the information you have stored about each contact.
You can work with substitution tags with the code editor or design editor.
Let me know if this helps at all!

Related

Google action builder/Google assitant How to use proper noun as type

i would like to have a type that represent proper nom, such as family name for exemple but i can't find anything on this.
My goal is to send a info to an other personne using google assistant and my backend.
For exemple the user can say "Send this info to john smith" the info is stored in my backend so i have no problem finding and i got the id of the personne who is talking to the google assistant so this is no problem either.
The problem is how can i get john smith as a parameter that i send to my webhook? So my backend can verify the user list in my database and send the info if the user existe. I tried to use Type but a family doesn't match any pattern because it's can be anything...
If anyone know how to use google action builder with proper noun i would be grateful to know how i can manage to do it.
You have generally two options.
Free form text approach
First you can create a "Free form text" type which can catch pretty much anything being said.
Then a custom intent can be trained with a few examples to pull out the correct proper noun (or anything else). Your webhook will be able to match at that point.
Type Overrides approach
Alternatively, you can create a new type that starts with a preset of sample names that you use in your custom intent. Then, when the action starts, you can get the user's personal contact list in the webhook and set session type overrides.
Here's an example of the code I got from a music player action:
conv.session.typeOverrides = [{
name: 'genre',
mode: Mode.TypeReplace,
synonym: {
entries: Array.from(trackGenres).map(genre => ({
name: genre,
synonyms: [genre]
}))
}
}]
Depending on your system architecture, one of these may make more sense than the other. The first is better at capturing everything, but may require more post-processing on your webhook. The latter is better at precision, but may mean names may not match if they don't match entirely.

Salesforce send Email by Apex

I'm making by a requirement a code able to send an E-mail to an specific list of E-mails, due the fact that I must to include the attachments of the record I decided to use an apex class instead an e-mail alert. This object (A custom object ) must populate some fields in an email template with some of the record´s fields. I implemented the following code
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(lista);
mail.setTemplateId('00X21000000QR22');
//mail.setWhatId(idMinuta);
mail.setTargetObjectId('005d0000005NMIx');
mail.setSaveAsActivity(false);
List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();
for (ContentVersion document: documents)
{
Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();
efa.setFileName(document.Title);
efa.setBody(document.VersionData);
fileAttachments.add(efa);
}
mail.setFileAttachments(fileAttachments);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
I understood that to make the fields merge it´s necesary to use the WhatId method. In the related code, I have commented it because It generates an error (INVALID_ID_FIELD, WhatId is not available for sending emails to UserIds.)
My question is, if is it possible to do this with a custom object. I´m a little confuse with salesforce documentation beacuse it looks like the method supports a custom object, or maybe If I am forggeting something to include in the code.
If i keep the WhatID line commented, effectively the email is sent with the attachments and the Template but it is not populated.
I really need this kind of solution because the org have in this object at least 20 email templates, for me will be easier just to pass the Id of the template instead of makig a code with 20 different html codes for each situation
Thanks a lot
Please publish this question at Salesforce StackExcahnge https://salesforce.stackexchange.com/

How can I add unsubscribe links to my emails when sending via sendgrid/mail

I'm sending emails using: https://github.com/sendgrid/sendgrid-nodejs/tree/master/packages/mail
I have not been able to find out HOW I can add the Unsubscribe equivalent. This is documented in here: https://sendgrid.com/docs/Classroom/Basics/Marketing_Campaigns/unsubscribe_groups.html#-Using-a-Custom-Unsubscribe-Link
On the website, you just use a shortcode [Unsubscribe], this does not work when sending emails via the sendgrid/mail package.
One tip that would have saved me an hour or two is that:
It's possible to send the following in the api json along with other stuff:
"asm":{
"group_id":123,
"groups_to_display": [123],
}
then the following variables become available to use within the template:
<%asm_group_unsubscribe_raw_url%>
<%asm_preferences_raw_url%>
If you want to keep things simple don't include the following variable as it fiddles with too many things (this wasn't obvious from the documentation so obviously I did so and wasted time :( ):
"tracking_settings": {
"subscription_tracking": {
"enable": true,
"substitution_tag": "[unsubscribe_url]"
}
}
Just use them in their raw format and you shall be fine.
Since you're sending using code, it's a "transactional" type of message. You'll want to either turn on the Subscription Tracking filter at the account level (via [UI](subscription tracking setting) or API), or turn it on as you send the message, as part of the mail/send API call, under tracking_settings.
It's important to note that you can't mix those. If you define anything in the mail/send API call, you'll need to define everything for Subscription Tracking in that call. SendGrid won't look at some settings at the mail level, and some at the account level.
Most users will just set it at the account level. There, you can customize the HTML & Text of the Unsubscribe footer, customize the HTML of the landing page, or redirect landing to a URL of your choosing, which will send the recipient there with ?email=test#domain.com in the URL string for your system to catch. You can also define the "replacement tag" like [%unsubscribe%], so that you can place the URL wherever you want within your HTML.
https://app.sendgrid.com/ > Suppressions > Unsubscribe Groups > Create New Group
Note down group_id/ids. e.g 123 (Only number !Not string)
Send email using node.js
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);
const tags = { invitedBy : Alex }
const msg = {
to: email,
from: { "email": SENDER_EMAIL,
"name": SENDER_NAME
},
templateId: TEMPLATE_ID,
dynamic_template_data: {
Sender_Name: name,
...tags
},
asm: {
group_id: 123,
groups_to_display: [
123
],
},
};
await sgMail.send(msg);
The best approach is to use Group Unsubscribes.
First create a group in Sendgrid:
Groups > Unsubscribe Groups > Create a group
Next, insert a module into the Sendgrid template that creates specific tags in your email, which are populated when you make an API request
Go to your template
Insert an unsubscribe module in an HTML block
Save
Finally make an API request and specify the group created in step 1:
"asm":{
"group_id":544,
"groups_to_display": [544, 788],
}
These will be inserted into the module mentioned in step 2 when the email is sent.
Unfortunately Sendgrid unsubscribe links are not as straightforward as they could be. They are explained in more detail here
The easiest way is to do this via the SendGrid GUI.
Go to Settings -> Tracking -> Subscription Tracking

Unable to retrieve 'ContentId' property of Attachment in Office365 REST Api

I'm trying to retrieve attachments in the Office365 rest api. Since I want to avoid downloading the entire attachments, I'm using a select clause to avoid downloading the content, which is in the ContentBytes property:
$select="ContentId,ContentType,Id,IsInline,Name,Size"
So basically, I want to retrieve everything except the content. However, this gives the following error message (json):
{
"error":
{
"code": "RequestBroker-ParseUri",
"message": "Could not find a property named 'ContentId' on type 'Microsoft.OutlookServices.Attachment'."
}
}
It's telling me that ContentId doesn't exist, which contradicts the specifications.
Edit: Here is the full request:
GET /api/v2.0/me/messages/AAMkAGZlZjI3N2I3LTg1YWUtNDFiNC05MGI0LTVjYTVmZGI5NGI2YQBGAAAAAABzr8uDji9LRqgTCEsDv22wBwBWTXbvZW0dTKuxUGxpK4-lAAAAAAEMAABWTXbvZW0dTKuxUGxpK4-lAAC5QnKBAAA=/attachments?%24select=ContentId%2CContentType%2CId%2CIsInline%2CName%2CSize
Even more strange, when I do the same query without specifying any select clause, it returns me a full attachment object, including a ContentId.
Anybody can help?
In case anyone has the same question for microsoft graph, you need to pass this filter:
$select=microsoft.graph.fileAttachment/contentId
like this:
GET https://graph.microsoft.com/v1.0/me/messages/attachments?$select=microsoft.graph.fileAttachment/contentId
The request that you posted is getting the message specifications but not the attachments. Since you need to get the content id, you need to add /attachments to the request with any required parameters.
GET https://outlook.office.com/api/v2.0/me/messages/{message_id}/attachments/{attachment_id}
So please add the attachments to your query to be able to get the content id.
Hope this helps.
Solved it. The answer was suggested by Brian's comment and I found an additional hint here.
Since 'ContentId' is a property of a FileAttachment, you need to specify that in the request, like so:
$select="Microsoft.OutlookServices.FileAttachment/ContentId,ContentType,Id,IsInline,Name,Size"
That did the trick. Thanks for the suggestions.

Copy specific text from email message to spreadsheet

I get my checking account balance emailed to me once per day. I want to use Google Apps Script to pull the balance from the email message and plug it into my checking account spreadsheet. I am a novice to coding, but so far I have figured out how to do the following, which gets me a log of HTML code of the correct email message:
function myFunction() {
var thread = GmailApp.getUserLabelByName("CHK BAL").getThreads(0,1)[0]; // get first thread in inbox
var message = thread.getMessages()[0]; // get first message
Logger.log(message.getBody()); // log contents of the body
}
However, because this method returns the HTML code for the email message and not the actual message text, it doesn't contain the balance number that shows up in the email itself.
I tried substituting getPlainBody in place of getBody, but it returns a null value in the Log.
The question posted here is pretty much my same question (Google script that find text in my gmail and adds it to a spreadsheet?), but even with Mogsdad's reply and helpful links I haven't been able to figure out what's going wrong.
Can anyone help redirect me on how to get the email content instead of the null value?
(Once that's solved, I can't say that the link on Mogsdad's other reply is very clear about how to identify the currency and copy it into the spreadsheet, but of course I haven't been able to play around yet since I can't even access the content yet.)
Thanks!
EDIT 1
See Serge's answer below for instructions on how to parse the HTML. I used those functions to grab the text of the most recent Bank Account Balance email from a Gmail label/filter and drop it into a cell in my spreadsheet.
Then I was able to use the following equation in an adjacent cell to strip it down to just the currency number:
LEFT(RIGHT(A5,LEN(A5)-FIND("$",A5)),FIND(CHAR(10),RIGHT(A5,LEN(A5)-FIND("$",A5)))-1)+0
Of course, this works for me because the currency number is always preceded by $ (the first, and in my case, only $ to appear in the text) and always followed by CHAR(10). Anyone trying to apply this formula would need similar consistency before and after the value they are seeking to isolate.
You could try this code snippet originally written by Corey G on SO to get the text from the html content. I use it quite often and it works nicely most of the time :) (Thanks Corey)
function getTextFromHtml(html) {
return getTextFromNode(Xml.parse(html, true).getElement());
}
function getTextFromNode(x) {
switch(x.toString()) {
case 'XmlText': return x.toXmlString();
case 'XmlElement': return x.getNodes().map(getTextFromNode).join('');
default: return '';
}
}
And a test function to try it :
function test(){
var html = GmailApp.getInboxThreads()[0].getMessages()[0].getBody();
throw(getTextFromHtml(html));
}
As to why getPlainBody() is returning null, it is most likely due to a bug in Google Apps Script. The issue has been filed at https://code.google.com/p/google-apps-script-issues/issues/detail?id=3980.
From that thread: "It seems the messages affected contain HTML in their content. A possible workaround involves using getBody() instead of getPlainBody() and parsing through the HTML directly."