eliasbaixas-sendgrid_toolkit 1.0.5
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.
- data/README.md +278 -0
- data/Rakefile +22 -0
- data/VERSION +1 -0
- data/lib/sendgrid_toolkit.rb +14 -0
- data/lib/sendgrid_toolkit/abstract_sendgrid_client.rb +38 -0
- data/lib/sendgrid_toolkit/bounces.rb +7 -0
- data/lib/sendgrid_toolkit/common.rb +43 -0
- data/lib/sendgrid_toolkit/invalid_emails.rb +7 -0
- data/lib/sendgrid_toolkit/sendgrid_error.rb +10 -0
- data/lib/sendgrid_toolkit/spam_reports.rb +7 -0
- data/lib/sendgrid_toolkit/statistics.rb +31 -0
- data/lib/sendgrid_toolkit/unsubscribes.rb +29 -0
- data/sendgrid_toolkit.gemspec +60 -0
- data/spec/helper.rb +13 -0
- data/spec/lib/sendgrid_toolkit/abstract_sendgrid_client_spec.rb +69 -0
- data/spec/lib/sendgrid_toolkit/bounces_spec.rb +52 -0
- data/spec/lib/sendgrid_toolkit/common_spec.rb +23 -0
- data/spec/lib/sendgrid_toolkit/invalid_emails_spec.rb +50 -0
- data/spec/lib/sendgrid_toolkit/spam_reports_spec.rb +45 -0
- data/spec/lib/sendgrid_toolkit/statistics_spec.rb +41 -0
- data/spec/lib/sendgrid_toolkit/unsubscribes_spec.rb +60 -0
- data/spec/lib/sendgrid_toolkit_spec.rb +4 -0
- data/spec/webconnect/sendgrid_toolkit_spec.rb +74 -0
- metadata +100 -0
data/README.md
ADDED
@@ -0,0 +1,278 @@
|
|
1
|
+
SendgridToolkit
|
2
|
+
===============
|
3
|
+
|
4
|
+
SendgridToolkit is a Ruby wrapper for the Sendgrid Web API
|
5
|
+
|
6
|
+
Supported Modules
|
7
|
+
-----------------
|
8
|
+
|
9
|
+
SendgridToolkit provides a class for interacting with each of the following Sendgrid API modules:
|
10
|
+
|
11
|
+
- Bounces
|
12
|
+
- InvalidEmails
|
13
|
+
- SpamReports
|
14
|
+
- Statistics
|
15
|
+
- Unsubscribes
|
16
|
+
|
17
|
+
Consuming the Sendgrid API is as simple as instantiating a class and making the call:
|
18
|
+
|
19
|
+
unsubscribes = SendgridToolkit::Unsubscribes.new("username", "api_key")
|
20
|
+
unsubscribes.add :email => "email@to.unsubscribe"
|
21
|
+
|
22
|
+
Two lines, and voila!
|
23
|
+
|
24
|
+
Common actions are documented below under each module. For more details, visit the [Sendgrid Web API Documentation][2]
|
25
|
+
|
26
|
+
Contributing
|
27
|
+
------------
|
28
|
+
|
29
|
+
When submitting patches, please be sure you include rspec tests!
|
30
|
+
|
31
|
+
Big thanks to [James Brennan][1] for refactoring old code and writing the Bounces, InvalidEmails and SpamReports modules.
|
32
|
+
|
33
|
+
Bounces Module
|
34
|
+
--------------
|
35
|
+
The bounces module provides access to all of your bounces.
|
36
|
+
|
37
|
+
- - -
|
38
|
+
|
39
|
+
Instantiate the Bounces object:
|
40
|
+
|
41
|
+
bounces = SendgridToolkit::Bounces.new(api_user, api_key)
|
42
|
+
|
43
|
+
- - -
|
44
|
+
|
45
|
+
Retrieve bounces:
|
46
|
+
|
47
|
+
all_bounces = bounces.retrieve
|
48
|
+
|
49
|
+
`all_bounces` will be an array of hashes, each of which contains the following keys:
|
50
|
+
|
51
|
+
- `email`: the recipient's email address
|
52
|
+
- `status`: the status of email
|
53
|
+
- `reason`: the reason for the bounce, as specified by the recipient's email server
|
54
|
+
|
55
|
+
- - -
|
56
|
+
|
57
|
+
Get the timestamp of each bounce:
|
58
|
+
|
59
|
+
all_bounces = bounces.retrieve_with_timestamps
|
60
|
+
|
61
|
+
Each hash in `all_bounces` will now contain a `created` key, which holds a Ruby Time object.
|
62
|
+
|
63
|
+
- - -
|
64
|
+
|
65
|
+
If you believe an email address will no longer bounce and would like Sendgrid to deliver future emails to that address, you may delete the Bounce entry:
|
66
|
+
|
67
|
+
bounces.delete :email => "email@address.of.bounce.to.delete"
|
68
|
+
|
69
|
+
InvalidEmails Module
|
70
|
+
--------------------
|
71
|
+
|
72
|
+
The InvalidEmails module provides access to all of your email addresses.
|
73
|
+
|
74
|
+
- - -
|
75
|
+
|
76
|
+
Instantiate the InvalidEmails object:
|
77
|
+
|
78
|
+
invalid_emails_obj = SendgridToolkit::InvalidEmails.new(api_user, api_key)
|
79
|
+
|
80
|
+
- - -
|
81
|
+
|
82
|
+
Retrieve invalid emails:
|
83
|
+
|
84
|
+
invalid_emails = invalid_emails_obj.retrieve
|
85
|
+
|
86
|
+
`invalid_emails` will be an array of hashes, each of which contains the following keys:
|
87
|
+
|
88
|
+
- `email`: the recipient's email address
|
89
|
+
- `reason`: the reason the email address is believed to be invalid
|
90
|
+
|
91
|
+
- - -
|
92
|
+
|
93
|
+
Get the timestamp that each email was determined to be invalid:
|
94
|
+
|
95
|
+
invalid_emails = invalid_emails_obj.retrieve_with_timestamps
|
96
|
+
|
97
|
+
Each hash in `invalid_emails` will now contain a `created` key, which holds a Ruby Time object.
|
98
|
+
|
99
|
+
- - -
|
100
|
+
|
101
|
+
If you believe a once-invalid email address is now valid and would like Sendgrid to deliver future emails to that address, you may delete the InvalidEmail entry:
|
102
|
+
|
103
|
+
invalid_emails.delete :email => "email@address.of.invalid.to.delete"
|
104
|
+
|
105
|
+
SpamReports Module
|
106
|
+
------------------
|
107
|
+
|
108
|
+
The SpamReports module provides access to all email addresses that have reported you for spam.
|
109
|
+
|
110
|
+
- - -
|
111
|
+
|
112
|
+
Instantiate the SpamReports object:
|
113
|
+
|
114
|
+
spam_reports_obj = SendgridToolkit::SpamReports.new(api_user, api_key)
|
115
|
+
|
116
|
+
- - -
|
117
|
+
|
118
|
+
Retrieve spam reports:
|
119
|
+
|
120
|
+
spam_reports = spam_reports_obj.retrieve
|
121
|
+
|
122
|
+
`spam_reports` will be an array of hashes, each of which contains an `email` key, indicating the email address that reported you for spam.
|
123
|
+
|
124
|
+
- - -
|
125
|
+
|
126
|
+
Get the timestamp of each spam report:
|
127
|
+
|
128
|
+
spam_reports = spam_reports_obj.retrieve_with_timestamps
|
129
|
+
|
130
|
+
Each hash in `spam_reports` will now contain a `created` key, which holds a Ruby Time object.
|
131
|
+
|
132
|
+
- - -
|
133
|
+
|
134
|
+
If you believe a user will no longer consider your content to be spam, you may delete the SpamReport entry:
|
135
|
+
|
136
|
+
spam_reports.delete :email => "email@address.that.called.you.a.spammer"
|
137
|
+
|
138
|
+
Statistics Module
|
139
|
+
-----------------
|
140
|
+
The statistics module provides access to all of your email statistics.
|
141
|
+
|
142
|
+
- - -
|
143
|
+
|
144
|
+
Instantiate the Statistics object:
|
145
|
+
|
146
|
+
statistics = SendgridToolkit::Statistics.new(api_user, api_key)
|
147
|
+
|
148
|
+
- - -
|
149
|
+
|
150
|
+
Retrieve statistics:
|
151
|
+
|
152
|
+
stats = statistics.retrieve
|
153
|
+
|
154
|
+
`stats` will be an array of hashes, each of which contains the following keys:
|
155
|
+
|
156
|
+
- `date`: The date to which the statistics in this hash refer to
|
157
|
+
- `requests`: The number of emails you sent
|
158
|
+
- `bounces`: The number of users who opened your email but did not click on your links
|
159
|
+
- `clicks`: The number of users who clicked on a link in your email
|
160
|
+
- `opens`: The number of users who opened your email
|
161
|
+
- `spamreports`: The number of users who have reported your emails as spam
|
162
|
+
|
163
|
+
`stats` may also contain some keys that Sendgrid does not officially document, such as: `delivered`, `invalid_email`, `repeat_bounces`,`+repeat_spamreports`, `repeat_unsubscribes` and `unsubscribes`
|
164
|
+
|
165
|
+
- - -
|
166
|
+
|
167
|
+
To narrow your retrieval to the past 5 days:
|
168
|
+
|
169
|
+
stats = statistics.retrieve :days => 5
|
170
|
+
|
171
|
+
To narrow your retrieval to emails within the last month but before one week ago:
|
172
|
+
|
173
|
+
stats = statistics.retrieve :start_date => 1.month.ago, :end_date => 1.week.ago
|
174
|
+
|
175
|
+
To narrow your search to a particular category (applicable only if you use this Sendgrid feature):
|
176
|
+
|
177
|
+
stats = statistics.retrieve :category => "NameOfYourCategory"
|
178
|
+
|
179
|
+
Note: You may combine a category query with other options, i.e.:
|
180
|
+
|
181
|
+
stats = statistics.retrieve :category => "NameOfYourCategory", :days => 5
|
182
|
+
|
183
|
+
- - -
|
184
|
+
|
185
|
+
Receive your all-time statistics:
|
186
|
+
|
187
|
+
stats = statistics.retrieve_aggregate
|
188
|
+
|
189
|
+
`stats` will be a single hash containing all of the aforementioned keys except `date`.
|
190
|
+
|
191
|
+
- - -
|
192
|
+
|
193
|
+
If you use Sendgrid's category feature, you can list your categories:
|
194
|
+
|
195
|
+
cats = statistics.list_categories
|
196
|
+
|
197
|
+
`cats` is an array of hashes, each of which has a `category` key that holds the name of a category.
|
198
|
+
|
199
|
+
Unsubscribes Module
|
200
|
+
-------------------
|
201
|
+
The unsubscribes module manages your list of unsubscribed email addresses.
|
202
|
+
|
203
|
+
- - -
|
204
|
+
|
205
|
+
Instantiate the Unsubscribes object:
|
206
|
+
|
207
|
+
unsubscribes = SendgridToolkit::Unsubscribes.new(api_user, api_key)
|
208
|
+
|
209
|
+
- - -
|
210
|
+
|
211
|
+
List everybody who has unsubscribed from your emails with:
|
212
|
+
|
213
|
+
listing = unsubscribes.retrieve
|
214
|
+
`listing` will be an array of hashes, each of which has an `email` key.
|
215
|
+
|
216
|
+
- - -
|
217
|
+
|
218
|
+
Get the timestamp when each user unsubscribed:
|
219
|
+
|
220
|
+
listing = unsubscribes.retrieve_with_timestamps
|
221
|
+
|
222
|
+
Each hash in `listing` will now contain a `created` key, which holds a Ruby Time object.
|
223
|
+
|
224
|
+
- - -
|
225
|
+
|
226
|
+
Unsubscribe a user from your sendgrid email:
|
227
|
+
|
228
|
+
unsubscribes.add :email => "email@to.unsubscribe"
|
229
|
+
|
230
|
+
SendgridToolkit will throw `UnsubscribeEmailAlreadyExists` if the email you specified is already on the list
|
231
|
+
|
232
|
+
- - -
|
233
|
+
|
234
|
+
Remove a user from your unsubscribe list:
|
235
|
+
|
236
|
+
unsubscribes.delete :email => "email@that_is.unsubscribed"
|
237
|
+
|
238
|
+
SendgridToolkit will throw `UnsubscribeEmailDoesNotExist` if the email you specified is not on the list
|
239
|
+
|
240
|
+
|
241
|
+
A note about authentication
|
242
|
+
---------------------------
|
243
|
+
|
244
|
+
Each class is initialized with `api_user` and `api_key` parameters. `api_user` is your sendgrid account email address, and `api_key` is your sendgrid password.
|
245
|
+
|
246
|
+
If you don't supply `api_user` or `api_key`, SendgridToolkit will look for the `SMTP_USERNAME` or `SMTP_PASSWORD` environment variables. If they are not found, SendgridToolkit will throw `NoAPIKeySpecified` or `NoAPIUserSpecified`, depending on what you omitted.
|
247
|
+
|
248
|
+
If authentication fails during an API request, SendgridToolkit throws `AuthenticationFailed`.
|
249
|
+
|
250
|
+
|
251
|
+
In Case You're Curious...
|
252
|
+
-------------------------
|
253
|
+
|
254
|
+
API requests are made and responses are received in JSON. All requests are made as POSTs unless noted otherwise (Sendgrid's examples are via GET, but they support POST)
|
255
|
+
|
256
|
+
Each class takes a final options parameter in the form of a hash. You may use this parameter to pass additional options to the Sendgrid API. For example, let's say you are using the unsubscribes function:
|
257
|
+
|
258
|
+
unsubscribes = SendgridToolkit::Unsubscribes.new(api_user, api_key)
|
259
|
+
listing = unsubscribes.retrieve
|
260
|
+
|
261
|
+
If Sendgrid were to add a `only_verified` option to this API call, you could call:
|
262
|
+
|
263
|
+
listing = unsubscribes.retrieve :only_verified => true
|
264
|
+
|
265
|
+
to make use of it.
|
266
|
+
|
267
|
+
Testing
|
268
|
+
-------
|
269
|
+
|
270
|
+
In addition to unit tests, SendgridToolkit comes with a limited suite of "webconnect" tests that will actually hit Sendgrid's servers and perform various actions for purposes of real-world testing. In order to use these tests, you must:
|
271
|
+
|
272
|
+
1. Create a test account with sendgrid and store the credentials in `TEST_SMTP_USERNAME` and `TEST_SMTP_PASSWORD` environment variables. This is so that actions are performed on a test account and not your real Sendgrid account. If you forget, don't worry -- the tests will fail but they will **not** fall back on the account that uses `SMTP_USERNAME` and `SMTP_PASSWORD`.
|
273
|
+
2. Change "xit" it "it" on the tests you wish to run.
|
274
|
+
|
275
|
+
Running "spec spec" out of the box will run the standard suite of tests (all network access is stubbed out).
|
276
|
+
|
277
|
+
[1]: http://github.com/jamesBrennan
|
278
|
+
[2]: http://wiki.sendgrid.com/doku.php?id=web_api
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "sendgrid_toolkit"
|
8
|
+
gemspec.summary = "A Ruby wrapper and utility library for communicating with the Sendgrid API"
|
9
|
+
gemspec.description = "A Ruby wrapper and utility library for communicating with the Sendgrid API"
|
10
|
+
gemspec.email = "robby@freerobby.com"
|
11
|
+
gemspec.homepage = "http://github.com/freerobby/sendgrid_toolkit"
|
12
|
+
gemspec.authors = ["Robby Grossman"]
|
13
|
+
|
14
|
+
gemspec.add_dependency "httparty"
|
15
|
+
# Development dependencies: fakeweb, rake, jeweler, rspec
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler must be installed. Use 'sudo gem install jeweler'."
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each {|ext| load ext}
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.5
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
require 'sendgrid_toolkit/abstract_sendgrid_client'
|
4
|
+
require 'sendgrid_toolkit/common'
|
5
|
+
require 'sendgrid_toolkit/sendgrid_error'
|
6
|
+
require 'sendgrid_toolkit/statistics'
|
7
|
+
require 'sendgrid_toolkit/unsubscribes'
|
8
|
+
require 'sendgrid_toolkit/spam_reports'
|
9
|
+
require 'sendgrid_toolkit/bounces'
|
10
|
+
require 'sendgrid_toolkit/invalid_emails'
|
11
|
+
|
12
|
+
module SendgridToolkit
|
13
|
+
BASE_URI = "sendgrid.com/api"
|
14
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SendgridToolkit
|
2
|
+
class AbstractSendgridClient
|
3
|
+
|
4
|
+
def initialize(api_user = nil, api_key = nil)
|
5
|
+
@api_user = (api_user.nil?) ? ENV['SMTP_USERNAME'] : api_user
|
6
|
+
@api_key = (api_key.nil?) ? ENV['SMTP_PASSWORD'] : api_key
|
7
|
+
|
8
|
+
raise SendgridToolkit::NoAPIUserSpecified if @api_user.blank?
|
9
|
+
raise SendgridToolkit::NoAPIKeySpecified if @api_key.blank?
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def api_post(module_name, action_name, opts = {})
|
15
|
+
response = HTTParty.post("https://#{BASE_URI}/#{module_name}.#{action_name}.json?", :query => get_credentials.merge(opts), :format => :json)
|
16
|
+
if response.code > 401
|
17
|
+
raise(SendgridToolkit::SendgridServerError, "The sengrid server returned an error. #{response.inspect}")
|
18
|
+
elsif has_error?(response) and
|
19
|
+
response['error'].respond_to?(:has_key?) and
|
20
|
+
response['error'].has_key?('code') and
|
21
|
+
response['error']['code'].to_i == 401
|
22
|
+
raise SendgridToolkit::AuthenticationFailed
|
23
|
+
elsif has_error?(response)
|
24
|
+
raise(SendgridToolkit::APIError, response['error'])
|
25
|
+
end
|
26
|
+
response
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_credentials
|
30
|
+
{:api_user => @api_user, :api_key => @api_key}
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def has_error?(response)
|
35
|
+
response.kind_of?(Hash) && response.has_key?('error')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module SendgridToolkit
|
2
|
+
|
3
|
+
module Common
|
4
|
+
|
5
|
+
def retrieve(options = {})
|
6
|
+
response = api_post(module_name, 'get', options)
|
7
|
+
response
|
8
|
+
end
|
9
|
+
|
10
|
+
def retrieve_with_timestamps(options = {})
|
11
|
+
options.merge! :date => 1
|
12
|
+
response = retrieve options
|
13
|
+
if response.is_a? Array
|
14
|
+
response.each do |message|
|
15
|
+
parse_message_time message
|
16
|
+
end
|
17
|
+
else
|
18
|
+
parse_message_time response
|
19
|
+
end
|
20
|
+
response
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete(options = {})
|
24
|
+
response = api_post(module_name, 'delete', options)
|
25
|
+
if !response["message"].nil?
|
26
|
+
raise EmailDoesNotExist if response['message'].include?('does not exist')
|
27
|
+
end
|
28
|
+
response
|
29
|
+
end
|
30
|
+
|
31
|
+
def module_name
|
32
|
+
self.class.to_s.split("::").last.downcase
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def parse_message_time(message)
|
38
|
+
message['created'] = Time.parse(message['created']) if message.has_key?('created')
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module SendgridToolkit
|
2
|
+
class AuthenticationFailed < StandardError; end
|
3
|
+
class NoAPIKeySpecified < StandardError; end
|
4
|
+
class NoAPIUserSpecified < StandardError; end
|
5
|
+
class UnsubscribeEmailAlreadyExists < StandardError; end
|
6
|
+
class UnsubscribeEmailDoesNotExist < StandardError; end
|
7
|
+
class EmailDoesNotExist < StandardError; end
|
8
|
+
class SendgridServerError < StandardError; end
|
9
|
+
class APIError < StandardError; end
|
10
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SendgridToolkit
|
2
|
+
class Statistics < AbstractSendgridClient
|
3
|
+
def retrieve(options = {})
|
4
|
+
response = api_post('stats', 'get', options)
|
5
|
+
response
|
6
|
+
end
|
7
|
+
|
8
|
+
def retrieve_aggregate(options = {})
|
9
|
+
options.merge! :aggregate => 1
|
10
|
+
response = retrieve options
|
11
|
+
if Hash === response.parsed_response
|
12
|
+
to_ints(response.parsed_response)
|
13
|
+
elsif Array === response.parsed_response
|
14
|
+
response.parsed_response.each {|o| to_ints(o) }
|
15
|
+
end
|
16
|
+
response
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_ints(resp)
|
20
|
+
%w(bounces clicks delivered invalid_email opens repeat_bounces repeat_spamreports repeat_unsubscribes requests spamreports unsubscribes).each do |int_field|
|
21
|
+
resp[int_field] = resp[int_field].to_i if resp.has_key?(int_field)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def list_categories(options = {})
|
26
|
+
options.merge! :list => true
|
27
|
+
response = retrieve options
|
28
|
+
response
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module SendgridToolkit
|
2
|
+
class Unsubscribes < AbstractSendgridClient
|
3
|
+
def add(options = {})
|
4
|
+
response = api_post('unsubscribes', 'add', options)
|
5
|
+
raise UnsubscribeEmailAlreadyExists if response['message'].include?('already exists')
|
6
|
+
response
|
7
|
+
end
|
8
|
+
|
9
|
+
def delete(options = {})
|
10
|
+
response = api_post('unsubscribes', 'delete', options)
|
11
|
+
raise UnsubscribeEmailDoesNotExist if response['message'].include?('does not exist')
|
12
|
+
response
|
13
|
+
end
|
14
|
+
|
15
|
+
def retrieve(options = {})
|
16
|
+
response = api_post('unsubscribes', 'get', options)
|
17
|
+
response
|
18
|
+
end
|
19
|
+
|
20
|
+
def retrieve_with_timestamps(options = {})
|
21
|
+
options.merge! :date => 1
|
22
|
+
response = retrieve options
|
23
|
+
response.each do |unsubscribe|
|
24
|
+
unsubscribe['created'] = Time.parse(unsubscribe['created']) if unsubscribe.has_key?('created')
|
25
|
+
end
|
26
|
+
response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{eliasbaixas-sendgrid_toolkit}
|
8
|
+
s.version = "1.0.5"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Robby Grossman}]
|
12
|
+
s.date = %q{2011-09-19}
|
13
|
+
s.description = %q{A Ruby wrapper and utility library for communicating with the Sendgrid API}
|
14
|
+
s.email = %q{robby@freerobby.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"README.md",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"lib/sendgrid_toolkit.rb",
|
23
|
+
"lib/sendgrid_toolkit/abstract_sendgrid_client.rb",
|
24
|
+
"lib/sendgrid_toolkit/bounces.rb",
|
25
|
+
"lib/sendgrid_toolkit/common.rb",
|
26
|
+
"lib/sendgrid_toolkit/invalid_emails.rb",
|
27
|
+
"lib/sendgrid_toolkit/sendgrid_error.rb",
|
28
|
+
"lib/sendgrid_toolkit/spam_reports.rb",
|
29
|
+
"lib/sendgrid_toolkit/statistics.rb",
|
30
|
+
"lib/sendgrid_toolkit/unsubscribes.rb",
|
31
|
+
"sendgrid_toolkit.gemspec",
|
32
|
+
"spec/helper.rb",
|
33
|
+
"spec/lib/sendgrid_toolkit/abstract_sendgrid_client_spec.rb",
|
34
|
+
"spec/lib/sendgrid_toolkit/bounces_spec.rb",
|
35
|
+
"spec/lib/sendgrid_toolkit/common_spec.rb",
|
36
|
+
"spec/lib/sendgrid_toolkit/invalid_emails_spec.rb",
|
37
|
+
"spec/lib/sendgrid_toolkit/spam_reports_spec.rb",
|
38
|
+
"spec/lib/sendgrid_toolkit/statistics_spec.rb",
|
39
|
+
"spec/lib/sendgrid_toolkit/unsubscribes_spec.rb",
|
40
|
+
"spec/lib/sendgrid_toolkit_spec.rb",
|
41
|
+
"spec/webconnect/sendgrid_toolkit_spec.rb"
|
42
|
+
]
|
43
|
+
s.homepage = %q{http://github.com/freerobby/sendgrid_toolkit}
|
44
|
+
s.require_paths = [%q{lib}]
|
45
|
+
s.rubygems_version = %q{1.8.6}
|
46
|
+
s.summary = %q{A Ruby wrapper and utility library for communicating with the Sendgrid API}
|
47
|
+
|
48
|
+
if s.respond_to? :specification_version then
|
49
|
+
s.specification_version = 3
|
50
|
+
|
51
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
52
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0"])
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'fakeweb'
|
2
|
+
require 'sendgrid_toolkit'
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
FakeWeb.allow_net_connect = false
|
6
|
+
|
7
|
+
def backup_env
|
8
|
+
@env_backup = Hash.new
|
9
|
+
ENV.keys.each {|key| @env_backup[key] = ENV[key]}
|
10
|
+
end
|
11
|
+
def restore_env
|
12
|
+
@env_backup.keys.each {|key| ENV[key] = @env_backup[key]}
|
13
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../helper")
|
2
|
+
|
3
|
+
describe SendgridToolkit::AbstractSendgridClient do
|
4
|
+
before do
|
5
|
+
backup_env
|
6
|
+
end
|
7
|
+
after do
|
8
|
+
restore_env
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#api_post" do
|
12
|
+
it "throws error when authentication fails" do
|
13
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/profile\.get\.json\?|, :body => '{"error":{"code":401,"message":"Permission denied, wrong credentials"}}')
|
14
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new("fakeuser", "fakepass")
|
15
|
+
lambda {
|
16
|
+
@obj.send(:api_post, "profile", "get", {})
|
17
|
+
}.should raise_error SendgridToolkit::AuthenticationFailed
|
18
|
+
end
|
19
|
+
it "thows error when sendgrid response is a server error" do
|
20
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/profile\.get\.json\?|, :body => 'A server error occured', :status => ['500', 'Internal Server Error'])
|
21
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new("someuser", "somepass")
|
22
|
+
lambda {
|
23
|
+
@obj.send(:api_post, "profile", "get", {})
|
24
|
+
}.should raise_error SendgridToolkit::SendgridServerError
|
25
|
+
end
|
26
|
+
it "thows error when sendgrid response is an API error" do
|
27
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/stats\.get\.json\?|, :body => '{"error": "error in end_date: end date is in the future"}', :status => ['400', 'Bad Request'])
|
28
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new("someuser", "somepass")
|
29
|
+
lambda {
|
30
|
+
@obj.send(:api_post, "stats", "get", {})
|
31
|
+
}.should raise_error SendgridToolkit::APIError
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#initialize" do
|
36
|
+
it "stores api credentials when passed in" do
|
37
|
+
ENV['SMTP_USERNAME'] = "env_username"
|
38
|
+
ENV['SMTP_PASSWORD'] = "env_apikey"
|
39
|
+
|
40
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new("username", "apikey")
|
41
|
+
@obj.instance_variable_get("@api_user").should == "username"
|
42
|
+
@obj.instance_variable_get("@api_key").should == "apikey"
|
43
|
+
end
|
44
|
+
it "resorts to environment variables when no credentials specified" do
|
45
|
+
ENV['SMTP_USERNAME'] = "env_username"
|
46
|
+
ENV['SMTP_PASSWORD'] = "env_apikey"
|
47
|
+
|
48
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new()
|
49
|
+
@obj.instance_variable_get("@api_user").should == "env_username"
|
50
|
+
@obj.instance_variable_get("@api_key").should == "env_apikey"
|
51
|
+
end
|
52
|
+
it "throws error when no credentials are found" do
|
53
|
+
ENV['SMTP_USERNAME'] = nil
|
54
|
+
ENV['SMTP_PASSWORD'] = nil
|
55
|
+
|
56
|
+
lambda {
|
57
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new()
|
58
|
+
}.should raise_error SendgridToolkit::NoAPIUserSpecified
|
59
|
+
|
60
|
+
lambda {
|
61
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new(nil, "password")
|
62
|
+
}.should raise_error SendgridToolkit::NoAPIUserSpecified
|
63
|
+
|
64
|
+
lambda {
|
65
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new("user", nil)
|
66
|
+
}.should raise_error SendgridToolkit::NoAPIKeySpecified
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../helper")
|
2
|
+
|
3
|
+
describe SendgridToolkit::Bounces do
|
4
|
+
before do
|
5
|
+
FakeWeb.clean_registry
|
6
|
+
@obj = SendgridToolkit::Bounces.new("fakeuser", "fakepass")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#retrieve" do
|
10
|
+
it "returns array of bounced emails" do
|
11
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/bounces\.get\.json\?|, :body => '[{"email":"email1@domain.com","status":"5.1.1","reason":"host [127.0.0.1] said: 550 5.1.1 unknown or illegal user: email1@domain.com"},{"email":"email2@domain2.com","status":"5.1.1","reason":"host [127.0.0.1] said: 550 5.1.1 unknown or illegal user: email2@domain2.com"}]')
|
12
|
+
bounces = @obj.retrieve
|
13
|
+
bounces[0]['email'].should == "email1@domain.com"
|
14
|
+
bounces[0]['status'].should == "5.1.1"
|
15
|
+
bounces[0]['reason'].should == "host [127.0.0.1] said: 550 5.1.1 unknown or illegal user: email1@domain.com"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#retrieve_with_timestamps" do
|
20
|
+
it "parses timestamps" do
|
21
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/bounces\.get\.json\?.*date=1|, :body => '[{"email":"email1@domain.com","status":"5.1.1","reason":"host [127.0.0.1] said: 550 5.1.1 unknown or illegal user: email1@domain.com","created":"2009-06-01 19:41:39"},{"email":"email2@domain2.com","status":"5.1.1","reason":"host [127.0.0.1] said: 550 5.1.1 unknown or illegal user: email2@domain2.com","created":"2009-06-12 19:41:39"}]')
|
22
|
+
bounces = @obj.retrieve_with_timestamps
|
23
|
+
0.upto(1) do |index|
|
24
|
+
bounces[index]['created'].kind_of?(Time).should == true
|
25
|
+
end
|
26
|
+
bounces[0]['created'].asctime.should == "Mon Jun 1 19:41:39 2009"
|
27
|
+
bounces[1]['created'].asctime.should == "Fri Jun 12 19:41:39 2009"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#delete" do
|
32
|
+
it "raises no errors on success" do
|
33
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/bounces\.delete\.json\?.*email=.+|, :body => '{"message":"success"}')
|
34
|
+
lambda {
|
35
|
+
@obj.delete :email => "user@domain.com"
|
36
|
+
}.should_not raise_error
|
37
|
+
end
|
38
|
+
it "raises error when email address does not exist" do
|
39
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/bounces\.delete\.json\?.*email=.+|, :body => '{"message":"Email does not exist"}')
|
40
|
+
lambda {
|
41
|
+
@obj.delete :email => "user@domain.com"
|
42
|
+
}.should raise_error SendgridToolkit::EmailDoesNotExist
|
43
|
+
end
|
44
|
+
it "does not choke if response does not have a 'message' field" do
|
45
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/bounces\.delete\.json\?.*email=.+|, :body => 'An internal server error occurred. Please try again later.')
|
46
|
+
lambda {
|
47
|
+
@obj.delete :email => "user@domain.com"
|
48
|
+
}.should_not raise_error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../helper")
|
2
|
+
|
3
|
+
describe SendgridToolkit::Common do
|
4
|
+
|
5
|
+
before do
|
6
|
+
class FakeClass < SendgridToolkit::AbstractSendgridClient
|
7
|
+
include SendgridToolkit::Common
|
8
|
+
end
|
9
|
+
@fake_class = FakeClass.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it "creates a module_name method that returns the class name downcased" do
|
13
|
+
@fake_class.module_name.should == "fakeclass"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "does not choke if response does not have a 'message' field" do
|
17
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/fakeclass\.delete\.json\?.*email=.+|, :body => 'An internal server error occurred. Please try again later.')
|
18
|
+
lambda {
|
19
|
+
@fake_class.delete :email => "user@domain.com"
|
20
|
+
}.should_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../helper")
|
2
|
+
|
3
|
+
describe SendgridToolkit::InvalidEmails do
|
4
|
+
before do
|
5
|
+
FakeWeb.clean_registry
|
6
|
+
@obj = SendgridToolkit::InvalidEmails.new("fakeuser", "fakepass")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#retrieve" do
|
10
|
+
it "returns array of invalid emails" do
|
11
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/invalidemails\.get\.json\?|, :body => '[{"email":"isaac@hotmail.comm","reason":"Mail domain mentioned in email address is unknown"},{"email":"isaac@hotmail","reason":"Bad Syntax"},{"email":"isaac@example.com","reason":"Known bad domain"}]')
|
12
|
+
invalid_emails = @obj.retrieve
|
13
|
+
invalid_emails[0]['email'].should == "isaac@hotmail.comm"
|
14
|
+
invalid_emails[0]['reason'].should == "Mail domain mentioned in email address is unknown"
|
15
|
+
invalid_emails[1]['email'].should == "isaac@hotmail"
|
16
|
+
invalid_emails[1]['reason'].should == "Bad Syntax"
|
17
|
+
invalid_emails[2]['email'].should == "isaac@example.com"
|
18
|
+
invalid_emails[2]['reason'].should == "Known bad domain"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#retrieve_with_timestamps" do
|
23
|
+
it "parses timestamps" do
|
24
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/invalidemails\.get\.json\?.*date=1|, :body => '[{"email":"isaac@hotmail.comm","reason":"Mail domain mentioned in email address is unknown","created":"2009-06-01 19:41:39"},{"email":"isaac@hotmail","reason":"Bad Syntax","created":"2009-06-12 19:41:39"},{"email":"isaac@example.com","reason":"Known bad domain","created":"2009-06-13 09:40:01"}]')
|
25
|
+
invalid_emails = @obj.retrieve_with_timestamps
|
26
|
+
0.upto(2) do |index|
|
27
|
+
invalid_emails[index]['created'].kind_of?(Time).should == true
|
28
|
+
end
|
29
|
+
invalid_emails[0]['created'].asctime.should == "Mon Jun 1 19:41:39 2009"
|
30
|
+
invalid_emails[1]['created'].asctime.should == "Fri Jun 12 19:41:39 2009"
|
31
|
+
invalid_emails[2]['created'].asctime.should == "Sat Jun 13 09:40:01 2009"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#delete" do
|
36
|
+
it "raises no errors on success" do
|
37
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/invalidemails\.delete\.json\?.*email=.+|, :body => '{"message":"success"}')
|
38
|
+
lambda {
|
39
|
+
@obj.delete :email => "user@domain.com"
|
40
|
+
}.should_not raise_error
|
41
|
+
end
|
42
|
+
it "raises error when email address does not exist" do
|
43
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/invalidemails\.delete\.json\?.*email=.+|, :body => '{"message":"Email does not exist"}')
|
44
|
+
lambda {
|
45
|
+
@obj.delete :email => "user@domain.com"
|
46
|
+
}.should raise_error SendgridToolkit::EmailDoesNotExist
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../helper")
|
2
|
+
|
3
|
+
describe SendgridToolkit::SpamReports do
|
4
|
+
before do
|
5
|
+
FakeWeb.clean_registry
|
6
|
+
@obj = SendgridToolkit::SpamReports.new("fakeuser", "fakepass")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#retrieve" do
|
10
|
+
it "returns array of bounced emails" do
|
11
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/spamreports\.get\.json\?|, :body => '[{"email":"email1@domain.com"},{"email":"email2@domain2.com"}]')
|
12
|
+
bounces = @obj.retrieve
|
13
|
+
bounces[0]['email'].should == "email1@domain.com"
|
14
|
+
bounces[1]['email'].should == "email2@domain2.com"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#retrieve_with_timestamps" do
|
19
|
+
it "parses timestamps" do
|
20
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/spamreports\.get\.json\?.*date=1|, :body => '[{"email":"email1@domain.com","created":"2009-06-01 19:41:39"},{"email":"email2@domain2.com","created":"2009-06-12 19:41:39"}]')
|
21
|
+
bounces = @obj.retrieve_with_timestamps
|
22
|
+
0.upto(1) do |index|
|
23
|
+
bounces[index]['created'].kind_of?(Time).should == true
|
24
|
+
end
|
25
|
+
bounces[0]['created'].asctime.should == "Mon Jun 1 19:41:39 2009"
|
26
|
+
bounces[1]['created'].asctime.should == "Fri Jun 12 19:41:39 2009"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#delete" do
|
31
|
+
it "raises no errors on success" do
|
32
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/spamreports\.delete\.json\?.*email=.+|, :body => '{"message":"success"}')
|
33
|
+
lambda {
|
34
|
+
@obj.delete :email => "user@domain.com"
|
35
|
+
}.should_not raise_error
|
36
|
+
end
|
37
|
+
it "raises error when email address does not exist" do
|
38
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/spamreports\.delete\.json\?.*email=.+|, :body => '{"message":"Email does not exist"}')
|
39
|
+
lambda {
|
40
|
+
@obj.delete :email => "user@domain.com"
|
41
|
+
}.should raise_error SendgridToolkit::EmailDoesNotExist
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../helper")
|
2
|
+
|
3
|
+
describe SendgridToolkit::Statistics do
|
4
|
+
before do
|
5
|
+
FakeWeb.clean_registry
|
6
|
+
@obj = SendgridToolkit::Statistics.new("fakeuser", "fakepass")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#retrieve" do
|
10
|
+
it "parses daily totals" do
|
11
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/stats\.get\.json\?|, :body => '[{"date":"2009-06-20","requests":12342,"bounces":12,"clicks":10223,"opens":9992,"spamreports":5},{"date":"2009-06-21","requests":32342,"bounces":10,"clicks":14323,"opens":10995,"spamreports":7},{"date":"2009-06-22","requests":52342,"bounces":11,"clicks":19223,"opens":12992,"spamreports":2}]')
|
12
|
+
stats = @obj.retrieve
|
13
|
+
stats.each do |stat|
|
14
|
+
%w(bounces clicks delivered invalid_email opens repeat_bounces repeat_spamreports repeat_unsubscribes requests spamreports unsubscribes).each do |int|
|
15
|
+
stat[int].kind_of?(Integer).should == true if stat.has_key?(int) # We support all fields presently returned, but we are only testing what sendgrid officially documents
|
16
|
+
end
|
17
|
+
stat['date'].kind_of?(Date).should == true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#retrieve_aggregate" do
|
23
|
+
it "parses aggregate statistics" do
|
24
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/stats\.get\.json\?.*aggregate=1|, :body => '{"requests":12342,"bounces":12,"clicks":10223,"opens":9992,"spamreports":5}')
|
25
|
+
stats = @obj.retrieve_aggregate
|
26
|
+
%w(bounces clicks delivered invalid_email opens repeat_bounces repeat_spamreports repeat_unsubscribes requests spamreports unsubscribes).each do |int|
|
27
|
+
stats[int].kind_of?(Integer).should == true if stats.has_key?(int) # We support all fields presently returned, but we are only testing what sendgrid officially documents
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#list_categories" do
|
33
|
+
it "parses categories list" do
|
34
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/stats\.get\.json\?.*list=true|, :body => '[{"category":"categoryA"},{"category":"categoryB"},{"category":"categoryC"}]')
|
35
|
+
cats = @obj.list_categories
|
36
|
+
cats[0]['category'].should == 'categoryA'
|
37
|
+
cats[1]['category'].should == 'categoryB'
|
38
|
+
cats[2]['category'].should == 'categoryC'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../helper")
|
2
|
+
|
3
|
+
describe SendgridToolkit::Unsubscribes do
|
4
|
+
before do
|
5
|
+
FakeWeb.clean_registry
|
6
|
+
@obj = SendgridToolkit::Unsubscribes.new("fakeuser", "fakepass")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#retrieve" do
|
10
|
+
it "returns array of unsubscribed email addresses" do
|
11
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/unsubscribes\.get\.json\?|, :body => '[{"email":"user@domain.com"},{"email":"user2@domain2.com"},{"email":"user3@domain2.com"}]')
|
12
|
+
emails = @obj.retrieve
|
13
|
+
emails[0]['email'].should == "user@domain.com"
|
14
|
+
emails[1]['email'].should == "user2@domain2.com"
|
15
|
+
emails[2]['email'].should == "user3@domain2.com"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
describe "#retrieve_with_timestamps" do
|
19
|
+
it "parses timestamps" do
|
20
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/unsubscribes\.get\.json\?.*date=1|, :body => '[{"email":"user@domain.com","created":"2010-03-03 11:00:00"},{"email":"user2@domain2.com","created":"2010-03-04 21:00:00"},{"email":"user3@domain2.com","created":"2010-03-05 23:00:00"}]')
|
21
|
+
emails = @obj.retrieve_with_timestamps
|
22
|
+
0.upto(2) do |index|
|
23
|
+
emails[index]['created'].kind_of?(Time).should == true
|
24
|
+
end
|
25
|
+
emails[0]['created'].asctime.should == "Wed Mar 3 11:00:00 2010"
|
26
|
+
emails[1]['created'].asctime.should == "Thu Mar 4 21:00:00 2010"
|
27
|
+
emails[2]['created'].asctime.should == "Fri Mar 5 23:00:00 2010"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#add" do
|
32
|
+
it "raises no errors on success" do
|
33
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/unsubscribes\.add\.json\?.*email=.+|, :body => '{"message":"success"}')
|
34
|
+
lambda {
|
35
|
+
@obj.add :email => "user@domain.com"
|
36
|
+
}.should_not raise_error
|
37
|
+
end
|
38
|
+
it "raises error when email already exists" do
|
39
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/unsubscribes\.add\.json\?.*email=.+|, :body => '{"message":"Unsubscribe email address already exists"}')
|
40
|
+
lambda {
|
41
|
+
@obj.add :email => "user@domain.com"
|
42
|
+
}.should raise_error SendgridToolkit::UnsubscribeEmailAlreadyExists
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#delete" do
|
47
|
+
it "raises no errors on success" do
|
48
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/unsubscribes\.delete\.json\?.*email=.+|, :body => '{"message":"success"}')
|
49
|
+
lambda {
|
50
|
+
@obj.delete :email => "user@domain.com"
|
51
|
+
}.should_not raise_error
|
52
|
+
end
|
53
|
+
it "raises error when email address does not exist" do
|
54
|
+
FakeWeb.register_uri(:post, %r|https://sendgrid\.com/api/unsubscribes\.delete\.json\?.*email=.+|, :body => '{"message":"Email does not exist"}')
|
55
|
+
lambda {
|
56
|
+
@obj.delete :email => "user@domain.com"
|
57
|
+
}.should raise_error SendgridToolkit::UnsubscribeEmailDoesNotExist
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../helper")
|
2
|
+
|
3
|
+
FakeWeb.allow_net_connect = true
|
4
|
+
|
5
|
+
describe SendgridToolkit do
|
6
|
+
before :all do
|
7
|
+
FakeWeb.clean_registry
|
8
|
+
FakeWeb.allow_net_connect = true
|
9
|
+
end
|
10
|
+
after :all do
|
11
|
+
FakeWeb.allow_net_connect = false
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
backup_env
|
16
|
+
|
17
|
+
# Don't let SendgridToolkit fall back to SMTP_USERNAME and SMTP_PASSWORD
|
18
|
+
ENV['SMTP_USERNAME'] = ENV['TEST_SMTP_USERNAME'].blank? ? "fakeuser" : ENV['TEST_SMTP_USERNAME']
|
19
|
+
ENV['SMTP_PASSWORD'] = ENV['TEST_SMTP_PASSWORD'].blank? ? "fakepass" : ENV['TEST_SMTP_PASSWORD']
|
20
|
+
end
|
21
|
+
after do
|
22
|
+
restore_env
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "abstract_sendgrid_client i/o" do
|
26
|
+
xit "throws authentication error when authentication fails" do
|
27
|
+
@obj = SendgridToolkit::AbstractSendgridClient.new("fakeuser", "fakepass")
|
28
|
+
lambda {
|
29
|
+
@obj.send(:api_post, "profile", "get", {})
|
30
|
+
}.should raise_error SendgridToolkit::AuthenticationFailed
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "statistics i/o" do
|
35
|
+
before do
|
36
|
+
@obj = SendgridToolkit::Statistics.new
|
37
|
+
end
|
38
|
+
xit "retrieves statistics by day" do
|
39
|
+
stats = @obj.retrieve
|
40
|
+
stats.count.should > 0
|
41
|
+
day_stats = stats.first
|
42
|
+
%w(date requests bounces clicks opens spamreports).each do |k|
|
43
|
+
day_stats.has_key?(k).should == true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
xit "retrieves aggregate statistics" do
|
47
|
+
stats = @obj.retrieve_aggregate
|
48
|
+
%w(requests bounces clicks opens spamreports).each do |k|
|
49
|
+
stats.has_key?(k).should == true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "unsubscribes i/o" do
|
55
|
+
before do
|
56
|
+
@obj = SendgridToolkit::Unsubscribes.new
|
57
|
+
unsubscribes = @obj.retrieve
|
58
|
+
unsubscribes.each do |u|
|
59
|
+
@obj.delete u['email']
|
60
|
+
end
|
61
|
+
end
|
62
|
+
xit "adds, retrieves and deletes email addresses properly" do
|
63
|
+
@obj.add "user@domain.com"
|
64
|
+
@obj.add "user2@domain.com"
|
65
|
+
unsubs = @obj.retrieve_with_timestamps
|
66
|
+
emails = unsubs.map {|h| h['email']}
|
67
|
+
emails.include?('user@domain.com').should == true
|
68
|
+
emails.include?('user2@domain.com').should == true
|
69
|
+
@obj.delete 'user@domain.com'
|
70
|
+
@obj.delete 'user2@domain.com'
|
71
|
+
@obj.retrieve.count.should == 0
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eliasbaixas-sendgrid_toolkit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 5
|
10
|
+
version: 1.0.5
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Robby Grossman
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-09-19 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: httparty
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: A Ruby wrapper and utility library for communicating with the Sendgrid API
|
35
|
+
email: robby@freerobby.com
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files:
|
41
|
+
- README.md
|
42
|
+
files:
|
43
|
+
- README.md
|
44
|
+
- Rakefile
|
45
|
+
- VERSION
|
46
|
+
- lib/sendgrid_toolkit.rb
|
47
|
+
- lib/sendgrid_toolkit/abstract_sendgrid_client.rb
|
48
|
+
- lib/sendgrid_toolkit/bounces.rb
|
49
|
+
- lib/sendgrid_toolkit/common.rb
|
50
|
+
- lib/sendgrid_toolkit/invalid_emails.rb
|
51
|
+
- lib/sendgrid_toolkit/sendgrid_error.rb
|
52
|
+
- lib/sendgrid_toolkit/spam_reports.rb
|
53
|
+
- lib/sendgrid_toolkit/statistics.rb
|
54
|
+
- lib/sendgrid_toolkit/unsubscribes.rb
|
55
|
+
- sendgrid_toolkit.gemspec
|
56
|
+
- spec/helper.rb
|
57
|
+
- spec/lib/sendgrid_toolkit/abstract_sendgrid_client_spec.rb
|
58
|
+
- spec/lib/sendgrid_toolkit/bounces_spec.rb
|
59
|
+
- spec/lib/sendgrid_toolkit/common_spec.rb
|
60
|
+
- spec/lib/sendgrid_toolkit/invalid_emails_spec.rb
|
61
|
+
- spec/lib/sendgrid_toolkit/spam_reports_spec.rb
|
62
|
+
- spec/lib/sendgrid_toolkit/statistics_spec.rb
|
63
|
+
- spec/lib/sendgrid_toolkit/unsubscribes_spec.rb
|
64
|
+
- spec/lib/sendgrid_toolkit_spec.rb
|
65
|
+
- spec/webconnect/sendgrid_toolkit_spec.rb
|
66
|
+
homepage: http://github.com/freerobby/sendgrid_toolkit
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.8.10
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: A Ruby wrapper and utility library for communicating with the Sendgrid API
|
99
|
+
test_files: []
|
100
|
+
|