multi_mail 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +10 -0
  3. data/README.md +283 -59
  4. data/Rakefile +38 -19
  5. data/lib/multi_mail/cloudmailin/receiver.rb +3 -13
  6. data/lib/multi_mail/mailgun/message.rb +67 -0
  7. data/lib/multi_mail/mailgun/receiver.rb +20 -13
  8. data/lib/multi_mail/mailgun/sender.rb +79 -2
  9. data/lib/multi_mail/mandrill/message.rb +74 -0
  10. data/lib/multi_mail/mandrill/receiver.rb +36 -16
  11. data/lib/multi_mail/mandrill/sender.rb +77 -2
  12. data/lib/multi_mail/message/base.rb +40 -0
  13. data/lib/multi_mail/postmark/receiver.rb +1 -1
  14. data/lib/multi_mail/postmark/sender.rb +35 -5
  15. data/lib/multi_mail/receiver/base.rb +31 -2
  16. data/lib/multi_mail/receiver.rb +1 -4
  17. data/lib/multi_mail/sender/base.rb +23 -1
  18. data/lib/multi_mail/sendgrid/message.rb +74 -0
  19. data/lib/multi_mail/sendgrid/receiver.rb +72 -23
  20. data/lib/multi_mail/sendgrid/sender.rb +63 -2
  21. data/lib/multi_mail/service.rb +48 -56
  22. data/lib/multi_mail/simple/receiver.rb +4 -4
  23. data/lib/multi_mail/version.rb +1 -1
  24. data/lib/multi_mail.rb +16 -1
  25. data/multi_mail.gemspec +4 -1
  26. data/spec/fixtures/empty.gif +0 -0
  27. data/spec/fixtures/mailgun/raw/invalid.txt +13 -0
  28. data/spec/fixtures/mailgun/raw/missing.txt +13 -0
  29. data/spec/fixtures/mailgun/raw/spam.txt +13 -0
  30. data/spec/fixtures/mailgun/raw/valid.txt +13 -0
  31. data/spec/fixtures/mandrill/invalid.txt +15 -0
  32. data/spec/fixtures/mandrill/missing.txt +14 -0
  33. data/spec/fixtures/mandrill/multiple.txt +15 -0
  34. data/spec/fixtures/mandrill/valid.txt +10 -5
  35. data/spec/fixtures/postmark/valid.txt +13 -13
  36. data/spec/fixtures/sendgrid/encoding.txt +90 -0
  37. data/spec/fixtures/sendgrid/spam.txt +94 -0
  38. data/spec/fixtures/sendgrid/valid.txt +136 -0
  39. data/spec/mailgun/message_spec.rb +251 -0
  40. data/spec/mailgun/receiver_spec.rb +35 -20
  41. data/spec/mailgun/sender_spec.rb +175 -0
  42. data/spec/mandrill/message_spec.rb +305 -0
  43. data/spec/mandrill/receiver_spec.rb +90 -46
  44. data/spec/mandrill/sender_spec.rb +138 -0
  45. data/spec/message/base_spec.rb +81 -0
  46. data/spec/postmark/receiver_spec.rb +4 -4
  47. data/spec/postmark/sender_spec.rb +118 -0
  48. data/spec/receiver/base_spec.rb +16 -9
  49. data/spec/sender/base_spec.rb +24 -10
  50. data/spec/sendgrid/message_spec.rb +265 -0
  51. data/spec/sendgrid/receiver_spec.rb +77 -0
  52. data/spec/sendgrid/sender_spec.rb +140 -0
  53. data/spec/service_spec.rb +18 -1
  54. data/spec/simple/receiver_spec.rb +1 -1
  55. data/spec/spec_helper.rb +46 -4
  56. metadata +226 -143
  57. data/lib/multi_mail/sender.rb +0 -46
  58. data/lib/multi_mail/simple/sender.rb +0 -14
  59. data/spec/sender_spec.rb +0 -13
  60. data/spec/simple/sender_spec.rb +0 -0
data/.gitignore CHANGED
@@ -4,4 +4,5 @@
4
4
  Gemfile.lock
5
5
  doc/*
6
6
  pkg/*
7
- api_keys.yml
7
+ spec/cassettes
8
+ api_keys.yml
data/.travis.yml CHANGED
@@ -5,3 +5,13 @@ rvm:
5
5
  - 1.9.3
6
6
  - 2.0.0
7
7
  - ree
8
+ env:
9
+ global:
10
+ # MAILGUN_API_KEY
11
+ - secure: "hQrNP1++1GVNuFp7xHIUOp938sbuko/hLdhyw+D/yNn1XXvak7UGNVvKNHvL\n8a+CxP8D3iqHitkcSEccWhzwnALiljZKl7tFfX/OPouYrPpuhhjHtv8X/y3n\nFpeMVNFXaF1QfwSEMYWNMdL24WUgBr+V5WhRsmi/BCIA+4PtCRk="
12
+ # MANDRILL_API_KEY
13
+ - secure: "sjbNGWtWzaPup1yQN+cbtY264NgpNYZrOirVuYj5PMD31emoAiaobS7+cCJH\nx0MUXskjtbzvbJwvzLwkwDpdRA2Hx4dvOKh0HrOVLy1B0bKbVdb7P3eET2aN\nE07nmVNC79jiopD+1pWcbMGXr9s4/sOogK23ktVPegrWH7c0pfI="
14
+ # SENDGRID_API_USER
15
+ - secure: "THUH/QdYAVXIFBn24PhcqChMF4XGUzDnzoRxNQMBjVZ3mTM6/dw5lGApx3HQ\nZZy4iUQ0sCWcsPo/tK4AdhZ7/NEcKh/9Uxr1J7GOKBIAJVd5veDe6RCy1eyP\niCmF6QuzVsEgprcxcOPypeybLoUd8TCIhVGPTYaOCamjwx59e3Y="
16
+ # SENDGRID_API_KEY
17
+ - secure: "ovfCD7gOOiHteTihQ9YGyUQiSdWrrI15kE2nU8qEfH8suQACBxW4By9D4CY6\ngompkj1svDscXb9u55nbOIH5JWQxM+Uc5OH6vFWBikRdyFPHN0lfsRyUXQj7\nqPkjaEIEAW0Q7bTetdpfTDV1qmCiHALmc2CaexEj9o4JOcN7AeM="
data/README.md CHANGED
@@ -1,101 +1,243 @@
1
- # MultiMail: easily switch between email APIs
1
+ # MultiMail: easily switch email APIs
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/opennorth/multi_mail.png)](http://travis-ci.org/opennorth/multi_mail)
4
4
  [![Dependency Status](https://gemnasium.com/opennorth/multi_mail.png)](https://gemnasium.com/opennorth/multi_mail)
5
5
  [![Coverage Status](https://coveralls.io/repos/opennorth/multi_mail/badge.png?branch=master)](https://coveralls.io/r/opennorth/multi_mail)
6
6
  [![Code Climate](https://codeclimate.com/github/opennorth/multi_mail.png)](https://codeclimate.com/github/opennorth/multi_mail)
7
7
 
8
- Many providers – including [Cloudmailin](http://www.cloudmailin.com/), [Mailgun](http://www.mailgun.com/), [Mandrill](http://mandrill.com/), [Postmark](http://postmarkapp.com/) and [SendGrid](http://sendgrid.com/) – offer APIs to send, receive, parse and forward email. MultiMail lets you easily switch between these APIs.
8
+ Many providers offer APIs to send, receive, and parse email. MultiMail lets you easily switch between these APIs, and integrates tightly with the [Mail](https://github.com/mikel/mail) gem.
9
+
10
+ * [Cloudmailin](http://www.cloudmailin.com/): [Example](#cloudmailin)
11
+ * [Mailgun](http://www.mailgun.com/): [Example](#mailgun)
12
+ * [Mandrill](http://mandrill.com/): [Example](#mandrill)
13
+ * [Postmark](http://postmarkapp.com/): [Example](#postmark)
14
+ * [SendGrid](http://sendgrid.com/): [Example](#sendgrid)
9
15
 
10
16
  ## Usage
11
17
 
12
- require 'multi_mail'
13
-
14
- service = MultiMail::Receiver.new(:provider => 'mandrill')
15
-
16
- message = service.process data # raw POST data or params hash
18
+ ### Incoming
17
19
 
18
- `message` is an array of [Mail::Message](https://github.com/mikel/mail) instances.
20
+ ```ruby
21
+ require 'multi_mail'
19
22
 
20
- ## Supported APIs
23
+ # Create an object to consume the webhook data.
24
+ service = MultiMail::Receiver.new(:provider => 'mandrill')
21
25
 
22
- Incoming email:
26
+ # Process the webhook data, whether it's raw POST data, a params hash, a Rack request, etc.
27
+ messages = service.process(data)
28
+ ```
23
29
 
24
- * [Mailgun](http://www.mailgun.com/)
25
- * [Mandrill](http://mandrill.com/)
26
- * [Postmark](http://postmarkapp.com/)
27
- * [Cloudmailin](http://www.cloudmailin.com/)
30
+ `messages` will be an array of [Mail::Message](https://github.com/mikel/mail) instances.
28
31
 
29
- Any additional information provided by an API is added to the message as a header. For example, Mailgun provides `stripped-text`, which is the message body without quoted parts or signature block. You can access it with `message['stripped-text'].value`.
32
+ Any non-standard parameters provided by an API are added to each message as a header. For example, Mailgun provides `stripped-text`, which is the message body without quoted parts or signature block. You can access it as `message['stripped-text'].value`.
30
33
 
31
- ## Cloudmailin
34
+ ### Outgoing
35
+
36
+ With MultiMail, you send a message the same way you do with the [Mail](https://github.com/mikel/mail#sending-an-email) gem. Just set `delivery_method`:
37
+
38
+ ```ruby
39
+ require 'multi_mail'
40
+ require 'multi_mail/postmark/sender'
41
+
42
+ message = Mail.new do
43
+ delivery_method MultiMail::Sender::Postmark, :api_key => 'your-api-key'
44
+ ...
45
+ end
46
+
47
+ message.deliver
48
+ ```
49
+
50
+ Alternatively, instead of setting `delivery_method` during initialization, you can set it before delivery:
51
+
52
+ ```ruby
53
+ message = Mail.new do
54
+ ...
55
+ end
56
+
57
+ message.delivery_method MultiMail::Sender::Postmark, :api_key => 'your-api-key'
58
+
59
+ message.deliver
60
+ ```
61
+
62
+ Or, if you are sending many messages, you can set a default `delivery_method` for all messages:
63
+
64
+ ```ruby
65
+ Mail.defaults do
66
+ delivery_method MultiMail::Sender::Postmark, :api_key => 'your-api-key'
67
+ end
68
+ ```
69
+
70
+ #### Track opens and clicks
71
+
72
+ Mailgun and Mandrill allow you to set open tracking and click tracking on a per-message basis:
32
73
 
33
- service = MultiMail::Receiver.new({
34
- :provider => 'cloudmailin',
35
- })
74
+ ```ruby
75
+ require 'multi_mail'
76
+ require 'multi_mail/mailgun/sender'
36
77
 
37
- The default HTTP POST format is `raw`. Add a `:http_post_format` option to change the HTTP POST format, with possible values of `"multipart"`, `"json"` or `"raw"` (default). (The [original format](http://docs.cloudmailin.com/http_post_formats/original/) is deprecated.) For example:
78
+ message = Mail.new do
79
+ delivery_method MultiMail::Sender::Mailgun,
80
+ :api_key => 'your-api-key',
81
+ :domain => 'your-domain.mailgun.org',
82
+ :track => {
83
+ :opens => true,
84
+ :clicks => false,
85
+ }
86
+ ...
87
+ end
88
+
89
+ message.deliver
90
+ ```
91
+
92
+ [Mailgun](http://documentation.mailgun.com/user_manual.html#tracking-clicks) and [Mandrill](http://help.mandrill.com/entries/21721852-Why-aren-t-clicks-being-tracked-) track whether a recipient has clicked a link in a message by rewriting its URL.
93
+
94
+ If want to rewrite URLs in HTML parts only – leaving URLs as-is in text parts – use `:clicks => 'htmlonly'` if you are using Mailgun; if you are using Mandrill, do not set `:clicks` and instead configure click tracking globally in your [Mandrill sending options](https://mandrillapp.com/settings/sending-options).
95
+
96
+ ```ruby
97
+ require 'multi_mail'
98
+ require 'multi_mail/mandrill/sender'
99
+
100
+ message = Mail.new do
101
+ delivery_method MultiMail::Sender::Mandrill,
102
+ :api_key => 'your-api-key',
103
+ :track => {
104
+ :opens => true,
105
+ :clicks => false,
106
+ }
107
+ ...
108
+ end
109
+
110
+ message.deliver
111
+ ```
112
+
113
+ #### Inspect the API response
114
+
115
+ Pass `:return_response => true` to `delivery_method` and use the `deliver!` method to send the message:
116
+
117
+ ```ruby
118
+ message = Mail.new do
119
+ delivery_method MultiMail::Sender::Postmark, :api_key => 'your-api-key', :return_response => true
120
+ ...
121
+ end
122
+
123
+ message.deliver!
124
+ ```
125
+
126
+ Note that the `deliver!` method ignores Mail's `perform_deliveries` and `raise_delivery_errors` flags.
127
+
128
+ ## Cloudmailin
38
129
 
39
- service = MultiMail::Receiver.new({
40
- :provider => 'cloudmailin',
41
- :http_post_format => 'raw',
42
- })
130
+ ### Incoming
43
131
 
44
- **Note:** [MultiMail doesn't yet support Cloudmailin's URL attachments (attachment stores).](https://github.com/opennorth/multi_mail/issues/11) Please use regular attachments (always the case if you use the `raw` format) if you are using MultiMail.
132
+ ```ruby
133
+ service = MultiMail::Receiver.new({
134
+ :provider => 'cloudmailin',
135
+ })
136
+ ```
45
137
 
46
- **2013-04-15:** If an email contains multiple HTML parts and you are using the `multipart` or `json` HTTP POST formats, Cloudmailin will only include the first HTML part in its `html` parameter. Use the `raw` format to avoid data loss. Cloudmailin also removes a newline from the end of each attachment.
138
+ The default HTTP POST format is `raw`. Add a `:http_post_format` option to change the HTTP POST format, with possible values of `"multipart"`, `"json"` or `"raw"` (default):
47
139
 
48
- ### Additional information provided by the API
140
+ ```ruby
141
+ service = MultiMail::Receiver.new({
142
+ :provider => 'cloudmailin',
143
+ :http_post_format => 'raw',
144
+ })
145
+ ```
49
146
 
50
- See [Cloudmailin's documentation](http://docs.cloudmailin.com/http_post_formats/):
147
+ See [Cloudmailin's documentation](http://docs.cloudmailin.com/http_post_formats/) for these additional parameters provided by the API:
51
148
 
52
149
  * `reply_plain`
53
150
  * `spf-result`
54
151
 
152
+ **Note:** [MultiMail doesn't yet support Cloudmailin's URL attachments (attachment stores).](https://github.com/opennorth/multi_mail/issues/11) Please use regular attachments (always the case if you use the default `raw` format).
153
+
55
154
  ## Mailgun
56
155
 
57
- service = MultiMail::Receiver.new({
58
- :provider => 'mailgun',
59
- :mailgun_api_key => 'key-xxxxxxxxxxxxxxxxxxxxxxx-x-xxxxxx',
60
- })
156
+ ### Incoming
157
+
158
+ ```ruby
159
+ service = MultiMail::Receiver.new({
160
+ :provider => 'mailgun',
161
+ })
162
+ ```
61
163
 
62
- If you have a route with a URL ending with "mime" and you are using the raw MIME format, add a `:http_post_format => 'raw'` option. For example:
164
+ To check that a request originates from Mailgun, add a `:mailgun_api_key` option:
63
165
 
64
- service = MultiMail::Receiver.new({
65
- :provider => 'mailgun',
66
- :mailgun_api_key => 'key-xxxxxxxxxxxxxxxxxxxxxxx-x-xxxxxx',
67
- :http_post_format => 'raw',
68
- })
166
+ ```ruby
167
+ service = MultiMail::Receiver.new({
168
+ :provider => 'mailgun',
169
+ :mailgun_api_key => 'key-xxxxxxxxxxxxxxxxxxxxxxx-x-xxxxxx',
170
+ })
171
+ ```
69
172
 
70
- **2013-04-15:** Mailgun's `stripped-text` and `stripped-html` parameters do not return the same parts of the message. `stripped-html` sometimes incorrectly drops non-quoted, non-signature parts of the message; `stripped-text` doesn't.
173
+ If you are using the [raw MIME format](http://documentation.mailgun.com/user_manual.html#mime-messages-parameters), add a `:http_post_format => 'raw'` option:
71
174
 
72
- ### Additional information provided by the API
175
+ ```ruby
176
+ service = MultiMail::Receiver.new({
177
+ :provider => 'mailgun',
178
+ :http_post_format => 'raw',
179
+ })
180
+ ```
73
181
 
74
- See [Mailgun's documentation](http://documentation.mailgun.net/user_manual.html#parsed-messages-parameters):
182
+ See [Mailgun's documentation](http://documentation.mailgun.net/user_manual.html#parsed-messages-parameters) for these additional parameters provided by the API:
75
183
 
76
184
  * `stripped-text`
77
185
  * `stripped-signature`
78
186
  * `stripped-html`
79
187
  * `content-id-map`
80
188
 
189
+ ### Outgoing
190
+
191
+ ```ruby
192
+ require 'multi_mail/mailgun/sender'
193
+
194
+ Mail.deliver do
195
+ delivery_method MultiMail::Sender::Mailgun, :api_key => 'your-api-key', :domain => 'your-domain.mailgun.org'
196
+ ...
197
+ end
198
+ ```
199
+
200
+ You may pass additional arguments to `delivery_method` to use Mailgun-specific features ([see docs](http://documentation.mailgun.com/api-sending.html)):
201
+
202
+ * `o:tag`
203
+ * `o:campaign`
204
+ * `o:dkim`
205
+ * `o:deliverytime`
206
+ * `o:testmode`
207
+ * `o:tracking`
208
+ * `v:`
209
+
81
210
  ## Mandrill
82
211
 
83
- service = MultiMail::Receiver.new({
84
- :provider => 'mandrill',
85
- })
212
+ ### Incoming
86
213
 
87
- The default SpamAssassin score needed to flag an email as spam is `5`. Add a `:spamassassin_threshold` option to increase or decrease it. For example:
214
+ ```ruby
215
+ service = MultiMail::Receiver.new({
216
+ :provider => 'mandrill',
217
+ })
218
+ ```
88
219
 
89
- service = MultiMail::Receiver.new({
90
- :provider => 'mandrill',
91
- :spamassassin_threshold => 4.5,
92
- })
220
+ To check that a request originates from Mandrill, add `:mandrill_webhook_key` and `:mandrill_webhook_url` options:
93
221
 
94
- **2013-04-15:** If an email contains multiple HTML parts, Mandrill will only include the first HTML part in its `html` parameter. We therefore parse its `raw_msg` parameter to set the HTML part correctly. Mandrill also adds a newline to the end of each message part.
222
+ ```ruby
223
+ service = MultiMail::Receiver.new({
224
+ :provider => 'mandrill',
225
+ :mandrill_webhook_key => 'xxxxxxxxxxxxxxxxxxxxxx',
226
+ :mandrill_webhook_url => 'http://example.com/post',
227
+ })
228
+ ```
229
+ You can get your webhook key from [Mandrill's Webhooks Settings](https://mandrillapp.com/settings/webhooks).
95
230
 
96
- ### Additional information provided by the API
231
+ The default SpamAssassin score needed to flag an email as spam is `5`. Add a `:spamassassin_threshold` option to increase or decrease it:
97
232
 
98
- See [Mandrill's documentation](http://help.mandrill.com/entries/22092308-What-is-the-format-of-inbound-email-webhooks-):
233
+ ```ruby
234
+ service = MultiMail::Receiver.new({
235
+ :provider => 'mandrill',
236
+ :spamassassin_threshold => 4.5,
237
+ })
238
+ ```
239
+
240
+ See [Mandrill's documentation](http://help.mandrill.com/entries/22092308-What-is-the-format-of-inbound-email-webhooks-) for these additional parameters provided by the API:
99
241
 
100
242
  * `ts`
101
243
  * `email`
@@ -104,22 +246,104 @@ See [Mandrill's documentation](http://help.mandrill.com/entries/22092308-What-is
104
246
  * `spam_report-score`
105
247
  * `spf-result`
106
248
 
107
- ## Postmark
249
+ ### Outgoing
250
+
251
+ ```ruby
252
+ require 'multi_mail/mandrill/sender'
253
+
254
+ Mail.deliver do
255
+ delivery_method MultiMail::Sender::Mandrill, :api_key => 'your-api-key'
256
+ ...
257
+ end
258
+ ```
259
+
260
+ You may pass additional arguments to `delivery_method` to use Mandrill-specific features ([see docs](https://mandrillapp.com/api/docs/messages.ruby.html#method-send)):
261
+
262
+ * `important`
263
+ * `auto_text` and `auto_html`
264
+ * `inline_css`
265
+ * `url_strip_qs`
266
+ * `preserve_recipients`
267
+ * `bcc_address`
268
+ * `tracking_domain` and `signing_domain`
269
+ * `merge`, `global_merge_vars` and `merge_vars`
270
+ * `tags`
271
+ * `google_analytics_domains` and `google_analytics_campaign`
272
+ * `metadata` and `recipient_metadata`
273
+ * `async`
274
+ * `ip_pool`
275
+ * `send_at`
108
276
 
109
- service = MultiMail::Receiver.new({
110
- :provider => 'postmark',
111
- })
277
+ ## Postmark
112
278
 
113
- **2013-05-15:** If an email contains multiple HTML parts, Postmark will only include the first HTML part in its `HtmlBody` parameter. You cannot avoid this loss of data. Postmark is therefore not recommended.
279
+ ### Incoming
114
280
 
115
- ### Additional information provided by the API
281
+ ```ruby
282
+ service = MultiMail::Receiver.new({
283
+ :provider => 'postmark',
284
+ })
285
+ ```
116
286
 
117
- See [Postmark's documentation](http://developer.postmarkapp.com/developer-inbound-parse.html#mailboxhash):
287
+ See [Postmark's documentation](http://developer.postmarkapp.com/developer-inbound-parse.html#mailboxhash) for these additional parameters provided by the API:
118
288
 
119
289
  * `MailboxHash`
120
290
  * `MessageID`
121
291
  * `Tag`
122
292
 
293
+ ### Outgoing
294
+
295
+ ```ruby
296
+ require 'multi_mail/postmark/sender'
297
+
298
+ Mail.deliver do
299
+ delivery_method MultiMail::Sender::Postmark, :api_key => 'your-api-key'
300
+ ...
301
+ end
302
+ ```
303
+
304
+ MultiMail depends on the `postmark` gem for its Postmark integration.
305
+
306
+ You may also pass a `Tag` option to `delivery_method` ([see Postmark's documentation](http://developer.postmarkapp.com/developer-build.html#message-format)).
307
+
308
+ ## SendGrid
309
+
310
+ ### Incoming
311
+
312
+ ```ruby
313
+ service = MultiMail::Receiver.new({
314
+ :provider => 'sendgrid',
315
+ })
316
+ ```
317
+
318
+ The default SpamAssassin score needed to flag an email as spam is `5`. Add a `:spamassassin_threshold` option to increase or decrease it:
319
+
320
+ ```ruby
321
+ service = MultiMail::Receiver.new({
322
+ :provider => 'sendgrid',
323
+ :spamassassin_threshold => 4.5,
324
+ })
325
+ ```
326
+
327
+ See [SendGrid's documentation](http://sendgrid.com/docs/API_Reference/Webhooks/parse.html) for these additional parameters provided by the API:
328
+
329
+ * `dkim`
330
+ * `SPF`
331
+ * `spam_report`
332
+ * `spam_score`
333
+
334
+ ### Outgoing
335
+
336
+ ```ruby
337
+ require 'multi_mail/sendgrid/sender'
338
+
339
+ Mail.deliver do
340
+ delivery_method MultiMail::Sender::SendGrid, :api_user => 'username', :api_key => 'password'
341
+ ...
342
+ end
343
+ ```
344
+
345
+ You may also pass a `x-smtpapi` option to `delivery_method` ([see SendGrid's documentation](http://sendgrid.com/docs/API_Reference/Web_API/mail.html)).
346
+
123
347
  ## Bugs? Questions?
124
348
 
125
349
  This gem's main repository is on GitHub: [http://github.com/opennorth/multi_mail](http://github.com/opennorth/multi_mail), where your contributions, forks, bug reports, feature requests, and feedback are greatly welcomed.
data/Rakefile CHANGED
@@ -48,17 +48,9 @@ task :mailgun do
48
48
  end
49
49
 
50
50
  if catch_all_route
51
- action = catch_all_route['actions'].find do |action|
52
- action[%r{\Aforward\("(http://requestb\.in/\w+)"\)\z}]
53
- end
54
-
55
- if action
56
- bin_url = $1
57
- else
58
- bin_url, action = bin_url_and_action
59
- puts "Updating the catch_all() route..."
60
- JSON.load(RestClient.put("#{base_url}/routes/#{catch_all_route['id']}", :action => action))
61
- end
51
+ bin_url, action = bin_url_and_action
52
+ puts "Updating the catch_all() route..."
53
+ JSON.load(RestClient.put("#{base_url}/routes/#{catch_all_route['id']}", :action => action))
62
54
  else
63
55
  bin_url, action = bin_url_and_action
64
56
  puts "Creating a catch_all() route..."
@@ -77,7 +69,7 @@ task :mandrill do
77
69
 
78
70
  if domain
79
71
  domain_name = domain['domain']
80
- routes = api.inbound.routes domain_name
72
+ routes = api.inbound.routes(domain_name)
81
73
  match = routes.find{|route| route['pattern'] == '*'}
82
74
 
83
75
  puts "The MX for #{domain_name} is not valid" unless domain['valid_mx']
@@ -95,18 +87,45 @@ task :postmark do
95
87
  require 'rest-client'
96
88
 
97
89
  api = Postmark::ApiClient.new(credentials[:postmark_api_key])
98
-
99
90
  info = api.server_info
100
91
 
101
- if info.key?(:inbound_hook_url)
102
- url = info[:inbound_hook_url]
92
+ bin_name = JSON.load(RestClient.post('http://requestb.in/api/v1/bins', {}))['name']
93
+ url = "http://requestb.in/#{bin_name}"
94
+ puts "Setting the POST URL..."
95
+ api.update_server_info :inbound_hook_url => url
96
+
97
+ puts "#{info[:inbound_hash]}@inbound.postmarkapp.com POSTs to #{url}?inspect"
98
+ end
99
+
100
+ desc 'Create a SendGrid route forwarding to a postbin'
101
+ task :sendgrid do
102
+ require 'json'
103
+ require 'rest-client'
104
+ require 'sendgrid_webapi'
105
+
106
+ api = SendGridWebApi::Client.new(credentials[:sendgrid_username], credentials[:sendgrid_password])
107
+ routes = api.parse_email.get['parse']
108
+
109
+ if routes.empty? && ENV['DOMAIN'].nil?
110
+ abort 'usage: DOMAIN=example.com bundle exec rake sendgrid'
111
+ end
112
+
113
+ domain_name = if routes.any?
114
+ routes.first['hostname']
103
115
  else
104
- bin_name = JSON.load(RestClient.post('http://requestb.in/api/v1/bins', {}))['name']
105
- url = "http://requestb.in/#{bin_name}"
106
- api.update_server_info :inbound_hook_url => url
116
+ ENV['DOMAIN']
107
117
  end
108
118
 
109
- puts "#{info[:inbound_hash]}@inbound.postmarkapp.com POSTs to #{url}?inspect"
119
+ bin_name = JSON.load(RestClient.post('http://requestb.in/api/v1/bins', {}))['name']
120
+ url = "http://requestb.in/#{bin_name}"
121
+ puts "Setting the POST URL..."
122
+ result = api.parse_email.set(:hostname => domain_name, :url => url, :spam_check => 0)
123
+
124
+ if result['error']
125
+ puts "HTTP #{result['error']['code']} #{result['error']['message']}"
126
+ else
127
+ puts "#{domain_name} POSTs to #{url}?inspect"
128
+ end
110
129
  end
111
130
 
112
131
  desc 'POST a test fixture to an URL'
@@ -6,7 +6,7 @@ module MultiMail
6
6
  # that a request originates from Cloudmailin.
7
7
  #
8
8
  # @see http://docs.cloudmailin.com/receiving_email/securing_your_email_url_target/
9
- class Cloudmailin < MultiMail::Service
9
+ class Cloudmailin
10
10
  include MultiMail::Receiver::Base
11
11
 
12
12
  recognizes :http_post_format
@@ -37,21 +37,11 @@ module MultiMail
37
37
  # `helo_domain` and `remote_ip`.
38
38
  [message]
39
39
  when 'multipart', 'json'
40
- headers = Multimap.new
41
- params['headers'].each do |key,value|
42
- if Array === value
43
- value.each do |v|
44
- headers[key] = v
45
- end
46
- else
47
- headers[key] = value
48
- end
49
- end
50
-
51
40
  # Mail changes `self`.
41
+ headers = self.class.multimap(params['headers'])
52
42
  http_post_format = @http_post_format
53
-
54
43
  this = self
44
+
55
45
  message = Mail.new do
56
46
  headers headers
57
47
 
@@ -0,0 +1,67 @@
1
+ module MultiMail
2
+ module Message
3
+ # @see http://documentation.mailgun.com/api-sending.html
4
+ class Mailgun < MultiMail::Message::Base
5
+ # Returns the message headers in Mailgun format.
6
+ #
7
+ # @return [Multimap] the message headers in Mailgun format
8
+ def mailgun_headers
9
+ hash = Multimap.new
10
+ header_fields.each do |field|
11
+ key = field.name.downcase
12
+ unless %w(from to cc bcc subject message-id).include?(key)
13
+ hash["h:#{field.name}"] = field.value
14
+ end
15
+ end
16
+ hash
17
+ end
18
+
19
+ # Returns the message's attachments in Mailgun format.
20
+ #
21
+ # @return [Multimap] the attachments in Mailgun format
22
+ # @see http://documentation.mailgun.com/user_manual.html#inline-image
23
+ def mailgun_attachments
24
+ hash = Multimap.new
25
+ attachments.each do |attachment|
26
+ key = attachment.content_type.start_with?('image/') ? 'inline' : 'attachment'
27
+ hash[key] = Faraday::UploadIO.new(StringIO.new(attachment.body.decoded), attachment.content_type, attachment.filename)
28
+ end
29
+ hash
30
+ end
31
+
32
+ # Returns the message as parameters to POST to Mailgun.
33
+ #
34
+ # @return [Hash] the message as parameters to POST to Mailgun
35
+ def to_mailgun_hash
36
+ hash = Multimap.new
37
+
38
+ %w(from subject).each do |field|
39
+ if self[field]
40
+ hash[field] = self[field].value
41
+ end
42
+ end
43
+
44
+ %w(to cc bcc).each do |field|
45
+ if self[field]
46
+ if self[field].value.respond_to?(:each)
47
+ self[field].value.each do |value|
48
+ hash[field] = value
49
+ end
50
+ else
51
+ hash[field] = self[field].value
52
+ end
53
+ end
54
+ end
55
+
56
+ if body_text && !body_text.empty?
57
+ hash['text'] = body_text
58
+ end
59
+ if body_html && !body_html.empty?
60
+ hash['html'] = body_html
61
+ end
62
+
63
+ normalize(hash.merge(mailgun_attachments).merge(mailgun_headers).to_hash)
64
+ end
65
+ end
66
+ end
67
+ end