dm_courier 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +25 -0
- data/.gitignore +5 -0
- data/.hound.yml +4 -0
- data/.rubocop.yml +292 -0
- data/.ruby-version +1 -0
- data/.travis.yml +15 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +95 -0
- data/Rakefile +8 -0
- data/lib/dm_courier/configurable.rb +41 -0
- data/lib/dm_courier/default.rb +81 -0
- data/lib/dm_courier/delivery_method.rb +22 -0
- data/lib/dm_courier/errors.rb +4 -0
- data/lib/dm_courier/message_helper.rb +95 -0
- data/lib/dm_courier/railtie.rb +11 -0
- data/lib/dm_courier/service_locator.rb +43 -0
- data/lib/dm_courier/services/mandrill.rb +111 -0
- data/lib/dm_courier/services/sparkpost.rb +107 -0
- data/lib/dm_courier/version.rb +3 -0
- data/lib/dm_courier.rb +20 -0
- data/lib/monkey_patch/sparkpost/request.rb +21 -0
- data/rails_courier.gemspec +39 -0
- metadata +221 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2b8943c2c5c0940d2bd7682f47f6c0a28e990a95
|
4
|
+
data.tar.gz: 770b51e01c169f6d68d7144d53dff1e5f6eac861
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5cae0696f9e1d6a629eb7723bd4f8dd992b0b3edf0ff803065fcd8f032aa5de9f56d7b7eacde1b180ebc8b3c7e169ace7ddf9faadeb2e54fa5c27ab53f8494df
|
7
|
+
data.tar.gz: 78365d346b2c0d932d3df221edc56bde790f848afe0606e32e0dd3234628ce22c74c488009a7e682bbe6b6d08a1fe283d9c77829ddea859fc0d9e1a421d91a94
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
---
|
2
|
+
engines:
|
3
|
+
duplication:
|
4
|
+
enabled: true
|
5
|
+
config:
|
6
|
+
languages:
|
7
|
+
- ruby
|
8
|
+
- javascript
|
9
|
+
- python
|
10
|
+
- php
|
11
|
+
fixme:
|
12
|
+
enabled: true
|
13
|
+
rubocop:
|
14
|
+
enabled: true
|
15
|
+
ratings:
|
16
|
+
paths:
|
17
|
+
- "**.inc"
|
18
|
+
- "**.js"
|
19
|
+
- "**.jsx"
|
20
|
+
- "**.module"
|
21
|
+
- "**.php"
|
22
|
+
- "**.py"
|
23
|
+
- "**.rb"
|
24
|
+
exclude_paths:
|
25
|
+
- spec/
|
data/.hound.yml
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,292 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.2
|
3
|
+
Exclude:
|
4
|
+
- "Gemfile"
|
5
|
+
UseCache: false
|
6
|
+
|
7
|
+
LineLength:
|
8
|
+
Max: 120
|
9
|
+
|
10
|
+
Style/CollectionMethods:
|
11
|
+
Description: Preferred collection methods.
|
12
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
|
13
|
+
Enabled: true
|
14
|
+
PreferredMethods:
|
15
|
+
collect: map
|
16
|
+
collect!: map!
|
17
|
+
|
18
|
+
Style/DotPosition:
|
19
|
+
Description: Checks the position of the dot in multi-line method calls.
|
20
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
|
21
|
+
Enabled: true
|
22
|
+
EnforcedStyle: leading
|
23
|
+
SupportedStyles:
|
24
|
+
- leading
|
25
|
+
- trailing
|
26
|
+
|
27
|
+
Style/FileName:
|
28
|
+
Description: Use snake_case for source file names.
|
29
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
|
30
|
+
Enabled: true
|
31
|
+
|
32
|
+
Style/GuardClause:
|
33
|
+
Description: Check for conditionals that can be replaced with guard clauses
|
34
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
|
35
|
+
Enabled: false
|
36
|
+
MinBodyLength: 1
|
37
|
+
|
38
|
+
Style/IfUnlessModifier:
|
39
|
+
Description: Favor modifier if/unless usage when you have a single-line body.
|
40
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
|
41
|
+
Enabled: false
|
42
|
+
MaxLineLength: 120
|
43
|
+
|
44
|
+
Style/OptionHash:
|
45
|
+
Description: Don't use option hashes when you can use keyword arguments.
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
Style/PercentLiteralDelimiters:
|
49
|
+
Description: Use `%`-literal delimiters consistently
|
50
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
|
51
|
+
Enabled: false
|
52
|
+
PreferredDelimiters:
|
53
|
+
"%": "()"
|
54
|
+
"%i": "()"
|
55
|
+
"%q": "()"
|
56
|
+
"%Q": "()"
|
57
|
+
"%r": "{}"
|
58
|
+
"%s": "()"
|
59
|
+
"%w": "()"
|
60
|
+
"%W": "()"
|
61
|
+
"%x": "()"
|
62
|
+
|
63
|
+
Style/PredicateName:
|
64
|
+
Description: Check the names of predicate methods.
|
65
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
|
66
|
+
Enabled: true
|
67
|
+
NamePrefix:
|
68
|
+
- is_
|
69
|
+
- has_
|
70
|
+
- have_
|
71
|
+
NamePrefixBlacklist:
|
72
|
+
- is_
|
73
|
+
Exclude:
|
74
|
+
- spec/**/*
|
75
|
+
|
76
|
+
Style/RaiseArgs:
|
77
|
+
Description: Checks the arguments passed to raise/fail.
|
78
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
|
79
|
+
Enabled: false
|
80
|
+
EnforcedStyle: exploded
|
81
|
+
SupportedStyles:
|
82
|
+
- compact
|
83
|
+
- exploded
|
84
|
+
|
85
|
+
Style/SignalException:
|
86
|
+
Description: Checks for proper usage of fail and raise.
|
87
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
|
88
|
+
Enabled: false
|
89
|
+
EnforcedStyle: semantic
|
90
|
+
SupportedStyles:
|
91
|
+
- only_raise
|
92
|
+
- only_fail
|
93
|
+
- semantic
|
94
|
+
|
95
|
+
Style/SingleLineBlockParams:
|
96
|
+
Description: Enforces the names of some block params.
|
97
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
|
98
|
+
Enabled: false
|
99
|
+
Methods:
|
100
|
+
- reduce:
|
101
|
+
- a
|
102
|
+
- e
|
103
|
+
- inject:
|
104
|
+
- a
|
105
|
+
- e
|
106
|
+
Style/CollectionMethods:
|
107
|
+
Description: Preferred collection methods.
|
108
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
|
109
|
+
Enabled: true
|
110
|
+
PreferredMethods:
|
111
|
+
collect: map
|
112
|
+
collect!: map!
|
113
|
+
reduce: inject
|
114
|
+
|
115
|
+
Style/SingleLineMethods:
|
116
|
+
Description: Avoid single-line methods.
|
117
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
|
118
|
+
Enabled: false
|
119
|
+
AllowIfMethodIsEmpty: true
|
120
|
+
|
121
|
+
Style/StringLiterals:
|
122
|
+
Description: Checks if uses of quotes match the configured preference.
|
123
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
|
124
|
+
Enabled: true
|
125
|
+
EnforcedStyle: double_quotes
|
126
|
+
SupportedStyles:
|
127
|
+
- single_quotes
|
128
|
+
- double_quotes
|
129
|
+
|
130
|
+
Style/StringLiteralsInInterpolation:
|
131
|
+
Description: Checks if uses of quotes inside expressions in interpolated strings
|
132
|
+
match the configured preference.
|
133
|
+
Enabled: true
|
134
|
+
EnforcedStyle: single_quotes
|
135
|
+
SupportedStyles:
|
136
|
+
- single_quotes
|
137
|
+
- double_quotes
|
138
|
+
|
139
|
+
Style/TrailingCommaInArguments:
|
140
|
+
Description: 'Checks for trailing comma in argument lists.'
|
141
|
+
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
|
142
|
+
Enabled: false
|
143
|
+
EnforcedStyleForMultiline: no_comma
|
144
|
+
SupportedStyles:
|
145
|
+
- comma
|
146
|
+
- consistent_comma
|
147
|
+
- no_comma
|
148
|
+
|
149
|
+
Style/TrailingCommaInLiteral:
|
150
|
+
Description: 'Checks for trailing comma in array and hash literals.'
|
151
|
+
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
|
152
|
+
Enabled: false
|
153
|
+
EnforcedStyleForMultiline: no_comma
|
154
|
+
SupportedStyles:
|
155
|
+
- comma
|
156
|
+
- consistent_comma
|
157
|
+
- no_comma
|
158
|
+
|
159
|
+
Metrics/AbcSize:
|
160
|
+
Description: A calculated magnitude based on number of assignments, branches, and
|
161
|
+
conditions.
|
162
|
+
Enabled: false
|
163
|
+
Max: 15
|
164
|
+
|
165
|
+
Metrics/ClassLength:
|
166
|
+
Description: Avoid classes longer than 100 lines of code.
|
167
|
+
Enabled: false
|
168
|
+
CountComments: false
|
169
|
+
Max: 100
|
170
|
+
|
171
|
+
Metrics/ModuleLength:
|
172
|
+
CountComments: false
|
173
|
+
Max: 100
|
174
|
+
Description: Avoid modules longer than 100 lines of code.
|
175
|
+
Enabled: false
|
176
|
+
|
177
|
+
Metrics/CyclomaticComplexity:
|
178
|
+
Description: A complexity metric that is strongly correlated to the number of test
|
179
|
+
cases needed to validate a method.
|
180
|
+
Enabled: false
|
181
|
+
Max: 6
|
182
|
+
|
183
|
+
Metrics/MethodLength:
|
184
|
+
Description: Avoid methods longer than 10 lines of code.
|
185
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
|
186
|
+
Enabled: false
|
187
|
+
CountComments: false
|
188
|
+
Max: 10
|
189
|
+
|
190
|
+
Metrics/ParameterLists:
|
191
|
+
Description: Avoid parameter lists longer than three or four parameters.
|
192
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
|
193
|
+
Enabled: false
|
194
|
+
Max: 5
|
195
|
+
CountKeywordArgs: true
|
196
|
+
|
197
|
+
Metrics/PerceivedComplexity:
|
198
|
+
Description: A complexity metric geared towards measuring complexity for a human
|
199
|
+
reader.
|
200
|
+
Enabled: false
|
201
|
+
Max: 7
|
202
|
+
|
203
|
+
Lint/AssignmentInCondition:
|
204
|
+
Description: Don't use assignment in conditions.
|
205
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
|
206
|
+
Enabled: false
|
207
|
+
AllowSafeAssignment: true
|
208
|
+
|
209
|
+
Style/InlineComment:
|
210
|
+
Description: Avoid inline comments.
|
211
|
+
Enabled: true
|
212
|
+
|
213
|
+
Style/AccessorMethodName:
|
214
|
+
Description: Check the naming of accessor methods for get_/set_.
|
215
|
+
Enabled: true
|
216
|
+
|
217
|
+
Style/Alias:
|
218
|
+
Description: Use alias_method instead of alias.
|
219
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
|
220
|
+
Enabled: true
|
221
|
+
|
222
|
+
Style/Documentation:
|
223
|
+
Description: Document classes and non-namespace modules.
|
224
|
+
Enabled: false
|
225
|
+
|
226
|
+
Style/DoubleNegation:
|
227
|
+
Description: Checks for uses of double negation (!!).
|
228
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
|
229
|
+
Enabled: false
|
230
|
+
|
231
|
+
Style/EachWithObject:
|
232
|
+
Description: Prefer `each_with_object` over `inject` or `reduce`.
|
233
|
+
Enabled: false
|
234
|
+
|
235
|
+
Style/EmptyLiteral:
|
236
|
+
Description: Prefer literals to Array.new/Hash.new/String.new.
|
237
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
|
238
|
+
Enabled: true
|
239
|
+
|
240
|
+
Style/ModuleFunction:
|
241
|
+
Description: Checks for usage of `extend self` in modules.
|
242
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
|
243
|
+
Enabled: true
|
244
|
+
|
245
|
+
Style/OneLineConditional:
|
246
|
+
Description: Favor the ternary operator(?:) over if/then/else/end constructs.
|
247
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
|
248
|
+
Enabled: true
|
249
|
+
|
250
|
+
Style/PerlBackrefs:
|
251
|
+
Description: Avoid Perl-style regex back references.
|
252
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
|
253
|
+
Enabled: true
|
254
|
+
|
255
|
+
Style/Send:
|
256
|
+
Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
|
257
|
+
may overlap with existing methods.
|
258
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
|
259
|
+
Enabled: false
|
260
|
+
|
261
|
+
Style/SpecialGlobalVars:
|
262
|
+
Description: Avoid Perl-style global variables.
|
263
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
|
264
|
+
Enabled: true
|
265
|
+
|
266
|
+
Style/VariableInterpolation:
|
267
|
+
Description: Don't interpolate global, instance and class variables directly in
|
268
|
+
strings.
|
269
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
|
270
|
+
Enabled: false
|
271
|
+
|
272
|
+
Style/WhenThen:
|
273
|
+
Description: Use when x then ... for one-line cases.
|
274
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
|
275
|
+
Enabled: false
|
276
|
+
|
277
|
+
Lint/EachWithObjectArgument:
|
278
|
+
Description: Check for immutable argument given to each_with_object.
|
279
|
+
Enabled: true
|
280
|
+
|
281
|
+
Lint/HandleExceptions:
|
282
|
+
Description: Don't suppress exception.
|
283
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
|
284
|
+
Enabled: false
|
285
|
+
|
286
|
+
Lint/LiteralInCondition:
|
287
|
+
Description: Checks of literals used in conditions.
|
288
|
+
Enabled: false
|
289
|
+
|
290
|
+
Lint/LiteralInInterpolation:
|
291
|
+
Description: Checks for literals used in interpolation.
|
292
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.0
|
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
rvm:
|
4
|
+
- 2.2
|
5
|
+
- 2.3.0
|
6
|
+
notifications:
|
7
|
+
email:
|
8
|
+
on_success: change
|
9
|
+
on_failure: always
|
10
|
+
addons:
|
11
|
+
code_climate:
|
12
|
+
repo_token: e3eac13dabf5af3f7cd993b869ae5bce1cee735332537815badda3fd4ee2fc28
|
13
|
+
script:
|
14
|
+
- bundle exec rubocop
|
15
|
+
- bundle exec rake spec
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Jaison Erick
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
|
2
|
+
# DM Courier
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/sumoners/dm_courier.svg?branch=master)](https://travis-ci.org/sumoners/dm_courier)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/dm_courier.svg)](http://badge.fury.io/rb/dm_courier)
|
6
|
+
[![security](https://hakiri.io/github/sumoners/dm_courier/master.svg)](https://hakiri.io/github/sumoners/dm_courier/master)
|
7
|
+
[![Test Coverage](https://codeclimate.com/github/sumoners/dm_courier/badges/coverage.svg)](https://codeclimate.com/github/sumoners/dm_courier/coverage)
|
8
|
+
[![Code Climate](https://codeclimate.com/github/sumoners/dm_courier/badges/gpa.svg)](https://codeclimate.com/github/sumoners/dm_courier)
|
9
|
+
|
10
|
+
Stick with just one Gem and be free to choose your email delivery service. Rails
|
11
|
+
Courier allows you to change easily the deliery method anytime you want.
|
12
|
+
|
13
|
+
## Rails Setup
|
14
|
+
|
15
|
+
First, add the gem to your Gemfile and run the `bundle` command to install it.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'dm_courier'
|
19
|
+
```
|
20
|
+
|
21
|
+
Second, set the delivery method in `config/environments/production.rb`.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
config.action_mailer.delivery_method = :dm_courier
|
25
|
+
```
|
26
|
+
|
27
|
+
Third, create an initializer such as `config/initializers/dm_courier.rb` and
|
28
|
+
paste in the following code:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
DMCourier.configure do |config|
|
32
|
+
config.api_key = ENV['DM_COURIER_APIKEY']
|
33
|
+
config.service_name = :mandrill # Choose here the service you want to use
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
NOTE: If you don't already have an environment variable for delivery service API
|
38
|
+
key, don't forget to create one.
|
39
|
+
|
40
|
+
### Available configuration options
|
41
|
+
|
42
|
+
Any option with Mailer Support can be used inside the mailer like:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
class MyMailer < ActionMailer::Base
|
46
|
+
default track_opens: false
|
47
|
+
|
48
|
+
def notify_user(email)
|
49
|
+
mail(auto_html: false, inline_css: true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
Option | Mailer Support | Description
|
55
|
+
-----------|----------------|-------------
|
56
|
+
`api_key` | false | Your service API key<br />**Default:** `ENV['DM_COURIER_API_KEY']`
|
57
|
+
`service_name` | false | Your service API name.<br />**Default:** `ENV['DM_COURIER_SERVICE']`
|
58
|
+
`async` | false | If the message with be sent asynchronous (depends on the service support)<br />**Default:** false<br />**Services:** mandrill
|
59
|
+
`from` | true | A default from address for all emails<br />**Services:** all
|
60
|
+
`auto_html` | true | whether or not to automatically generate an HTML part for messages that are not given HTML<br />**Services:** mandrill
|
61
|
+
`auto_text` | true | whether or not to automatically generate a text part for messages that are not given text<br />**Services:** mandrill
|
62
|
+
`important` | true | whether or not this message is important, and should be delivered ahead of non-important messages<br />**Default**: false<br />**Services:** mandrill
|
63
|
+
`inline_css` | true | whether or not to automatically inline all CSS styles provided in the message HTML - only for HTML documents less than 256KB in size<br />**Services:** mandrill, sparkpost
|
64
|
+
`track_clicks` | true | whether or not to turn on click tracking for the message<br />**Services:** mandrill, sparkpost
|
65
|
+
`track_opens` | true | whether or not to turn on open tracking for the message<br />**Services:** mandrill, sparkpost
|
66
|
+
`track_url_without_query_string` | true | whether or not to strip the query string from URLs when aggregating tracked URL data<br />**Services:** mandrill
|
67
|
+
`log_content` | true | set to false to remove content logging for sensitive emails<br />**Services:** mandrill
|
68
|
+
`bcc_address` | true | an optional address to receive an exact copy of each recipient's email<br />**Services:** mandrill
|
69
|
+
`return_path_domain` | true | a custom domain to use for the messages's return-path<br />**Services:** mandrill, sparkpost
|
70
|
+
`signing_domain` | true | a custom domain to use for SPF/DKIM signing (for "via" or "on behalf of" in email clients)<br />**Services:** mandrill
|
71
|
+
`subaccount` | true | the unique id of a subaccount - must already exist or will fail with an error<br />**Services:** mandrill
|
72
|
+
`tracking_domain` | true | a custom domain to use for tracking opens and clicks<br />**Services:** mandrill
|
73
|
+
`tags` | true | an array of string to tag the message with. Stats are accumulated using tags, though we only store the first 100 we see, so this should not be unique or change frequently. Tags should be 50 characters or less. Any tags starting with an underscore are reserved for internal use and will cause errors.<br />**Services:** mandrill
|
74
|
+
|
75
|
+
## Services
|
76
|
+
|
77
|
+
### Mandrill
|
78
|
+
|
79
|
+
### SparkPost
|
80
|
+
|
81
|
+
The options were choosen to create an abstraction layer above the original
|
82
|
+
service API. Because of that some options have different names:
|
83
|
+
|
84
|
+
- **return_path_domain**: Is called **return_path** on SparkPost
|
85
|
+
- **track_opens**: Is called **open_tracking** on SparkPost
|
86
|
+
- **track_clicks**: Is called **click_tracking** on SparkPost
|
87
|
+
|
88
|
+
> TODO: Sparkpost service implementation does not support BCC emails yet.
|
89
|
+
|
90
|
+
## Development & Feedback
|
91
|
+
|
92
|
+
Questions or problems? Please use the issue tracker. If you would like to
|
93
|
+
contribute to this project, fork this repository. Pull requests appreciated.
|
94
|
+
|
95
|
+
This gem is based on the [mandrill_dm](https://github.com/mandrill_dm) gem.
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "dm_courier/default"
|
2
|
+
|
3
|
+
module DMCourier
|
4
|
+
module Configurable
|
5
|
+
attr_accessor :api_key, :service_name, :async, :auto_html, :auto_text, :important,
|
6
|
+
:inline_css, :track_clicks, :track_opens, :track_url_without_query_string,
|
7
|
+
:log_content, :bcc_address, :return_path_domain, :signing_domain,
|
8
|
+
:subaccount, :tracking_domain, :tags, :from
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def keys
|
12
|
+
@keys ||= [:api_key, :service_name, :async, :auto_html, :auto_text, :important,
|
13
|
+
:inline_css, :track_clicks, :track_opens, :track_url_without_query_string,
|
14
|
+
:log_content, :bcc_address, :return_path_domain, :signing_domain,
|
15
|
+
:subaccount, :tracking_domain, :tags, :from]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def configure
|
20
|
+
yield self
|
21
|
+
end
|
22
|
+
|
23
|
+
def reset!
|
24
|
+
DMCourier::Configurable.keys.each do |key|
|
25
|
+
instance_variable_set(:"@#{key}", DMCourier::Default.options[key])
|
26
|
+
end
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
alias setup reset!
|
31
|
+
|
32
|
+
def same_options?(opts)
|
33
|
+
opts.hash == options.hash
|
34
|
+
end
|
35
|
+
|
36
|
+
def options
|
37
|
+
Hash[DMCourier::Configurable
|
38
|
+
.keys.map { |key| [key, instance_variable_get(:"@#{key}")] }]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module DMCourier
|
2
|
+
module Default
|
3
|
+
class << self
|
4
|
+
def options
|
5
|
+
Hash[DMCourier::Configurable.keys.map { |key| [key, send(key)] }]
|
6
|
+
end
|
7
|
+
|
8
|
+
def api_key
|
9
|
+
ENV["DM_COURIER_API_KEY"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def service_name
|
13
|
+
ENV["DM_COURIER_SERVICE"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def async
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def auto_html
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def auto_text
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def important
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def inline_css
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def track_clicks
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def track_opens
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def track_url_without_query_string
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def log_content
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def bcc_address
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def return_path_domain
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def signing_domain
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def subaccount
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def tracking_domain
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def tags
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def from
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "dm_courier/service_locator"
|
2
|
+
|
3
|
+
module DMCourier
|
4
|
+
class DeliveryMethod
|
5
|
+
include DMCourier::ServiceLocator
|
6
|
+
include DMCourier::Configurable
|
7
|
+
|
8
|
+
attr_reader :response
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
DMCourier::Configurable.keys.each do |key|
|
12
|
+
instance_variable_set(:"@#{key}", options[key] ||
|
13
|
+
DMCourier.instance_variable_get(:"@#{key}"))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
alias settings options
|
17
|
+
|
18
|
+
def deliver!(mail)
|
19
|
+
@response = service.new(mail, options).deliver!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require "base64"
|
2
|
+
|
3
|
+
module DMCourier
|
4
|
+
module Services
|
5
|
+
module MessageHelper
|
6
|
+
def extract_params(params)
|
7
|
+
json = {}
|
8
|
+
|
9
|
+
json
|
10
|
+
.merge!(Hash[
|
11
|
+
params[:nil_true_false].map { |name, key| [name.to_sym, nil_true_false?(key.to_sym)] }
|
12
|
+
]) if params.key?(:nil_true_false)
|
13
|
+
|
14
|
+
json
|
15
|
+
.merge!(Hash[
|
16
|
+
params[:string].map { |name, key| [name.to_sym, return_string_value(key.to_sym)] }
|
17
|
+
]) if params.key?(:string)
|
18
|
+
|
19
|
+
json
|
20
|
+
end
|
21
|
+
|
22
|
+
def from_email
|
23
|
+
from.address if from_address
|
24
|
+
end
|
25
|
+
|
26
|
+
def from_name
|
27
|
+
from.display_name if from_address
|
28
|
+
end
|
29
|
+
|
30
|
+
def from
|
31
|
+
Mail::Address.new(from_address)
|
32
|
+
end
|
33
|
+
|
34
|
+
def from_address
|
35
|
+
mail[:from] ? mail[:from].formatted.first : options[:from]
|
36
|
+
end
|
37
|
+
|
38
|
+
def text_part
|
39
|
+
return mail.text_part.body.decoded if mail.multipart? && mail.text_part
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def html_part
|
44
|
+
mail.html_part ? mail.html_part.body.decoded : mail.body.decoded
|
45
|
+
end
|
46
|
+
|
47
|
+
def subject
|
48
|
+
mail.subject
|
49
|
+
end
|
50
|
+
|
51
|
+
def return_string_value(field)
|
52
|
+
value = fallback_options(field)
|
53
|
+
value ? value.to_s : nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def nil_true_false?(field)
|
57
|
+
value = fallback_options(field)
|
58
|
+
return nil if value.nil?
|
59
|
+
value.to_s == "true" ? true : false
|
60
|
+
end
|
61
|
+
|
62
|
+
def fallback_options(field)
|
63
|
+
mail[field] || options[field]
|
64
|
+
end
|
65
|
+
|
66
|
+
def attachments(filter = {})
|
67
|
+
Enumerator.new do |y|
|
68
|
+
attachments = mail.attachments
|
69
|
+
attachments = if filter[:inline]
|
70
|
+
attachments.select(&:inline?)
|
71
|
+
else
|
72
|
+
attachments.reject(&:inline?)
|
73
|
+
end if filter.key?(:inline)
|
74
|
+
|
75
|
+
attachments.map do |attachment|
|
76
|
+
y.yield(name: attachment.inline? ? attachment.cid : attachment.filename,
|
77
|
+
type: attachment.mime_type,
|
78
|
+
content: Base64.encode64(attachment.body.decoded),
|
79
|
+
inline: attachment.inline?)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def attachments?(filter = {})
|
85
|
+
found = mail.attachments && !mail.attachments.empty?
|
86
|
+
|
87
|
+
if found && filter.key?(:inline)
|
88
|
+
found &&= mail.attachments.any? { |a| a.inline? == filter[:inline] }
|
89
|
+
end
|
90
|
+
|
91
|
+
found
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "dm_courier"
|
2
|
+
|
3
|
+
module DMCourier
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
initializer "dm_courier.add_delivery_method" do
|
6
|
+
ActiveSupport.on_load :action_mailer do
|
7
|
+
ActionMailer::Base.add_delivery_method :dm_courier, DMCourier::DeliveryMethod
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "dm_courier/services/mandrill"
|
2
|
+
require "dm_courier/services/sparkpost"
|
3
|
+
|
4
|
+
module DMCourier
|
5
|
+
module ServiceLocator
|
6
|
+
def service
|
7
|
+
@service ||= begin
|
8
|
+
raise DMCourier::InvalidService unless @service_name
|
9
|
+
|
10
|
+
constantize(@service_name)
|
11
|
+
end
|
12
|
+
rescue NameError => e
|
13
|
+
raise DMCourier::InvalidService, e
|
14
|
+
end
|
15
|
+
|
16
|
+
def constantize(service_name)
|
17
|
+
camel_cased_word = "DMCourier::Services::#{service_name.to_s.tr('_', ' ').split.map(&:capitalize).join('')}"
|
18
|
+
names = camel_cased_word.split("::")
|
19
|
+
|
20
|
+
Object.const_get(camel_cased_word) if names.empty?
|
21
|
+
|
22
|
+
names.shift if names.size > 1 && names.first.empty?
|
23
|
+
|
24
|
+
names.inject(Object) do |constant, name|
|
25
|
+
if constant == Object
|
26
|
+
constant.const_get(name)
|
27
|
+
else
|
28
|
+
candidate = constant.const_get(name)
|
29
|
+
next candidate if constant.const_defined?(name, false)
|
30
|
+
next candidate unless Object.const_defined?(name)
|
31
|
+
|
32
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
33
|
+
break const if ancestor == Object
|
34
|
+
break ancestor if ancestor.const_defined?(name, false)
|
35
|
+
const
|
36
|
+
end
|
37
|
+
|
38
|
+
constant.const_get(name, false)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require "mandrill"
|
2
|
+
require "base64"
|
3
|
+
|
4
|
+
require "dm_courier/message_helper"
|
5
|
+
|
6
|
+
module DMCourier
|
7
|
+
module Services
|
8
|
+
class Mandrill
|
9
|
+
include DMCourier::Services::MessageHelper
|
10
|
+
|
11
|
+
attr_reader :api_key, :async, :mail, :options
|
12
|
+
|
13
|
+
def initialize(mail, options = {})
|
14
|
+
@mail = mail
|
15
|
+
@api_key = options.fetch(:api_key)
|
16
|
+
@async = options.fetch(:async, false)
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
:mandrill
|
22
|
+
end
|
23
|
+
|
24
|
+
def deliver!
|
25
|
+
mandrill_api = ::Mandrill::API.new(api_key)
|
26
|
+
mandrill_api.messages.send(mandrill_message, async)
|
27
|
+
end
|
28
|
+
|
29
|
+
def mandrill_message
|
30
|
+
message = extract_params(nil_true_false: { auto_html: :auto_html,
|
31
|
+
auto_text: :auto_text,
|
32
|
+
important: :important,
|
33
|
+
inline_css: :inline_css,
|
34
|
+
track_clicks: :track_clicks,
|
35
|
+
track_opens: :track_opens,
|
36
|
+
url_strip_qs: :track_url_without_query_string,
|
37
|
+
view_content_link: :log_content },
|
38
|
+
string: { bcc_address: :bcc_address,
|
39
|
+
return_path_domain: :return_path_domain,
|
40
|
+
signing_domain: :signing_domain,
|
41
|
+
subaccount: :subaccount,
|
42
|
+
tracking_domain: :tracking_domain })
|
43
|
+
|
44
|
+
message[:important] ||= false
|
45
|
+
|
46
|
+
message.merge!(from_email: from_email,
|
47
|
+
from_name: from_name,
|
48
|
+
headers: headers,
|
49
|
+
html: html_part,
|
50
|
+
subject: subject,
|
51
|
+
tags: tags,
|
52
|
+
text: text_part,
|
53
|
+
to: to)
|
54
|
+
|
55
|
+
message[:attachments] = regular_attachments if attachments?(inline: false)
|
56
|
+
message[:images] = inline_attachments if attachments?(inline: true)
|
57
|
+
message
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def headers
|
63
|
+
headers = {}
|
64
|
+
value = mail["Reply-To"] || options[:reply_to]
|
65
|
+
headers["Reply-To"] = value.to_s if value
|
66
|
+
headers
|
67
|
+
end
|
68
|
+
|
69
|
+
def tags
|
70
|
+
mail[:tags].to_s.split(", ").map { |tag| tag } +
|
71
|
+
options[:tags].to_s.split(", ").map { |tag| tag }
|
72
|
+
end
|
73
|
+
|
74
|
+
def to
|
75
|
+
%w(to cc bcc)
|
76
|
+
.map { |field| hash_addresses(mail[field]) }
|
77
|
+
.reject(&:nil?)
|
78
|
+
.flatten
|
79
|
+
end
|
80
|
+
|
81
|
+
def hash_addresses(address_field)
|
82
|
+
return nil unless address_field
|
83
|
+
|
84
|
+
address_field.formatted.map do |address|
|
85
|
+
address_obj = Mail::Address.new(address)
|
86
|
+
{
|
87
|
+
email: address_obj.address,
|
88
|
+
name: address_obj.display_name,
|
89
|
+
type: address_field.name.downcase
|
90
|
+
}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def regular_attachments
|
95
|
+
attachments(inline: false).map do |attachment|
|
96
|
+
{ name: attachment[:name],
|
97
|
+
type: attachment[:type],
|
98
|
+
content: attachment[:content] }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def inline_attachments
|
103
|
+
attachments(inline: true).map do |attachment|
|
104
|
+
{ name: attachment[:name],
|
105
|
+
type: attachment[:type],
|
106
|
+
content: attachment[:content] }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "sparkpost"
|
2
|
+
require "base64"
|
3
|
+
|
4
|
+
require "monkey_patch/sparkpost/request"
|
5
|
+
require "dm_courier/message_helper"
|
6
|
+
|
7
|
+
module DMCourier
|
8
|
+
module Services
|
9
|
+
class Sparkpost
|
10
|
+
include DMCourier::Services::MessageHelper
|
11
|
+
|
12
|
+
attr_reader :api_key, :mail, :options
|
13
|
+
|
14
|
+
def initialize(mail, options = {})
|
15
|
+
@mail = mail
|
16
|
+
@api_key = options.fetch(:api_key)
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
:sparkpost
|
22
|
+
end
|
23
|
+
|
24
|
+
def deliver!
|
25
|
+
sparkpost = ::SparkPost::Client.new(api_key)
|
26
|
+
transmission = sparkpost.transmission
|
27
|
+
|
28
|
+
transmission.send(:request, transmission.endpoint, api_key, sparkpost_message)
|
29
|
+
end
|
30
|
+
|
31
|
+
def sparkpost_message
|
32
|
+
parameters = extract_params(nil_true_false: { inline_css: :inline_css,
|
33
|
+
click_tracking: :track_clicks,
|
34
|
+
open_tracking: :track_opens },
|
35
|
+
string: { return_path: :return_path_domain })
|
36
|
+
|
37
|
+
message = { options: {} }
|
38
|
+
message[:options][:inline_css] = parameters[:inline_css] unless parameters[:inline_css].nil?
|
39
|
+
message[:options][:click_tracking] = parameters[:click_tracking] unless parameters[:click_tracking].nil?
|
40
|
+
message[:options][:open_tracking] = parameters[:open_tracking] unless parameters[:open_tracking].nil?
|
41
|
+
|
42
|
+
message[:return_path] = parameters[:return_path] unless parameters[:return_path].nil?
|
43
|
+
|
44
|
+
from = { email: from_email }
|
45
|
+
from[:name] = from_name if from_name
|
46
|
+
|
47
|
+
message[:content] = {
|
48
|
+
from: from,
|
49
|
+
subject: subject
|
50
|
+
}
|
51
|
+
|
52
|
+
message[:content][:reply_to] = reply_to if reply_to
|
53
|
+
message[:content][:html] = html_part if html_part
|
54
|
+
message[:content][:text] = text_part if text_part
|
55
|
+
|
56
|
+
message[:recipients] = recipients
|
57
|
+
|
58
|
+
message[:content][:attachments] = regular_attachments if attachments?(inline: false)
|
59
|
+
message[:content][:inline_images] = inline_attachments if attachments?(inline: true)
|
60
|
+
message
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def reply_to
|
66
|
+
value = mail["Reply-To"] || options[:reply_to]
|
67
|
+
value.to_s if value
|
68
|
+
end
|
69
|
+
|
70
|
+
def recipients
|
71
|
+
%w(to cc)
|
72
|
+
.map { |field| hash_addresses(mail[field]) }
|
73
|
+
.reject(&:nil?)
|
74
|
+
.flatten
|
75
|
+
end
|
76
|
+
|
77
|
+
def hash_addresses(address_field)
|
78
|
+
return nil unless address_field
|
79
|
+
|
80
|
+
address_field.formatted.map do |address|
|
81
|
+
address_obj = Mail::Address.new(address)
|
82
|
+
{
|
83
|
+
address: { email: address_obj.address }.tap do |hash|
|
84
|
+
hash[:name] = address_obj.display_name if address_obj.display_name
|
85
|
+
end
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def regular_attachments
|
91
|
+
attachments(inline: false).map do |attachment|
|
92
|
+
{ name: attachment[:name],
|
93
|
+
type: attachment[:type],
|
94
|
+
content: attachment[:content] }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def inline_attachments
|
99
|
+
attachments(inline: true).map do |attachment|
|
100
|
+
{ name: attachment[:name],
|
101
|
+
type: attachment[:type],
|
102
|
+
content: attachment[:content] }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/dm_courier.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "dm_courier/version"
|
2
|
+
require "dm_courier/errors"
|
3
|
+
require "dm_courier/configurable"
|
4
|
+
require "dm_courier/delivery_method"
|
5
|
+
|
6
|
+
require "dm_courier/railtie" if defined? Rails
|
7
|
+
|
8
|
+
module DMCourier
|
9
|
+
class << self
|
10
|
+
include DMCourier::Configurable
|
11
|
+
|
12
|
+
def delivery_method
|
13
|
+
return @delivery_method if defined?(@delivery_method) &&
|
14
|
+
@delivery_method.same_options?(options)
|
15
|
+
@delivery_method = DMCourier::DeliveryMethod.new(options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
DMCourier.setup
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module SparkPost
|
5
|
+
module Request
|
6
|
+
def request(url, api_key, data)
|
7
|
+
uri = URI.parse(url)
|
8
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
9
|
+
http.use_ssl = true
|
10
|
+
headers = {
|
11
|
+
"User-Agent" => "ruby-sparkpost/" + VERSION,
|
12
|
+
"Content-Type" => "application/json",
|
13
|
+
"Authorization" => api_key
|
14
|
+
}
|
15
|
+
req = Net::HTTP::Post.new(uri.path, headers)
|
16
|
+
req.body = JSON.generate(data)
|
17
|
+
|
18
|
+
process_response(http.request(req))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "dm_courier/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "dm_courier"
|
7
|
+
spec.version = DMCourier::VERSION.dup
|
8
|
+
spec.authors = ["Jaison Erick"]
|
9
|
+
spec.email = ["jaisonreis@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "A delivery method that abstract the most common email delivery APIs"
|
12
|
+
spec.description = "A delivery method that abstract the most common email delivery APIs"
|
13
|
+
spec.homepage = "http://github.com/sumoners/dm_courier"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`
|
17
|
+
.split("\x0")
|
18
|
+
.reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.required_ruby_version = ">= 2.2.0"
|
25
|
+
spec.required_rubygems_version = ">= 2.4.5"
|
26
|
+
|
27
|
+
spec.add_dependency "mandrill-api", "~> 1.0.53"
|
28
|
+
spec.add_dependency "sparkpost", "~> 0.1.2"
|
29
|
+
spec.add_dependency "http", "0.9.8"
|
30
|
+
|
31
|
+
spec.add_development_dependency "codeclimate-test-reporter", "~> 0.5"
|
32
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.4"
|
34
|
+
spec.add_development_dependency "mail", "~> 2.6"
|
35
|
+
spec.add_development_dependency "rake"
|
36
|
+
spec.add_development_dependency "simplecov", "~> 0.11"
|
37
|
+
spec.add_development_dependency "rubocop", "~> 0.36"
|
38
|
+
spec.add_development_dependency "pry"
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dm_courier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jaison Erick
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mandrill-api
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.53
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.53
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sparkpost
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: http
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.9.8
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.9.8
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: codeclimate-test-reporter
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.7'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.4'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.4'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mail
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2.6'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2.6'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.11'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.11'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.36'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.36'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pry
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
description: A delivery method that abstract the most common email delivery APIs
|
168
|
+
email:
|
169
|
+
- jaisonreis@gmail.com
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- ".codeclimate.yml"
|
175
|
+
- ".gitignore"
|
176
|
+
- ".hound.yml"
|
177
|
+
- ".rubocop.yml"
|
178
|
+
- ".ruby-version"
|
179
|
+
- ".travis.yml"
|
180
|
+
- Gemfile
|
181
|
+
- LICENSE
|
182
|
+
- README.md
|
183
|
+
- Rakefile
|
184
|
+
- lib/dm_courier.rb
|
185
|
+
- lib/dm_courier/configurable.rb
|
186
|
+
- lib/dm_courier/default.rb
|
187
|
+
- lib/dm_courier/delivery_method.rb
|
188
|
+
- lib/dm_courier/errors.rb
|
189
|
+
- lib/dm_courier/message_helper.rb
|
190
|
+
- lib/dm_courier/railtie.rb
|
191
|
+
- lib/dm_courier/service_locator.rb
|
192
|
+
- lib/dm_courier/services/mandrill.rb
|
193
|
+
- lib/dm_courier/services/sparkpost.rb
|
194
|
+
- lib/dm_courier/version.rb
|
195
|
+
- lib/monkey_patch/sparkpost/request.rb
|
196
|
+
- rails_courier.gemspec
|
197
|
+
homepage: http://github.com/sumoners/dm_courier
|
198
|
+
licenses:
|
199
|
+
- MIT
|
200
|
+
metadata: {}
|
201
|
+
post_install_message:
|
202
|
+
rdoc_options: []
|
203
|
+
require_paths:
|
204
|
+
- lib
|
205
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - ">="
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: 2.2.0
|
210
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: 2.4.5
|
215
|
+
requirements: []
|
216
|
+
rubyforge_project:
|
217
|
+
rubygems_version: 2.4.5
|
218
|
+
signing_key:
|
219
|
+
specification_version: 4
|
220
|
+
summary: A delivery method that abstract the most common email delivery APIs
|
221
|
+
test_files: []
|