diff --git a/USE_CASES.md b/USE_CASES.md index 2f7e255f4..98848348b 100644 --- a/USE_CASES.md +++ b/USE_CASES.md @@ -3,6 +3,7 @@ This documentation provides examples for specific use cases. Please [open an iss # Table of Contents - [Table of Contents](#table-of-contents) - [Attachments](#attachments) +- [Attaching a File from Box](#attaching-a-file-from-box) - [Kitchen Sink - an example with all settings used](#kitchen-sink) - [Send an Email to a Single Recipient](#send-an-email-to-a-single-recipient) - [Send an Email to Multiple Recipients](#send-an-email-to-multiple-recipients) @@ -58,6 +59,181 @@ try { } ``` + +# Attaching a File from Box + +You can attach a file from [Box](https://www.box.com) to your emails. +Because there is no official Box SDK for PHP, this example requires +[firebase/php-jwt](https://github.com/firebase/php-jwt) to generate a +[JSON Web Token](https://jwt.io) assertion. Before using this code, you should +set up a JWT application on [Box](https://developer.box.com/docs/setting-up-a-jwt-app). +For more information about authenticating with JWT, see +[this page](https://developer.box.com/docs/construct-jwt-claim-manually). + +After completing the setup tutorial, you will want to make sure your app’s +configuration settings have at least the following options enabled: + +**Application Access** +* Enterprise + +**Application Scopes** +* Read all files and folders stored in Box +* Read and write all files and folders stored in Box +* Manage users + +**Advanced Features** +* Perform Actions as Users + +Remember to reauthorize your app +[here](https://app.box.com/master/settings/openbox) after making any changes to +your app’s JWT scopes. + +```php + 'RS256', + 'typ' => 'JWT', + 'kid' => $boxConfig->boxAppSettings->appAuth->publicKeyID +); +$claims = array( + 'iss' => $boxConfig->boxAppSettings->clientID, + 'sub' => $boxConfig->enterpriseID, + 'box_sub_type' => 'enterprise', + 'aud' => 'https://api.box.com/oauth2/token', + 'jti' => bin2hex(openssl_random_pseudo_bytes(16)), + 'exp' => time() + 50 +); + +$privateKey = openssl_get_privatekey($boxConfig->boxAppSettings->appAuth->privateKey, $boxConfig->boxAppSettings->appAuth->passphrase); + +$assertion = JWT::encode($claims, $privateKey, 'RS256', null, $header); + +// Get access token +$url = 'https://api.box.com/oauth2/token'; +$data = array( + 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', + 'client_id' => $boxConfig->boxAppSettings->clientID, + 'client_secret' => $boxConfig->boxAppSettings->clientSecret, + 'assertion' => $assertion +); +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); +$result = json_decode(curl_exec($ch)); +curl_close($ch); +$accessToken = $result->access_token; + +// Get user ID +$url = 'https://api.box.com/2.0/users'; +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Authorization: Bearer '.$accessToken +)); +$result = json_decode(curl_exec($ch)); +curl_close($ch); +foreach ($result->entries as $entry){ + if ($entry->login === $fileOwner){ + $userId = $entry->id; + } +} + +// Get file ID +$url = 'https://api.box.com/2.0/search'; +$data = array( + 'query' => urlencode(end($path)) +); +$urlEncoded = http_build_query($data); +$ch = curl_init($url.'?'.$urlEncoded); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Authorization: Bearer '.$accessToken, + 'As-User: '.$userId +)); +$result = json_decode(curl_exec($ch)); +curl_close($ch); +foreach ($result->entries as $entry){ + if (count($entry->path_collection->entries) === count($path) -1){ + if (count($path) > 2){ + // File is located in a subdirectory. + for ($i = 1; $i < (count($path) - 1); $i++){ + if ($path[$i] === $entry->path_collection->entries[$i]->name){ + $fileId = $entry->id; + } + } + } else { + // File is located in default directory. + $fileId = $entry->id; + } + } +} + +if (isset($fileId) && isset($userId)){ + // Get file data + $url = 'https://api.box.com/2.0/files/'.$fileId.'/content'; + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Authorization: Bearer '.$accessToken, + 'As-User: '.$userId + )); + $result = curl_exec($ch); + $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); + curl_close($ch); + + $attachmentFilename = end($path); + $attachmentContent = base64_encode($result); + $attachmentContentType = $contentType; + + $email = new \SendGrid\Mail\Mail(); + $email->setFrom("test@example.com", "Example User"); + $email->setSubject("Attaching a File from Box"); + $email->addTo("test@example.com", "Example User"); + $email->addContent("text/plain", "See attached file from Box."); + $email->addContent( + "text/html", "See attached file from Box." + ); + + $attachment = new \SendGrid\Mail\Attachment(); + $attachment->setContent($attachmentContent); + $attachment->setType($attachmentContentType); + $attachment->setFilename($attachmentFilename); + $attachment->setDisposition("attachment"); + $attachment->setContentId($attachmentFilename); // Only used if disposition is set to inline + $email->addAttachment($attachment); + + $sendgrid = new \SendGrid(getenv('SENDGRID_API_KEY')); + try { + $response = $sendgrid->send($email); + print $response->statusCode() . "\n"; + print_r($response->headers()); + print $response->body() . "\n"; + } catch (Exception $e) { + echo 'Caught exception: '. $e->getMessage() ."\n"; + } +} else { + echo "Error: file or owner could not be located\n"; +} +``` + # Kitchen Sink - an example with all settings used diff --git a/composer.json b/composer.json index 9db36e363..ac8834b30 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "sendgrid/php-http-client": "~3.9", "ext-curl": "*", "ext-json": "*", - "ext-mbstring": "*" + "ext-mbstring": "*", + "ext-openssl": "*" }, "require-dev": { "phpunit/phpunit": "^5.7.9 || ^6.4.3",