Repository: SparkPost/php-sparkpost Branch: master Commit: 2c7f60d27afb Files: 39 Total size: 98.4 KB Directory structure: gitextract_jlhy3dwi/ ├── .coveralls.yml ├── .editorconfig ├── .travis.yml ├── AUTHORS.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── MIGRATION.md ├── README.md ├── composer.json ├── examples/ │ ├── bootstrap.php │ ├── debug/ │ │ └── index.php │ ├── message-events/ │ │ ├── get_message_events.php │ │ └── get_message_events_with_retry_logic.php │ ├── templates/ │ │ ├── create_template.php │ │ ├── delete_template.php │ │ ├── get_all_templates.php │ │ ├── get_template.php │ │ ├── preview_template.php │ │ └── update_template.php │ └── transmissions/ │ ├── create_transmission.php │ ├── create_transmission_with_attachment.php │ ├── create_transmission_with_cc_and_bcc.php │ ├── create_transmission_with_recipient_list.php │ ├── create_transmission_with_template.php │ ├── delete_transmission.php │ ├── get_all_transmissions.php │ └── get_transmission.php ├── lib/ │ └── SparkPost/ │ ├── Resource.php │ ├── ResourceBase.php │ ├── SparkPost.php │ ├── SparkPostException.php │ ├── SparkPostPromise.php │ ├── SparkPostResponse.php │ └── Transmission.php ├── phpunit.xml.dist └── test/ └── unit/ ├── SparkPostResponseTest.php ├── SparkPostTest.php └── TransmissionTest.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .coveralls.yml ================================================ # single file coverage_clover: test/output/clover.xml json_path: test/output/coveralls-upload.json ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 trim_trailing_whitespace = true [*.md] trim_trailing_whitespace = false [*.yml] indent_style = space indent_size = 2 ================================================ FILE: .travis.yml ================================================ language: php php: - '7.2' - '7.3' - '7.4' - '8.0' install: - composer install --no-interaction script: - mkdir -p test/output/report - composer test after_script: - php vendor/bin/php-coveralls notifications: slack: secure: mw6HF2KR0YwYcIaYvV6qjuWC+XSIP8SQOe13VwmGf3b783hMcZDZTUS9N4bIfpwYi74A9qmzKdc425OSu45nceAf7hzFusCY5rYMoLQK/ksJ7sd+ay7tWhPRuomG1w8idTyXtzce23zOfBtOCHQakbavH2Uz6mh5lJYPFlMKW4c= ================================================ FILE: AUTHORS.md ================================================ php-sparkpost is maintained by Message Systems. # Contributors * Jordan Nornhold, [@beardyman](https://github.com/beardyman) * Rich Leland, [@richleland](https://github.com/richleland) * Jason Rhodes [@jasonrhodes](https://github.com/jasonrhodes) * Matthew April, [@MattApril](https://github.com/MattApril) * James Fellows, [@j4m3s](https://github.com/j4m3s) * LF Bittencourt, [@lfbittencourt](https://github.com/lfbittencourt) * Jakub Piasecki, [@zaporylie](https://github.com/zaporylie) * Danil Zakablukovskiy, [@djagya](https://github.com/djagya) * Chris Wilson, [@yepher](https://github.com/yepher) * Maxim Dzhuliy, [@max-si-m](https://github.com/max-si-m) * [@chandon](https://github.com/chandon) * Avi Goldman, [@avrahamgoldman](https://github.com/avrahamgoldman) * Vincent Song, [@vwsong](https://github.com/vwsong) * Tobias Nyholm, [@Nyholm](https://github.com/Nyholm) ================================================ FILE: CHANGELOG.md ================================================ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased][unreleased] ## [2.3.0] - 2021-03-16 - [#201](https://github.com/SparkPost/php-sparkpost/pull/201) Update examples, README - [#200](https://github.com/SparkPost/php-sparkpost/pull/200) PHP 8 support ## [2.2.1] - 2021-03-08 - [#198](https://github.com/SparkPost/php-sparkpost/pull/198) Address #197: No longer need formfeed replacement. README work. - [#191](https://github.com/SparkPost/php-sparkpost/pull/191) Updating License ## [2.2.0] - 2019-06-04 - [#187](https://github.com/SparkPost/php-sparkpost/pull/187) Updated composer.json - [#169](https://github.com/SparkPost/php-sparkpost/pull/169) Optional automatic retry on 5xx - [#166](https://github.com/SparkPost/php-sparkpost/pull/166/files) Quick fix for using the API without composer - [#149](https://github.com/SparkPost/php-sparkpost/pull/149) Setters should return current object ## [2.1.0] - 2017-01-09 ### Added - [#161](https://github.com/SparkPost/php-sparkpost/pull/161) added example for sending email with attachment and simplified the examples setup - [#159](https://github.com/SparkPost/php-sparkpost/pull/159) added `debug` option for seeing the full request sent to SparkPost - [#151](https://github.com/SparkPost/php-sparkpost/pull/151) added packagist badges - [#139](https://github.com/SparkPost/php-sparkpost/pull/139) added examples for message events and templates ### Changed - [#150](https://github.com/SparkPost/php-sparkpost/issues/150) renamed the `Resource` class to `ResourceBase` since resource soft reserved in php 7 - [#137](https://github.com/SparkPost/php-sparkpost/pull/137) cleaned up tests and post install scripts - [#138](https://github.com/SparkPost/php-sparkpost/pull/138) added PHP 7.1 as a test environment ### Fixed - [#156](https://github.com/SparkPost/php-sparkpost/pull/156) fixed typo in README.md - [#152](https://github.com/SparkPost/php-sparkpost/issues/152) fixed propagation of coverage tests to coveralls.io - [#147](https://github.com/SparkPost/php-sparkpost/pull/147) fixed examples in README.md - [#139](https://github.com/SparkPost/php-sparkpost/pull/139) fixed the ability to send using recipient lists - Issue[#141](https://github.com/SparkPost/php-sparkpost/issues/141) removed form feeds from the JSON body sent to the API ## [2.0.3] - 2016-07-28 ### Fixed - Issue [#135](https://github.com/SparkPost/php-sparkpost/issues/135) reported `Http\Discovery\NotFoundException` caused by 2.0.2 update. ## [2.0.2] - 2016-07-28 ### Fixed - [#131](https://github.com/SparkPost/php-sparkpost/pull/131) removed any dependency on Guzzle by replacing it with `MessageFactoryDiscovery` ## [2.0.1] - 2016-06-29 ### Fixed - [#129](https://github.com/SparkPost/php-sparkpost/pull/129) issue with `content.from` being expected even when using a stored template ## [2.0.0] - 2016-06-24 This major release included a complete refactor of the library to be a thin HTTP client layer with some sugar methods on the Transmission class. There is now a base resource that can be used to call any SparkPost API with a one to one mapping of payload parameters to what is listed in our API documentation. ### Changed - [#123](https://github.com/SparkPost/php-sparkpost/pull/123) Rewrote docs and updated composer name - [#122](https://github.com/SparkPost/php-sparkpost/pull/122) Add transmission class and examples - [#121](https://github.com/SparkPost/php-sparkpost/pull/121) Update base resource and tests ## [1.2.1] - 2016-05-27 ### Fixed - [#111](https://github.com/SparkPost/php-sparkpost/pull/111) allow pass through of timeout setting in http config ## [1.2.0] - 2016-05-04 ### Added - [EditorConfig](http://editorconfig.org/) file to maintain consistent coding style - `composer run-script fix-style` can now be run to enforce PSR-2 style ### Changed - Responses from the SparkPost API with HTTP status code 403 now properly raise with message, code, and description ### Fixed - Removed reliance on composer for version of library ## [1.1.0] - 2016-05-02 ### Added - Message Events API added. ### Changed - Transmission API now accepts a DateTime object for startDate ## [1.0.3] - 2016-03-25 ### Added - Support for attachments, inline attachments, inline css, sandbox, start time, and transactional options in `Transmission` class - API response exceptions now include message, code, and description from API ## [1.0.2] - 2016-02-28 ### Fixed - Miscellaneous code cleanups related to docs and namespacing ## [1.0.1] - 2016-02-24 ### Added - Example for using `setupUnwrapped()` to get a list of webhooks. - CHANGELOG.md for logging release updates and backfilled it with previous release. ### Fixed - Library will now throw a `SparkPost\APIReponseException` properly when a 4XX http status is encountered. ## 1.0.0 - 2015-10-15 ### Added - Request adapter interface for passing in request adapters via `Ivory\HttpAdapter` - Ability to create 'unwrapped' modules for API endpoints that haven't had functionality included yet. - Instructions for setting up request adapters in README ### Changed - Library now requires PHP 5.5 or greater - Updated interface to be instance based with referenceable objects rather than static functions. ### Fixed - README now has proper code blocks denoting PHP language [unreleased]: https://github.com/sparkpost/php-sparkpost/compare/2.2.1...HEAD [2.2.1]: https://github.com/sparkpost/php-sparkpost/compare/2.2.0...2.2.1 [2.2.0]: https://github.com/sparkpost/php-sparkpost/compare/2.1.0...2.2.0 [2.1.0]: https://github.com/sparkpost/php-sparkpost/compare/2.0.3...2.1.0 [2.0.3]: https://github.com/sparkpost/php-sparkpost/compare/2.0.2...2.0.3 [2.0.2]: https://github.com/sparkpost/php-sparkpost/compare/2.0.1...2.0.2 [2.0.1]: https://github.com/sparkpost/php-sparkpost/compare/2.0.0...2.0.1 [2.0.0]: https://github.com/sparkpost/php-sparkpost/compare/1.2.1...2.0.0 [1.2.1]: https://github.com/sparkpost/php-sparkpost/compare/1.2.0...1.2.1 [1.2.0]: https://github.com/sparkpost/php-sparkpost/compare/v1.1.0...1.2.0 [1.1.0]: https://github.com/sparkpost/php-sparkpost/compare/v1.0.3...v1.1.0 [1.0.3]: https://github.com/sparkpost/php-sparkpost/compare/v1.0.2...v1.0.3 [1.0.2]: https://github.com/sparkpost/php-sparkpost/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/sparkpost/php-sparkpost/compare/v1.0.0...v1.0.1 ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to php-sparkpost Transparency is one of our core values, and we encourage developers to contribute and become part of the SparkPost developer community. The following is a set of guidelines for contributing to php-sparkpost, which is hosted in the [SparkPost Organization](https://github.com/sparkpost) on GitHub. These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request. ## Submitting Issues * You can create an issue [here](https://github.com/sparkpost/php-sparkpost/issues/new), but before doing that please read the notes below on debugging and submitting issues, and include as many details as possible with your report. * Include the version of php-sparkpost you are using. * Perform a [cursory search](https://github.com/SparkPost/php-sparkpost/issues?q=is%3Aissue+is%3Aopen) to see if a similar issue has already been submitted. ## Development ### Setup (Getting the Tools) #### Install Composer ``` curl -sS https://getcomposer.org/installer | php ``` Add composer install directory to $PATH `~/.composer/vendor/bin/` ### phpenv [phpenv](https://github.com/phpenv/phpenv-installer) is useful for testing locally across different PHP versions. ### Developing your app against a local version of the SparkPost library If you're working on the library and your app together, you can tell Composer to get `php-sparkpost` from a local path. With a directory structure such as: home - php-sparkpost - my-app - composer.json - .. etc Use the following for `my-app/composer.json`: ```json { "name": "sparkpost/php_simple_email_send", "description": "a small test program to send an email", "repositories": [ { "type": "path", "url": "../php-sparkpost" } ], "require": { "php-http/guzzle6-adapter": "^1.1", "guzzlehttp/guzzle": "^6.0", "sparkpost/sparkpost": "dev-master" } } ``` ### Memory We recommend increasing PHP’s memory limit, by default it uses 128MB. We ran into some issues during local development without doing so. You can do this by editing your php.ini file and modifying `memory_limit`. We set ours to `memory_limit = 1024M`. #### Install XDebug for code coverage generation Follow the instructions at [xdebug.org](http://xdebug.org/wizard.php) #### Development Tool Resources * https://getcomposer.org/doc/00-intro.md#globally-on-osx-via-homebrew- * https://phpunit.de/manual/current/en/installation.html ### Local Development * Fork [this repository](http://github.com/SparkPost/php-sparkpost) * Clone your fork * Run `composer install` * Write code! ### Contribution Steps #### Guidelines - Provide documentation for any newly added code. - Provide tests for any newly added code. - Follow [PSR-2](http://www.php-fig.org/psr/psr-2/) (_will be auto-enforced by php-cs-fixer in a later step_) 1. Create a new branch named after the issue you’ll be fixing (include the issue number as the branch name, example: Issue in GH is #8 then the branch name should be ISSUE-8) 1. Write corresponding tests and code (only what is needed to satisfy the issue and tests please) * Include your tests in the 'test' directory in an appropriate test file * Write code to satisfy the tests 1. Ensure automated tests pass 1. Run `composer run-script fix-style` to enforce PSR-2 style 1. Send a pull request and bug the maintainer until it gets merged and published. :) Make sure to add yourself to [AUTHORS](https://github.com/SparkPost/php-sparkpost/blob/master/AUTHORS.md). ### Testing Once you are setup for local development: * You can execute the unit tests using: `composer test` * You can view coverage information by viewing: `open test/output/report/index.html` ## Releasing * Update version in the [library](https://github.com/SparkPost/php-sparkpost/blob/eeb6ba971584fcc4c12fd69247c6b24df7827af5/lib/SparkPost/SparkPost.php#L16) during development. This is used in the `user_agent` of your requests. * Once it's been merged down, create a release tag in git. * Composer will automatically pickup the new tag and present it as a release. ================================================ FILE: LICENSE.txt ================================================ Copyright 2014 Message Systems, Inc. or its affiliates. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MIGRATION.md ================================================ # Migration Guide This is a guide to help you make the switch when the SparkPost PHP library changes major versions. ## Migrating from 1.0 to 2.0 ## Package name change The composer package name has changed from `sparkpost/php-sparkpost` to `sparkpost/sparkpost` ### No more setupUnwrapped We replaced the idea of 'wrapping' API resources with a simple `request` function. To see it in action, check out this [example](https://github.com/SparkPost/php-sparkpost/tree/2.0.0#send-an-api-call-using-the-base-request-function). ### `transmission` becomes `transmissions` Transmission endpoints are now under `$sparky->transmissions` instead of `$sparky->transmission` to map more directly to the [API docs](https://developers.sparkpost.com/api/). * We no longer map parameters to the API - we simplified. Instead custom mapping, now set the payload to match the API docs. * The exceptions to the previous statement are `cc` and `bcc`. They are helpers to make it easier to add cc and bcc recipients. [Example](https://github.com/SparkPost/php-sparkpost/tree/2.0.0#send-an-email-using-the-transmissions-endpoint) ### Switched from Ivory Http Adapter to HTTPlug Ivory Http Adapter was deprecated in favor of HTTPlug. ### Asynchronous support We addeded in support for [asynchronous calls](https://github.com/SparkPost/php-sparkpost/tree/2.0.0#asynchronous) (assuming your client supports it). ### Example #### 2.0 ```php try { $sparky->setOptions([ 'async' => false ]); // Build your email and send it! $results = $sparky->transmissions->post([ 'content'=>[ 'from'=>[ 'name' => 'From Envelope', 'email' => 'from@sparkpostbox.com>' ], 'subject'=>'First Mailing From PHP', 'html'=>'
You just sent your very first mailing!
', 'text'=>'Congratulations, {{name}}!! You just sent your very first mailing!', ], 'substitution_data'=>['name'=>'YOUR FIRST NAME'], 'recipients'=>[ [ 'address'=>[ 'name'=>'YOUR FULL NAME', 'email'=>'YOUR EMAIL ADDRESS' ] ] ] ]); echo 'Woohoo! You just sent your first mailing!'; } catch (\Exception $err) { echo 'Whoops! Something went wrong'; var_dump($err); } ``` #### 1.0 ```php try { // Build your email and send it! $results = $sparky->transmission->send([ 'from'=>[ 'name' => 'From Envelope', 'email' => 'from@sparkpostbox.com>' ], 'html'=>'You just sent your very first mailing!
', 'text'=>'Congratulations, {{name}}!! You just sent your very first mailing!', 'substitutionData'=>['name'=>'YOUR FIRST NAME'], 'subject'=>'First Mailing From PHP', 'recipients'=>[ [ 'address'=>[ 'name'=>'YOUR FULL NAME', 'email'=>'YOUR EMAIL ADDRESS' ] ] ] ]); echo 'Woohoo! You just sent your first mailing!'; } catch (\Exception $err) { echo 'Whoops! Something went wrong'; var_dump($err); } ``` ================================================ FILE: README.md ================================================You just sent your very first mailing!
', 'text' => 'Congratulations, {{name}}!! You just sent your very first mailing!', ], 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], 'recipients' => [ [ 'address' => [ 'name' => 'YOUR_NAME', 'email' => 'YOUR_EMAIL', ], ], ], 'cc' => [ [ 'address' => [ 'name' => 'ANOTHER_NAME', 'email' => 'ANOTHER_EMAIL', ], ], ], 'bcc' => [ [ 'address' => [ 'name' => 'AND_ANOTHER_NAME', 'email' => 'AND_ANOTHER_EMAIL', ], ], ], ]); } catch (\Exception $error) { var_dump($error); } print($response->getStatusCode()); $results = $response->getBody()['results']; var_dump($results); ?> ``` More examples [here](./examples/): ### [Transmissions](./examples/transmissions/) - Create with attachment - Create with recipient list - Create with cc and bcc - Create with template - Create - Delete (scheduled transmission by campaign_id *only*) ### [Templates](./examples/templates/) - Create - Get - Get (list) all - Update - Delete ### [Message Events](./examples/message-events/) - get - get (with retry logic) ### Send An API Call Using The Base Request Function We provide a base request function to access any of our API resources. ```php getenv('SPARKPOST_API_KEY'), 'async' => false]); $webhookId = 'afd20f50-865a-11eb-ac38-6d7965d56459'; $response = $sparky->request('DELETE', 'webhooks/' . $webhookId); print($response->getStatusCode()); ?> ``` > Be sure to not have a leading `/` in your resource URI. For complete list of resources, refer to [API documentation](https://developers.sparkpost.com/api/). ## Handling Responses The API calls either return a `SparkPostPromise` or `SparkPostResponse` depending on if `async` is `true` or `false` ### Synchronous ```php $sparky->setOptions(['async' => false]); try { $response = ... // YOUR API CALL GOES HERE echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ``` ### Asynchronous Asynchronous an be handled in two ways: by passing callbacks or waiting for the promise to be fulfilled. Waiting acts like synchronous request. ##### Wait (Synchronous) ```php $promise = ... // YOUR API CALL GOES HERE try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } echo "I will print out after the promise is fulfilled"; ``` ##### Then (Asynchronous) ```php $promise = ... // YOUR API CALL GOES HERE $promise->then( // Success callback function ($response) { echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; }, // Failure callback function (Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ); echo "I will print out before the promise is fulfilled"; // You can combine multiple promises using \GuzzleHttp\Promise\all() and other functions from the library. $promise->wait(); ``` ## Handling Exceptions An exception will be thrown in two cases: there is a problem with the request or the server returns a status code of `400` or higher. ### SparkPostException * **getCode()** * Returns the response status code of `400` or higher * **getMessage()** * Returns the exception message * **getBody()** * If there is a response body it returns it as an `Array`. Otherwise it returns `null`. * **getRequest()** * Returns an array with the request values `method`, `url`, `headers`, `body` when `debug` is `true` ### Contributing See [contributing](https://github.com/SparkPost/php-sparkpost/blob/master/CONTRIBUTING.md). ================================================ FILE: composer.json ================================================ { "name": "sparkpost/sparkpost", "description": "Client library for interfacing with the SparkPost API.", "license": "MIT", "authors": [ { "name": "SparkPost" } ], "minimum-stability": "stable", "scripts": { "test": "XDEBUG_MODE=coverage ./vendor/bin/phpunit", "fix-style": "php-cs-fixer fix ." }, "require": { "php": "^7.1 || ^8.0", "php-http/httplug": "^1.0 || ^2.0", "php-http/message": "^1.0", "php-http/client-implementation": "^1.0", "php-http/discovery": "^1.0" }, "require-dev": { "phpunit/phpunit": "^8.0 || ^9.0", "php-http/guzzle6-adapter": "^1.0", "mockery/mockery": "^1.3", "nyholm/nsa": "^1.0", "php-coveralls/php-coveralls": "^2.4", "friendsofphp/php-cs-fixer": "^2.18" }, "autoload": { "psr-4": { "SparkPost\\": "lib/SparkPost" } }, "autoload-dev": { "psr-4": { "SparkPost\\Test\\": "test/unit" } } } ================================================ FILE: examples/bootstrap.php ================================================ getenv('SPARKPOST_API_KEY'), // fetch API KEY from environment variable "debug" => true ]); $promise = $sparky->request('GET', 'templates'); try { $response = $promise->wait(); var_dump($response); echo "Request:\n"; print_r($response->getRequest()); echo "Response:\n"; echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo "Request:\n"; print_r($e->getRequest()); echo "Exception:\n"; echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/message-events/get_message_events.php ================================================ getenv('SPARKPOST_API_KEY')]); // New endpoint - https://developers.sparkpost.com/api/events/ $promise = $sparky->request('GET', 'events/message', [ 'campaign_ids' => 'CAMPAIGN_ID', ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/message-events/get_message_events_with_retry_logic.php ================================================ getenv('SPARKPOST_API_KEY'), "retries" => 3]); // New endpoint - https://developers.sparkpost.com/api/events/ $promise = $sparky->request('GET', 'events/message', [ 'campaign_ids' => 'CAMPAIGN_ID', ]); /** * If this fails with a 5xx it will have failed 4 times */ try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; if ($e->getCode() >= 500 && $e->getCode() <= 599) { echo "Wow, this failed epically"; } } ================================================ FILE: examples/templates/create_template.php ================================================ getenv('SPARKPOST_API_KEY')]); $template_name = "PHP example template"; $template_id = "PHP-example-template"; // put your own sending domain here $sending_domain = "steve2-test.trymsys.net"; // Valid short template content examples $plain_text = 'Write your text message part here.'; $html = <<Write your HTML message part here
HTML; $amp_html = << Hello World! Let's get started using AMP HTML together! HTML; $promise = $sparky->request('POST', 'templates', [ 'name' => $template_name, 'id' => $template_id, 'content' => [ 'from' => "from@$sending_domain", 'subject' => 'Your Subject', 'text' => $plain_text, 'html' => $html, 'amp_html' => $amp_html, ], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/templates/delete_template.php ================================================ getenv('SPARKPOST_API_KEY')]); $template_id = "PHP-example-template"; $promise = $sparky->request('DELETE', "templates/$template_id"); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/templates/get_all_templates.php ================================================ getenv('SPARKPOST_API_KEY')]); $promise = $sparky->request('GET', 'templates'); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/templates/get_template.php ================================================ getenv('SPARKPOST_API_KEY')]); $template_id = "PHP-example-template"; $promise = $sparky->request('GET', "templates/$template_id?draft=true"); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/templates/preview_template.php ================================================ getenv('SPARKPOST_API_KEY')]); $template_id = "PHP-example-template"; $promise = $sparky->request('POST', "templates/$template_id/preview?draft=true", [ 'substitution_data' => [ 'some_key' => 'some_value', ], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/templates/update_template.php ================================================ getenv('SPARKPOST_API_KEY')]); $template_id = "PHP-example-template"; $promise = $sparky->request('PUT', "templates/$template_id", [ 'options' => [ 'open_tracking' => true, ], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/transmissions/create_transmission.php ================================================ getenv('SPARKPOST_API_KEY')]); // put your own sending domain and test recipient address here $sending_domain = "steve2-test.trymsys.net"; $your_email = "bob@sink.sparkpostmail.com"; $promise = $sparky->transmissions->post([ 'content' => [ 'from' => [ 'name' => 'SparkPost Team', 'email' => "from@$sending_domain", ], 'subject' => 'First Mailing From PHP', 'html' => 'You just sent your very first mailing!
', 'text' => 'Congratulations, {{name}}! You just sent your very first mailing!', ], 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], 'recipients' => [ [ 'address' => [ 'name' => 'YOUR_NAME', 'email' => $your_email, ], ], ], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/transmissions/create_transmission_with_attachment.php ================================================ getenv('SPARKPOST_API_KEY')]); $filePath = dirname(__FILE__).'/'; $fileName = 'sparkpost.png'; $fileType = mime_content_type($filePath.$fileName); $fileData = base64_encode(file_get_contents($filePath.$fileName)); // put your own sending domain and test recipient address here $sending_domain = "steve2-test.trymsys.net"; $your_email = "bob@sink.sparkpostmail.com"; $promise = $sparky->transmissions->post([ 'content' => [ 'from' => [ 'name' => 'SparkPost Team', 'email' => "from@$sending_domain", ], 'subject' => 'Mailing With Attachment From PHP', 'html' => 'You just sent an email with an attachment!
', 'text' => 'Congratulations, {{name}}! You just sent an email with an attachment', 'attachments' => [ [ 'name' => $fileName, 'type' => $fileType, 'data' => $fileData, ], ], ], 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], 'recipients' => [ [ 'address' => [ 'name' => 'YOUR_NAME', 'email' => $your_email, ], ], ], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/transmissions/create_transmission_with_cc_and_bcc.php ================================================ getenv('SPARKPOST_API_KEY')]); // put your own sending domain and test recipient address here $sending_domain = "steve2-test.trymsys.net"; $your_email = "bob@sink.sparkpostmail.com"; $your_cc = "alice@sink.sparkpostmail.com"; $your_bcc = "charles@sink.sparkpostmail.com"; $promise = $sparky->transmissions->post([ 'content' => [ 'from' => [ 'name' => 'SparkPost Team', 'email' => "from@$sending_domain", ], 'subject' => 'Mailing With CC and BCC From PHP', 'html' => 'You just sent your very first mailing with CC and BCC recipients!
', 'text' => 'Congratulations, {{name}}! You just sent your very first mailing with CC and BCC recipients!', ], 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], 'recipients' => [ [ 'address' => [ 'name' => 'YOUR_NAME', 'email' => $your_email, ], ], ], 'cc' => [ [ 'address' => [ 'name' => 'ANOTHER_NAME', 'email' => $your_cc, ], ], ], 'bcc' => [ [ 'address' => [ 'name' => 'AND_ANOTHER_NAME', 'email' => $your_bcc, ], ], ], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/transmissions/create_transmission_with_recipient_list.php ================================================ getenv('SPARKPOST_API_KEY')]); // put your own sending domain and test recipient address here $sending_domain = "steve2-test.trymsys.net"; // The ID of a list in your SparkPost account $my_list = "mylist1"; $promise = $sparky->transmissions->post([ 'content' => [ 'from' => [ 'name' => 'SparkPost Team', 'email' => "from@$sending_domain", ], 'subject' => 'Mailing With Recipient List From PHP', 'html' => 'You just sent an email to everyone on your recipient list!
', 'text' => 'Congratulations, {{name}}! You just sent an email to everyone on your recipient list!', ], 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], 'recipients' => ['list_id' => $my_list], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/transmissions/create_transmission_with_template.php ================================================ getenv('SPARKPOST_API_KEY')]); // put your own sending domain and test recipient address here $sending_domain = "steve2-test.trymsys.net"; $your_email = "bob@sink.sparkpostmail.com"; $template_id = "PHP-example-template"; $promise = $sparky->transmissions->post([ 'content' => ['template_id' => $template_id], 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], 'recipients' => [ [ 'address' => [ 'name' => 'YOUR_NAME', 'email' => $your_email, ], ], ], ]); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/transmissions/delete_transmission.php ================================================ getenv('SPARKPOST_API_KEY')]); // Delete *scheduled* transmissions (only) by *campaign ID* (only) // See https://developers.sparkpost.com/api/transmissions/#transmissions-delete-delete-a-scheduled-transmission $promise = $sparky->transmissions->delete('?campaign_id=white_christmas'); try { $response = $promise->wait(); echo $response->getStatusCode()."\n"; print_r($response->getBody())."\n"; } catch (\Exception $e) { echo $e->getCode()."\n"; echo $e->getMessage()."\n"; } ================================================ FILE: examples/transmissions/get_all_transmissions.php ================================================ sparkpost = $sparkpost; $this->endpoint = $endpoint; } /** * Sends get request to API at the set endpoint. * * @see SparkPost->request() */ public function get($uri = '', $payload = [], $headers = []) { return $this->request('GET', $uri, $payload, $headers); } /** * Sends put request to API at the set endpoint. * * @see SparkPost->request() */ public function put($uri = '', $payload = [], $headers = []) { return $this->request('PUT', $uri, $payload, $headers); } /** * Sends post request to API at the set endpoint. * * @see SparkPost->request() */ public function post($payload = [], $headers = []) { return $this->request('POST', '', $payload, $headers); } /** * Sends delete request to API at the set endpoint. * * @see SparkPost->request() */ public function delete($uri = '', $payload = [], $headers = []) { return $this->request('DELETE', $uri, $payload, $headers); } /** * Sends requests to SparkPost object to the resource endpoint. * * @see SparkPost->request() * * @return SparkPostPromise or SparkPostResponse depending on sync or async request */ public function request($method = 'GET', $uri = '', $payload = [], $headers = []) { if (is_array($uri)) { $headers = $payload; $payload = $uri; $uri = ''; } $uri = $this->endpoint.'/'.$uri; return $this->sparkpost->request($method, $uri, $payload, $headers); } } ================================================ FILE: lib/SparkPost/SparkPost.php ================================================ 'api.sparkpost.com', 'protocol' => 'https', 'port' => 443, 'key' => '', 'version' => 'v1', 'async' => true, 'debug' => false, 'retries' => 0 ]; /** * @var Transmission Instance of Transmission class */ public $transmissions; /** * Sets up the SparkPost instance. * * @param HttpClient $httpClient - An httplug client or adapter * @param array $options - An array to overide default options or a string to be used as an API key */ public function __construct($httpClient, array $options) { $this->setOptions($options); $this->setHttpClient($httpClient); $this->setupEndpoints(); } /** * Sends either sync or async request based on async option. * * @param string $method * @param string $uri * @param array $payload - either used as the request body or url query params * @param array $headers * * @return SparkPostPromise|SparkPostResponse Promise or Response depending on sync or async request */ public function request($method = 'GET', $uri = '', $payload = [], $headers = []) { if ($this->options['async'] === true) { return $this->asyncRequest($method, $uri, $payload, $headers); } else { return $this->syncRequest($method, $uri, $payload, $headers); } } /** * Sends sync request to SparkPost API. * * @param string $method * @param string $uri * @param array $payload * @param array $headers * * @return SparkPostResponse * * @throws SparkPostException */ public function syncRequest($method = 'GET', $uri = '', $payload = [], $headers = []) { $requestValues = $this->buildRequestValues($method, $uri, $payload, $headers); $request = call_user_func_array(array($this, 'buildRequestInstance'), $requestValues); $retries = $this->options['retries']; try { if ($retries > 0) { $resp = $this->syncReqWithRetry($request, $retries); } else { $resp = $this->httpClient->sendRequest($request); } return new SparkPostResponse($resp, $this->ifDebug($requestValues)); } catch (\Exception $exception) { throw new SparkPostException($exception, $this->ifDebug($requestValues)); } } private function syncReqWithRetry($request, $retries) { $resp = $this->httpClient->sendRequest($request); $status = $resp->getStatusCode(); if ($status >= 500 && $status <= 599 && $retries > 0) { return $this->syncReqWithRetry($request, $retries-1); } return $resp; } /** * Sends async request to SparkPost API. * * @param string $method * @param string $uri * @param array $payload * @param array $headers * * @return SparkPostPromise */ public function asyncRequest($method = 'GET', $uri = '', $payload = [], $headers = []) { if ($this->httpClient instanceof HttpAsyncClient) { $requestValues = $this->buildRequestValues($method, $uri, $payload, $headers); $request = call_user_func_array(array($this, 'buildRequestInstance'), $requestValues); $retries = $this->options['retries']; if ($retries > 0) { return new SparkPostPromise($this->asyncReqWithRetry($request, $retries), $this->ifDebug($requestValues)); } else { return new SparkPostPromise($this->httpClient->sendAsyncRequest($request), $this->ifDebug($requestValues)); } } else { throw new \Exception('Your http client does not support asynchronous requests. Please use a different client or use synchronous requests.'); } } private function asyncReqWithRetry($request, $retries) { return $this->httpClient->sendAsyncRequest($request)->then(function($response) use ($request, $retries) { $status = $response->getStatusCode(); if ($status >= 500 && $status <= 599 && $retries > 0) { return $this->asyncReqWithRetry($request, $retries-1); } return $response; }); } /** * Builds request values from given params. * * @param string $method * @param string $uri * @param array $payload * @param array $headers * * @return array $requestValues */ public function buildRequestValues($method, $uri, $payload, $headers) { $method = trim(strtoupper($method)); if ($method === 'GET') { $params = $payload; $body = []; } else { $params = []; $body = $payload; } $url = $this->getUrl($uri, $params); $headers = $this->getHttpHeaders($headers); // old form-feed workaround now removed $body = json_encode($body); return [ 'method' => $method, 'url' => $url, 'headers' => $headers, 'body' => $body, ]; } /** * Build RequestInterface from given params. * * @param array $requestValues * * @return RequestInterface */ public function buildRequestInstance($method, $url, $headers, $body) { return $this->getMessageFactory()->createRequest($method, $url, $headers, $body); } /** * Build RequestInterface from given params. * * @param array $requestValues * * @return RequestInterface */ public function buildRequest($method, $uri, $payload, $headers) { $requestValues = $this->buildRequestValues($method, $uri, $payload, $headers); return call_user_func_array(array($this, 'buildRequestInstance'), $requestValues); } /** * Returns an array for the request headers. * * @param array $headers - any custom headers for the request * * @return array $headers - headers for the request */ public function getHttpHeaders($headers = []) { $constantHeaders = [ 'Authorization' => $this->options['key'], 'Content-Type' => 'application/json', 'User-Agent' => 'php-sparkpost/'.$this->version, ]; foreach ($constantHeaders as $key => $value) { $headers[$key] = $value; } return $headers; } /** * Builds the request url from the options and given params. * * @param string $path - the path in the url to hit * @param array $params - query parameters to be encoded into the url * * @return string $url - the url to send the desired request to */ public function getUrl($path, $params = []) { $options = $this->options; $paramsArray = []; foreach ($params as $key => $value) { if (is_array($value)) { $value = implode(',', $value); } array_push($paramsArray, $key.'='.$value); } $paramsString = implode('&', $paramsArray); return $options['protocol'].'://'.$options['host'].($options['port'] ? ':'.$options['port'] : '').'/api/'.$options['version'].'/'.$path.($paramsString ? '?'.$paramsString : ''); } /** * Sets $httpClient to be used for request. * * @param HttpClient|HttpAsyncClient $httpClient - the client to be used for request * * @return SparkPost */ public function setHttpClient($httpClient) { if (!($httpClient instanceof HttpAsyncClient || $httpClient instanceof HttpClient)) { throw new \LogicException(sprintf('Parameter to SparkPost::setHttpClient must be instance of "%s" or "%s"', HttpClient::class, HttpAsyncClient::class)); } $this->httpClient = $httpClient; return $this; } /** * Sets the options from the param and defaults for the SparkPost object. * * @param array $options - either an string API key or an array of options * * @return SparkPost */ public function setOptions($options) { // if the options map is a string we should assume that its an api key if (is_string($options)) { $options = ['key' => $options]; } // Validate API key because its required if (!isset($this->options['key']) && (!isset($options['key']) || !preg_match('/\S/', $options['key']))) { throw new \Exception('You must provide an API key'); } $this->options = isset($this->options) ? $this->options : self::$defaultOptions; // set options, overriding defaults foreach ($options as $option => $value) { if (key_exists($option, $this->options)) { $this->options[$option] = $value; } } return $this; } /** * Returns the given value if debugging, an empty instance otherwise. * * @param any $param * * @return any $param */ private function ifDebug($param) { return $this->options['debug'] ? $param : null; } /** * Sets up any endpoints to custom classes e.g. $this->transmissions. */ private function setupEndpoints() { $this->transmissions = new Transmission($this); } /** * @return RequestFactory */ private function getMessageFactory() { if (!$this->messageFactory) { $this->messageFactory = MessageFactoryDiscovery::find(); } return $this->messageFactory; } /** * @param RequestFactory $messageFactory * * @return SparkPost */ public function setMessageFactory(RequestFactory $messageFactory) { $this->messageFactory = $messageFactory; return $this; } } ================================================ FILE: lib/SparkPost/SparkPostException.php ================================================ request = $request; $message = $exception->getMessage(); $code = $exception->getCode(); if ($exception instanceof HttpException) { $message = $exception->getResponse()->getBody()->__toString(); $this->body = json_decode($message, true); $code = $exception->getResponse()->getStatusCode(); } parent::__construct($message, $code, $exception->getPrevious()); } /** * Returns the request values sent. * * @return array $request */ public function getRequest() { return $this->request; } /** * Returns the body. * * @return array $body - the json decoded body from the http response */ public function getBody() { return $this->body; } } ================================================ FILE: lib/SparkPost/SparkPostPromise.php ================================================ promise = $promise; $this->request = $request; } /** * Hand off the response functions to the original promise and return a custom response or exception. * * @param callable $onFulfilled - function to be called if the promise is fulfilled * @param callable $onRejected - function to be called if the promise is rejected */ public function then(callable $onFulfilled = null, callable $onRejected = null) { $request = $this->request; return $this->promise->then(function ($response) use ($onFulfilled, $request) { if (isset($onFulfilled)) { $onFulfilled(new SparkPostResponse($response, $request)); } }, function ($exception) use ($onRejected, $request) { if (isset($onRejected)) { $onRejected(new SparkPostException($exception, $request)); } }); } /** * Hand back the state. * * @return $state - returns the state of the promise */ public function getState() { return $this->promise->getState(); } /** * Wraps the wait function and returns a custom response or throws a custom exception. * * @param bool $unwrap * * @return SparkPostResponse * * @throws SparkPostException */ public function wait($unwrap = true) { try { $response = $this->promise->wait($unwrap); return $response ? new SparkPostResponse($response, $this->request) : $response; } catch (\Exception $exception) { throw new SparkPostException($exception, $this->request); } } } ================================================ FILE: lib/SparkPost/SparkPostResponse.php ================================================ response = $response; $this->request = $request; } /** * Returns the request values sent. * * @return array $request */ public function getRequest() { return $this->request; } /** * Returns the body. * * @return array $body - the json decoded body from the http response */ public function getBody() { $body = $this->response->getBody(); $body_string = $body->__toString(); $json = json_decode($body_string, true); return $json; } /** * pass these down to the response given in the constructor. */ public function getProtocolVersion() { return $this->response->getProtocolVersion(); } public function withProtocolVersion($version) { return $this->response->withProtocolVersion($version); } public function getHeaders() { return $this->response->getHeaders(); } public function hasHeader($name) { return $this->response->hasHeader($name); } public function getHeader($name) { return $this->response->getHeader($name); } public function getHeaderLine($name) { return $this->response->getHeaderLine($name); } public function withHeader($name, $value) { return $this->response->withHeader($name, $value); } public function withAddedHeader($name, $value) { return $this->response->withAddedHeader($name, $value); } public function withoutHeader($name) { return $this->response->withoutHeader($name); } public function withBody(StreamInterface $body) { return $this->response->withBody($body); } public function getStatusCode() { return $this->response->getStatusCode(); } public function withStatus($code, $reasonPhrase = '') { return $this->response->withStatus($code, $reasonPhrase); } public function getReasonPhrase() { return $this->response->getReasonPhrase(); } } ================================================ FILE: lib/SparkPost/Transmission.php ================================================ formatPayload($payload); } return parent::post($payload, $headers); } /** * Runs the given payload through the formatting functions. * * @param array $payload - the request body * * @return array - the modified request body */ public function formatPayload($payload) { $payload = $this->formatBlindCarbonCopy($payload); //Fixes BCCs into payload $payload = $this->formatCarbonCopy($payload); //Fixes CCs into payload $payload = $this->formatShorthandRecipients($payload); //Fixes shorthand recipients format return $payload; } /** * Formats bcc list into recipients list. * * @param array $payload - the request body * * @return array - the modified request body */ private function formatBlindCarbonCopy($payload) { //If there's a list of BCC recipients, move them into the correct format if (isset($payload['bcc'])) { $payload = $this->addListToRecipients($payload, 'bcc'); } return $payload; } /** * Formats cc list into recipients list and adds the CC header to the content. * * @param array $payload - the request body * * @return array - the modified request body */ private function formatCarbonCopy($payload) { if (isset($payload['cc'])) { $ccAddresses = []; for ($i = 0; $i < count($payload['cc']); ++$i) { array_push($ccAddresses, $this->toAddressString($payload['cc'][$i]['address'])); } // set up the content headers as either what it was before or an empty array $payload['content']['headers'] = isset($payload['content']['headers']) ? $payload['content']['headers'] : []; // add cc header $payload['content']['headers']['CC'] = implode(',', $ccAddresses); $payload = $this->addListToRecipients($payload, 'cc'); } return $payload; } /** * Formats all recipients into the long form of [ "name" => "John", "email" => "john@exmmple.com" ]. * * @param array $payload - the request body * * @return array - the modified request body */ private function formatShorthandRecipients($payload) { if (isset($payload['content']['from'])) { $payload['content']['from'] = $this->toAddressObject($payload['content']['from']); } for ($i = 0; $i < count($payload['recipients']); ++$i) { $payload['recipients'][$i]['address'] = $this->toAddressObject($payload['recipients'][$i]['address']); } return $payload; } /** * Loops through the given listName in the payload and adds all the recipients to the recipients list after removing their names. * * @param array $payload - the request body * @param array $listName - the name of the array in the payload to be moved to the recipients list * * @return array - the modified request body */ private function addListToRecipients($payload, $listName) { $originalAddress = $this->toAddressString($payload['recipients'][0]['address']); foreach ($payload[$listName] as $recipient) { $recipient['address'] = $this->toAddressObject($recipient['address']); $recipient['address']['header_to'] = $originalAddress; // remove name from address - name is only put in the header for cc and not at all for bcc if (isset($recipient['address']['name'])) { unset($recipient['address']['name']); } array_push($payload['recipients'], $recipient); } //Delete the original object from the payload. unset($payload[$listName]); return $payload; } /** * Takes the shorthand form of an email address and converts it to the long form. * * @param $address - the shorthand form of an email address "Name