smtpcom-sendapi 1.0.0
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 +15 -0
- data/.gitignore +37 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +51 -0
- data/LICENSE +22 -0
- data/README.md +197 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/smtpcom/sendapi/api_resource.rb +33 -0
- data/lib/smtpcom/sendapi/campaign.rb +44 -0
- data/lib/smtpcom/sendapi/clicks_report.rb +54 -0
- data/lib/smtpcom/sendapi/email.rb +109 -0
- data/lib/smtpcom/sendapi/opens_report.rb +44 -0
- data/lib/smtpcom/sendapi/real_time_reporting.rb +39 -0
- data/lib/smtpcom/sendapi/request.rb +61 -0
- data/lib/smtpcom/sendapi/sender.rb +11 -0
- data/lib/smtpcom/sendapi/sends_report.rb +44 -0
- data/lib/smtpcom/sendapi/stats_summary.rb +42 -0
- data/lib/smtpcom/sendapi/template.rb +49 -0
- data/lib/smtpcom/sendapi/utils.rb +32 -0
- data/lib/smtpcom/sendapi/version.rb +5 -0
- data/lib/smtpcom/sendapi.rb +26 -0
- data/smtpcom-sendapi.gemspec +29 -0
- metadata +169 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MzQ1NzA5OGMxOGI1MDk3ZDFkOWNkMzdhM2M4N2E2Yjg0NjY2MjU5Zg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZjdlZTA0OWY4YzlkNzc5NDJlZTlkZGI0ZWI0ZGY1ZmM2MzE0MmRhYQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
Nzk5NjllZjdlMTI5MDk1ODdjZDZjMTZmNzIwMzkxYTJiYjNmNTcxYWNiMWZl
|
10
|
+
MDYwZTM2OTBkNGZmODYyOGU4YTcxODg1ODdjZTM4MmQxYzMxNjlhMmFkMGNh
|
11
|
+
ODBhZjBkYmU3ZDRiYzQ4MWY2YTU1NDU4NWRjYzRmMjdmMWNkNmQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Nzg3YzEyZDAzMGE0ODk3MDk2Y2ZiMzhiMWZjZmU3YjgwOTg2ZDc2ZWE5YzZi
|
14
|
+
ZmM0NGRjN2FlODI2ZjZkMjQyMWNjYThiYTJkYWEwZjhlOTA1OWU2MzUxNDAy
|
15
|
+
M2MzZTY5NmE0YmRkODhiMzI4M2VhYzRiYzU3OWIwMmRkMmFlZWU=
|
data/.gitignore
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/vendor/bundle
|
26
|
+
/lib/bundler/man/
|
27
|
+
|
28
|
+
# for a library or gem, you might want to ignore these files since the code is
|
29
|
+
# intended to run in multiple environments; otherwise, check them in:
|
30
|
+
# Gemfile.lock
|
31
|
+
# .ruby-version
|
32
|
+
# .ruby-gemset
|
33
|
+
|
34
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
35
|
+
.rvmrc
|
36
|
+
|
37
|
+
.rubocop.*
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
smtpcom-sendapi (1.0.0)
|
5
|
+
httparty (~> 0.13)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
addressable (2.3.8)
|
11
|
+
crack (0.4.2)
|
12
|
+
safe_yaml (~> 1.0.0)
|
13
|
+
diff-lcs (1.2.5)
|
14
|
+
httparty (0.13.5)
|
15
|
+
json (~> 1.8)
|
16
|
+
multi_xml (>= 0.5.2)
|
17
|
+
json (1.8.3)
|
18
|
+
multi_xml (0.5.5)
|
19
|
+
rake (10.4.2)
|
20
|
+
rspec (3.2.0)
|
21
|
+
rspec-core (~> 3.2.0)
|
22
|
+
rspec-expectations (~> 3.2.0)
|
23
|
+
rspec-mocks (~> 3.2.0)
|
24
|
+
rspec-core (3.2.3)
|
25
|
+
rspec-support (~> 3.2.0)
|
26
|
+
rspec-expectations (3.2.1)
|
27
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
+
rspec-support (~> 3.2.0)
|
29
|
+
rspec-mocks (3.2.1)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.2.0)
|
32
|
+
rspec-support (3.2.2)
|
33
|
+
safe_yaml (1.0.4)
|
34
|
+
vcr (2.9.3)
|
35
|
+
webmock (1.21.0)
|
36
|
+
addressable (>= 2.3.6)
|
37
|
+
crack (>= 0.3.2)
|
38
|
+
|
39
|
+
PLATFORMS
|
40
|
+
ruby
|
41
|
+
|
42
|
+
DEPENDENCIES
|
43
|
+
bundler (~> 1.9)
|
44
|
+
rake (~> 10.0)
|
45
|
+
rspec (~> 3.2, >= 3.2.0)
|
46
|
+
smtpcom-sendapi!
|
47
|
+
vcr (~> 2.9, >= 2.9.3)
|
48
|
+
webmock (~> 1.21, >= 1.21.0)
|
49
|
+
|
50
|
+
BUNDLED WITH
|
51
|
+
1.10.4
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 SMTP, inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
# SMTP.com Sendapi
|
2
|
+
|
3
|
+
Website: https://www.smtp.com/solutions/transactional-email-service-api/
|
4
|
+
API documentation: https://www.smtp.com/wp-content/uploads/SMTP-Transactional-API-Documentation.pdf
|
5
|
+
|
6
|
+
## Requirements
|
7
|
+
|
8
|
+
Ruby 1.9.3 or above
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
gem install smtpcom-sendapi
|
13
|
+
|
14
|
+
## Bundler
|
15
|
+
|
16
|
+
source 'https://rubygems.org'
|
17
|
+
|
18
|
+
gem 'smtpcom-sendapi', require: 'smtpcom/sendapi'
|
19
|
+
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Setting your API key
|
24
|
+
|
25
|
+
Smtpcom::Sendapi.api_key = 'YOUR_API_KEY'
|
26
|
+
|
27
|
+
### Campaigns
|
28
|
+
|
29
|
+
List all
|
30
|
+
|
31
|
+
Smtpcom::Sendapi::Campaign.all
|
32
|
+
|
33
|
+
Create
|
34
|
+
|
35
|
+
campaign = Smtpcom::Sendapi::Campaign.new
|
36
|
+
campaign.name = 'MyCampaign'
|
37
|
+
campaign.save
|
38
|
+
|
39
|
+
puts campaign.id
|
40
|
+
#=> 556998d4130e7f0aa881b5c1
|
41
|
+
|
42
|
+
Find
|
43
|
+
|
44
|
+
campaign = Smtpcom::Sendapi::Campaign.find('556998d4130e7f0aa881b5c1')
|
45
|
+
|
46
|
+
# you can also get some stats from campaign object
|
47
|
+
puts campaign.opens
|
48
|
+
puts campaign.clicks
|
49
|
+
puts campaign.delivered
|
50
|
+
puts campaign.bounced
|
51
|
+
|
52
|
+
Delete
|
53
|
+
|
54
|
+
campaign.delete
|
55
|
+
|
56
|
+
|
57
|
+
### Email
|
58
|
+
|
59
|
+
email = Smtpcom::Sendapi::Email.new
|
60
|
+
|
61
|
+
email.subject = 'Hello world subj'
|
62
|
+
email.from = 'from@mywebsite.com'
|
63
|
+
email.body_text = 'Hello world'
|
64
|
+
|
65
|
+
# add recipients
|
66
|
+
email.add_recipient 'john@mywebsite.com', 'John'
|
67
|
+
email.add_recipient 'linda@mywebsite.com'
|
68
|
+
|
69
|
+
# add headers
|
70
|
+
email.add_header 'X-CustomID', '81d4350b'
|
71
|
+
|
72
|
+
# add attachment
|
73
|
+
# can be attachment data in base64 format, or a url where the attachment can be downloaded from
|
74
|
+
email.add_attachment 'Image1', 'image/jpeg', base64_content
|
75
|
+
|
76
|
+
# send email
|
77
|
+
email.send
|
78
|
+
|
79
|
+
|
80
|
+
Allowed email attributes:
|
81
|
+
|
82
|
+
- subject
|
83
|
+
- body_html
|
84
|
+
- body_text
|
85
|
+
- template_id
|
86
|
+
- from
|
87
|
+
- from_name
|
88
|
+
- reply_to
|
89
|
+
- reply_to_name
|
90
|
+
- return_path
|
91
|
+
- recipients
|
92
|
+
- recipients_url
|
93
|
+
- default_recipient_data
|
94
|
+
- attachments
|
95
|
+
- campaign
|
96
|
+
- utm_codes
|
97
|
+
- email_headers
|
98
|
+
|
99
|
+
|
100
|
+
### Templates
|
101
|
+
|
102
|
+
List all
|
103
|
+
|
104
|
+
Smtpcom::Sendapi::Template.all
|
105
|
+
|
106
|
+
Create
|
107
|
+
|
108
|
+
template = Smtpcom::Sendapi::Template.new
|
109
|
+
template.name = 'Template 1'
|
110
|
+
template.from = 'john@mywebsite.com'
|
111
|
+
template.from_name = 'John'
|
112
|
+
template.subject = 'Hello world'
|
113
|
+
template.html = 'HTML email body'
|
114
|
+
template.save
|
115
|
+
|
116
|
+
puts template.id
|
117
|
+
#=> 156928d1130a7f0ab781b5c2
|
118
|
+
|
119
|
+
Find
|
120
|
+
|
121
|
+
template = Smtpcom::Sendapi::Template.find '156928d1130a7f0ab781b5c2'
|
122
|
+
|
123
|
+
Delete
|
124
|
+
|
125
|
+
template.delete
|
126
|
+
|
127
|
+
### Senders
|
128
|
+
|
129
|
+
List all
|
130
|
+
|
131
|
+
Smtpcom::Sendapi::Sender.all
|
132
|
+
|
133
|
+
|
134
|
+
### Reporting
|
135
|
+
|
136
|
+
#### Sends Report
|
137
|
+
|
138
|
+
# Parametes: time_start, time_finish, sender, campaign_id
|
139
|
+
report = Smtpcom::Sendapi::SendsReport.new time_start, time_finish
|
140
|
+
|
141
|
+
# return sends as array, accepts 2 optional parameters - count, page
|
142
|
+
report.all
|
143
|
+
|
144
|
+
# return failed sends as array, accepts 2 optional parameters - count, page
|
145
|
+
report.failed
|
146
|
+
|
147
|
+
|
148
|
+
#### Opens
|
149
|
+
|
150
|
+
# Parametes: time_start, time_finish, sender, campaign_id
|
151
|
+
report = Smtpcom::Sendapi::OpensReport.new time_start, time_finish
|
152
|
+
|
153
|
+
# return opens as array, accepts 2 optional parameters - count, page
|
154
|
+
report.all
|
155
|
+
|
156
|
+
# return opens as csv
|
157
|
+
report.csv
|
158
|
+
|
159
|
+
|
160
|
+
#### Clicks
|
161
|
+
|
162
|
+
# Parametes: time_start, time_finish, sender, campaign_id, url
|
163
|
+
report = Smtpcom::Sendapi::ClicksReport.new time_start, time_finish
|
164
|
+
|
165
|
+
# return clicks as array, accepts 2 optional parameters - count, page
|
166
|
+
report.all
|
167
|
+
|
168
|
+
# return clicks as csv
|
169
|
+
report.csv
|
170
|
+
|
171
|
+
#### Stats Summary
|
172
|
+
|
173
|
+
# Parametes: time_start, time_finish, sender, campaign_id, url
|
174
|
+
report = Smtpcom::Sendapi::StatsSummary.new time_start, time_finish
|
175
|
+
|
176
|
+
report.all
|
177
|
+
|
178
|
+
# in csv format
|
179
|
+
report.csv
|
180
|
+
|
181
|
+
#### Real Time Reporting
|
182
|
+
|
183
|
+
# get real time reporting settings
|
184
|
+
Smtpcom::Sendapi::RealTimeReporting.settings
|
185
|
+
|
186
|
+
# configure real time reporting
|
187
|
+
r = new Smtpcom::Sendapi::RealTimeReporting
|
188
|
+
|
189
|
+
r.queue_name = 'MyQueue'
|
190
|
+
r.server_region = 'us-west-2'
|
191
|
+
r.public_access_key = 'public_key'
|
192
|
+
r.private_access_key = 'private_key'
|
193
|
+
r.notify_opens = false
|
194
|
+
r.notify_clicks = true
|
195
|
+
r.notify_delivert_info = false
|
196
|
+
|
197
|
+
r.save
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "smtpcom/sendapi"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class ApiResource
|
4
|
+
include Request
|
5
|
+
|
6
|
+
def initialize(attrs = {})
|
7
|
+
self.class::MAPPINGS.keys.each do |k|
|
8
|
+
instance_variable_set("@#{k}", attrs[k]) if attrs.key? k
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.build_from_response(data)
|
13
|
+
new Hash[self::MAPPINGS.map { |k, v| [k.to_sym, data[v.to_s]] }] if data
|
14
|
+
end
|
15
|
+
|
16
|
+
def _get(*attrs)
|
17
|
+
self.class._get(*attrs)
|
18
|
+
end
|
19
|
+
|
20
|
+
def _get_raw(*attrs)
|
21
|
+
self.class._get_raw(*attrs)
|
22
|
+
end
|
23
|
+
|
24
|
+
def _post(*attrs)
|
25
|
+
self.class._post(*attrs)
|
26
|
+
end
|
27
|
+
|
28
|
+
def prepare_params
|
29
|
+
Hash[self.class::MAPPINGS.map { |k, v| [v, instance_variable_get("@#{k}")] }]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class Campaign < ApiResource
|
4
|
+
MAPPINGS = {
|
5
|
+
id: :CampaignID,
|
6
|
+
name: :CampaignName,
|
7
|
+
opens: :Opens,
|
8
|
+
clicks: :Clicks,
|
9
|
+
delivered: :Delivered,
|
10
|
+
bounced: :Bounced
|
11
|
+
}
|
12
|
+
|
13
|
+
attr_accessor :id, :name
|
14
|
+
attr_reader :opens, :clicks, :delivered, :bounced
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def all
|
18
|
+
_get('/campaigns/get')['Data'].map do |row|
|
19
|
+
build_from_response row
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def find(id)
|
24
|
+
all.find { |c| c.id == id }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def save
|
29
|
+
attrs = { CampaignName: @name }
|
30
|
+
res = if @id
|
31
|
+
_get '/campaigns/update', attrs.merge(CampaignID: @id), :formatted
|
32
|
+
else
|
33
|
+
_post '/campaigns/add', attrs, :formatted
|
34
|
+
end
|
35
|
+
@id = res[:id]
|
36
|
+
res
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete
|
40
|
+
_post('/campaigns/delete', { CampaignID: @id }, :formatted)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class ClicksReport < ApiResource
|
4
|
+
attr_reader :start, :finish, :sender, :campaign, :url, :total
|
5
|
+
|
6
|
+
def initialize(start, finish, sender = nil, campaign = nil, url = nil)
|
7
|
+
@start = start
|
8
|
+
@finish = finish
|
9
|
+
@sender = sender
|
10
|
+
@campaign = campaign
|
11
|
+
@url = url
|
12
|
+
end
|
13
|
+
|
14
|
+
def all(count = 100, page = 1)
|
15
|
+
response = _get(list_url, prepare_params(count, page))
|
16
|
+
@total = response['Total']
|
17
|
+
format_response response['Data']
|
18
|
+
end
|
19
|
+
|
20
|
+
def csv(count = 100, page = 1)
|
21
|
+
_get_raw(csv_url, prepare_params(count, page).merge(headers: { 'Accept' => 'text/csv' }))
|
22
|
+
end
|
23
|
+
|
24
|
+
def list_url
|
25
|
+
@url ? '/clicksbyurl/get' : '/clicks/get'
|
26
|
+
end
|
27
|
+
|
28
|
+
def csv_url
|
29
|
+
@url ? '/clicksbyurlexport/get' : '/clicksexport/get'
|
30
|
+
end
|
31
|
+
|
32
|
+
def prepare_params(count, page)
|
33
|
+
attributes = {
|
34
|
+
DateFrom: @start.strftime("%m/%d/%Y"),
|
35
|
+
DateTo: @finish.strftime("%m/%d/%Y"),
|
36
|
+
Count: count,
|
37
|
+
Page: page
|
38
|
+
}
|
39
|
+
attributes[:Sender] = @sender if @sender
|
40
|
+
attributes[:CampaignID] = @campaign if @campaign
|
41
|
+
attributes[:Url] = @url if @url
|
42
|
+
attributes
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def format_response(data)
|
48
|
+
data.map do |row|
|
49
|
+
Utils.format_response_row(row)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class Email < ApiResource
|
4
|
+
MAPPINGS = {
|
5
|
+
subject: :Subject,
|
6
|
+
body_html: :BodyHtml,
|
7
|
+
body_text: :BodyText,
|
8
|
+
template_id: :TemplateID,
|
9
|
+
from: :From,
|
10
|
+
from_name: :FromName,
|
11
|
+
reply_to: :ReplyTo,
|
12
|
+
reply_to_name: :ReplyToName,
|
13
|
+
return_path: :ReturnPath,
|
14
|
+
recipients: :Recipients,
|
15
|
+
recipients_url: :RecipientsUrl,
|
16
|
+
default_recipient_data: :DefaultRecipientData,
|
17
|
+
attachments: :Attachments,
|
18
|
+
campaign: :Campaign,
|
19
|
+
utm_codes: :UTMCodes,
|
20
|
+
email_headers: :EmailHeaders
|
21
|
+
}
|
22
|
+
attr_accessor(*MAPPINGS.keys)
|
23
|
+
|
24
|
+
def initialize(*params)
|
25
|
+
super(*params)
|
26
|
+
@recipients = []
|
27
|
+
@attachments = []
|
28
|
+
@email_headers = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_recipient(email, name = nil)
|
32
|
+
@recipients << {
|
33
|
+
to_address: email,
|
34
|
+
to_name: name
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_attachment(name, content_type, body)
|
39
|
+
@attachments << {
|
40
|
+
name: name,
|
41
|
+
content_type: content_type,
|
42
|
+
content: body
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_header(name, value)
|
47
|
+
@email_headers << {
|
48
|
+
name: name,
|
49
|
+
value: value
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def send
|
54
|
+
_post '/send', prepare_params, :formatted
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def prepare_params
|
60
|
+
{
|
61
|
+
Subject: @subject,
|
62
|
+
BodyHtml: @body_html,
|
63
|
+
BodyText: @body_text,
|
64
|
+
TemplateID: @template_id,
|
65
|
+
From: @from,
|
66
|
+
FromName: @from_name,
|
67
|
+
ReplyTo: @reply_to,
|
68
|
+
ReplyToName: @reply_to_name,
|
69
|
+
ReturnPath: @return_path,
|
70
|
+
Recipients: prepare_recipients,
|
71
|
+
RecipientsUrl: @recipients_url,
|
72
|
+
DefaultRecipientData: @default_recipient_data,
|
73
|
+
Attachments: prepare_attachments,
|
74
|
+
Campaign: @campaign,
|
75
|
+
UTMCodes: @utm_codes,
|
76
|
+
EmailHeaders: prepare_headers
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def prepare_recipients
|
81
|
+
@recipients.map do |item|
|
82
|
+
{
|
83
|
+
ToAddress: item[:to_address],
|
84
|
+
ToName: item[:to_name]
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def prepare_attachments
|
90
|
+
@attachments.map do |item|
|
91
|
+
{
|
92
|
+
Name: item[:name],
|
93
|
+
ContentType: item[:content_type],
|
94
|
+
Content: item[:body]
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def prepare_headers
|
100
|
+
@email_headers.map do |item|
|
101
|
+
{
|
102
|
+
Name: item[:name],
|
103
|
+
Value: item[:value]
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class OpensReport < ApiResource
|
4
|
+
attr_reader :start, :finish, :sender, :campaign, :total
|
5
|
+
|
6
|
+
def initialize(start, finish, sender = nil, campaign = nil)
|
7
|
+
@start = start
|
8
|
+
@finish = finish
|
9
|
+
@sender = sender
|
10
|
+
@campaign = campaign
|
11
|
+
end
|
12
|
+
|
13
|
+
def all(count = 100, page = 1)
|
14
|
+
response = _get('/opens/get', prepare_params(count, page))
|
15
|
+
@total = response['Total']
|
16
|
+
format_response response['Data']
|
17
|
+
end
|
18
|
+
|
19
|
+
def csv(count = 100, page = 1)
|
20
|
+
_get_raw('/opensexport/get', prepare_params(count, page).merge(headers: { 'Accept' => 'text/csv' }))
|
21
|
+
end
|
22
|
+
|
23
|
+
def prepare_params(count, page)
|
24
|
+
attributes = {
|
25
|
+
DateFrom: @start.strftime("%m/%d/%Y"),
|
26
|
+
DateTo: @finish.strftime("%m/%d/%Y"),
|
27
|
+
Count: count,
|
28
|
+
Page: page
|
29
|
+
}
|
30
|
+
attributes[:Sender] = @sender if @sender
|
31
|
+
attributes[:CampaignID] = @campaign if @campaign
|
32
|
+
attributes
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def format_response(data)
|
38
|
+
data.map do |row|
|
39
|
+
Utils.format_response_row(row)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class RealTimeReporting < ApiResource
|
4
|
+
MAPPINGS = {
|
5
|
+
queue_name: :QueueName,
|
6
|
+
server_region: :ServerRegion,
|
7
|
+
public_access_key: :PublicAccessKey,
|
8
|
+
private_access_key: :PrivateAccessKey,
|
9
|
+
notify_opens: :NotifyOpens,
|
10
|
+
notify_clicks: :NotifyClicks,
|
11
|
+
notify_delivert_info: :NotifyDelivertInfo
|
12
|
+
}
|
13
|
+
|
14
|
+
attr_accessor(*MAPPINGS.keys)
|
15
|
+
|
16
|
+
def self.settings
|
17
|
+
build_from_response(_get('/realtimereporting/get'))
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.build_from_response(data)
|
21
|
+
new Hash[MAPPINGS.map { |k, v| [k.to_sym, data["InstantNotification_#{v}"]] }].merge \
|
22
|
+
notify_opens: data['InstantNotification_NotifyOpens'] == 'On',
|
23
|
+
notify_clicks: data['InstantNotification_NotifyClicks'] == 'On',
|
24
|
+
notify_delivert_info: data['InstantNotification_NotifyDelivertInfo'] == 'On'
|
25
|
+
end
|
26
|
+
|
27
|
+
def save
|
28
|
+
_post '/realtimereporting/update', prepare_params, :formatted
|
29
|
+
end
|
30
|
+
|
31
|
+
def prepare_params
|
32
|
+
super.merge \
|
33
|
+
NotifyOpens: (notify_opens ? 'On' : 'Off'),
|
34
|
+
NotifyClicks: (notify_clicks ? 'On' : 'Off'),
|
35
|
+
NotifyDelivertInfo: (notify_delivert_info ? 'On' : 'Off')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
module Request
|
4
|
+
module ClassMethods
|
5
|
+
include HTTParty
|
6
|
+
|
7
|
+
attr_reader :response
|
8
|
+
|
9
|
+
def _get(path, params = {}, formatted = false)
|
10
|
+
@response = HTTParty.get \
|
11
|
+
_url(path),
|
12
|
+
headers: _json_headers,
|
13
|
+
query: params.merge(_auth_key),
|
14
|
+
format: :json
|
15
|
+
if formatted
|
16
|
+
Utils.format_response_row @response.parsed_response
|
17
|
+
else
|
18
|
+
@response.parsed_response
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def _get_raw(path, params = {})
|
23
|
+
@response = HTTParty.get \
|
24
|
+
_url(path),
|
25
|
+
headers: (params.delete(:headers) || _json_headers),
|
26
|
+
query: params.merge(_auth_key)
|
27
|
+
@response.body
|
28
|
+
end
|
29
|
+
|
30
|
+
def _post(path, params = {}, formatted = false)
|
31
|
+
@response = HTTParty.post \
|
32
|
+
_url(path),
|
33
|
+
headers: _json_headers,
|
34
|
+
body: params.merge(_auth_key).to_json,
|
35
|
+
format: :json
|
36
|
+
if formatted
|
37
|
+
Utils.format_response_row @response.parsed_response
|
38
|
+
else
|
39
|
+
@response.parsed_response
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def _url(path)
|
44
|
+
File.join Smtpcom::Sendapi.api_host, Smtpcom::Sendapi.api_base, path
|
45
|
+
end
|
46
|
+
|
47
|
+
def _json_headers
|
48
|
+
{ 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
|
49
|
+
end
|
50
|
+
|
51
|
+
def _auth_key
|
52
|
+
{ apiKey: Smtpcom::Sendapi.api_key }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.included(base)
|
57
|
+
base.extend(ClassMethods)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class SendsReport < ApiResource
|
4
|
+
attr_reader :start, :finish, :sender, :campaign, :total
|
5
|
+
|
6
|
+
def initialize(start, finish, sender = nil, campaign = nil)
|
7
|
+
@start = start
|
8
|
+
@finish = finish
|
9
|
+
@sender = sender
|
10
|
+
@campaign = campaign
|
11
|
+
end
|
12
|
+
|
13
|
+
def all(count = 100, page = 1)
|
14
|
+
response = _get('/sends/get', prepare_params(count, page))
|
15
|
+
@total = response['Total']
|
16
|
+
format_response response['Data']
|
17
|
+
end
|
18
|
+
|
19
|
+
def failed(count = 100, page = 1)
|
20
|
+
response = _get('/sends/failed', prepare_params(count, page))
|
21
|
+
@total = response['Total']
|
22
|
+
format_response response['Data']
|
23
|
+
end
|
24
|
+
|
25
|
+
def prepare_params(count, page)
|
26
|
+
attributes = {
|
27
|
+
DateFrom: @start.strftime("%m/%d/%Y"),
|
28
|
+
DateTo: @finish.strftime("%m/%d/%Y"),
|
29
|
+
Count: count,
|
30
|
+
Page: page
|
31
|
+
}
|
32
|
+
attributes[:Sender] = @sender if @sender
|
33
|
+
attributes[:CampaignID] = @campaign if @campaign
|
34
|
+
attributes
|
35
|
+
end
|
36
|
+
|
37
|
+
def format_response(data)
|
38
|
+
data.map do |row|
|
39
|
+
Utils.format_response_row(row)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class StatsSummary < ApiResource
|
4
|
+
attr_reader :start, :finish, :sender, :campaign, :total
|
5
|
+
|
6
|
+
def initialize(start, finish, sender = nil, campaign = nil)
|
7
|
+
@start = start
|
8
|
+
@finish = finish
|
9
|
+
@sender = sender
|
10
|
+
@campaign = campaign
|
11
|
+
end
|
12
|
+
|
13
|
+
def all
|
14
|
+
format_response _get('/summarystats/get', prepare_params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def csv
|
18
|
+
_get_raw('/summarystatsexport/get', prepare_params.merge(headers: { 'Accept' => 'text/csv' }))
|
19
|
+
end
|
20
|
+
|
21
|
+
def prepare_params
|
22
|
+
attributes = {
|
23
|
+
DateFrom: @start.strftime("%m/%d/%Y"),
|
24
|
+
DateTo: @finish.strftime("%m/%d/%Y")
|
25
|
+
}
|
26
|
+
attributes[:Sender] = @sender if @sender
|
27
|
+
attributes[:CampaignID] = @campaign if @campaign
|
28
|
+
attributes
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def format_response(data)
|
34
|
+
dd = Utils.format_response_row(data)
|
35
|
+
dd[:day_stats].map! do |row|
|
36
|
+
Utils.format_response_row(row)
|
37
|
+
end
|
38
|
+
dd
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
class Template < ApiResource
|
4
|
+
MAPPINGS = {
|
5
|
+
id: :_id,
|
6
|
+
name: :TemplateName,
|
7
|
+
from: :From,
|
8
|
+
from_name: :FromName,
|
9
|
+
subject: :Subject,
|
10
|
+
html: :Html
|
11
|
+
}
|
12
|
+
|
13
|
+
attr_accessor(*MAPPINGS.keys)
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def all
|
17
|
+
_get('/templates/get')['Data'].map do |row|
|
18
|
+
build_from_response row
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def find(id)
|
23
|
+
build_from_response _get('/template/get', TemplateID: id)['Data']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def save
|
28
|
+
attrs = {
|
29
|
+
TemplateName: @name,
|
30
|
+
From: @from,
|
31
|
+
FromName: @from_name,
|
32
|
+
Subject: @subject,
|
33
|
+
Html: @html
|
34
|
+
}
|
35
|
+
res = if @id
|
36
|
+
_post '/templates/update', attrs.merge(TemplateID: @id), :formatted
|
37
|
+
else
|
38
|
+
_post '/templates/add', attrs, :formatted
|
39
|
+
end
|
40
|
+
@id = res[:id]
|
41
|
+
res
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete
|
45
|
+
_post('/templates/delete', { TemplateID: @id }, :formatted)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Smtpcom
|
2
|
+
module Sendapi
|
3
|
+
module Utils
|
4
|
+
class << self
|
5
|
+
def underscore(str)
|
6
|
+
str.gsub(/::/, '/')
|
7
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
8
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
9
|
+
.tr("-", "_")
|
10
|
+
.downcase
|
11
|
+
end
|
12
|
+
|
13
|
+
def underscore_hash(h)
|
14
|
+
Hash[h.map { |k, v| [Utils.underscore(k), v] }]
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_time(str)
|
18
|
+
Time.at(str.scan(/\d{13}/).first.to_i / 1000)
|
19
|
+
end
|
20
|
+
|
21
|
+
def format_response_row(row)
|
22
|
+
row.each do |k, v|
|
23
|
+
row[k] = parse_time(v) if v.is_a?(String) && v =~ /\/Date\(\d{13}\)\//
|
24
|
+
end
|
25
|
+
underscore_hash(row)
|
26
|
+
.reject { |k, _v| k.start_with? '_' }
|
27
|
+
.inject({}) { |res, (k, v)| res[k.to_sym] = v; res }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
require "smtpcom/sendapi/version"
|
4
|
+
require "smtpcom/sendapi/request"
|
5
|
+
require "smtpcom/sendapi/utils"
|
6
|
+
require "smtpcom/sendapi/api_resource"
|
7
|
+
require "smtpcom/sendapi/campaign"
|
8
|
+
require "smtpcom/sendapi/template"
|
9
|
+
require "smtpcom/sendapi/email"
|
10
|
+
require "smtpcom/sendapi/sender"
|
11
|
+
require "smtpcom/sendapi/real_time_reporting"
|
12
|
+
require "smtpcom/sendapi/clicks_report"
|
13
|
+
require "smtpcom/sendapi/opens_report"
|
14
|
+
require "smtpcom/sendapi/sends_report"
|
15
|
+
require "smtpcom/sendapi/stats_summary"
|
16
|
+
|
17
|
+
module Smtpcom
|
18
|
+
module Sendapi
|
19
|
+
@api_host = 'http://sendapi.smtp.com'
|
20
|
+
@api_base = '/transsend/api'
|
21
|
+
|
22
|
+
class << self
|
23
|
+
attr_accessor :api_key, :api_host, :api_base
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'smtpcom/sendapi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "smtpcom-sendapi"
|
8
|
+
spec.version = Smtpcom::Sendapi::VERSION
|
9
|
+
spec.authors = ["Vasiliy Sablin"]
|
10
|
+
spec.email = ["vasiliy.sablin@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Wrapper for Smtpcom Sendapi}
|
13
|
+
spec.description = %q{Details - https://www.smtp.com/solutions/transactional-email-service-api/}
|
14
|
+
spec.homepage = "https://www.smtp.com/solutions/transactional-email-service-api/"
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_runtime_dependency "httparty", "~> 0.13"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", '~> 3.2', '>= 3.2.0'
|
27
|
+
spec.add_development_dependency "vcr", '~> 2.9', '>= 2.9.3'
|
28
|
+
spec.add_development_dependency "webmock", '~> 1.21', '>= 1.21.0'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: smtpcom-sendapi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vasiliy Sablin
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.13'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.9'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.9'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.2'
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 3.2.0
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ~>
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '3.2'
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 3.2.0
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: vcr
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ~>
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.9'
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 2.9.3
|
85
|
+
type: :development
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ~>
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '2.9'
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 2.9.3
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: webmock
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.21'
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 1.21.0
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ~>
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '1.21'
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 1.21.0
|
115
|
+
description: Details - https://www.smtp.com/solutions/transactional-email-service-api/
|
116
|
+
email:
|
117
|
+
- vasiliy.sablin@gmail.com
|
118
|
+
executables: []
|
119
|
+
extensions: []
|
120
|
+
extra_rdoc_files: []
|
121
|
+
files:
|
122
|
+
- .gitignore
|
123
|
+
- Gemfile
|
124
|
+
- Gemfile.lock
|
125
|
+
- LICENSE
|
126
|
+
- README.md
|
127
|
+
- Rakefile
|
128
|
+
- bin/console
|
129
|
+
- bin/setup
|
130
|
+
- lib/smtpcom/sendapi.rb
|
131
|
+
- lib/smtpcom/sendapi/api_resource.rb
|
132
|
+
- lib/smtpcom/sendapi/campaign.rb
|
133
|
+
- lib/smtpcom/sendapi/clicks_report.rb
|
134
|
+
- lib/smtpcom/sendapi/email.rb
|
135
|
+
- lib/smtpcom/sendapi/opens_report.rb
|
136
|
+
- lib/smtpcom/sendapi/real_time_reporting.rb
|
137
|
+
- lib/smtpcom/sendapi/request.rb
|
138
|
+
- lib/smtpcom/sendapi/sender.rb
|
139
|
+
- lib/smtpcom/sendapi/sends_report.rb
|
140
|
+
- lib/smtpcom/sendapi/stats_summary.rb
|
141
|
+
- lib/smtpcom/sendapi/template.rb
|
142
|
+
- lib/smtpcom/sendapi/utils.rb
|
143
|
+
- lib/smtpcom/sendapi/version.rb
|
144
|
+
- smtpcom-sendapi.gemspec
|
145
|
+
homepage: https://www.smtp.com/solutions/transactional-email-service-api/
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
metadata: {}
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ! '>='
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
requirements: []
|
164
|
+
rubyforge_project:
|
165
|
+
rubygems_version: 2.4.6
|
166
|
+
signing_key:
|
167
|
+
specification_version: 4
|
168
|
+
summary: Wrapper for Smtpcom Sendapi
|
169
|
+
test_files: []
|