SimpleSpark
What?
The simplest and cleanest way to access the SparkPost API from Ruby or from Rails.
Installation
Add this line to your application's Gemfile:
gem 'simple_spark'
And then execute:
$ bundle
Or install it yourself as:
$ gem install simple_spark
Usage
Why?
The official gem was somewhat lacking in functionality, though with the demise of Mandrill it seems SparkPost decided to restart development on it, they abandoned that as of 17th May 2016
As we would have to write wrappers around all the functions we would need for our app to use SparkPost anyway, it seemed much easier to write the wrapper as a gem and allow others to use it too.
Status
Breaking change: initialising the client is now done with a hash instead of with ordered parameters, as there were getting to be too many after supporting Subaccounts and user specified headers
Endpoints
Creating a Client
First you need to ensure you are requiring the library
require 'simple_spark'
The simplest version of the client is to just provide your API key from SparkPost
simple_spark = SimpleSpark::Client.new(api_key: 'your_api_key')
You can also use ENV vars to configure the key, setting ENV['SPARKPOST_API_KEY'] will allow you to just use
simple_spark = SimpleSpark::Client.new
You can also override the other options if you need to in advanced scenarios, the full signature is (api_key, api_host, base_path, debug), i.e.
simple_spark = SimpleSpark::Client.new(api_key: 'your_api_key', api_host: 'https://api.sparkpost.com', base_path: '/api/v1/', debug: false, subaccount_id: 'my_subaccount')
Debug
Setting debug to true will cause Excon to output full debug information to the log.
This will default to true if you are running under Rails and are in a development environment, otherwise it will default to false (setting other values to nil will cause them to use their defaults)
You can also pass a Logger into the client options to have SimpleSpark log there. By default Rails.logger will be used when runnign under Rails, and STDOUT will be used otherwise
simple_spark = SimpleSpark::Client.new(api_key: 'your_api_key', debug: true, logger: Rails.logger)
Subaccounts
By setting subaccount_id on your client you are telling Simple Spark to use that subaccount for all calls made on this instance of the client.
Not all Sparkpost calls support the Subaccount feature, and their API will throw an unauthorized error if you use a subaccount_id on an unsupported call. Depending on your code this may mean you need to instantiate two instances of the Simple Spark client in your code, one for subaccount calls, and one for other calls. This is a less than ideal solution, but due to the rapid pace of Sparkpost development on their API this is the option that causes least dependency up Simple Spark to be updated as their API is.
Headers
Should you have any need to override the headers that are sent by default, then you can specify headers as an option. The headers specified here will override any of the generated headers that the library creates. In normal operation there should be no reason to use this option, but it is provided for convenience and to allow for Sparkpost updating their API in any unexpected way.
simple_spark = SimpleSpark::Client.new(api_key: 'your_api_key', headers: { 'NewSparkpostHeader' => 'hello'})
Exceptions
SimpleSpark wraps all the common errors from the SparkPost API
If the API takes too long to respond (times out in Excon) a GatewayTimeoutExceeded will be raised
Status 400 raises Exceptions::BadRequest
Status 404 raises Exceptions::NotFound
Status 422 raises Exceptions::UnprocessableEntity
Status 420/429 raises Exceptions::ThrottleLimitExceeded
Other response status codes raise Exceptions::UnprocessableEntity
In some cases it is possible to send too fast for the API (apparently) to handle , in this case the SparkPost API returns a 504 status with an empty body. This is raised by SimpleSpark as Exceptions::GatewayTimeoutExceeded
Account
Retrieve account information
simple_spark.account.retrieve
The argument can be specified in a comma separated list. The only valid value is currently usage.
simple_spark.account.retrieve("usage")
see SparkPost API Documentation
Update account information
properties = {
company_name: "SparkPost",
options: {
smtp_tracking_default: true,
rest_tracking_default: true,
transactional_unsub: true,
transactional_default: true
}
}
simple_spark.account.update(properties)
see SparkPost API Documentation
Metrics
Discoverability Links
simple_spark.metrics.discoverability_links
see SparkPost API Documentation
Deliverability Metrics Summary
Summary of metrics
properties = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12',
metrics: 'count_accepted',
timezone: 'America/New_York'
}
simple_spark.metrics.deliverability_metrics_summary(properties)
see SparkPost API Documentation
Deliverability Metrics by Domain
Metrics grouped by Domain
properties = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12',
metrics: 'count_accepted',
timezone: 'America/New_York'
}
simple_spark.metrics.deliverability_metrics_by_domain(properties)
see SparkPost API Documentation
Deliverability Metrics by Sending Domain
Metrics grouped by Sending Domain
properties = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12',
metrics: 'count_accepted',
timezone: 'America/New_York'
}
simple_spark.metrics.deliverability_metrics_by_sending_domain(properties)
see SparkPost API Documentation
Deliverability Metrics by Subaccount
Metrics grouped by Subaccount
properties = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12',
metrics: 'count_accepted',
timezone: 'America/New_York'
}
simple_spark.metrics.deliverability_metrics_by_subaccount(properties)
see SparkPost API Documentation
Deliverability Metrics by Campaign
Metrics grouped by Campaign
properties = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12',
metrics: 'count_accepted',
timezone: 'America/New_York'
}
simple_spark.metrics.deliverability_metrics_by_campaign(properties)
see SparkPost API Documentation
Deliverability Metrics by Template
Metrics grouped by Template
properties = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12',
metrics: 'count_accepted',
timezone: 'America/New_York'
}
simple_spark.metrics.deliverability_metrics_by_template(properties)
see SparkPost API Documentation
Deliverability Metrics as Time Series
Metrics across a Time Series
properties = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12',
metrics: 'count_accepted',
timezone: 'America/New_York',
precision: 'day'
}
simple_spark.metrics.deliverability_time_series(properties)
Returns an array of metrics with time stamps:
[{ "count_targeted"=>2, "ts"=>"2011-06-01T00:00:00+00:00" }, { "count_targeted"=>3, "ts"=>"2011-06-02T00:00:00+00:00" }]
see SparkPost API Documentation
Transmissions
List
List all Transmissions
When messages are sent the Transmission will be deleted, so this will only return transmissions that are about to be sent or are scheduled for the future
simple_spark.transmissions.list
see SparkPost API Documentation
Create
Create a new Transmission
properties = {
options: { open_tracking: true, click_tracking: true },
campaign_id: 'christmas_campaign',
return_path: '[email protected]',
metadata: {user_type: 'students'},
substitution_data: { sender: 'Big Store Team' },
recipients: [
{ address: { email: '[email protected]', name: 'Your Customer' },
tags: ['greeting', 'sales'],
metadata: { place: 'Earth' }, substitution_data: { address: '123 Their Road' } }
],
content:
{ from: { name: 'Your Name', email: '[email protected]' },
subject: 'I am a test email',
reply_to: 'Sales <[email protected]>',
headers: { 'X-Customer-CampaignID' => 'christmas_campaign' },
text: 'Hi from {{sender}} ... this is a test, and here is your address {{address}}',
html: '<p>Hi from {{sender}}</p><p>This is a test</p>'
}
# Or to use a template, change the content key to be:
# content: { template_id: 'first-template-id' }
}
simple_spark.transmissions.create(properties)
To send attachments, they need to be Base64 encoded
require 'base64'
properties = {
recipients: [{ address: { email: '[email protected]', name: 'Your Customer' }],
content:
{ from: { name: 'Your Name', email: '[email protected]' },
subject: 'I am a test email',
html: '<p>Hi from {{sender}}</p<p>This is a test</p>',
attachments: [{ name: "attachment.txt", type: "text/plain", data: attachment }]
}
}
# load your file contents first, then use Base64 to encode them
encoded_attachment = Base64.encode64('My file contents')
properties[:content][:attachments] = [{ name: "attachment.txt", type: "text/plain", data: encoded_attachment }]
simple_spark.transmissions.create(properties)
Delete by campaign
simple_spark.transmissions.delete_campaign("white-christmas")
see SparkPost API Documentation
Subaccounts
List
List all Subaccounts
simple_spark.subaccounts.list
see SparkPost API Documentation
Create
Create a new Subaccount
properties = {
name: 'Sparkle Ponies', key_label: 'API Key for Sparkle Ponies Subaccount',
key_grants: ['smtp/inject', 'sending_domains/manage', 'message_events/view', 'suppression_lists/manage']
}
simple_spark.subaccounts.create(properties)
see SparkPost API Documentation
Retrieve
Retrieves a Subaccount by its id
simple_spark.subaccounts.retrieve(123)
see SparkPost API Documentation
Update
Updates a Subaccount with new values
properties = { name: "new name" }
simple_spark.subaccounts.update('mail.mydomain.com', properties)
see SparkPost API Documentation
Messsage Events
Samples
List an example of the event data that will be included in a response from the Message Events search endpoint
simple_spark..samples
To limit to just some events
simple_spark..samples('bounce')
see SparkPost API Documentation
Search
Perform a filtered search for message event data. The response is sorted by descending timestamp. For full options you should consult the SparkPost API documentation
simple_spark..search(campaign_ids: 'christmas-campaign, summer-campaign')
see SparkPost API Documentation
Events
Samples
List an example of the event data that will be included in a response from the Events search endpoint
simple_spark.events.samples
To limit to just some events
simple_spark.events.samples('bounce')
see SparkPost API Documentation
Search
Perform a filtered search for event data. The response is sorted by descending timestamp. For full options you should consult the SparkPost API documentation
simple_spark.events.search(campaign_ids: 'christmas-campaign, summer-campaign')
see SparkPost API Documentation
Webhooks
List
List all Webhooks, optionally providing a timezone property
simple_spark.webhooks.list('America/New_York')
see SparkPost API Documentation
Create
Create a new Webhook
simple_spark.webhooks.create(values)
see SparkPost API Documentation
Retrieve
Retrieves a Webhook
simple_spark.webhooks.retrieve(webhook_id)
see SparkPost API Documentation
Update
Updates a Webhook with new values
properties = { "name" => "New name" }
simple_spark.webhooks.update(webhook_id, properties)
see SparkPost API Documentation
Validate
Validates a Webhook by sending an example message event batch from the Webhooks API to the target URL
simple_spark.webhooks.validate(webhook_id)
see SparkPost API Documentation
Batch Status
Retrieve the Batch Status Information for a Webhook
simple_spark.webhooks.batch_status(webhook_id)
see SparkPost API Documentation
Samples
List an example of the event data that will be sent from a webhook
simple_spark.webhooks.samples
To limit to just some events
simple_spark.webhooks.samples('bounce')
see SparkPost API Documentation
Sending Domains
List
List all Sending Domains
simple_spark.sending_domains.list
see SparkPost API Documentation
Create
Create a new Sending Domain
simple_spark.sending_domains.create({domain: 'mail.mydomain.com'})
see SparkPost API Documentation
Retrieve
Retrieves a Sending Domain by its domain name
simple_spark.sending_domains.retrieve('mail.mydomain.com')
see SparkPost API Documentation
Update
Updates a Sending Domain with new values
properties = { "tracking_domain" => "new.tracking.domain" }
simple_spark.sending_domains.update('mail.mydomain.com', properties)
see SparkPost API Documentation
Verify
Forces verification of a Sending Domain.
Including the fields "dkim_verify" and/or "spf_verify" in the request initiates a check against the associated DNS record type for the specified sending domain.Including the fields "postmaster_at_verify" and/or "abuse_at_verify" in the request results in an email sent to the specified sending domain's postmaster@ and/or abuse@ mailbox where a verification link can be clicked. Including the fields "postmaster_at_token" and/or "abuse_at_token" in the request initiates a check of the provided token(s) against the stored token(s) for the specified sending domain.
properties = { "dkim_verify": true, "spf_verify": true }
simple_spark.sending_domains.verify('mail.mydomain.com', properties)
see SparkPost API Documentation
Delete
Deletes a Sending Domain permanently
simple_spark.sending_domains.delete('mail.mydomain.com')
see SparkPost API Documentation
Inbound Domains
List
List all Inbound Domains
simple_spark.inbound_domains.list
see SparkPost API Documentation
Create
Create a new Inbound Domain
simple_spark.inbound_domains.create('mail.mydomain.com')
see SparkPost API Documentation
Retrieve
Retrieves an Inbound Domain by its domain name
simple_spark.inbound_domains.retrieve('mail.mydomain.com')
see SparkPost API Documentation
Delete
Deletes an Inbound Domain permanently
simple_spark.inbound_domains.delete('mail.mydomain.com')
see SparkPost API Documentation
Supression List
Search
Find supression list entries
params = {
from: '2013-04-20T07:12',
to: '2018-04-20T07:12'
}
simple_spark.suppression_list.search(params)
see SparkPost API Documentation
Create or Update
Bulk update supression list entries
recipients = [
{
recipient: "[email protected]",
type: "transactional",
description: "User requested to not receive any transactional emails."
},
{
recipient: "[email protected]",
type: "non_transactional"
}
]
simple_spark.suppression_list.create_or_update(recipients)
see SparkPost API Documentation
Retrieve
simple_spark.suppression_list.retrieve("[email protected]")
see SparkPost API Documentation
Delete
simple_spark.suppression_list.delete("[email protected]")
see SparkPost API Documentation
Relay Webhooks
List
List all Relay Webhooks
simple_spark.relay_webhooks.list
see SparkPost API Documentation
Create
Create a new Relay Webhook
properties = {
name: "Replies Webhook",
target: "https://webhooks.customer.example/replies",
auth_token: "",
match: {
protocol: "SMTP",
domain: "email.example.com"
}
}
simple_spark.relay_webhooks.create(properties)
see SparkPost API Documentation
Retrieve
Retrieves a Relay Webhook by its id
simple_spark.relay_webhooks.retrieve(id)
see SparkPost API Documentation
Update
Updates a Relay Webhook with new values
properties = { name: "Replies Webhook" }
simple_spark.relay_webhooks.update(id, properties)
see SparkPost API Documentation
Delete
Deletes a Relay Webhook permanently
simple_spark.relay_webhooks.delete(id)
see SparkPost API Documentation
Templates
List
List all templates
simple_spark.templates.list
see SparkPost API Documentation
Create
Create a new Template
properties = { "name" => "Summer Sale!",
"content"=> { "from" => "[email protected]",
"subject"=> "Summer deals",
"html"=> "<b>Check out these deals!</b>"
}
}
simple_spark.templates.create(properties)
see SparkPost API Documentation
Retrieve
Retrieves a Template by its ID
draft = nil
simple_spark.templates.retrieve(yourtemplateid, draft)
see SparkPost API Documentation
Update
Updates a Template with new values
properties = { "name" => "Sorry, the Winter Sale!" }
update_published = false
simple_spark.templates.update(yourtemplateid, properties, update_published)
see SparkPost API Documentation
Preview
Merges the template with the Substitution data and returns the result
properties = { substitution_data: { name: 'Mr test User' } }
draft = nil
simple_spark.templates.preview(yourtemplateid, properties, draft)
see SparkPost API Documentation
Delete
Deletes a template permanently
simple_spark.templates.delete(yourtemplateid)
see SparkPost API Documentation
Recipient Lists
List
List all recipient lists
simple_spark.recipient_lists.list
see SparkPost API Documentation
Create
Create a new Recipient list
properties = { "name" => "Small List",
"recipients"=> [
{
"address" => {
"email" => "[email protected]"
}
}
]
}
num_rcpt_errors = 1
simple_spark.recipient_lists.create(properties, num_rcpt_errors)
see SparkPost API Documentation
Retrieve
Retrieves a Recipient list by its ID
show_recipients = true
simple_spark.recipient_lists.retrieve(your_list_id, show_recipients)
see SparkPost API Documentation
Update
Updates a Recipient list with new values
properties = { "name" => "New List Name" }
simple_spark.recipient_lists.update(your_list_id, properties)
see SparkPost API Documentation
Delete
Deletes a Recipient list permanently
simple_spark.recipient_lists.delete(your_list_id)
see SparkPost API Documentation
Changelog
1.0.12 Fix param name on suppression list https://github.com/leadmachineapp/simple_spark/pull/27
1.0.10 / 1.0.11 Minor documentation updates
1.0.9
- Add Recipients List Endpoint
1.0.8
- Add Events Endpoint
1.0.6
- Exceptions now return SparkPost results object too
1.0.5
- Add Account API Endpoint
- Add Delete Campaign
- Bug fixes
1.0.4
- Add Supression List Endpoint
1.0.3
- Using JSON.generate instead of .to_json (https://github.com/leadmachineapp/simple_spark/pull/11)
- Fixing inbound domains bug (https://github.com/leadmachineapp/simple_spark/pull/9)
1.0.2
Add sparkpost error code into exception message to allow more specific error handling
1.0.1
Suppress Excon warning for using :debug parameter
1.0.0
As SparkPost have now stopped development on their own gem, and have recommended this one as being a better alternative, bumping version to 1.0.0 - the code has been running in production for a while now and seems stable and near feature complete.
0.0.13
Adding status error code to message as SparkPost uses a wide range of status codes
0.0.12
Check :progname before assigning
0.0.11
- long day ... bug in 504 exception syntax came back with merge
0.0.10
- Bug in 504 exception syntax
0.0.9
- Breaking change: 204 responses now return an empty hash t simplify consuming code
- Added logging, if debug is set then SimpleSpark will log its options and calls in addition to Excon.
0.0.8
- Improved exception handling
0.0.7
- Added Time Series to Metrics
0.0.6
- Fixed accidental bug
0.0.5
- Subaccounts endpoint added
- Metrics main endpoints added
0.0.4
- Merged pull request to fix Rails development check for debug
0.0.3
- Breaking change: client paramaters are now a hash of options instead of ordered params
- Added Subaccount support to client
- Added Headers support to client
Contributing
Passing tests are encouraged going forwards, and generally code should follow most of the standard rules that Rubocop checks for.
- Fork it ( https://github.com/leadmachineapp/simple_spark/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request