sparkpost 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +1 -0
- data/README.md +53 -3
- data/Rakefile +5 -4
- data/bin/console +3 -3
- data/examples/template/list.rb +8 -0
- data/examples/transmission/attachment.txt +1 -0
- data/examples/transmission/send.rb +12 -0
- data/examples/transmission/with_attachment.rb +29 -0
- data/examples/transmission/with_substitution.rb +14 -0
- data/examples/transmission/with_template.rb +18 -0
- data/lib/sparkpost.rb +2 -1
- data/lib/sparkpost/client.rb +20 -17
- data/lib/sparkpost/helpers.rb +23 -0
- data/lib/sparkpost/request.rb +45 -13
- data/lib/sparkpost/template.rb +112 -0
- data/lib/sparkpost/transmission.rb +47 -31
- data/lib/sparkpost/version.rb +1 -1
- data/sparkpost.gemspec +14 -13
- data/spec/lib/sparkpost/client_spec.rb +36 -17
- data/spec/lib/sparkpost/core_extensions/object_spec.rb +18 -19
- data/spec/lib/sparkpost/helpers_spec.rb +91 -0
- data/spec/lib/sparkpost/request_spec.rb +96 -22
- data/spec/lib/sparkpost/template_spec.rb +276 -0
- data/spec/lib/sparkpost/transmission_spec.rb +263 -38
- data/spec/lib/sparkpost/version_spec.rb +1 -1
- data/spec/spec_helper.rb +7 -59
- metadata +34 -8
- data/examples/transmission.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 796669253fea19aa5100d4947812dcd522c5b740
|
4
|
+
data.tar.gz: 1ef22cf099b5f094ff1d4fe947f45e27bd3c6ae8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d8ebe367055686b7d287464754e8b868b9c25d228f8e96ccb3ff9ddafcf13be99555994badb816a63fc15a47fd7a7377d180c3083445473f9cf45863b8483a7
|
7
|
+
data.tar.gz: 6e5a7ff2c7532b778c5e87534a5d15d0e73bee8c53ed9bd452b2e3834e4730c0f8d74f5c18d0a13942b1094d7448a460d003bab998da0ec3b682f9efd78f22c5
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -4,9 +4,9 @@
|
|
4
4
|
|
5
5
|
# SparkPost Ruby API Client
|
6
6
|
|
7
|
-
[![Travis CI](https://travis-ci.org/SparkPost/ruby-sparkpost.svg?branch=master)](https://travis-ci.org/SparkPost/ruby-sparkpost) [![Coverage Status](https://coveralls.io/repos/SparkPost/ruby-sparkpost/badge.svg?branch=master&service=github)](https://coveralls.io/github/SparkPost/ruby-sparkpost?branch=master)
|
7
|
+
[![Travis CI](https://travis-ci.org/SparkPost/ruby-sparkpost.svg?branch=master)](https://travis-ci.org/SparkPost/ruby-sparkpost) [![Coverage Status](https://coveralls.io/repos/SparkPost/ruby-sparkpost/badge.svg?branch=master&service=github)](https://coveralls.io/github/SparkPost/ruby-sparkpost?branch=master) [![Slack Status](http://slack.sparkpost.com/badge.svg)](http://slack.sparkpost.com)
|
8
8
|
|
9
|
-
The official Ruby client library for
|
9
|
+
The official Ruby client library for SparkPost
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -22,9 +22,59 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
$ gem install sparkpost
|
24
24
|
|
25
|
+
**Important: Implementations may change frequently until we reach v1.0.0**
|
26
|
+
|
25
27
|
## Usage
|
26
28
|
|
27
|
-
|
29
|
+
**Send an email**
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require 'sparkpost'
|
33
|
+
|
34
|
+
sp = SparkPost::Client.new() # api key was set in ENV through ENV['SPARKPOST_API_KEY']
|
35
|
+
response = sp.transmission.send_message('RECIPIENT_EMAIL', 'SENDER_EMAIL', 'test email', '<h1>HTML message</h1>')
|
36
|
+
puts response
|
37
|
+
|
38
|
+
# {"total_rejected_recipients"=>0, "total_accepted_recipients"=>1, "id"=>"123456789123456789"}
|
39
|
+
```
|
40
|
+
|
41
|
+
**Send email with substitution data**
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require 'sparkpost'
|
45
|
+
|
46
|
+
values = { substitution_data: { name: 'Sparky'}}
|
47
|
+
sp = SparkPost::Client.new() # pass api key or get api key from ENV
|
48
|
+
response = sp.transmission.send_message('RECIPIENT_EMAIL', 'SENDER_EMAIL', 'testemail', '<h1>HTML message from {{name}}</h1>', values)
|
49
|
+
puts response
|
50
|
+
|
51
|
+
# {"total_rejected_recipients"=>0, "total_accepted_recipients"=>1, "id"=>"123456789123456789"}
|
52
|
+
```
|
53
|
+
|
54
|
+
**Send email with attachment**
|
55
|
+
|
56
|
+
*You need to base64 encode of your attachment contents.*
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
require 'sparkpost'
|
60
|
+
|
61
|
+
# assuming there is a file named attachment.txt in the same directory
|
62
|
+
attachment = Base64.encode64(File.open(File.expand_path('../attachment.txt', __FILE__), 'r') { |f| f.read })
|
63
|
+
|
64
|
+
# prepare attachment data to pass to send_message method
|
65
|
+
values = {
|
66
|
+
attachments: [{
|
67
|
+
name: 'attachment.txt',
|
68
|
+
type: 'text/plain',
|
69
|
+
data: attachment
|
70
|
+
}]
|
71
|
+
}
|
72
|
+
|
73
|
+
sp = SparkPost::Client.new() # pass api key or get api key from ENV
|
74
|
+
sp.transmission.send_message('RECIPIENT_EMAIL', 'SENDER_EMAIL', 'testemail', '<h1>Email with an attachment</h1>', values)
|
75
|
+
```
|
76
|
+
|
77
|
+
See: [examples](examples)
|
28
78
|
|
29
79
|
## Development
|
30
80
|
|
data/Rakefile
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rubocop/rake_task'
|
3
4
|
|
4
5
|
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
RuboCop::RakeTask.new
|
5
7
|
|
6
|
-
task :
|
7
|
-
|
8
|
+
task default: [:rubocop, :spec]
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'sparkpost'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "sparkpost"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start
|
@@ -0,0 +1 @@
|
|
1
|
+
This attachment contains just this!
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../../lib/sparkpost'
|
4
|
+
|
5
|
+
sp = SparkPost::Client.new # api key was set in ENV
|
6
|
+
response = sp.transmission.send_message(
|
7
|
+
'RECIPIENT_EMAIL',
|
8
|
+
'SENDER_EMAIL',
|
9
|
+
'test email',
|
10
|
+
'<h1>HTML message</h1>')
|
11
|
+
|
12
|
+
puts response
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
require_relative '../../lib/sparkpost'
|
5
|
+
|
6
|
+
# read file and base64 encoding
|
7
|
+
attachment = Base64.encode64(
|
8
|
+
File.open(File.expand_path('../attachment.txt', __FILE__), 'r', &:read))
|
9
|
+
|
10
|
+
# prepare attachment data to pass to send_message method
|
11
|
+
options = {
|
12
|
+
attachments: [{
|
13
|
+
name: 'Sparky.txt',
|
14
|
+
type: 'text/plain',
|
15
|
+
data: attachment
|
16
|
+
}]
|
17
|
+
}
|
18
|
+
|
19
|
+
sp = SparkPost::Client.new # pass api key or get api key from ENV
|
20
|
+
|
21
|
+
# send message with attachment
|
22
|
+
response = sp.transmission.send_message(
|
23
|
+
'RECIPIENT_EMAIL',
|
24
|
+
'SENDER_EMAIL',
|
25
|
+
'test email',
|
26
|
+
'<h1>Message with attachment</h1>',
|
27
|
+
options)
|
28
|
+
|
29
|
+
puts response
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../../lib/sparkpost'
|
4
|
+
|
5
|
+
values = { substitution_data: { name: 'Sparky' } }
|
6
|
+
sp = SparkPost::Client.new # pass api key or get api key from ENV
|
7
|
+
response = sp.transmission.send_message(
|
8
|
+
'RECIPIENT_EMAIL',
|
9
|
+
'SENDER_EMAIL',
|
10
|
+
'test email',
|
11
|
+
'<h1>HTML message from {{name}}</h1>',
|
12
|
+
values)
|
13
|
+
|
14
|
+
puts response
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../../lib/sparkpost'
|
4
|
+
|
5
|
+
# prepare the payload as required by SparkPost API endpoint
|
6
|
+
payload = {
|
7
|
+
recipients: [{ address: { email: 'RECIPIENT_EMAIL' } }],
|
8
|
+
content: {
|
9
|
+
from: 'SENDER_EMAIL',
|
10
|
+
subject: 'test email',
|
11
|
+
template_id: 'YOUR_TEMPLATE_ID'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
sp = SparkPost::Client.new # api key was set in ENV
|
16
|
+
response = sp.transmission.send_payload(payload)
|
17
|
+
|
18
|
+
puts response
|
data/lib/sparkpost.rb
CHANGED
data/lib/sparkpost/client.rb
CHANGED
@@ -1,23 +1,26 @@
|
|
1
1
|
module SparkPost
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
class Client
|
3
|
+
attr_reader :transmission
|
4
|
+
attr_reader :template
|
5
|
+
def initialize(api_key = nil, api_host = 'https://api.sparkpost.com')
|
6
|
+
@api_key = (api_key || ENV['SPARKPOST_API_KEY']).to_s
|
7
|
+
@api_host = (api_host || ENV['SPARKPOST_API_HOST']).to_s
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
raise ArgumentError, 'No API key is provided. Either provide
|
10
|
+
api_key with constructor or set SPARKPOST_API_KEY environment
|
11
|
+
variable' if @api_key.blank?
|
12
12
|
|
13
|
+
raise ArgumentError, 'No API host is provided. Either provide
|
14
|
+
api_host with constructor or set SPARKPOST_API_HOST environment
|
15
|
+
variable' if @api_host.blank?
|
16
|
+
end
|
13
17
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
+
def transmission
|
19
|
+
@transmission ||= Transmission.new(@api_key, @api_host)
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
+
def template
|
23
|
+
@template ||= Template.new(@api_key, @api_host)
|
22
24
|
end
|
23
|
-
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative '../core_extensions/object'
|
2
|
+
|
3
|
+
module SparkPost
|
4
|
+
module Helpers
|
5
|
+
def copy_value(src_hash, src_key, dst_hash, dst_key)
|
6
|
+
dst_hash[dst_key] = src_hash[src_key] if src_hash.key?(src_key)
|
7
|
+
end
|
8
|
+
|
9
|
+
def deep_merge(source_hash, other_hash)
|
10
|
+
source_hash.merge(other_hash) do |_key, oldval, newval|
|
11
|
+
if newval.respond_to?(:blank?) && newval.blank?
|
12
|
+
oldval
|
13
|
+
elsif oldval.is_a?(Hash) && newval.is_a?(Hash)
|
14
|
+
deep_merge(oldval, newval)
|
15
|
+
else
|
16
|
+
newval
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module_function :copy_value, :deep_merge
|
22
|
+
end
|
23
|
+
end
|
data/lib/sparkpost/request.rb
CHANGED
@@ -6,31 +6,63 @@ require_relative 'exceptions'
|
|
6
6
|
|
7
7
|
module SparkPost
|
8
8
|
module Request
|
9
|
-
|
10
|
-
def request(url, api_key, data)
|
9
|
+
def request(url, api_key, data, verb = 'POST')
|
11
10
|
uri = URI.parse(url)
|
12
|
-
http =
|
13
|
-
http.use_ssl = true
|
11
|
+
http = configure_http(uri)
|
14
12
|
headers = {
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
'User-Agent' => 'ruby-sparkpost/' + VERSION,
|
14
|
+
'Content-Type' => 'application/json',
|
15
|
+
'Authorization' => api_key
|
18
16
|
}
|
19
|
-
req =
|
20
|
-
req
|
17
|
+
req = configure_request(uri, headers, data, verb)
|
18
|
+
process_response(http.request(req))
|
19
|
+
end
|
20
|
+
|
21
|
+
def endpoint(subpath = nil, params = {})
|
22
|
+
url = String.new(@base_endpoint)
|
23
|
+
if subpath
|
24
|
+
url << '/' unless subpath.start_with?('/')
|
25
|
+
url << subpath
|
26
|
+
end
|
27
|
+
if params && params.any?
|
28
|
+
url << '?'
|
29
|
+
url << params.to_a.map { |x| "#{x[0]}=#{x[1]}" }.join('&')
|
30
|
+
end
|
31
|
+
url
|
32
|
+
end
|
21
33
|
|
22
|
-
|
34
|
+
def configure_http(uri)
|
35
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
36
|
+
http.use_ssl = true
|
37
|
+
http
|
38
|
+
end
|
39
|
+
|
40
|
+
def configure_request(uri, headers, data, verb)
|
41
|
+
req = case verb
|
42
|
+
when 'GET'
|
43
|
+
Net::HTTP::Get.new(uri.path, headers)
|
44
|
+
when 'PUT'
|
45
|
+
Net::HTTP::Put.new(uri.path, headers)
|
46
|
+
when 'DELETE'
|
47
|
+
Net::HTTP::Delete.new(uri.path, headers)
|
48
|
+
else
|
49
|
+
Net::HTTP::Post.new(uri.path, headers)
|
50
|
+
end
|
51
|
+
|
52
|
+
req.body = JSON.generate(data) if data.present?
|
53
|
+
req
|
23
54
|
end
|
24
55
|
|
25
56
|
def process_response(response)
|
26
57
|
response = JSON.parse(response.body)
|
27
58
|
if response['errors']
|
28
|
-
|
59
|
+
raise SparkPost::DeliveryException, response['errors']
|
29
60
|
else
|
30
61
|
response['results']
|
31
62
|
end
|
32
|
-
end
|
63
|
+
end
|
33
64
|
|
34
|
-
module_function :request, :
|
65
|
+
module_function :request, :configure_http, :configure_request,
|
66
|
+
:process_response
|
35
67
|
end
|
36
68
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require_relative 'request'
|
4
|
+
require_relative 'helpers'
|
5
|
+
require_relative 'exceptions'
|
6
|
+
|
7
|
+
module SparkPost
|
8
|
+
class Template
|
9
|
+
include Request
|
10
|
+
include Helpers
|
11
|
+
|
12
|
+
def initialize(api_key, api_host)
|
13
|
+
@api_key = api_key
|
14
|
+
@api_host = api_host
|
15
|
+
@base_endpoint = "#{@api_host}/api/v1/templates"
|
16
|
+
end
|
17
|
+
|
18
|
+
def create(id, from = nil, subject = nil, html = nil, **options)
|
19
|
+
data = deep_merge(
|
20
|
+
payload_from_args(id, from, subject, html),
|
21
|
+
payload_from_options(options)
|
22
|
+
)
|
23
|
+
request(endpoint, @api_key, data, 'POST')
|
24
|
+
end
|
25
|
+
|
26
|
+
def update(id, from = nil, subject = nil, html = nil, **options)
|
27
|
+
params = {}
|
28
|
+
copy_value(options, :update_published, params, :update_published)
|
29
|
+
data = deep_merge(
|
30
|
+
payload_from_args(nil, from, subject, html),
|
31
|
+
payload_from_options(options)
|
32
|
+
)
|
33
|
+
request(endpoint(id, params), @api_key, data, 'PUT')
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete(id)
|
37
|
+
request(endpoint(id), @api_key, nil, 'DELETE')
|
38
|
+
end
|
39
|
+
|
40
|
+
def get(id, draft = nil)
|
41
|
+
params = {}
|
42
|
+
params[:draft] = draft unless draft.nil?
|
43
|
+
request(endpoint(id, params), @api_key, nil, 'GET')
|
44
|
+
end
|
45
|
+
|
46
|
+
def list
|
47
|
+
request(endpoint, @api_key, nil, 'GET')
|
48
|
+
end
|
49
|
+
|
50
|
+
def preview(id, substitution_data, draft = nil)
|
51
|
+
params = {}
|
52
|
+
params[:draft] = draft unless draft.nil?
|
53
|
+
request(
|
54
|
+
endpoint("#{id}/preview", params),
|
55
|
+
@api_key,
|
56
|
+
{ substitution_data: substitution_data },
|
57
|
+
'POST'
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def payload_from_args(id, from, subject, html)
|
64
|
+
model = { content: {}, options: {} }
|
65
|
+
|
66
|
+
model[:id] = id unless id.nil?
|
67
|
+
model[:content][:from] = from unless from.nil?
|
68
|
+
model[:content][:subject] = subject unless subject.nil?
|
69
|
+
model[:content][:html] = html unless html.nil?
|
70
|
+
|
71
|
+
model
|
72
|
+
end
|
73
|
+
|
74
|
+
def payload_from_options(**options)
|
75
|
+
model = { content: { from: {} }, options: {} }
|
76
|
+
|
77
|
+
# Mapping optional arguments to root
|
78
|
+
[
|
79
|
+
[:name, :name],
|
80
|
+
[:id, :id],
|
81
|
+
[:description, :description],
|
82
|
+
[:published, :published]
|
83
|
+
].each { |skey, dkey| copy_value(options, skey, model, dkey) }
|
84
|
+
|
85
|
+
# Mapping optional arguments to options
|
86
|
+
[
|
87
|
+
[:track_opens, :open_tracking],
|
88
|
+
[:track_clicks, :click_tracking],
|
89
|
+
[:is_transactional, :transactional]
|
90
|
+
].each { |skey, dkey| copy_value(options, skey, model[:options], dkey) }
|
91
|
+
|
92
|
+
# Mapping optional arguments to content
|
93
|
+
[
|
94
|
+
[:html, :html],
|
95
|
+
[:text, :text],
|
96
|
+
[:subject, :subject],
|
97
|
+
[:reply_to, :reply_to],
|
98
|
+
[:custom_headers, :headers]
|
99
|
+
].each { |skey, dkey| copy_value(options, skey, model[:content], dkey) }
|
100
|
+
|
101
|
+
# Mapping optional arguments to sender information
|
102
|
+
[
|
103
|
+
[:from_email, :email],
|
104
|
+
[:from_name, :name]
|
105
|
+
].each do |skey, dkey|
|
106
|
+
copy_value(options, skey, model[:content][:from], dkey)
|
107
|
+
end
|
108
|
+
|
109
|
+
model
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|