Sendgrid sending mail with attachment using web api v3 - php

I'm new to using sendgrid web api v3. link here
Right now. It was easy to send a plain html using there api 'POST https://api.sendgrid.com/v3/mail/send' but I have this instance where we will attach a file (csv/xls,pdf) and I can't seem to get it right.
Here is my code below:
My function postSendMail
public function postSendMail($data = [])
{
if ( ! arrayHasValue($data) ) $this->error(__METHOD__, "Data is empty.");
$request = Curl::to( $this->apiUrl.'mail/send' )
->withHeader('Authorization: Bearer '. $this->apiKey)
->withData( $data )
->asJson(true)
->enableDebug(storage_path('logs/laravel-'.php_sapi_name().'.log'))
->post();
return $request;
}
//my instance
$sendgrid = new Sendgrid;
$data = [
'personalizations' => [
[
'to' => [
[ 'email' => 'myemail#gmail.com' ]
],
'subject' => 'Hello, World!'
]
],
'from' => [
'email' => 'myemail#gmail.com',
'name' => 'my_site'
],
'content' => [
[
'type' => 'text',
'value' => 'Hello, World!'
]
],
'track_settings' => [
[
'click_tracking' => true,
'open_tracking' => true
]
],
'attachments' => [
[
'content' => base64_encode(config('global.UPLOAD_PATH') . '/my_file.pdf'),
'type' => 'application/pdf',
'filename' => 'my_file.pdf',
'disposition' => 'attachment'
]
]
];
$lists = $sendgrid->postSendMail($data);
Mail was successfully sent but when I view the attached file, it was corrupted/unable to view. Can anyone help me? :(
Please help.

The problem is that you are not reading the file into an object and then encoding that object; you're encoding a string containing the file path.
'content' => base64_encode(config('global.UPLOAD_PATH') . '/my_file.pdf')
All of your attachments in the tests are probably the same size, and smaller than the actual file as a result.
Try something like:
$imagedata = file_get_contents(config('global.UPLOAD_PATH') . '/my_file.pdf');
$base64 = base64_encode($imagedata);

Coming to main point you need to get file content either by curl request or by file_get_content then encode the that content into attachments->content parameter, Please check following code which works for me:
'attachments' => [
[
'content' => base64_encode(file_get_contents(config('global.UPLOAD_PATH') . '/my_file.pdf')),
'type' => 'application/pdf',
'filename' => 'my_file.pdf',
'disposition' => 'attachment'
]
]

Related

Upload image to facebook using graph api in PHP

I'm trying to upload an image to facebook using graph api. I want to submit the image as a file instead of providing a URL which is another option. I'm using PHP Laravel and guzzle to achieve this. Unfortunately when I upload the file I'm getting an error which would seem to indicate that the image is not recognised.
This is the documentation I am using
https://developers.facebook.com/docs/graph-api/reference/page/photos/#publish
This is my error message
message: "Client error: `POST https://graph.facebook.com/v12.0/99999999999/photos` resulted in a `400 Bad Request` response:\n{\"error\":{\"message\":\"(#324) Requires upload file\",\"type\":\"OAuthException\",\"code\":324,\"fbtrace_id\":\"ACxilINTWYdb3wGOXfGg7 (truncated...)\n"
Here is my code
public function media(Request $request)
{
$facebookPageConnection = FacebookPageConnection::find(2);
$file = $request->file('file');
$client = new Client();
$body = $client->post("https://graph.facebook.com/v12.0/$facebookPageConnection->facebook_page_id/photos", [
'multipart' => [
[
'name' => 'message',
'contents' => 'test post'
],
[
'name' => 'source',
'contents' => base64_encode(file_get_contents($file))
],
[
'name' => 'access_token',
'contents' => $facebookPageConnection->access_token
]
]
])->getBody();
return json_decode($body);
}
My mistake was to use
file_get_contents
and
base64_encode
Instead to get it to work I needed to use fopen
$body = $client->post("https://graph.facebook.com/v12.0/$facebookPageConnection->facebook_page_id/photos", [
'multipart' => [
[
'name' => 'message',
'contents' => 'test post'
],
[
'name' => 'source',
'contents' => fopen($file, 'rb')
],
[
'name' => 'access_token',
'contents' => $facebookPageConnection->access_token
]
]
])->getBody();

Paypal Customer Dispute API - Provide Evidence always returns MISSING_OR_INVALID_REQUEST_BODY

I've been trying to upload a pdf file when providing an evidence to Paypal Disputes in the Claim Stage after verifying that the dispute case has the /provide-evidence on its HATEOAS links, the curl code below works in the CLI:
$ curl -v -X POST https://api.sandbox.paypal.com/v1/customer/disputes/PP-D-12345/provide-evidence \
-H "Content-Type: multipart/related" \
-H "Authorization: Bearer {AccessToken}" \
-F 'input={"evidences":[{"evidence_type": "PROOF_OF_FULFILLMENT", "evidence_info": {"tracking_info": [{"carrier_name": "FEDEX", "tracking_number": "123456789"}]}, "notes": "Test"}]};type=application/json' \
-F 'file1=#D:\Sample\storage\app\paypal\sample.pdf'
However when converted to PHP, either using curl or guzzle the API returns VALIDATION_ERROR - MISSING_OR_INVALID_REQUEST_BODY, I've tried almost every possible approach, but the error is consistent.
Using Guzzle: (trying to copy the working curl above as much as possible, since Guzzle can't send multipart/related request, I had to modify the content-type manually).
$pdf = 'D:\Sample\storage\app\paypal\sample.pdf';
$input = [
'evidences' => [
[
'evidence_type' => 'PROOF_OF_FULFILLMENT',
'evidence_info' => [
'tracking_info' => [
'carrier_name' => "FEDEX",
'tracking_number' => '122533485'
]
],
'notes' => 'Test',
],
]
];
$client = new \GuzzleHttp\Client([
'base_uri' => 'https://api.sandbox.paypal.com',
'timeout' => 2.0,
'version' => 1.1
]);
$options = [
'headers' => [
'Authorization' => "Bearer $token",
],
'multipart' => [
[
'name' => 'input',
'contents' => json_encode($input),
'headers' => ['Content-Type' => 'application/json']
],
[
'name' => 'file1',
'contents' => fopen($pdf, 'r'),
'filename' => 'sample.pdf',
'headers' => ['Content-Type' => 'application/pdf']
],
]
];
$url = '/v1/customer/disputes/'.$disputeId.'/provide-evidence';
$headers = isset($options['headers']) ? $options['headers'] : [];
$body = new \GuzzleHttp\Psr7\MultipartStream($options['multipart']);
$request = new \GuzzleHttp\Psr7\Request('POST', $url, $headers, $body, '1.1');
$modify['set_headers']['Content-Type'] = 'multipart/related; boundary=' . $request->getBody()->getBoundary();
$request = \GuzzleHttp\Psr7\modify_request($request, $modify);
$response = $client->send($request);
The guzzle code above still return {VALIDATION_ERROR - MISSING_OR_INVALID_REQUEST_BODY} and same result when I just do a normal multipart/form-data request.
What could be the issue? Any ideas or suggestion would very much help, thanks.
$input = [
'evidences' => [
[
'evidence_type' => 'PROOF_OF_FULFILLMENT',
'evidence_info' => [
'tracking_info' => [
'carrier_name' => "FEDEX",
'tracking_number' => '122533485'
]
],
'notes' => 'Test',
],
]
];
This is your $input, if you json_encode() it, you get
{
"evidences":
[
{
"evidence_type":"PROOF_OF_FULFILLMENT",
"evidence_info":{
"tracking_info":{
"carrier_name":"FEDEX",
"tracking_number":"122533485"
}
},
"notes":"Test"
}
]
}
which does not matches with your request body,
I have changed your $input by inserting another square bracket,
$input = [
'evidences' => [
[
'evidence_type' => 'PROOF_OF_FULFILLMENT',
'evidence_info' => [
'tracking_info' => [[
'carrier_name' => "FEDEX",
'tracking_number' => '122533485'
]]
],
'notes' => 'Test',
],
]
];
Now it matches your curl request,
{
"evidences":
[
{
"evidence_type":"PROOF_OF_FULFILLMENT",
"evidence_info":
{
"tracking_info":
[
{
"carrier_name":"FEDEX",
"tracking_number":"122533485"
}
]
},
"notes":"Test"
}
]
}
I hope it helps. If it doesn't work, then problem might lie somewhere else but the request body will match, you can try the guzzle call first.

Guzzle: how to send a file and a second text field?

I must simulate the sending of a form which has
a file selector
a text input
I'm sending the file using this snippet
$response = $this->getClient()->request(
$method,
$endpoint,
[
'headers' => ['Content-Type' => 'multipart/form-data' ],
'multipart' => [
[
'Content-type' => 'multipart/form-data',
'name' => 'file _name.tiicsti',
'contents' => 'hello my content',
'filename' => 'filename.txt',
]
]
]
)
;
It works.
My question is: how to send a text field in addition to my file?
Resolved !
I am surprise that headers is not needed. Probably Guzzle makes some magic
$response = $this->getClient()->request(
$method,
$endpoint,
'multipart' => [
[
'name' => 'text-field-name',
'contents' => 'text field value'
],
[
'name' => 'file _name.tiicsti',
'contents' => 'hello my content',
'filename' => 'filename.txt',
]
]
]
)
;

Send Multipart Form from PHP with Guzzle

I'm trying to create a multipart form for upload file in my API.
According the docs of guzzle :
\\$data = picture of form
\\$uri = Endpoint in my API
$this->client->post($uri, [
'multipart' => [
[
'name' => 'picture',
'contents' => file_get_contents($data),
]
],
'headers' => $headers
]);
When I'm using Insomnia or Postman :
I'm not understand why it not working in Guzzle.
$file = new File($data->getPathname());
$tmp_picture_path = Storage::putFile("temp_dir", $file);
$tmp_picture = Storage::readStream($tmp_picture_path);
$response = $this->client->post(
$uri,
[
'multipart' => [
[
'name' => 'picture',
'contents' => $tmp_picture,
'filename' => "avatar." . $data->getClientOriginalExtension()
]
],
'headers' => $headers
]
);
Storage::delete($tmp_picture_path);
Just save locally the file and read the stream dor send it properly.

Upload image file using slack API files.upload method

The following code seems to work, but the Slack API saves the file a plain text.
protected function upload($file)
{
$client = $this->guzzle;
if (!$token) {
$token = env('SLACK_TOKEN');
}
$response = $client->request('POST', env('SLACK_API') . "/files.upload?token=$token", [
'form_params' => [
'name' => $file->getFilename(),
'content' => File::get($file->getRealPath()),
'filename' => $file->getFilename(),
'filetype' => 'image',
'channels' => "#_test",
]
]);
return json_decode((string)$response->getBody());
}
When I use the guzzle multipart post, I get the error: 'no_file_data' I feel like I am missing something.
Is there a way to upload images or non-text files using the files.upload method in the Slack API?
Almost as soon as I posted this question, I realized that I was formatting the array incorrectly on the multipart post in guzzle.
This seems to work:
$response = $this->guzzle->post(env('SLACK_API') . "/files.upload?token=$token",
['multipart' =>
[
[
'name' => 'filename',
'contents' => $file->getClientOriginalName()
],
[
'name' => 'file',
'contents' => fopen($file,'r')
],
[
'name' => 'channels',
'contents' => '#_test'
]
]
]);

Categories