smtpcom-sendapi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|