class Litmus::Instant

Constants

BEARER_REGEX

This deliberately allows for multiple authentication challenges within WWW-Authenticate

VERSION

Public Class Methods

api_key(key = nil) click to toggle source

Get or set your Instant API key @return [String]

# File lib/litmus/instant.rb, line 73
def self.api_key(key = nil)
  self.api_key = key if key
  @key
end
api_key=(key) click to toggle source

Set your Instant API key

# File lib/litmus/instant.rb, line 79
def self.api_key=(key)
  self.default_options.delete :basic_auth
  basic_auth key, "" if key
  @key = key
end
client_configurations() click to toggle source

List supported email client configurations @return [Hash] hash keyed by email client name, values are a Hash with the

the keys +orientation_options+ and +images_options+
# File lib/litmus/instant.rb, line 160
def self.client_configurations
  get "/clients/configurations"
end
clients() click to toggle source

List supported email clients @return [Array<String>] array of email client names

# File lib/litmus/instant.rb, line 153
def self.clients
  get "/clients"
end
create_email(email) click to toggle source

Describe an email’s content and metadata and, in exchange, receive an email_guid required to capture previews of it

We intend these objects to be treated as lightweight. Once uploaded, emails can't be modified. Obtain a new email_guid each time changes need to be reflected.

The uploaded email has a limited lifespan. As a result, a new email_guid should be obtained before requesting new previews if more than a day has passed since the last upload.

At least one of :html_text, :plain_text, :raw_source must be provided.

@param [Hash] email @option email [String] :html_text @option email [String] :plain_text @option email [String] :subject @option email [String] :from_address @option email [String] :from_display_name @option email [String] :raw_source

This field provides an alternative approach to defining the email and
so is only valid in the absence of all the fields above

@option email [String] :end_user_id A unique identifier for your end

users. When provided, we use this to partition your usage data.
See https://litmus.com/partners/api/documentation/instant/03-identifying-end-users/

@option email [Array<Hash>] :configurations

An array of capture capture configuration hashes
This allows pre-requesting previews that should be captured as soon as
possible. This can be a useful performance optimisation.
See +.prefetch_previews+ for further detail on format.

@param [String] token

optional OAuth authentication token when calling on behalf of a Litmus
user. This will be different for each OAuth connected user.

@return [Hash] the response containing the email_guid and also

confirmation of +end_user_id+ and +configurations+ if provided
# File lib/litmus/instant.rb, line 147
def self.create_email(email)
  post("/emails", body: email.to_json)
end
get_preview(email_guid, client, options = {}) click to toggle source

Request a preview

This triggers the capture of a preview. The method blocks until capture completes. The response contains URLs for each of the image sizes available. A further request will be needed to obtain actual image data from one of the provided URLs.

@param email_guid [String] @param client [String] @param options [Hash] @option options [String] :images allowed (default) or blocked @option options [String] :orientation horizontal or vertical (default)

@return [Hash] a hash mapping the available capture sizes to their

corresponding URLs
# File lib/litmus/instant.rb, line 179
def self.get_preview(email_guid, client, options = {})
  query = URI.encode_www_form(options)
  get "/emails/#{email_guid}/previews/#{client}?#{query}"
end
oauth_token(token = nil) click to toggle source

Get or set a global OAuth token to use This is not thread safe, if you intend to authorize multiple end users within the same application use

Litmus::Instant::Client.new(oauth_token: "XXX")

@return [String]

# File lib/litmus/instant.rb, line 92
def self.oauth_token(token = nil)
  self.api_token = token if token
  @token
end
oauth_token=(token) click to toggle source

Set an OAuth token to be used globally This is not thread safe, if you intend to authorize multiple end users within the same application use

Litmus::Instant::Client.new(oauth_token: "XXX")
# File lib/litmus/instant.rb, line 103
def self.oauth_token=(token)
  self.default_options[:headers].delete "Authorization"
  self.headers("Authorization" => "Bearer #{token}") if token
  @token = token
end
prefetch_previews(email_guid, configurations) click to toggle source

Pre-request a set of previews before download

This method is provided as an optional performance enhancement, typically useful before embedding a set of previews within a browser, where connection limits might otherwise delay the start of capture of some previews.

The method does not block while capture occurs, a response is returned immediately.

Note that should capture failure occur for a preview, it will only be discovered when the preview is later requested. Request errors, for instance attempting to prefetch an invalid client, will result raise normally howver.

@param email_guid [String] @param configurations [Array<Hash>]An array of capture capture configurations

Each configuration Hash must have a +:client+ key, and optional
+:orientation+ and +images+ keys

@return [Hash] confirmation of the configurations being captured

# File lib/litmus/instant.rb, line 205
def self.prefetch_previews(email_guid, configurations)
  post "/emails/#{email_guid}/previews/prefetch", body: { configurations: configurations }.to_json
end
preview_image_url(email_guid, client, options = {}) click to toggle source

Construct a preview image URL ready for download

The generated URLs can be embedded directly within a client application, for instance with the src tag of an HTML img tag.

This is also useful for downloading a capture in a single step, rather than calling .get_preview then making a follow up request to retrieve the image data.

@param [String] email_guid @param [String] client @param [Hash] options @option options [String] :capture_size full (default), thumb or thumb450 @option options [String] :images allowed (default) or blocked @option options [String] :orientation horizontal or vertical (default) @option options [Boolean] :fallback by default errors during capture

redirect to a fallback image, setting this to +false+ will mean that
GETs to the resulting URL will receive HTTP error responses instead

@option options [String] :fallback_url a custom fallback image to display

in case of errors. This must be an absolute URL and have a recognizable
image extension. Query parameters are not supported. The image should be
accessible publicly without the need for authentication.

@return [String] the preview URL, domain sharded by the client name

# File lib/litmus/instant.rb, line 233
def self.preview_image_url(email_guid, client, options = {})
  # We'd use Ruby 2.x keyword args here, but it's more useful to preserve
  # compatibility for anyone stuck with ruby < 2.x
  capture_size = options.delete(:capture_size) || "full"

  if options.keys.length > 0
    if options[:fallback_url]
      options[:fallback_url] = CGI.escape(options[:fallback_url])
    end
    query = URI.encode_www_form(options)
    "#{sharded_base_uri(client)}/emails/#{email_guid}/previews/#{client}/#{capture_size}?#{query}"
  else
    "#{sharded_base_uri(client)}/emails/#{email_guid}/previews/#{client}/#{capture_size}"
  end
end

Private Class Methods

extract_bearer_error(headers) click to toggle source
# File lib/litmus/instant.rb, line 288
def self.extract_bearer_error(headers)
  matches = headers["WWW-Authenticate"] &&
            headers["WWW-Authenticate"].match(BEARER_REGEX)

  return unless matches

  name = matches[:name]
  message = matches[:description]

  klass = case name
          when "invalid_token" then InvalidOAuthToken
          when "invalid_scope" then InvalidOAuthScope
          when "inactive_user" then InactiveUserError
          end

  klass && klass.new(message)
end
raise_on_failure(response) click to toggle source
# File lib/litmus/instant.rb, line 267
def self.raise_on_failure(response)
  unless response.success?
    message = response["description"] || ""

    bearer_error = extract_bearer_error(response.headers)
    raise bearer_error if bearer_error

    raise AuthenticationError.new(message) if response.code == 401
    raise AuthorizationError.new(message)  if response.code == 403
    raise RequestError.new(message)        if response.code == 400
    raise NotFound.new(message)            if response.code == 404
    raise TimeoutError.new(message)        if response.code == 504
    raise ServiceError.new(message)        if response.code == 500

    # For all other errors
    raise ApiError.new(message)
  end

  response
end
sharded_base_uri(client) click to toggle source

This avoids browser per domain connection limits

# File lib/litmus/instant.rb, line 258
def self.sharded_base_uri(client)
  # only shard where it's supported
  if base_uri =~ /\/\/instant-api/
    base_uri.gsub("://","://#{client}.")
  else
    base_uri
  end
end