Apostle.io is a web service for managing web app generated emails. This guide describes the requirements for writing a Client Library in any language.
Please check http://github.com/apostle to see if there is a client library for your language already.
This gist lives at https://gist.github.com/snikch/7606139
While this guide describes a style of writing a library in a certain way, this style may not be appropriate for any individual language. It's up to the author to decide if the style is appropriate for the language or if there is a more appropriate API style.
Delivery works by posting a JSON body to https://deliver.apostle.io. A json header must be supplied Content-Type: application/json
.
The JSON can contain multiple recipients, each sending a unique template. See the json files in this gist for more examples.
An Apostle.io “domain key” is required to send emails on behalf of an Apostle.io “domain”. This must be provided as an authentication header Authorization: Bearer DOMAIN_KEY
.
An invalid domain key will return a 401 response.
A global singleton with configuration available should be made available. The minimum values required are domain_key
and delivery_host
. Sane defaults should be provided. The default delivery_host
is http://deliver.apostle.io
, and the domain_key
should default to a configuration method that the language provides. For example, in Ruby, the convention is to make configuration variables available via the ENV
variable, so it defaults to ENV['DOMAIN_KEY]
.
# Setting a new domain key value
Apostle.domain_key = "My domain key"
Note: The delivery_host will not be changed in almost all cases. This is provided so that clients can be tested against non production Apostle.io delivery endpoints for testing and QA.
Note: For testing configuration, please see the testing section (tl;dr add a deliver
bool setting so that real delivery can be turned off in test suites).
A mail class should be defined to represent an email to a single recipient. This mail object should be able to accept any data, however the minimum requirement is the template id and email address.
You should be able to add any value to the mail object and have it added to an object called data
. The only attributes that are reserved and should be at the root level are email
, from
, headers
, layout_id
, name
and reply_to
. This maps to the json that gets sent to the delivery endpoint.
See all_attributes.json
in this gist for an example.
To deliver a mail object, a method deliver
should be defined. In languages where there is a convention for methods that are 'hard' rather than 'soft' (i.e. they raise exceptions rather than returning false on failure) then both methods should be defined. For example, the Ruby client has both deliver
and deliver!
methods.
A queue class should be provided to send multiple mail objects. Note: the deliver
method should define a queue with itself on it, and send via the queue's deliver method. This saves having to write delivery code in multiple places.
A queue should be able to be instantiated, have mail objects added to it, and then get those mail objects delivered as a single JSON object to Apostle.io.
See multiple_recipients.json
for a multiple recipients example.
A queue should validate only the minimum requirements for a mail object to be valid; the template_id
and email
address. If any email on the queue is invalid, the entire queue should not be sent.
The manner in which you access the validation errors will most likely depend on the language, and how that sort of information is usually passed. For example, in Ruby the information is provided via a #results
method, whereas in PHP the information is provided by passing a reference object to the deliver
method that gets populated.
queue.deliver
=> false
queue.results
=> {
:valid=>[#<Apostle::Mail:0x007fcee5ab2550>],
:invalid=>[#<Apostle::Mail:0x007fcee5ab23c0>]
}
queue.results[:invalid].first._exception
=> #<Apostle::DeliveryError @message="No recipient provided">
echo $queue->deliver($failures);
// false
echo count($failures);
// 2
echo $failures[0]->deliveryError();
// "No email provided"
echo $failures[1]->deliveryError();
// "No template provided"
All responses are JSON encoded. If an incorrect request is made, an error message describing the issue will be supplied
{
"status": "error",
"message": "Json Invalid: EOF",
"request_data": ""
}
Successful responses will respond with a success message
{
"status": "queued"
}
Unit tests are required before a client library will be accepted into the official repository.
To avoid integrators accidentally sending live emails in their test suite, you should provide a deliver
configuration flag. While defaulting to true, if set to false it should not attempt to post to the delivery endpoint, and should always return a true response.
Anyone integrating with Apostle.io should reach out to Mal Curtis, mal@apostle.io, for help – I'm always happy to contribute and answer questions where I can.