multi_mail 0.0.2 → 0.1.0

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.
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