Sending "CC" and "BCC" in substitution data when calling Node SparkPost API - javascript

I have templates created in SparkPost dashboard. But the problem I face is that I am not able to send "CC" or "BCC" by making the api calls. The code snippet below will help you understand what I am trying to do.
var SPARKPOST_KEY = "KEY"
var sparkpost = require('sparkpost');
var sparkclient = new sparkpost(SPARKPOST_KEY);
var req_opts = {
transmissionBody : {
content: {
template_id: 'order-confirmation',
from: 'support#domain.in',
subject: 'Order confirmation',
headers: {
"CC": "<anon2#gmail.com>"
}
},
substitution_data: {
"CC": "anon2#gmail.com",
"customer": "Aravind",
"order": 123532
},
recipients: [
{address: {email:'anon1#domain1.in'}},
{address: {email: 'anon2#gmail.com'}}
],
"return_path": "support#domain.in",
}
};
sparkclient.transmissions.send(req_opts, function(err, res){
if(err){
console.log("ERROR");
console.log(err)
}else {
console.log(res.body);
console.log("Mail has been successfully sent");
}
});

As mentioned in the reply on your github issue, you must use either inline content or a template. So as the documentation says, use just template_id in your content.
What needs to happen for this to work is that the headers in the template include a CC header, as described here. Currently there is no way to set the headers of a template in the UI -- it must be done using the API.
To do this execute a PUT against the templates endpoint, in your case https://api.sparkpost.com/api/v1/templates/order-confirmation, with a JSON payload containing the following:
{
"content": {
<other content parts>
"headers": {
"CC": "{{CC}}"
}
}
}
Note that you will also need to use the header_to parameter for your CC recipient to prevent their address showing up in the To: header. In your example this means replacing:
{address: {email: 'anon2#gmail.com'}}
with this:
{address: {email: 'anon2#gmail.com', header_to: 'anon1#domain1.in'}}
You also do not need the return_path parameter.
Hope this helps!

Related

Dialogflow Fulfilment webhook call failed

I am new to dialogflow fulfillment and I am trying to retrieve news from news API based on user questions. I followed documentation provided by news API, but I am not able to catch any responses from the search results, when I run the function in console it is not errors. I changed the code and it looks like now it is reaching to the newsapi endpoint but it is not fetching any results. I am utilizing https://newsapi.org/docs/client-libraries/node-js to make a request to search everything about the topic. when I diagnoise the function it says " Webhook call failed. Error: UNAVAILABLE. "
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const http = require('http');
const host = 'newsapi.org';
const NewsAPI = require('newsapi');
const newsapi = new NewsAPI('63756dc5caca424fb3d0343406295021');
process.env.DEBUG = 'dialogflow:debug';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((req, res) =>
{
// Get the city
let search = req.body.queryResult.parameters['search'];// search is a required param
// Call the weather API
callNewsApi(search).then((response) => {
res.json({ 'fulfillmentText': response }); // Return the results of the news API to Dialogflow
}).catch((xx) => {
console.error(xx);
res.json({ 'fulfillmentText': `I don't know the news but I hope it's good!` });
});
});
function callNewsApi(search)
{
console.log(search);
newsapi.v2.everything
(
{
q: 'search',
langauge: 'en',
sortBy: 'relevancy',
source: 'cbc-news',
domains: 'cbc.ca',
from: '2019-12-31',
to: '2020-12-12',
page: 2
}
).then (response => {console.log(response);
{
let articles = response['data']['articles'][0];
// Create response
let responce = `Current news in the $search with following title is ${articles['titile']} which says that
${articles['description']}`;
// Resolve the promise with the output text
console.log(output);
}
});
}
Also here is RAW API response
{
"responseId": "a871b8d2-16f2-4873-a5d1-b907a07adb9a-b4ef8d5f",
"queryResult": {
"queryText": "what is the latest news about toronto",
"parameters": {
"search": [
"toronto"
]
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"intent": {
"name": "projects/misty-ktsarh/agent/intents/b52c5774-e5b7-494a-8f4c-f783ebae558b",
"displayName": "misty.news"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {
"webhook_latency_ms": 543
},
"languageCode": "en"
},
"webhookStatus": {
"code": 14,
"message": "Webhook call failed. Error: UNAVAILABLE."
},
"outputAudio": "UklGRlQqAABXQVZFZm10IBAAAAABAAEAwF0AAIC7AAACABAAZGF0YTAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (The content is truncated. Click `COPY` for the original JSON.)",
"outputAudioConfig": {
"audioEncoding": "OUTPUT_AUDIO_ENCODING_LINEAR_16",
"synthesizeSpeechConfig": {
"speakingRate": 1,
"voice": {}
}
}
}
And Here is fulfillment request:
{
"responseId": "a871b8d2-16f2-4873-a5d1-b907a07adb9a-b4ef8d5f",
"queryResult": {
"queryText": "what is the latest news about toronto",
"parameters": {
"search": [
"toronto"
]
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"intent": {
"name": "projects/misty-ktsarh/agent/intents/b52c5774-e5b7-494a-8f4c-f783ebae558b",
"displayName": "misty.news"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {
"webhook_latency_ms": 543
},
"languageCode": "en"
},
"webhookStatus": {
"code": 14,
"message": "Webhook call failed. Error: UNAVAILABLE."
},
"outputAudio": "UklGRlQqAABXQVZFZm10IBAAAAABAAEAwF0AAIC7AAACABAAZGF0YTAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (The content is truncated. Click `COPY` for the original JSON.)",
"outputAudioConfig": {
"audioEncoding": "OUTPUT_AUDIO_ENCODING_LINEAR_16",
"synthesizeSpeechConfig": {
"speakingRate": 1,
"voice": {}
}
}
}
Also here is the screenshot from the firebase console.
Can anyone guide me what is that I am missing in here?
The key is the first three lines in the error message:
Function failed on loading user code. Error message: Code in file index.js can't be loaded.
Did you list all required modules in the package.json dependencies?
Detailed stack trace: Error: Cannot find module 'newsapi'
It is saying that the newsapi module couldn't be loaded and that the most likely cause of this is that you didn't list this as a dependency in your package.json file.
If you are using the Dialogflow Inline Editor, you need to select the package.json tab and add a line in the dependencies section.
Update
It isn't clear exactly when/where you're getting the "UNAVAILABLE" error, but one likely cause if you're using Dialogflow's Inline Editor is that it is using the Firebase "Spark" pricing plan, which has limitations on network calls outside Google's network.
You can upgrade to the Blaze plan, which does require a credit card on file, but does include the Spark plan's free tier, so you shouldn't incur any costs during light usage. This will allow for network calls.
Update based on TypeError: Cannot read property '0' of undefined
This indicates that either a property (or possibly an index of a property) is trying to reference against something that is undefined.
It isn't clear which line, exactly, this may be, but these lines all are suspicious:
let response = JSON.parse(body);
let source = response['data']['source'][0];
let id = response['data']['id'][0];
let name = response['data']['name'][0];
let author = response['author'][0];
let title = response['title'][0];
let description = response['description'][0];
since they are all referencing a property. I would check to see exactly what comes back and gets stored in response. For example, could it be that there is no "data" or "author" field in what is sent back?
Looking at https://newsapi.org/docs/endpoints/everything, it looks like none of these are fields, but that there is an articles property sent back which contains an array of articles. You may wish to index off that and get the attributes you want.
Update
It looks like that, although you are loading the parameter into a variable with this line
// Get the city and date from the request
let search = req.body.queryResult.parameters['search'];// city is a required param
You don't actually use the search variable anywhere. Instead, you seem to be passing a literal string "search" to your function with this line
callNewsApi('search').then((output) => {
which does a search for the word "search", I guess.
You indicated that "it goes to the catch portion", which indicates that something went wrong in the call. You don't show any logging in the catch portion, and it may be useful to log the exception that is thrown, so you know why it is going to the catch portion. Something like
}).catch((xx) => {
console.error(xx);
res.json({ 'fulfillmentText': `I don't know the news but I hope it's good!` });
});
is normal, but since it looks like you're logging it in the .on('error') portion, showing that error might be useful.
The name of the intent and the variable I was using to make the call had a difference in Casing, I guess calls are case sensitive just be aware of that

What is wrong with my JSON output for a Slack Message payload?

I have set up what I think should be a working JSON output to send a message in slack but Slack keeps rejecting it.
I have tried multiple different message layout formats using the guides on slack's api site, but so far the only method that has successfully sent is a fully flat JSON with no block formatting.
function submitValuesToSlack(e) {
var name = e.values[1];
var caseNumber = e.values[2];
var problemDescription = e.values[3];
var question = e.values[4];
var completedChecklist = e.values[5];
var payload = [{
"channel": postChannel,
"username": postUser,
"icon_emoji": postIcon,
"link_names": 1,
"blocks": [
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Name:*\n " + name
}
]
}]
}];
console.log(JSON.stringify(payload, null, "\t"));
var options = {
'method': 'post',
'payload': JSON.stringify(payload)
};
console.log(options)
var response = UrlFetchApp.fetch(slackIncomingWebhookUrl, options);
}
When I run this, I get the following output:
[
{
"channel":"#tech-support",
"username":"Form Response",
"icon_emoji":":mailbox_with_mail:",
"link_names":1,
"blocks":[
{
"type":"section",
"fields":[
{
"type":"mrkdwn",
"text":"*Name:*\n test"
}
]
}
]
}
]
Which I believe is correct, however slack api just rejects it with an HTTP 400 error "no text"
am I misunderstanding something about block formatting?
EDIT:
To Clarify, formatting works if I use this for my JSON instead of the more complex format:
{
"channel":"#tech-support",
"username":"Form Response",
"icon_emoji":":mailbox_with_mail:",
"link_names":1,
"text":"*Name:*\n test"
}
The reason you are getting the error no_text is because you do not have a valid message text property in your payload. You either need to have a text property as top line parameter (classic style - your example at the bottom) or a text block within a section block.
If you want to put to use blocks only (as you are asking) the section block is called text, not fields. fields is another type of section bock that has a different meaning.
So the correct syntax is:
[
{
"channel":"#tech-support",
"username":"Form Response",
"icon_emoji":":mailbox_with_mail:",
"link_names":1,
"blocks":[
{
"type":"section",
"text":[
{
"type":"mrkdwn",
"text":"*Name:*\n test"
}
]
}
]
}
]
Also see here for the official documentation on it.
Blocks are very powerful, but can be complicated at times. I would recommend to use the message builder to try out your messages and check out the examples in the docu.

FCM message payload errors, Nested object within data object errors out

According to the react-native-fcm package you can include a custom nested object within the data object for a FCM messaging payload.
according to this post by the package author
Like this:
var payload = {
data: {
custom_notification: {
title: 'title',
body: 'body',
priority: 'high',
id: 'id',
group: 'group'
}
}
};
This is for the purpose of receiving heads up notifications in all app states, which will not happen if you do just a notification payload or data payload.
When I implement this in my cloud function I get the following error:
Error: Messaging payload contains an invalid value for the "data.custom_notification" property. Values must be strings.
So I'm at a loss as to how others can be using this successfully?
I wonder if there's some issue going on with my environment or something as the following test payload which was given to me by firebase support (and is in the docs) errors out:
var payload = {
"to":"FCM_TOKEN",
"data": {
"type":"MEASURE_CHANGE",
"body": "test body",
"title": "test title",
"color":"#00ACD4",
"priority":"high",
"id": "id",
"show_in_foreground": true
}
};
I get the following error:
Error sending message stringify: {"code":"messaging/invalid-payload","message":"Messaging payload contains an invalid \"to\" property. Valid properties are \"data\" and \"notification\"."}
Been at this for days so hopefully I can get a bit of help on this.
Thanks in advance!
So I realised just now (after days of searching) that the package react-native-fcm is using a different send method than admin.messaging().sendToDevice(token, payload, options). I had been using that for a while now and didn't realize that it was not actually what was intended to be used with this library or atleast in this scenario. Mainly because everything was working fairly well using admin.messaging() up until I wanted heads up notifications in all app states.
The other method is like this
sendData(token) {
let body = {
"to": token,
"data":{
"title": "Simple FCM Client",
"body": "This is a notification with only DATA.",
"sound": "default",
"click_action": "fcm.ACTION.HELLO",
"remote": true
},
"priority": "normal"
}
this._send(JSON.stringify(body), "data");
}
_send(body, type) {
let headers = new Headers({
"Content-Type": "application/json",
"Content-Length": parseInt(body.length),
"Authorization": "key=" + FirebaseConstants.KEY
});
fetch(API_URL, { method: "POST", headers, body })
.then(response => console.log("Send " + type + " response", response))
.catch(error => console.log("Error sending " + type, error));
}
You can use nested objects within the data object using this method. The documentation is not super clear on this unfortunately, I didn't even realise there was an example until now. Of course this could have just been me.
When using the data message payload, it is stated to use key value pairs that are String, so what you could do is have the value of your custom_notification as JSON String by enclosing them in " ".
For the sample payload provided, are you actually using the FCM_TOKEN in the to parameter? You're supposed to replace it with an actual token.

Creating an envelope from a template returning "UNSPECIFIED_ERROR"

When I try to create an envelope from a template I get a response of:
{ errorCode: 'UNSPECIFIED_ERROR',
message: 'Non-static method requires a target.' }
Here's what I'm doing so far:
First I login, which returns
{ loginAccounts:
[ { name: '*****',
accountId: '*****',
baseUrl: 'https://demo.docusign.net/restapi/v2/accounts/******',
isDefault: 'true',
userName: '***** ********',
userId: '*******-*****-*****-*****-*********',
email: '********#*******.com',
siteDescription: '' } ] }
So then I take the baseUrl out of that response and I attempt to create the envelope. I'm using the hapi framework and async.waterfall of the async library, so for anyone unfamiliar with either of these my use of the async library uses the next callback to call the next function which in this case would be to get the url for the iframe, and with our usage of the hapi framework AppServer.Wreck is roughy equivalent to request:
function prepareEnvelope(baseUrl, next) {
var createEntitlementTemplateId = "99C44F50-2C97-4074-896B-2454969CAEF7";
var getEnvelopeUrl = baseUrl + "/envelopes";
var options = {
headers: {
"X-DocuSign-Authentication": JSON.stringify(authHeader),
"Content-Type": "application/json",
"Accept": "application/json",
"Content-Disposition": "form-data"
},
body : JSON.stringify({
status: "sent",
emailSubject: "Test email subject",
emailBlurb: "My email blurb",
templateId: createEntitlementTemplateId,
templateRoles: [
{
email: "anemailaddress#gmail.com",
name: "Recipient Name",
roleName: "Signer1",
clientUserId: "1099", // TODO: replace with the user's id
tabs : {
textTabs : [
{
tabLabel : "acct_nmbr",
value : "123456"
},
{
tabLabel : "hm_phn_nmbr",
value : "8005882300"
},
{
tabLabel : "nm",
value : "Mr Foo Bar"
}
]
}
}
]
})
};
console.log("--------> options: ", options); // REMOVE THIS ====
AppServer.Wreck.post(getEnvelopeUrl, options, function(err, res, body) {
console.log("Request Envelope Result: \r\n", JSON.parse(body));
next(null, body, baseUrl);
});
}
And what I get back is:
{ errorCode: 'UNSPECIFIED_ERROR',
message: 'Non-static method requires a target.' }
From a little googling it look like 'Non-static method requires a target.' is a C# error and doesn't really give me much indication of what part of my configuration object is wrong.
I've tried a simpler version of this call stripping out all of the tabs and clientUserId and I get the same response.
I created my template on the Docusign website and I haven't ruled out that something is set up incorrectly there. I created a template, confirmed that Docusign noticed the named form fields, and created a 'placeholder' templateRole.
Here's the templateRole placeholder:
Here's one of the named fields that I want to populate and corresponding data label:
As a side note, I was able to get the basic vanilla example working without named fields nor using a template using the docusign node package just fine but I didn't see any way to use tabs with named form fields with the library and decided that I'd rather have more fine-grained control over what I'm doing anyway and so I opted for just hitting the APIs.
Surprisingly when I search SO for the errorCode and message I'm getting I could only find one post without a resolution :/
Of course any help will be greatly appreciated. Please don't hesitate to let me know if you need any additional information.
Once I received feedback from Docusign that my api call had an empty body it didn't take but a couple minutes for me to realize that the issue was my options object containing a body property rather than a payload property, as is done in the hapi framework.

login page not working (javascript, firebase)

HELP!
I'm not sure what's going on, but my login page isn't working. It simply reloads even though I'm entering valid user/password.
I think the problem is it's getting stuck on issues with my data-structure, security-rules, and app.js, but I'm at a loss.
I was provided a sinatra/ruby simple api to work with users & groups (just a small project).
here's the site:
https://starter-vicks9985.firebaseapp.com/index.html
here's the code:
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
{
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}
), console.log("success");
{
"rules": {
".read": true,
"users": {
"$user": {
//can add a message if authenticated
".write": "auth.uid === $user"
}
},
"rooms": {
"$room": {
"users": {
// can write to the users list only if ADMINISTRATOR
"$user": {
"write":"newData.parent().child(auth.uid).val() === 99"
}
}
}
},
"messages": {
"$room": {
"$message": {
//can add a message if they are a MEMBER (if there was message/chat capability)
".write": "(!data.exists() && newData.exists() && root.child('rooms/' + $room + '/users/' + auth.uid).val() >= 10)"
}
}
}
}
}
$(document).ready(function() {
/**
*Set initial firebase ref. Use set to write in first admin user.
*/
var ref = new Firebase("https://starter-vicks9985.firebaseio.com/");
ref.set({
"name": "Admin",
"email": "admin#example.com",
"password": "secret",
"admin": true
});
/** Get email address from loginform, format email, get password
* Firebase keys cannot have a period (.) in them, so this converts the emails to valid keys
*/
var emailAddress = function emailToKey(emailAddress){
return btoa(emailAddress);
};
var password = document.getElementById('password');
/**
* Authorize user with email and password, passing in values from form.
*/
ref.authWithPassword({
email : emailAddress,
password : password,
}, function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
return authData;
}
});
/**
* If user is logged in (valid), redirect to user profile
*/
ref.onAuth(function(authData) {
window.open="https://starter-vicks9985.firebaseio.com/userprofile/userprofile.html";
})
});
Like #Kato said, this is a code dump so please consider creating an mcve. Although, first check out my comments below.
The Code You Posted
After glancing at your code, I see some errors that I will point out:
1. Your jQuery post syntax is incorrect, and wouldn't work even if it was correct.
Most importantly, you are making a post request to a Ruby file. Firebase Hosting is not a server, it is hosting for static files.
See this answer by Frank. He says:
Firebase hosting is a product to serve so-called static application, which consist only of files that the client interprets. Firebase's servers will not interpret any code that you upload. So Firebase hosting is not suited to host your Ruby-on-Rails application.
To quote Firebase hosting's documentation:
We deliver all your static content (html, js, images, etc)
That being said, take a look at the jQuery documentation for $.post().
See my comments on your code:
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
// ^ What is this '/'?
{
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}
), console.log("success");
// ^ You are closing the function call, 'console.log' falls outside of it.
What it should look like:
$.post("https://starter-vicks9985.firebaseapp.com/main.rb", {
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}, function() {
console.log("success");
});
2. What's even going on with the login functions?
Assuming you fix Uncaught SyntaxError: Unexpected token { in data-structure.js:14...
If you take a look at the console, you will see Uncaught Error: Firebase.authWithPassword failed: First argument must contain the key "email" with type "string".
That is because you are passing a function, emailAddress to .authWithPassword().
You declare emailAddress() like so:
var emailAddress = function emailToKey(emailAddress){
return btoa(emailAddress);
};
So the email parameter in the following is being passed emailAddress(), not a string that is an email address.
ref.authWithPassword({
email : emailAddress,
password : password,
}, function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
return authData;
}
});
Most importantly, all of these login functions are being called immediately after the page loads. Nothing in your code (app.js) waits for, and responds to, the submission of the form.
The Code on Your Website
I also went on your page, looked at your source code, and found some more issues.
1. Error in form HTML in index.html
<section class="loginform cf">
<form id= "login" form name="login" form type= "submit" accept-charset="utf-8">
<!-- extra^space ^duplicate "form"^ ^again, space -->
...
</form>
</section>
2. Syntax Errors in data-structures.js
Again, you have the same errors here as I described above ('/' and closing parentheses), but the object that you're passing the post is incorrectly formatted
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
{
"users" //missing ':' after users
//the following objects do not have keys - should be {"users":{"someUserKey1":{...},"someUserKey2":{...}}} etc.
{
"name": "admin",
"email": "...",
"password": "...",
"admin": true,
"role-value": 99,
},
{
"name": "aaa",
...
},
{
"name": "bbb",
...
}
},
), console.log("success");
And the same things apply for the post call for "groups".
I hope that provides some clarity.
I would suggest reading over other answers here on StackOverflow, like:
jQuery AJAX submit form
jQuery form submit
And search for more answers like:
https://stackoverflow.com/search?q=jquery+form+submit
In conclusion, I'd suggest doing some more research and reading documentation :)

Categories

Resources