apostle 0.0.1
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/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +164 -0
- data/Rakefile +2 -0
- data/lib/apostle/mail.rb +91 -0
- data/lib/apostle/queue.rb +150 -0
- data/lib/apostle/version.rb +3 -0
- data/lib/apostle.rb +53 -0
- data/penpal.gemspec +20 -0
- data/spec/mail_spec.rb +65 -0
- data/spec/queue_spec.rb +59 -0
- data/spec/spec_helper.rb +5 -0
- metadata +84 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Apostle
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
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, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# Apostle
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'apostle'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install apostle
|
18
|
+
|
19
|
+
## Domain Key
|
20
|
+
|
21
|
+
You will need to provide your apostle domain key to send emails. Apostle looks in `ENV['APOSTLE_DOMAIN_KEY']`, or you can set it manually.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
Apostle.configure do |config|
|
25
|
+
config.domain_key = 'Your domain key'
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
## Sending Email
|
30
|
+
|
31
|
+
Sending an email is easy. A minimal email might look like this.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Apostle::Mail.new('welcome_email', email: "mal@mal.co.nz").deliver!
|
35
|
+
```
|
36
|
+
The first param `Apostle::Mail` expects is the template slug, and the second is a hash of mail information.
|
37
|
+
|
38
|
+
### Adding data
|
39
|
+
|
40
|
+
You can assign any data you want, and it will be passed to the API for hydrating your template. If you had a template that required `{{username}}`, you could send them like this:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
mail = Apostle::Mail.new('welcome_email', email: 'mal@mal.co.nz', username: 'Snikch').deliver!
|
44
|
+
```
|
45
|
+
|
46
|
+
You can also set any data directly on the mail object.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
mail = Apostle::Mail.new('welcome_email')
|
50
|
+
mail.email = 'mal@mal.co.nz'
|
51
|
+
mail.username = 'Snikch'
|
52
|
+
mail.deliver!
|
53
|
+
```
|
54
|
+
|
55
|
+
### Setting name
|
56
|
+
|
57
|
+
In addition to the email, you can provide the name to be used in the `to` field of the email.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
Apostle::Mail.new('welcome_email', email: "mal@mal.co.nz", name: "Mal Curtis").deliver!
|
61
|
+
# Sends email with "to: Mal Curtis <mal@mal.co.nz>"
|
62
|
+
```
|
63
|
+
|
64
|
+
### Setting from address
|
65
|
+
|
66
|
+
Although the `from` address is set up in your template, you can override that for any individual email, or provide a reply to address.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
mail.from = 'support@example.com'
|
70
|
+
mail.reply_to = 'noreply@example.com'
|
71
|
+
```
|
72
|
+
|
73
|
+
|
74
|
+
### Additional Headers
|
75
|
+
|
76
|
+
You can provide custom headers to be sent with your email via `#header`.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
# Set
|
80
|
+
mail.header 'X-Some-Header', 'my custom header'
|
81
|
+
|
82
|
+
# Get
|
83
|
+
mail.header 'X-Some-Header'
|
84
|
+
=> "my custom header"
|
85
|
+
```
|
86
|
+
|
87
|
+
## Sending Multiple Emails
|
88
|
+
|
89
|
+
To speed up processing, you can send more than one email at a time.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
queue = Apostle::Queue.new
|
93
|
+
|
94
|
+
3.times do |count|
|
95
|
+
queue << Apostle::Mail.new("welcome_email", email: "user#{count}@example.com")
|
96
|
+
end
|
97
|
+
|
98
|
+
queue.deliver!
|
99
|
+
```
|
100
|
+
|
101
|
+
If any of the emails are invalid this will raise an exception and no emails will be sent; i.e. missing a template slug, or delivery address.
|
102
|
+
|
103
|
+
You can either catch `Apostle::DeliveryError`, or call the safer `#deliver`, then access a hash of results on the queue via `#results`.
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
queue = Apostle::Queue.new
|
107
|
+
|
108
|
+
queue << Apostle::Mail.new("welcome_email", email: "mal@mal.co.nz")
|
109
|
+
queue << Apostle::Mail.new("welcome_email")
|
110
|
+
|
111
|
+
queue.deliver
|
112
|
+
=> false
|
113
|
+
|
114
|
+
queue.results
|
115
|
+
=> {
|
116
|
+
:valid=>[#<Apostle::Mail:0x007fcee5ab2550>],
|
117
|
+
:invalid=>[#<Apostle::Mail:0x007fcee5ab23c0>]
|
118
|
+
}
|
119
|
+
queue.results[:invalid].first._exception
|
120
|
+
=> #<Apostle::DeliveryError @message="No recipient provided">
|
121
|
+
```
|
122
|
+
|
123
|
+
### Helpers
|
124
|
+
|
125
|
+
You have access to `#size` and `#clear` on the queue. You can use this to group requests.
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
users.each do |user|
|
129
|
+
queue << Penpan::Mail.new('welcome', email: user.email)
|
130
|
+
if queue.size == 1000
|
131
|
+
queue.deliver
|
132
|
+
queue.clear
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
Or use the helper method `#flush`, which does exactly this, calls `#deliver` then `#clear` if delivery succeeds.
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
users.each do |user|
|
141
|
+
queue << Penpan::Mail.new('welcome', email: user.email)
|
142
|
+
if queue.size == 1000
|
143
|
+
queue.flush
|
144
|
+
end
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
148
|
+
## Delivery Failure
|
149
|
+
|
150
|
+
If delivery to Apostle fails, an exception will be raised. There are various events that could cause a failure:
|
151
|
+
|
152
|
+
* `Apostle::Unauthorized`: The domain key was not provided, or valid
|
153
|
+
* `Apostle::UnprocessableEntity`: The server returned a 422 response. Check the content of the message for more details, but this will likely be a validation / content error
|
154
|
+
* `Apostle::ServerError`: Something went wrong at the Apostle API, you should try again with exponential backoff
|
155
|
+
* `Apostle::Forbidden`: The server returned a 403 response. This should not occur on the delivery API
|
156
|
+
* `Apostle::DeliveryError`: Anything which isn't covered by the above exceptions
|
157
|
+
|
158
|
+
## Contributing
|
159
|
+
|
160
|
+
1. Fork it
|
161
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
162
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
163
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
164
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/apostle/mail.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Apostle
|
5
|
+
|
6
|
+
class Mail
|
7
|
+
|
8
|
+
attr_accessor :data,
|
9
|
+
:email,
|
10
|
+
:from,
|
11
|
+
:headers,
|
12
|
+
:layout_id,
|
13
|
+
:name,
|
14
|
+
:reply_to,
|
15
|
+
:template_id,
|
16
|
+
:_exception
|
17
|
+
|
18
|
+
def initialize(template_id, options = {})
|
19
|
+
@template_id = template_id
|
20
|
+
@data = {}
|
21
|
+
|
22
|
+
options.each do |k, v|
|
23
|
+
self.send("#{k}=", v)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Provide a getter and setters for headers
|
28
|
+
def header(name, value = nil)
|
29
|
+
if value
|
30
|
+
(@headers ||= {})[name] = value
|
31
|
+
else
|
32
|
+
(@headers || {})[name]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Allow convenience setters for the data payload
|
37
|
+
# E.G. mail.potato= "Something" will set @data['potato']
|
38
|
+
def method_missing(method, *args)
|
39
|
+
return unless method.match /.*=/
|
40
|
+
@data[method.to_s.gsub(/=$/, '')] = args.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def deliver
|
44
|
+
begin
|
45
|
+
deliver!
|
46
|
+
true
|
47
|
+
rescue DeliveryError => e
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Shortcut method to deliver a single message
|
53
|
+
def deliver!
|
54
|
+
return true unless Apostle.deliver
|
55
|
+
|
56
|
+
unless template_id && template_id != ""
|
57
|
+
raise DeliveryError,
|
58
|
+
"No email template_id provided"
|
59
|
+
end
|
60
|
+
|
61
|
+
queue = Apostle::Queue.new
|
62
|
+
queue.add self
|
63
|
+
queue.deliver!
|
64
|
+
|
65
|
+
# Return true or false depending on successful delivery
|
66
|
+
if queue.results[:valid].include?(self)
|
67
|
+
return true
|
68
|
+
else
|
69
|
+
raise _exception
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_h
|
74
|
+
{
|
75
|
+
"#{self.email.to_s}" => {
|
76
|
+
"data" => @data,
|
77
|
+
"from" => from.to_s,
|
78
|
+
"headers" => headers,
|
79
|
+
"layout_id" => layout_id.to_s,
|
80
|
+
"name" => name.to_s,
|
81
|
+
"reply_to" => reply_to.to_s,
|
82
|
+
"template_id" => template_id.to_s
|
83
|
+
}.delete_if { |k, v| !v || v == '' }
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_json
|
88
|
+
JSON.generate(to_h)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Apostle
|
4
|
+
|
5
|
+
class Queue
|
6
|
+
|
7
|
+
attr_accessor :emails, :results
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@emails = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def <<(email)
|
14
|
+
add(email)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(email)
|
18
|
+
@emails << email
|
19
|
+
end
|
20
|
+
|
21
|
+
def size
|
22
|
+
emails.size
|
23
|
+
end
|
24
|
+
|
25
|
+
def clear
|
26
|
+
emails = []
|
27
|
+
results = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def flush
|
31
|
+
deliver && clear
|
32
|
+
end
|
33
|
+
|
34
|
+
def deliver
|
35
|
+
deliver!
|
36
|
+
rescue DeliveryError
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def deliver!
|
41
|
+
return true unless Apostle.deliver
|
42
|
+
|
43
|
+
# Validate the minimum requirement of a recipient and template
|
44
|
+
unless Apostle.domain_key
|
45
|
+
raise DeliveryError,
|
46
|
+
"No Apostle Domain Key has been defined. Preferably this should be in your environment, as ENV['APOSTLE_DOMAIN_KEY']. If you need to configure this manually, you can call Apostle.configure.
|
47
|
+
|
48
|
+
Apostle.configure do |config|
|
49
|
+
config.domain_key = 'Your domain key'
|
50
|
+
end"
|
51
|
+
end
|
52
|
+
|
53
|
+
raise DeliveryError, "Mail queue is empty" if emails.size == 0
|
54
|
+
|
55
|
+
payload, @results = process_emails
|
56
|
+
|
57
|
+
if @results[:invalid].size > 0
|
58
|
+
raise DeliveryError,
|
59
|
+
"Invalid emails: #{@results[:invalid].size}"
|
60
|
+
end
|
61
|
+
|
62
|
+
# Deliver the payload
|
63
|
+
response = deliver_payload(payload)
|
64
|
+
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def process_emails
|
71
|
+
results = { valid: [], invalid: [] }
|
72
|
+
|
73
|
+
payload = {recipients: {}}
|
74
|
+
|
75
|
+
emails.each do |mail|
|
76
|
+
# Validate each mail
|
77
|
+
begin
|
78
|
+
unless mail.email && mail.email != ""
|
79
|
+
raise DeliveryError,
|
80
|
+
"No recipient provided"
|
81
|
+
end
|
82
|
+
|
83
|
+
unless mail.template_id && mail.template_id != ""
|
84
|
+
raise DeliveryError,
|
85
|
+
"No email template_id provided"
|
86
|
+
end
|
87
|
+
|
88
|
+
payload[:recipients].merge!(mail.to_h)
|
89
|
+
results[:valid] << mail
|
90
|
+
rescue => e
|
91
|
+
results[:invalid] << mail
|
92
|
+
mail._exception = e
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
[payload, results]
|
97
|
+
end
|
98
|
+
|
99
|
+
def deliver_payload(payload)
|
100
|
+
delivery_api = Apostle.delivery_host
|
101
|
+
|
102
|
+
req = Net::HTTP::Post.new(
|
103
|
+
"/",
|
104
|
+
'Content-Type' =>'application/json',
|
105
|
+
"Authorization" => "Bearer #{Apostle.domain_key}")
|
106
|
+
if delivery_api.user
|
107
|
+
req.basic_auth delivery_api.user, delivery_api.password
|
108
|
+
end
|
109
|
+
req.body = JSON.generate(payload)
|
110
|
+
response = Net::HTTP.
|
111
|
+
new(delivery_api.host, delivery_api.port).
|
112
|
+
start do |http|
|
113
|
+
http.request(req)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Successful request
|
117
|
+
if [200, 201, 202].include?(response.code.to_i)
|
118
|
+
return true
|
119
|
+
end
|
120
|
+
|
121
|
+
begin
|
122
|
+
json = JSON.parse(response.body)
|
123
|
+
rescue JSON::ParserError
|
124
|
+
json = {}
|
125
|
+
end
|
126
|
+
|
127
|
+
if json["message"]
|
128
|
+
message = json["message"]
|
129
|
+
else
|
130
|
+
response.body
|
131
|
+
end
|
132
|
+
|
133
|
+
raise case response.code.to_i
|
134
|
+
when 401
|
135
|
+
Apostle::Unauthorized
|
136
|
+
when 403
|
137
|
+
Apostle::Forbidden
|
138
|
+
when 422
|
139
|
+
Apostle::UnprocessableEntity
|
140
|
+
when 500
|
141
|
+
Apostle::ServerError
|
142
|
+
else
|
143
|
+
Apostle::DeliveryError
|
144
|
+
end, message
|
145
|
+
|
146
|
+
response
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
data/lib/apostle.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require "apostle/version"
|
2
|
+
require 'apostle/mail'
|
3
|
+
require 'apostle/queue'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Apostle
|
7
|
+
@@delivery_host = URI(ENV['APOSTLE_DELIVERY_HOST'] || 'http://deliver.apostle.io')
|
8
|
+
@@domain_key = ENV['APOSTLE_DOMAIN_KEY']
|
9
|
+
@@deliver = true
|
10
|
+
|
11
|
+
def self.delivery_host=(host)
|
12
|
+
@@delivery_host = host
|
13
|
+
end
|
14
|
+
|
15
|
+
# Lazily create a delivery_host URI
|
16
|
+
def self.delivery_host
|
17
|
+
if @@delivery_host.is_a?(URI)
|
18
|
+
@@delivery_host
|
19
|
+
else
|
20
|
+
URI(@@delivery_host)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.domain_key=(key)
|
25
|
+
@@domain_key = key
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.domain_key
|
29
|
+
@@domain_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.deliver=(bool)
|
33
|
+
@@deliver = !!bool
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.deliver
|
37
|
+
@@deliver
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
def configure
|
42
|
+
yield self
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Error = Class.new(StandardError)
|
47
|
+
DeliveryError = Class.new(Error)
|
48
|
+
Unauthorized = Class.new(DeliveryError)
|
49
|
+
Forbidden = Class.new(DeliveryError)
|
50
|
+
UnprocessableEntity = Class.new(DeliveryError)
|
51
|
+
ServerError = Class.new(DeliveryError)
|
52
|
+
|
53
|
+
end
|
data/penpal.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/apostle/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Mal Curtis"]
|
6
|
+
gem.email = ["mal@sitepoint.com"]
|
7
|
+
gem.description = %q{: Write a gem description}
|
8
|
+
gem.summary = %q{: Write a gem summary}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "apostle"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Apostle::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency "minitest"
|
19
|
+
gem.add_development_dependency "webmock"
|
20
|
+
end
|
data/spec/mail_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require 'apostle'
|
3
|
+
|
4
|
+
describe Apostle::Mail do
|
5
|
+
before do
|
6
|
+
Apostle.configure do |config|
|
7
|
+
config.domain_key = "abc"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#initialize" do
|
12
|
+
it "assigns template and attributes" do
|
13
|
+
mail = Apostle::Mail.new "template_slug",
|
14
|
+
email: "email address",
|
15
|
+
unknown_key: "val"
|
16
|
+
|
17
|
+
mail.email.must_equal "email address"
|
18
|
+
mail.template_id.must_equal "template_slug"
|
19
|
+
mail.data.must_equal({ "unknown_key" => "val" })
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#deliver!" do
|
24
|
+
it "returns raises an exception without a template id" do
|
25
|
+
mail = Apostle::Mail.new nil
|
26
|
+
expect(mail.deliver!).to raise_error(Apostle::DeliveryError, "No template")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "delegates to a queue" do
|
30
|
+
end
|
31
|
+
|
32
|
+
it "raises any error returned"
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "to_json" do
|
36
|
+
it "returns a json representaion of the hash"
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "to_h" do
|
40
|
+
it "returns a hash of attributes" do
|
41
|
+
mail = Apostle::Mail.new "template_slug"
|
42
|
+
mail.from = :f
|
43
|
+
mail.email = 123
|
44
|
+
mail.reply_to = "someone"
|
45
|
+
mail.name = "name"
|
46
|
+
mail.data = { "Hello" => "World" }
|
47
|
+
mail.foo = 'Bar'
|
48
|
+
mail.to_h.must_equal({"123" => {
|
49
|
+
"template_id" => "template_slug",
|
50
|
+
"from" => "f",
|
51
|
+
"reply_to" => "someone",
|
52
|
+
"name" => "name",
|
53
|
+
"data" => { "Hello" => "World", "foo" => "Bar"}
|
54
|
+
}})
|
55
|
+
end
|
56
|
+
it "removes nil entries" do
|
57
|
+
mail = Apostle::Mail.new "slug"
|
58
|
+
mail.email = "to"
|
59
|
+
mail.to_h.must_equal({"to" => {
|
60
|
+
"template_id" => "slug",
|
61
|
+
"data" => {}
|
62
|
+
}})
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/queue_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
Apostle.domain_key = "abc123"
|
4
|
+
|
5
|
+
describe Apostle::Queue do
|
6
|
+
it "sends the auth header" do
|
7
|
+
stub = stub_request(:any, Apostle.delivery_host.to_s).with(
|
8
|
+
headers: { "Authorization" => "Bearer abc123" }
|
9
|
+
)
|
10
|
+
queue = Apostle::Queue.new
|
11
|
+
queue.send :deliver_payload, {}
|
12
|
+
assert_requested(stub)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "sends grouped requests" do
|
16
|
+
queue = Apostle::Queue.new
|
17
|
+
mail1 = Apostle::Mail.new "slug1", email: "recipient1"
|
18
|
+
mail2 = Apostle::Mail.new "slug2", email: "recipient2"
|
19
|
+
|
20
|
+
queue << mail1
|
21
|
+
queue << mail2
|
22
|
+
|
23
|
+
queue.emails.must_equal([mail1, mail2])
|
24
|
+
|
25
|
+
payload, results = queue.send :process_emails
|
26
|
+
results.must_equal({valid: [mail1, mail2], invalid: []})
|
27
|
+
payload.must_equal({
|
28
|
+
recipients: {
|
29
|
+
"recipient1" => {"template_id" => "slug1", "data" => {} },
|
30
|
+
"recipient2" => {"template_id" => "slug2", "data" => {} }
|
31
|
+
}
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
it "validates emails" do
|
36
|
+
queue = Apostle::Queue.new
|
37
|
+
mail1 = Apostle::Mail.new nil, email: "recipient1@example.com"
|
38
|
+
mail2 = Apostle::Mail.new "slug2"
|
39
|
+
|
40
|
+
queue << mail1
|
41
|
+
queue << mail2
|
42
|
+
|
43
|
+
queue.emails.must_equal([mail1, mail2])
|
44
|
+
|
45
|
+
payload, results = queue.send :process_emails
|
46
|
+
results.must_equal({invalid: [mail1, mail2], valid: []})
|
47
|
+
|
48
|
+
mail1._exception.message.must_equal("No email template_id provided")
|
49
|
+
mail2._exception.message.must_equal("No recipient provided")
|
50
|
+
payload[:recipients].must_equal({})
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#deliver" do
|
54
|
+
it "returns false if no delivery occurs" do
|
55
|
+
queue = Apostle::Queue.new
|
56
|
+
queue.deliver.must_equal(false)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: apostle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mal Curtis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: &70173682453920 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70173682453920
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: webmock
|
27
|
+
requirement: &70173682452780 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70173682452780
|
36
|
+
description: ': Write a gem description'
|
37
|
+
email:
|
38
|
+
- mal@sitepoint.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- Gemfile
|
45
|
+
- LICENSE
|
46
|
+
- README.md
|
47
|
+
- Rakefile
|
48
|
+
- lib/apostle.rb
|
49
|
+
- lib/apostle/mail.rb
|
50
|
+
- lib/apostle/queue.rb
|
51
|
+
- lib/apostle/version.rb
|
52
|
+
- penpal.gemspec
|
53
|
+
- spec/mail_spec.rb
|
54
|
+
- spec/queue_spec.rb
|
55
|
+
- spec/spec_helper.rb
|
56
|
+
homepage: ''
|
57
|
+
licenses: []
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.8.11
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: ': Write a gem summary'
|
80
|
+
test_files:
|
81
|
+
- spec/mail_spec.rb
|
82
|
+
- spec/queue_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
has_rdoc:
|