Using Angular and SendGrid, I am trying to send an email. I installed the NPM package correctly but am having issues with implementing the code. I generated an API key and stored it in the directory with
echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env
echo "sendgrid.env" >> .gitignore
source ./sendgrid.env
The Typescript is:
sgemail(){
const sgMail = require('#sendgrid/mail'); //ERROR: Cannot find name 'require'.
sgMail.setApiKey(process.env.SENDGRID_API_KEY); //ERROR: Cannot find name 'process'.
const msg = {
to: 'test#example.com',
from: 'test#example.com',
subject: 'Sending with SendGrid is Fun',
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>',
};
console.log(msg);
sgMail.send(msg);
}
I am firing this on a button click.
Sendgrid has no information on their site about importing packages like how you have to use import { Vibration } from '#ionic-native/vibration'; to use Ionic's vibration package.
You could try sending a POST request manually using fetch to their Send Mail API. And don't forget the Authorization Headers. Below is a same untested JavaScript code snippet to try. Fill in YOUR_API_KEY and update the to email to one of your emails.
var payload = {
"personalizations": [
{
"to": [
{
"email": "john#example.com"
}
],
"subject": "Hello, World!"
}
],
"from": {
"email": "from_address#example.com"
},
"content": [
{
"type": "text/plain",
"value": "Hello, World!"
}
]
};
var myHeaders = new Headers({
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY",
});
var data = new FormData();
data.append( "json", JSON.stringify( payload ) );
fetch("https://api.sendgrid.com/v3/mail/send",
{
method: "POST",
headers: myHeaders,
body: data
})
.then(function(res){ return res.json(); })
.then(function(data){ console.log( JSON.stringify( data ) ) })
Related
I am attempting to add dynamic links to push notifications so users tap them and open to a specific app page. I have been following the documentation and the links do not open to the page they should when I tap the push notifications but when tested in the browser the links do open to the correct page. From what I have read, there are 2 possible solutions depending on the version of firebase the project is using. The older "way" is to add a click_action property to the apns payload object, the newer way is to create a webpush object with the fcm_options property set to the value of the link. Neither of these options seems to work regardless of where the objects are placed in the request. Is my request formatted incorrectly or am I possibly missing something? Below is the current request:
const [title, body, deepLink] = titleAndBody;
let accessToken = await getAccessToken();
accessToken = "Bearer " + accessToken;
const options = {
method: "POST",
url: URL,
headers: {
Authorization: accessToken,
"Content-Type": "application/json",
},
body: JSON.stringify({
message: {
token: fcmToken,
notification: {
body: body,
title: title,
},
webpush: {
fcm_options: {
link: deepLink,
}
},
apns: {
headers: {
priority: "10",
},
payload: {
//click_action: deepLink,
aps: {
badge: 0,
mutable_content: 1,
},
},
}
},
}),
};```
Hi I have been experimenting with webhooks and I'm wondering how do you send a normal message(not embeded) through a webhook with a custom avatar and name
const user = message.mentions.users.first() || client.users.cache.get(args[0]);
let announcement = args.slice(1).join(" ");
if(!announcement) return message.channel.send(`lol say something`)
const wc = new WebhookClient('id', 'token')
const embed = new MessageEmbed()
.setTitle("").setColor('GREEN').setTimestamp().setDescription(announcement)
wc.send({
username : user.username,
avatarURL : user.displayAvatarURL({ dynamic : true }),
embeds : [embed]
})
}
```
If you wish to send Discord webhooks you need to make a POST API request to the webhook url.
For that you can basically use any module you want however in this example I'll use node-fetch. Simply install it in your console
npm install node-fetch
and then require it where you need to use it
const fetch = require('node-fetch');
Now that we have what we need to make it work lets create the API request.
For that we start with the params variable. Here you set all the things that make the webhook look like you want it to look. Note: I also included how to send embeds just in case. If you want to see all options check here.
var params = {
username: "Your name",
avatar_url: "",
content: "Some message you want to send",
embeds: [
{
"title": "Some title",
"color": 15258703,
"thumbnail": {
"url": "",
},
"fields": [
{
"name": "Your fields here",
"value": "Whatever you wish to send",
"inline": true
}
]
}
]
}
Now that we have the params we can create the actual POST request. For that you simply call the fetch function and provide the webhook url.
First you specify the method you want to use. By default the method is GET. Next make sure to set the headers to 'Content-type': 'application/json', otherwise you'll get an error. Lastly include the params from earlier in the body. We use JSON.stringify() here to make it work.
fetch('URL', {
method: "POST",
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => {
console.log(res);
})
At the end you have the option to catch any errors you might receive.
I am trying to send the file with the http-request node but it is not working.
Please find the following image of Node-red flow.
In the Request Body node I have added the following code.
const inputFile = msg.payload;
const dataJson =
{
'name': 'testName',
'description':'testdescription',
'inputfile': inputFile
};
msg.payload = dataJson;
msg.url = 'myAPIurl';
msg.headers = {
'authorization': 'Bearer TOKEN Here',
'cookie': 'Cookie here',
'content-type': 'multipart/form-data;'
};
return msg;
This is giving bad request error.
In the Read File node I tried choosing both options A single UTF8-String and a single Buffer Object still I got the same error
But I tried to call the API inside function node using the request module. It is giving the proper response.
const request = global.get("request");
const fs = global.get("fs");
const url = 'API';
const tkn = 'TOken Here';
const cookie = 'cookie here';
const fl = fs.createReadStream('/tmp/node-red/app/data/filename.txt');
var options = {
method: 'POST',
url: url,
headers: {
'Authorization': tkn,
'Cookie': cookie,
},
formData: {
"name": "test121",
"description": "",
inputfile: fl
}
};
request(options, function (err, resp, body) {
console.log(body);
});
return msg;
I am not sure where I am making the mistake if I use http-request node.
From the sidebar docs for the http-request node:
File Upload
To perform a file upload, msg.headers["content-type"] should be set
to multipart/form-data and the msg.payload passed to the node must
be an object with the following structure:
{
"KEY": {
"value": FILE_CONTENTS,
"options": {
"filename": "FILENAME"
}
}
}
The values of KEY, FILE_CONTENTS and FILENAME should be set to the
appropriate values.
Following this doc, your msg.payload is wrong, it should look something like:
msg.payload: {
"name": "testName",
"description": "description",
"inputfile": {
"value": inputfile,
"options": {
"filename": "filename.txt"
}
}
}
I am trying to send an email using POST request with just Node standard modules in NodeJS v8.10 via GMail API.
The sample code is given below.
I am getting an error:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalidArgument",
"message": "Recipient address required"
}
],
"code": 400,
"message": "Recipient address required"
}
}
It says recipient address required but according to what I think, (I may be wrong), my base64url conversion is proper since I checked it in Google API Explorer but my problem is in passing the data, I am doing it properly as told in the guide i.e. inside body with 'raw' key but it still does not work and this is where my problem must be. Maybe I am missing something, maybe I do not know the proper structure.
Yes, there are multiple posts regarding this but none of them provided solution.
I referred the guide on https://developers.google.com/gmail/api/v1/reference/users/messages/send
but the given example is of with the use of client library.
I tried everything, passing the 'raw' with base64url encoded data into write function of the request, passing it as a data parameter in options, passing it through body parameters in options, everything I can think of.
Am I missing something? Where am I going wrong?
I am a newbie in nodejs so please explain and if possible, an example structure of solution would be most welcome.
Base64url produced is working fine, I guess. I copied the string produced by conversion and tried it at https://developers.google.com/gmail/api/v1/reference/users/messages/send?apix=true
It works fine and sends me the mail but it does not work on my code.
var email = (
"Content-Type: text/plain; charset=\"UTF-8\"\n" +
"Content-length: 5000\n" +
"MIME-Version: 1.0\n" +
"Content-Transfer-Encoding: message/rfc2822\n" +
"to: something#something.com\n" +
"from: \"Some Name\" <something#gmail.com>\n" +
"subject: Hello world\n\n" +
"The actual message text goes here"
);
async function sendMail(token,resp) {
return new Promise((resolve,reject) => {
var base64EncodedEmail = Buffer.from(email).toString('base64');
var base64urlEncodedEmail = base64EncodedEmail.replace(/\+/g, '-').replace(/\//g, '_');
var params = {
userId: 'me',
resource: {
'raw': base64urlEncodedEmail
}
};
var body2 = {
"raw": base64urlEncodedEmail,
}
var options = {
hostname: 'www.googleapis.com',
path:'/upload/gmail/v1/users/me/messages/send',
headers: {
'Authorization':'Bearer '+token,
'Content-Type':'message/rfc822',
},
body: {
"raw": base64urlEncodedEmail,
'resource': {
'raw': base64urlEncodedEmail,
}
},
data: JSON.stringify({
'raw': base64urlEncodedEmail,
'resource': {
'raw': base64urlEncodedEmail,
}
}),
message: {
'raw': base64urlEncodedEmail,
},
payload: {
"raw": base64urlEncodedEmail, //this is me trying everything I can think of
},
// body: raw,
// }
userId: 'me',
// resource: {
// 'raw': base64urlEncodedEmail
// },
method: 'POST',
};
var id='';
console.log(base64urlEncodedEmail);
const req = https.request(options, (res) => {
var body = '';
res.on('data', (d) => {
body += d;
});
res.on('end', () => {
var parsed = body;
console.log(parsed);
})
});
req.on('error', (e) => {
console.error(e);
});
req.write(JSON.stringify(body2));
req.end();
});
};
Thank you for your time and answers.
I found the solution.
It says everywhere to convert the rfc822 formatted string to Base64url to send and attach it to 'raw' property in the POST body but I don't know what has changed and you don't need to do that anymore.
First things first, the Content-Type in header should be
'Content-Type':'message/rfc822'
Now, since we are specifying the content-type as message/rfc822, we don't need to convert the data we want to send into base64url format anymore, I guess (Not sure of the reason because I have a very little knowledge about this.)
Only passing "To: something#any.com" as body works.
Here is the complete code of how to get it done for someone who is struggling for the same problem.
function makeBody(to, from, subject, message) {
let str = [
"to: ", to, "\n",
"from: ", from, "\n",
"subject: ", subject, "\n\n",
message,
].join('');
return str;
}
async function getIdAsync(token,resp) {
return new Promise((resolve,reject) => {
let raw = makeBody("something#gmail.com", "something#gmail.com", "Subject Here", "blah blah blah");
var options = {
hostname: 'www.googleapis.com',
path:'/upload/gmail/v1/users/me/messages/send',
headers: {
'Authorization':'Bearer '+token,
'Content-Type':'message/rfc822'
},
method: 'POST',
};
const req = https.request(options, (res) => {
var body = '';
res.on('data', (d) => {
body += d;
});
res.on('end', () => {
var parsed = body;
console.log(parsed);
})
});
req.on('error', (e) => {
console.error(e);
});
req.write(raw);
req.end();
});
};
Happy Coding :)
I have problems with the discovery of devices of my Alexa Smart Home skill.
Steps which work:
activate Alexa skill
OAuth login screen appears. After successful login, the discovery of devices is triggered
in the lambda function I get the bearer token which I use to call the .../devices endpoint
I get the devices from the REST endpoint and construct the payload as described in https://developer.amazon.com/de/docs/smarthome/steps-to-build-a-smart-home-skill.html
The payload (same structure as in the example) is provided to context.succeed
My problem:
After the Alexa Skill returns from discovery of devices task, no new devices are visible in the Alexa Skill.
When I use the code from the sample (where no request to an external Rest API happens), the device is visible in the Alexa skill after the Alexa discovery task.
var https = require('https');
const AWS = require('aws-sdk');
exports.handler = function(request, context) {
var options = {
method: 'GET',
hostname: 'xyz.azurewebsites.net',
path: '/devices',
headers: {
Authorization: 'Bearer ' + request.directive.payload.scope.token,
'Content-Type': 'application/json'
}
};
var req = https.get(options, (response) => {
var data = '';
response.setEncoding('utf8');
response.on('data', function(x) { data += x; } );
response.on('error', console.error);
response.on('end', () => {
var dataObj = JSON.parse(data);
console.log("Retrieved response: " + JSON.stringify(dataObj.items));
const payload = {
"endpoints": []
};
dataObj.items.forEach(item => {
const device = {
"endpointId": item.id,
"manufacturerName": item.manufacturer,
"friendlyName": item.displayName,
"description": item.description,
"displayCategories": ["SWITCH"],
"cookie": {
"key1": "arbitrary key/value pairs for skill to reference this endpoint.",
"key2": "There can be multiple entries",
"key3": "but they should only be used for reference purposes.",
"key4": "This is not a suitable place to maintain current endpoint state."
},
"capabilities":
[
{
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
},
{
"interface": "Alexa.PowerController",
"version": "3",
"type": "AlexaInterface",
"properties": {
"supported": [{
"name": "powerState"
}],
"retrievable": true
}
}
]
};
payload.endpoints.push(device);
});
console.log('payload ' + JSON.stringify(payload));
var header = request.directive.header;
header.name = "Discover.Response";
console.log("DEBUG", "Discovery Response: ", JSON.stringify({ header: header, payload: payload }));
//NEXT LINE IS EXECUTED WITHOUT ANY ERROR
context.succeed({ event: { header: header, payload: payload } });
});
});
req.on('error', (e) => {
console.log('problem with request: ' + e.message);
});
};
I found the problem...
The value of the property 'endpointId' contained a '#'. Then I changed the name to only letters, and it worked.
Although in this article it says '#' can be used, the discovery of devices then has problems.
Hope this answer helps others from wasting time...
I found another cause for the same symptom: for the entity's additionalAttributes (manufacturer, model etc.), one cannot use non-English characters. You can actually use any character ASCII from 32 to 126 (space to tilde), but you cannot use the backslash. So, no accent characters (international or extended ASCII) allowed.
On the other hand, I could include a entity with '#' inside its endpointId. I cannot explain why you couldn't.