sparkpost 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
[](https://travis-ci.org/SparkPost/ruby-sparkpost) [](https://coveralls.io/github/SparkPost/ruby-sparkpost?branch=master)
|
7
|
+
[](https://travis-ci.org/SparkPost/ruby-sparkpost) [](https://coveralls.io/github/SparkPost/ruby-sparkpost?branch=master) [](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
|