Mailgun Attachment + Axios - reactjs

I would like to send an attachment with Mailgun using react+axios.
Currently, I get an email with an attachment, but it is not named correctly (the name is ".") and if I rename it to a text file it contains the text "[object Object]".
Do you have any idea how to solve this problem?
const form = new FormData();
const fs = require("fs");
form.append("from", "example#gmx.ch");
form.append("to", "Bob <example#hotmail.ch>");
form.append("subject", "Test");
form.append("text", "Hello!!");
form.append("attachment", [{
filename: "example.txt",
data: fs.readFileSync(__dirname + "/text.txt", {
encoding: "utf8",
flag: "r"
})
}]);
const endpoint = "https://api.mailgun.net/v3/sandbox123.mailgun.org/messages";
await axios.post(endpoint, form, {
auth: {
username: "api",
password: process.env.MAILGUN_API_KEY
},
headers: { "Content-Type": "multipart/form-data" }
});

Two things:
As per the mailgun docs when sending attachments you must use "multipart/form-data" encoding. Try:
await axios.post(endpoint, form, {
auth: {
username: "api",
password: process.env.MAILGUN_API_KEY
},
headers: { 'Content-Type': 'multipart/form-data' }
});
Try putting your attachment object inside an array. I am not familiar with the mailgun API but I saw a couple examples where the attachments were inside an array, maybe even if there is a single attachment the API is still expecting it this way.

Related

POST <input> file as binary/octet-stream Content-Type using Axios

My plan is to upload a file received from an input tag, to an S3 bucket.
I need to manage a way to pass that file of type [Object file] into a supported type for the header of my API "Content-Type: "binary/octet-stream". But I've tried using Buffer.from(), .toString("base64") but none of these made any changes.
This is the API POST request:
export async function sendToS3(uploadURL, file) {
let request = {
method: "PUT",
url: uploadURL,
headers: {
"Content-Type": "binary/octet-stream",
},
data: file
};
const response = await axios(request);
return response.data;
};
And this is how the received file looks, which I need to send to S3:
File {
name: "filename.jpg",
lastModified: "1652758134934",
size: "64058",
type: "image/jpeg",
webkitRelativePath: "folderName/filename.jpg"
}

React JS CORS-ORIGIN - Instagram Basic Display API

I have problem with CORS: Access-Control-Allow-Origin when try to exchange the code for access token from Instagram API.
Instagram API documentation Step 5 : https://developers.facebook.com/docs/instagram-basic-display-api/getting-started#step-5--exchange-the-code-for-a-token
Body parametars:
const body = {
'client_id': 'xxxxxxxxxxxxxx',
'client_secret': 'xxxxxxxxxxxxxx',
'grant_type': 'authorization_code',
'redirect_uri': 'https://localhost:3000/',
'code': instaCode
};
My request:
axios.post(`https://api.instagram.com/oauth/access_token`, qs.stringify(body), {
headers: {'content-type': 'application/x-www-form-urlencoded'}
});
Đ¢his code worked 2 months ago.
edit: you can try this axios post request to send form data first which seems better, below worked for me though
That won't work, you have to send the body in a form data.
I believe fetch API would work but that's available since node 17, if you're using earlier version this is what worked for me.
SOURCE https://www.section.io/engineering-education/integrating-instagram-basic-display-api/
const { post } = require("request");
const { promisify } = require("util");
const postAsync = promisify(post);
const form = {
client_id: NUMBER,
client_secret: STRING,
grant_type: "authorization_code",
redirect_uri: STRING,
code: req.body.code,
};
let { body, statusCode } = await postAsync({
// let result = await postAsync({
url: "https://api.instagram.com/oauth/access_token",
form,
headers: {
"content-type": "multipart/form-data",
host: "api.instagram.com",
},
});
npm i request
and use that inside a try/catch of course

axios POST request to strapi image upload [Internal Server Error]

I'm uploading an image to strapi using axios but the response is 500 error. However in Postman the request is 200
POSTMAN
AXIOS CODE
let bodyFormData = new FormData();
bodyFormData.append('files', this.state.avatar, this.state.avatar.name)
bodyFormData.append('ref', 'user')
bodyFormData.append('refId', getId())
bodyFormData.append('field', 'avatar')
bodyFormData.append('source', 'users-permmissions')
axios({
method: 'post',
url: `${strapi}/upload`,
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': `Bearer ${withToken()}`,
},
data: bodyFormData,
}).then(res=>console.log(res.data)).catch(err=>{console.log(err.response.data.message)})
what's supposed to be the issue here?
Here's part of the strapi user model
{
"avatar": {
"model": "file",
"via": "related",
"plugin": "upload",
"required": false
}
}
The solution is to throw Axios in the trash. I struggled with this for a day of my life that I will never get back. There's a longish, years-old thread at https://github.com/axios/axios/issues/318 with people complaining about being unable to get multipart form uploads to work with Axios.
I switched to the request-promise module and got it to work within minutes, using the following simple code:
const fs = require("fs-extra");
const rp = require('request-promise');
let out = await rp({
method: 'POST',
uri: 'http://mystrapihost/upload',
formData: {
// Like <input type="text" name="ref">
'ref': "customer", // name of the Strapi data type, singular
'field': "attachments", // a field named "attachments" of type "Media"
'refId': "838e238949ewhd82e8938299e289e99", // strapi ID of object to attach to
// Like <input type="file" name="files">
"files": { // must be called "files" to be "seen" by Strapi Upload module
name: "myfile.pdf",
value: fs.createReadStream("/path/to/myfile.pdf"),
options: {
filename: "myfile.pdf",
contentType: 'application/pdf'
},
},
},
headers: {Authorization: 'Bearer myjwtgobbledygook123456'} // put your JWT code here
});
console.log(out);
Enjoy!!

How to upload an image to Discord using Google Apps Script and a Discord Webhook?

I've written the following script:
function uploadImageToDiscord() {
var link = "https://i.imgur.com/image.jpg";
var img = UrlFetchApp.fetch(link).getBlob();
var discordUrl = "https://discordapp.com/api/webhooks/mywebhook";
var payload = {
"file": img
};
var params = {
headers: {
"Content-Type": "multipart/form-data"
},
method: "post",
payload: payload,
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(discordUrl, params);
Logger.log(response.getContentText());
}
However, GAS tells me that I'm trying to send an empty message. Can anyone help me?
Error Message
The error must be related to either the way of me trying to download the image:
var img = UrlFetchApp.fetch(link).getBlob();
or the way of how I define the payload for the multipart/form-data content:
var payload = {
"file": img
};
How about this modification?
Modified script:
From:
var params = {
headers: {
"Content-Type": "multipart/form-data"
},
method: "post",
payload: payload,
muteHttpExceptions: true
};
To:
var params = {
method: "post",
payload: payload,
muteHttpExceptions: true
};
Additional information:
For example, if you want to add the text to the file, please use the following request body.
var payload = {
content: "sample text", // Added
file: img
};
var params = {
method: "post",
payload: payload,
muteHttpExceptions: true
};
Reference:
Webhook Resource
In my environment, I am using such request body. And it works fine. But if in your environment, it didn't work, please tell me. I would like to think of other solutions.

S3 signature does not match on getSignedUrl serverside node

I'm trying to put a video file to my bucket using a pre-signed url in angular4.
Node:
let s3 = new AWS.S3();
s3.config.update({
accessKeyId: process.env.VIDEO_ACCESS_KEY,
secretAccessKey: process.env.VIDEO_SECRET_KEY
})
let videoId = await Video.createVideo()
let params = {
ACL: "public-read",
Bucket: process.env.BUCKET_NAME,
ContentType: 'video/mp4',
Expires: 100,
Key: req.jwt.username+"/"+videoId,
}
return s3.getSignedUrl('putObject', params, function (err, url) {
if(!err) {
console.log(url);
res.status(200);
res.json({
url: url,
reference: `${process.env.BUCKET_NAME}/${req.jwt.username}/${videoId}`,
acl: params.ACL,
bucket: params.Bucket,
key: params.Key,
contentType: params.ContentType,
});
} else {
console.log(err);
res.status(400);
res.json({
message: "Something went wrong"
})
}
});
This successfully generates a url for me, and I try to use it in my post request in the front end.
Angular:
this.auth.fileUpload().subscribe((result) => {
console.log(result["key"], result["acl"], result["bucket"], result["contentType"])
if(!result["message"]) {
let formData = new FormData();
formData.append('file', file.files[0]);
const httpOptions = {
headers: new HttpHeaders({
"Key": result["key"],
"ACL": result["acl"],
"Bucket": result["bucket"],
"Content-Type": result["contentType"],
})
};
this.http.post(result["url"], formData, httpOptions ).subscribe((response) => {
console.log("response");
console.log(response);
let reference = `https://s3.amazonaws.com/${result["reference"]}`
this.auth.makeVideo(result["reference"]).subscribe((result) => {
console.log(result);
});
}, (error) => {
console.log("error");
console.log(error);
})
But this generates an error.
SignatureDoesNotMatch
The request signature we calculated does not match the signature you provided. Check your key and signing method
Here's the URL that I generate
https://MY_BUCKET_HERE.s3.amazonaws.com/admin/87f314f1-9f2e-462e-84ff-25cba958ac50?AWSAccessKeyId=MY_ACCESS_KEY_HERE&Content-Type=video%2Fmp4&Expires=1520368428&Signature=Ks0wfzGyXmBTiAxGkHNgcYblpX8%3D&x-amz-acl=public-read
I'm pretty sure I'm just making a simple mistake, but I can't figure it out for the life of me. Do I need to do something with my headers? Do I need to change the way I read the file for the post? I've gotten it to work with a public bucket with FormData and a simple post request with no headers, but now that I'm working with Policies and a private bucket, my understanding is much less. What am I doing wrong?
If you generate a pre-signed URL for PutObject then you should use the HTTP PUT method to upload your file to that pre-signed URL. The POST method won't work (it's designed for browser uploads).
Also, don't supply HTTP headers when you invoke the PUT. They should be supplied when generating the pre-signed URL, but not when using the pre-signed URL.

Resources