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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc6408b4b46931661f45f43c8b1f37e0492ea4ba
4
- data.tar.gz: 8836156574c1979033b5b3638c3ec348c3519608
3
+ metadata.gz: 796669253fea19aa5100d4947812dcd522c5b740
4
+ data.tar.gz: 1ef22cf099b5f094ff1d4fe947f45e27bd3c6ae8
5
5
  SHA512:
6
- metadata.gz: ebdcdd2123e18efc025c971ca8333bda26c691bed4d27f1cb8ec2c2d6db55cc0413efaa54543747a7e15316da343e41c5af83550d51878ef561d4312976089c9
7
- data.tar.gz: 59b664eb000246a06381800f952d0d16a674f670ed1e93f539aef52ec319035e9c9d1dd30be86486552ca9c32725b8ae2b5cf2e799344bf84751f584e278b52d
6
+ metadata.gz: 3d8ebe367055686b7d287464754e8b868b9c25d228f8e96ccb3ff9ddafcf13be99555994badb816a63fc15a47fd7a7377d180c3083445473f9cf45863b8483a7
7
+ data.tar.gz: 6e5a7ff2c7532b778c5e87534a5d15d0e73bee8c53ed9bd452b2e3834e4730c0f8d74f5c18d0a13942b1094d7448a460d003bab998da0ec3b682f9efd78f22c5
data/.gitignore CHANGED
@@ -19,3 +19,5 @@ tmp
19
19
  .idea
20
20
  .ruby-gemset
21
21
  coverage
22
+ _examples
23
+ .byebug_history
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ Style/FirstParameterIndentation:
2
+ Enabled: false
3
+ Documentation:
4
+ Enabled: false
5
+ Metrics/MethodLength:
6
+ Enabled: false
7
+
8
+ Metrics/LineLength:
9
+ Exclude:
10
+ - spec/**/*
11
+ AllCops:
12
+ Exclude:
13
+ - _examples/**/*
data/.travis.yml CHANGED
@@ -3,6 +3,7 @@ rvm:
3
3
  - 2.0.0
4
4
  - 2.1.2
5
5
  - 2.2.4
6
+ - 2.3.0
6
7
  notifications:
7
8
  slack:
8
9
  secure: VNIwgvrbcwj0b2gfYSOeTyK7rkV62/belwhYthasHmN+DoTsEJF4+HFVtzOykS72LM/f5Id5zieWtxYG+soy+yEOc1iZizXRpRJORtTYfZJB9RCffavosl322BcpoTX99cGyiZjWjOFH70UWlFMB3zT0jS+9icuTfk7ZqBX/zDA=
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 Sparkpost
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
- Check [examples/transmission.rb](examples/transmission.rb)
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 "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
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 :default => :spec
7
-
8
+ task default: [:rubocop, :spec]
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "sparkpost"
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 "irb"
13
+ require 'irb'
14
14
  IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../../lib/sparkpost'
4
+
5
+ sp = SparkPost::Client.new # api key was set in ENV
6
+ templates = sp.template.list
7
+
8
+ puts templates
@@ -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
@@ -1,3 +1,4 @@
1
1
  require_relative 'sparkpost/version'
2
2
  require_relative 'sparkpost/transmission'
3
- require_relative 'sparkpost/client'
3
+ require_relative 'sparkpost/client'
4
+ require_relative 'sparkpost/template'
@@ -1,23 +1,26 @@
1
1
  module SparkPost
2
- class Client
3
- attr_reader :transmission
4
-
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
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
- if @api_key.blank?
10
- fail ArgumentError, 'No API key is provided. Either provide api_key with constructor or set SPARKPOST_API_KEY environment variable'
11
- end
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
- if @api_host.blank?
15
- fail ArgumentError, 'No API host is provided. Either provide api_host with constructor or set SPARKPOST_API_HOST environment variable'
16
- end
17
- end
18
+ def transmission
19
+ @transmission ||= Transmission.new(@api_key, @api_host)
20
+ end
18
21
 
19
- def transmission
20
- @transmission ||= Transmission.new(@api_key, @api_host)
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
@@ -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 = Net::HTTP.new(uri.host, uri.port)
13
- http.use_ssl = true
11
+ http = configure_http(uri)
14
12
  headers = {
15
- 'User-Agent' => 'ruby-sparkpost/' + VERSION,
16
- 'Content-Type' => 'application/json',
17
- 'Authorization' => api_key
13
+ 'User-Agent' => 'ruby-sparkpost/' + VERSION,
14
+ 'Content-Type' => 'application/json',
15
+ 'Authorization' => api_key
18
16
  }
19
- req = Net::HTTP::Post.new(uri.path, initheader=headers)
20
- req.body = data.to_json
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
- process_response(http.request(req));
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
- fail SparkPost::DeliveryException, response['errors']
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, :process_response
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