postmark 0.9.19 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +8 -0
- data/CHANGELOG.rdoc +20 -0
- data/Gemfile +6 -0
- data/README.md +351 -91
- data/VERSION +1 -1
- data/lib/postmark.rb +40 -132
- data/lib/postmark/api_client.rb +162 -0
- data/lib/postmark/bounce.rb +20 -17
- data/lib/postmark/handlers/mail.rb +10 -3
- data/lib/postmark/helpers/hash_helper.rb +35 -0
- data/lib/postmark/helpers/message_helper.rb +62 -0
- data/lib/postmark/http_client.rb +44 -28
- data/lib/postmark/inbound.rb +21 -0
- data/lib/postmark/inflector.rb +28 -0
- data/lib/postmark/message_extensions/mail.rb +50 -5
- data/lib/postmark/message_extensions/shared.rb +23 -28
- data/lib/postmark/version.rb +1 -1
- data/postmark.gemspec +4 -7
- data/spec/data/empty.gif +0 -0
- data/spec/integration/api_client_hashes_spec.rb +101 -0
- data/spec/integration/api_client_messages_spec.rb +127 -0
- data/spec/integration/mail_delivery_method_spec.rb +80 -0
- data/spec/spec_helper.rb +15 -5
- data/spec/support/helpers.rb +11 -0
- data/spec/{shared_examples.rb → support/shared_examples.rb} +0 -0
- data/spec/unit/postmark/api_client_spec.rb +246 -0
- data/spec/unit/postmark/bounce_spec.rb +142 -0
- data/spec/unit/postmark/handlers/mail_spec.rb +39 -0
- data/spec/unit/postmark/helpers/hash_helper_spec.rb +34 -0
- data/spec/unit/postmark/helpers/message_helper_spec.rb +115 -0
- data/spec/unit/postmark/http_client_spec.rb +204 -0
- data/spec/unit/postmark/inbound_spec.rb +88 -0
- data/spec/unit/postmark/inflector_spec.rb +35 -0
- data/spec/unit/postmark/json_spec.rb +37 -0
- data/spec/unit/postmark/message_extensions/mail_spec.rb +205 -0
- data/spec/unit/postmark_spec.rb +164 -0
- metadata +45 -93
- data/lib/postmark/attachments_fix_for_mail.rb +0 -48
- data/lib/postmark/message_extensions/tmail.rb +0 -115
- data/spec/bounce_spec.rb +0 -53
- data/spec/postmark_spec.rb +0 -253
data/.travis.yml
ADDED
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
= Changelog
|
2
2
|
|
3
|
+
== 1.0.0
|
4
|
+
|
5
|
+
* Introduced new instance-based architecture (see README for more details).
|
6
|
+
* Removed TMail support.
|
7
|
+
* Added support for sending emails in batches.
|
8
|
+
* Added API to send emails without Mail library.
|
9
|
+
* Introduced lock-free approach for Mail::Postmark delivery method.
|
10
|
+
* Deprecated the Mail::Message#postmark_attachments method
|
11
|
+
* Added Postmark::Inbound module.
|
12
|
+
* Added integration tests.
|
13
|
+
* Added support for the "server" endpoint of the Postmark API.
|
14
|
+
* Improved unit test coverage.
|
15
|
+
* Added more examples to the README file.
|
16
|
+
* Added official JRuby support.
|
17
|
+
* Fixed the inconsistent behaviour of Mail::Message#tag method added by the gem.
|
18
|
+
* Added Mail::Message#delivered property and Mail::Message#delivered? predicate.
|
19
|
+
* Added Mail::Message#postmark_response method.
|
20
|
+
* Removed Postmark::AttachmentsFixForMail class (that hack no longer works).
|
21
|
+
* Added Travis-CI for integration tests.
|
22
|
+
|
3
23
|
== 0.9.19
|
4
24
|
|
5
25
|
* Added support for native attachments API provided by Ruby Mail library.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,42 +1,315 @@
|
|
1
1
|
# Postmark Gem
|
2
|
+
[![Build Status](https://travis-ci.org/wildbit/postmark-gem.png?branch=master)](https://travis-ci.org/wildbit/postmark-gem) [![Code Climate](https://codeclimate.com/github/wildbit/postmark-gem.png)](https://codeclimate.com/github/wildbit/postmark-gem)
|
2
3
|
|
3
|
-
This gem is
|
4
|
+
This gem is the official wrapper for the [Postmark HTTP API](http://postmarkapp.com). Postmark allows you to send your application's emails with high delivery rates, including bounce/spam processing and detailed statistics. In addition, Postmark can parse incoming emails which are forwarded back to your application.
|
4
5
|
|
5
|
-
##
|
6
|
+
## Install the gem
|
6
7
|
|
7
|
-
|
8
|
+
With Bundler:
|
8
9
|
|
9
|
-
```
|
10
|
-
gem
|
10
|
+
``` ruby
|
11
|
+
gem 'postmark'
|
11
12
|
```
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
In addition to the `postmark` gem you also need to install `mail` gem.
|
14
|
+
Without Bundler:
|
16
15
|
|
17
16
|
``` bash
|
18
|
-
gem install
|
17
|
+
gem install postmark
|
19
18
|
```
|
20
19
|
|
21
|
-
|
22
|
-
new projects, but may be useful for legacy Ruby 1.8.7 projects.
|
23
|
-
|
24
|
-
### Get Postmark API key
|
20
|
+
## Get a Postmark API key
|
25
21
|
|
26
22
|
In order to send emails using Postmark ruby gem, you will need a
|
27
23
|
[Postmark](http://postmarkapp.com) account. If you don't have one please
|
28
24
|
register at https://postmarkapp.com/sign_up.
|
29
25
|
|
30
|
-
If you didn
|
26
|
+
If you didn’t create any servers yet, please create one, proceed to the
|
31
27
|
`Credentials` tab and copy an API key. API keys should be frequently rotated for
|
32
28
|
security reasons.
|
33
29
|
|
34
|
-
##
|
30
|
+
## Communicating with the API
|
35
31
|
|
36
32
|
Make sure you have a [sender signature](https://postmarkapp.com/signatures) for
|
37
|
-
every From email you specify.
|
33
|
+
every From email address you specify.
|
34
|
+
|
35
|
+
Create an instance of `Postmark::ApiClient` to start sending emails.
|
36
|
+
|
37
|
+
``` ruby
|
38
|
+
your_api_key = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
|
39
|
+
client = Postmark::ApiClient.new(your_api_key)
|
40
|
+
```
|
41
|
+
|
42
|
+
`Postmark::ApiClient` accepts various options:
|
43
|
+
|
44
|
+
``` ruby
|
45
|
+
client = Postmark::ApiClient.new(your_api_key, secure: true
|
46
|
+
http_open_timeout: 15)
|
47
|
+
```
|
48
|
+
|
49
|
+
Some useful options are:
|
50
|
+
|
51
|
+
* `secure` (`true` or `false`): set to true to use SSL connection.
|
52
|
+
* `http_read_timeout` (positive number): limit HTTP read time to `n` seconds.
|
53
|
+
* `http_open_timeout` (positive number): limit HTTP open time to `n` seconds.
|
54
|
+
* `proxy_host` (string): proxy address to use.
|
55
|
+
* `proxy_port` (positive number): proxy port to use.
|
56
|
+
* `proxy_user` (string): proxy user.
|
57
|
+
* `proxy_pass` (string): proxy password.
|
58
|
+
|
59
|
+
## Sending a plain text message
|
60
|
+
|
61
|
+
``` ruby
|
62
|
+
client.deliver(from: 'sheldon@bigbangtheory.com',
|
63
|
+
to: 'Leonard Hofstadter <leonard@bigbangtheory.com>',
|
64
|
+
subject: 'Re: Come on, Sheldon. It will be fun.',
|
65
|
+
text_body: 'That\'s what you said about the Green Lantern ' \
|
66
|
+
'movie. You were 114 minutes of wrong.')
|
67
|
+
# => {:to=>"Leonard Hofstadter <leonard@bigbangtheory.com>", :submitted_at=>"2013-05-09T02:45:16.2059023-04:00", :message_id=>"b2b268e3-6a70-xxxx-b897-49c9eb8b1d2e", :error_code=>0, :message=>"OK"}
|
68
|
+
```
|
69
|
+
|
70
|
+
## Sending an HTML message
|
71
|
+
|
72
|
+
``` ruby
|
73
|
+
client.deliver(from: 'sheldon@bigbangtheory.com',
|
74
|
+
to: 'Leonard Hofstadter <leonard@bigbangtheory.com>',
|
75
|
+
subject: 'Re: What, to you, is a large crowd?',
|
76
|
+
html_body: '<p>Any group big enough to trample me to death. ' \
|
77
|
+
'General rule of thumb is 36 adults or 70 ' \
|
78
|
+
'children.</p>')
|
79
|
+
# => {:to=>"Leonard Hofstadter <leonard@bigbangtheory.com>", :submitted_at=>"2013-05-09T02:51:08.8789433-04:00", :message_id=>"75c28987-564e-xxxx-b6eb-e8071873ac06", :error_code=>0, :message=>"OK"}
|
80
|
+
```
|
81
|
+
|
82
|
+
## Sending a message with attachments
|
83
|
+
|
84
|
+
You can add
|
85
|
+
[attachments](http://developer.postmarkapp.com/developer-build.html#attachments)
|
86
|
+
to your messages. Keep in mind message size limit (contents and attachment) is currently 10 MB.
|
87
|
+
|
88
|
+
``` ruby
|
89
|
+
client.deliver(from: 'leonard@bigbangtheory.com',
|
90
|
+
to: 'Dr. Sheldon Cooper <sheldon@bigbangtheory.com>',
|
91
|
+
subject: 'Have you seen these pictures of yours?',
|
92
|
+
text_body: 'You look like a real geek!',
|
93
|
+
attachments: [File.open('1.jpeg'),
|
94
|
+
{name: 'sheldon.jpeg',
|
95
|
+
content: [File.read('2.jpeg')].pack('m'),
|
96
|
+
content_type: 'image/jpeg'}])
|
97
|
+
# => {:to=>"Dr. Sheldon Cooper <sheldon@bigbangtheory.com>", :submitted_at=>"2013-05-09T02:56:12.2828813-04:00", :message_id=>"8ec0d283-8b93-xxxx-9d65-241d1777cf0f", :error_code=>0, :message=>"OK"}
|
98
|
+
```
|
99
|
+
|
100
|
+
## Sending a multipart message
|
101
|
+
|
102
|
+
``` ruby
|
103
|
+
client.deliver(from: 'sheldon@bigbangtheory.com',
|
104
|
+
to: 'Leonard Hofstadter <leonard@bigbangtheory.com>',
|
105
|
+
subject: 'Re: Anything Can Happen Thursday',
|
106
|
+
text_body: 'Apparently the news didn\'t reach my digestive ' \
|
107
|
+
'system, which when startled has it\'s own version ' \
|
108
|
+
'of "Anything Can Happen Thursday"',
|
109
|
+
html_body: '<p>Apparently the news didn’t reach my ' \
|
110
|
+
'digestive system, which when startled has ' \
|
111
|
+
'it’s own version of “Anything Can '\
|
112
|
+
'Happen Thursday”</p>')
|
113
|
+
# => {:to=>"Leonard Hofstadter <leonard@bigbangtheory.com>", :submitted_at=>"2013-05-09T02:58:00.089828-04:00", :message_id=>"bc973458-1315-xxxx-b295-6aa0a2b631ac", :error_code=>0, :message=>"OK"}
|
114
|
+
```
|
115
|
+
|
116
|
+
## Tagging messages
|
117
|
+
|
118
|
+
You can categorize outgoing email using the optional `:tag` property. If you use
|
119
|
+
different tags for the different types of emails your application generates,
|
120
|
+
you will be able to get detailed statistics for them through the Postmark user
|
121
|
+
interface.
|
122
|
+
|
123
|
+
``` ruby
|
124
|
+
client.deliver(from: 'sheldon@bigbangtheory.com',
|
125
|
+
to: 'Penny <penny@bigbangtheory.com>',
|
126
|
+
subject: 'Re: You cleaned my apartment???',
|
127
|
+
text_body: 'I couldn\'t sleep knowing that just outside my ' \
|
128
|
+
'bedroom is our living room and just outside our ' \
|
129
|
+
'living room is that hallway and immediately adjacent ' \
|
130
|
+
'to that hallway is this!',
|
131
|
+
tag: 'confidential')
|
132
|
+
|
133
|
+
# => {:to=>"Penny <penny@bigbangtheory.com>", :submitted_at=>"2013-05-09T03:00:55.4454938-04:00", :message_id=>"34aed4b3-3a95-xxxx-bd1d-88064909cc93", :error_code=>0, :message=>"OK"}
|
134
|
+
```
|
135
|
+
|
136
|
+
## Sending to multiple recipients
|
137
|
+
|
138
|
+
You can pass multiple recipient addresses in the `:to` field and the optional
|
139
|
+
`:cc` and `:bcc` fields. Note that Postmark has a limit of twenty recipients
|
140
|
+
per message in total. You need to take care not to exceed that limit.
|
141
|
+
Otherwise, you will get an error.
|
142
|
+
|
143
|
+
``` ruby
|
144
|
+
client.deliver(from: 'sheldon@bigbangtheory.com',
|
145
|
+
to: ['Leonard Hofstadter <leonard@bigbangtheory.com>',
|
146
|
+
'Penny <penny@bigbangtheory.com>'],
|
147
|
+
cc: ['Dr. Koothrappali <raj@bigbangtheory.com>'],
|
148
|
+
bcc: 'secretsheldonstorage@bigbangtheory.com',
|
149
|
+
subject: 'Re: Come on, Sheldon. It will be fun.',
|
150
|
+
text_body: 'That\'s what you said about the Green Lantern ' \
|
151
|
+
'movie. You were 114 minutes of wrong.')
|
152
|
+
# => {:to=>"Leonard Hofstadter <leonard@bigbangtheory.com>, Penny <penny@bigbangtheory.com>", :submitted_at=>"2013-05-09T05:04:16.3247488-04:00", :message_id=>"d647c5d6-xxxx-466d-9411-557dcd5c2297", :error_code=>0, :message=>"OK"}
|
153
|
+
```
|
154
|
+
|
155
|
+
## Sending in batches
|
156
|
+
|
157
|
+
While Postmark is focused on transactional email, we understand that developers
|
158
|
+
with higher volumes or processing time constraints need to send their messages
|
159
|
+
in batches. To facilitate this we provide a batching endpoint that permits you
|
160
|
+
to send up to 500 well-formed Postmark messages in a single API call.
|
161
|
+
|
162
|
+
``` ruby
|
163
|
+
messages = []
|
164
|
+
|
165
|
+
messages << {from: 'sheldon@bigbangtheory.com',
|
166
|
+
to: 'Leonard Hofstadter <leonard@bigbangtheory.com>',
|
167
|
+
subject: 'Re: Come on, Sheldon. It will be fun.',
|
168
|
+
text_body: 'That\'s what you said about the Green Lantern ' \
|
169
|
+
'movie. You were 114 minutes of wrong.'}
|
170
|
+
|
171
|
+
messages << {from: 'sheldon@bigbangtheory.com',
|
172
|
+
to: 'Penny <penny@bigbangtheory.com>',
|
173
|
+
subject: 'Re: You cleaned my apartment???',
|
174
|
+
text_body: 'I couldn\'t sleep knowing that just outside my ' \
|
175
|
+
'bedroom is our living room and just outside our ' \
|
176
|
+
'living room is that hallway and immediately ' \
|
177
|
+
'adjacent to that hallway is this!',
|
178
|
+
tag: 'confidential'}
|
179
|
+
|
180
|
+
client.deliver_in_batches(messages)
|
181
|
+
# => [{:to=>"Leonard Hofstadter <leonard@bigbangtheory.com>", :submitted_at=>"2013-05-09T05:19:16.3361118-04:00", :message_id=>"247e43a9-6b0d-4914-a87f-7b74bf76b5cb", :error_code=>0, :message=>"OK"}, {:to=>"Penny <penny@bigbangtheory.com>", :submitted_at=>"2013-05-09T05:19:16.3517099-04:00", :message_id=>"26467642-f169-4da8-87a8-b89154067dfb", :error_code=>0, :message=>"OK"}]
|
182
|
+
```
|
183
|
+
|
184
|
+
## Parsing inbound
|
185
|
+
|
186
|
+
Inbound processing allows you (or your users) to send emails to Postmark, which we then
|
187
|
+
process and deliver to you via a web hook in a nicely formatted JSON document.
|
188
|
+
|
189
|
+
Here is a simple Ruby/Sinatra application that does basic inbound processing.
|
190
|
+
|
191
|
+
``` ruby
|
192
|
+
logger = Logger.new(STDOUT)
|
193
|
+
|
194
|
+
class Comment
|
195
|
+
attr_accessor :attributes
|
196
|
+
|
197
|
+
def self.create_from_inbound_hook(message)
|
198
|
+
self.new(:text => message["TextBody"],
|
199
|
+
:user_email => message["From"],
|
200
|
+
:discussion_id => message["MailboxHash"])
|
201
|
+
end
|
202
|
+
|
203
|
+
def initialize(attributes={})
|
204
|
+
@attributes = attributes
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
post '/inbound' do
|
209
|
+
request.body.rewind
|
210
|
+
comment = Comment.create_from_inbound_hook(Postmark::Json.decode(request.body.read))
|
211
|
+
logger.info comment.inspect
|
212
|
+
end
|
213
|
+
```
|
214
|
+
|
215
|
+
If you don’t like that the fields of the Inbound JSON document are all in CamelCase, you
|
216
|
+
can use the `Postmark::Inbound.to_ruby_hash` method to give it some Ruby flavor.
|
217
|
+
|
218
|
+
```
|
219
|
+
postmark_hash = Postmark::Json.decode(request.body.read)
|
220
|
+
ruby_hash = Postmark::Inbound.to_ruby_hash(postmark_hash)
|
221
|
+
# => {:from=>"myUser@theirDomain.com", :from_full=>{:email=>"myUser@theirDomain.com", :name=>"John Doe"}, :to=>"451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com", :to_full=>[{:email=>"451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com", :name=>""}], :cc=>"\"Full name\" <sample.cc@emailDomain.com>, \"Another Cc\" <another.cc@emailDomain.com>", :cc_full=>[{:email=>"sample.cc@emailDomain.com", :name=>"Full name"}, {:email=>"another.cc@emailDomain.com", :name=>"Another Cc"}], :reply_to=>"myUsersReplyAddress@theirDomain.com", :subject=>"This is an inbound message", :message_id=>"22c74902-a0c1-4511-804f2-341342852c90", :date=>"Thu, 5 Apr 2012 16:59:01 +0200", :mailbox_hash=>"ahoy", :text_body=>"[ASCII]", :html_body=>"[HTML(encoded)]", :tag=>"", :headers=>[{:name=>"X-Spam-Checker-Version", :value=>"SpamAssassin 3.3.1 (2010-03-16) onrs-ord-pm-inbound1.wildbit.com"}, {:name=>"X-Spam-Status", :value=>"No"}, {:name=>"X-Spam-Score", :value=>"-0.1"}, {:name=>"X-Spam-Tests", :value=>"DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_PASS"}, {:name=>"Received-SPF", :value=>"Pass (sender SPF authorized) identity=mailfrom; client-ip=209.85.160.180; helo=mail-gy0-f180.google.com; envelope-from=myUser@theirDomain.com; receiver=451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com"}, {:name=>"DKIM-Signature", :value=>"v=1; a=rsa-sha256; c=relaxed/relaxed; d=wildbit.com; s=google; h=mime-version:reply-to:date:message-id:subject:from:to:cc :content-type; bh=cYr/+oQiklaYbBJOQU3CdAnyhCTuvemrU36WT7cPNt0=; b=QsegXXbTbC4CMirl7A3VjDHyXbEsbCUTPL5vEHa7hNkkUTxXOK+dQA0JwgBHq5C+1u iuAJMz+SNBoTqEDqte2ckDvG2SeFR+Edip10p80TFGLp5RucaYvkwJTyuwsA7xd78NKT Q9ou6L1hgy/MbKChnp2kxHOtYNOrrszY3JfQM="}, {:name=>"MIME-Version", :value=>"1.0"}, {:name=>"Message-ID", :value=>"<CAGXpo2WKfxHWZ5UFYCR3H_J9SNMG+5AXUovfEFL6DjWBJSyZaA@mail.gmail.com>"}], :attachments=>[{:name=>"myimage.png", :content=>"[BASE64-ENCODED CONTENT]", :content_type=>"image/png", :content_length=>4096}, {:name=>"mypaper.doc", :content=>"[BASE64-ENCODED CONTENT]", :content_type=>"application/msword", :content_length=>16384}]}
|
222
|
+
```
|
223
|
+
|
224
|
+
## Working with bounces
|
225
|
+
|
226
|
+
Use `#get_bounces` to retrieve a list of bounces (use `:count` and `:offset`
|
227
|
+
parameters to control pagination).
|
228
|
+
|
229
|
+
``` ruby
|
230
|
+
client.get_bounces(count: 1, offset: 0)
|
231
|
+
# => [{:id=>654714902, :type=>"Transient", :type_code=>2, :name=>"Message delayed", :message_id=>"1fdf3729-xxxx-4d5c-8a7b-96da7a23268b", :description=>"The server could not temporarily deliver your message (ex: Message is delayed due to network troubles).", :details=>"action: failed\r\n", :email=>"tema@wildbit.org", :bounced_at=>"2013-04-10T01:01:35.0965184-04:00", :dump_available=>true, :inactive=>false, :can_activate=>true, :subject=>"bounce test"}]
|
232
|
+
```
|
233
|
+
|
234
|
+
Use `#get_bounced_tags` to retrieve a list of tags used for bounced emails.
|
235
|
+
|
236
|
+
``` ruby
|
237
|
+
client.get_bounced_tags
|
238
|
+
# => ["confidential"]
|
239
|
+
```
|
240
|
+
|
241
|
+
Use `#get_bounce` to get info for a specific bounce using ID:
|
242
|
+
|
243
|
+
``` ruby
|
244
|
+
client.get_bounce(654714902)
|
245
|
+
# => {:id=>654714902, :type=>"Transient", :type_code=>2, :name=>"Message delayed", :message_id=>"1fdf3729-xxxx-xxxx-8a7b-96da7a23268b", :description=>"The server could not temporarily deliver your message (ex: Message is delayed due to network troubles).", :details=>"action: failed\r\n", :email=>"tema@wildbit.com", :bounced_at=>"2013-04-10T01:01:35.0965184-04:00", :dump_available=>true, :inactive=>false, :can_activate=>true, :subject=>"bounce test", :content=>"..."}
|
246
|
+
```
|
247
|
+
|
248
|
+
Use `#dump_bounce` to get the full bounce body:
|
249
|
+
|
250
|
+
``` ruby
|
251
|
+
client.dump_bounce(654714902)
|
252
|
+
# => {:body=>"Return-Path: <>\r\nReceived: from m1.mtasv.net (74.205.19.136) by sc-ord-mail2.mtasv.net id hcjov61jk5ko for <pm_bounces@pm.mtasv.net>; Wed, 10 Apr 2013 01:00:35 -0400 (envelope-from <>)\r\nDate: Wed, 10 Apr 2013 01:00:48 -0400\r\nFrom: postmaster@m1.mtasv.net\r\n..."}
|
253
|
+
```
|
38
254
|
|
39
|
-
|
255
|
+
You can activate email addresses that were disabled due to a hard bounce by using `#activate_bounce`:
|
256
|
+
|
257
|
+
``` ruby
|
258
|
+
client.activate_bounce(654714902)
|
259
|
+
# => {:id=>654714902, :type=>"Transient", :type_code=>2, :name=>"Message delayed", :message_id=>"1fdf3729-xxxx-xxxx-xxxx-96da7a23268b", :description=>"The server could not temporarily deliver your message (ex: Message is delayed due to network troubles).", :details=>"action: failed\r\n", :email=>"tema@wildbit.com", :bounced_at=>"2013-04-10T01:01:35.0965184-04:00", :dump_available=>true, :inactive=>false, :can_activate=>true, :subject=>"bounce test"}
|
260
|
+
```
|
261
|
+
|
262
|
+
## Getting delivery stats
|
263
|
+
|
264
|
+
Currently delivery stats only include a summary of inactive emails and bounces
|
265
|
+
by type.
|
266
|
+
|
267
|
+
``` ruby
|
268
|
+
stats = client.delivery_stats
|
269
|
+
# => {:inactive_mails=>1, :bounces=>[{:name=>"All", :count=>3}, {:type=>"HardBounce", :name=>"Hard bounce", :count=>2}, {:type=>"Transient", :name=>"Message delayed", :count=>1}]}
|
270
|
+
```
|
271
|
+
|
272
|
+
## Server Info
|
273
|
+
|
274
|
+
The gem also allows you to read and update the server info:
|
275
|
+
|
276
|
+
``` ruby
|
277
|
+
client.server_info
|
278
|
+
# => {:name=>"Testing", :color=>"blue", :bounce_hook_url=>"", :inbound_hash=>"c2ffffff74f8643e5f6086c81", :inbound_hook_url=>"", :smtp_api_activated=>true}
|
279
|
+
```
|
280
|
+
|
281
|
+
For example, you can use `#update_server_info` to set inbound hook URL:
|
282
|
+
|
283
|
+
``` ruby
|
284
|
+
client.update_server_info inbound_hook_url: 'http://example.org/bounces'
|
285
|
+
```
|
286
|
+
|
287
|
+
# Using Postmark with the [Mail](http://rubygems.org/gems/mail) library
|
288
|
+
|
289
|
+
You can use Postmark with the `mail` gem.
|
290
|
+
|
291
|
+
``` bash
|
292
|
+
gem install mail
|
293
|
+
```
|
294
|
+
|
295
|
+
Make sure you have a [sender signature](https://postmarkapp.com/signatures) for
|
296
|
+
every `From` email address you specify.
|
297
|
+
|
298
|
+
To send a `Mail::Message` via Postmark you’ll need to specify `Mail::Postmark` as
|
299
|
+
a delivery method for the message:
|
300
|
+
|
301
|
+
``` ruby
|
302
|
+
message = Mail.new do
|
303
|
+
# ...
|
304
|
+
delivery_method Mail::Postmark, api_key: 'your-postmark-api-key', secure: true
|
305
|
+
end
|
306
|
+
```
|
307
|
+
|
308
|
+
Delivery method accepts all options supported by `Postmark::ApiClient`
|
309
|
+
documented above. A new instance of `Postmark::ApiClient` is created every time
|
310
|
+
you deliver a message to preserve thread safety.
|
311
|
+
|
312
|
+
## Plain text message
|
40
313
|
|
41
314
|
``` ruby
|
42
315
|
require 'rubygems'
|
@@ -58,7 +331,7 @@ message.deliver
|
|
58
331
|
# => #<Mail::Message:70355890541720, Multipart: false, Headers: <From: sheldon@bigbangtheory.com>, <To: leonard@bigbangtheory.com>, <Message-ID: e439fec0-4c89-475b-b3fc-eb446249a051>, <Subject: Re: Come on, Sheldon. It will be fun.>>
|
59
332
|
```
|
60
333
|
|
61
|
-
|
334
|
+
## HTML message
|
62
335
|
|
63
336
|
``` ruby
|
64
337
|
require 'rubygems'
|
@@ -82,7 +355,7 @@ message.deliver
|
|
82
355
|
# => #<Mail::Message:70355902117460, Multipart: false, Headers: <From: sheldon@bigbangtheory.com>, <To: leonard@bigbangtheory.com>, <Message-ID: 3a9370a2-6c24-4304-a03c-320a54cc59f7>, <Subject: Re: What, to you, is a large crowd?>, <Content-Type: text/html; charset=UTF-8>>
|
83
356
|
```
|
84
357
|
|
85
|
-
|
358
|
+
## Message with attachments
|
86
359
|
|
87
360
|
``` ruby
|
88
361
|
message = Mail.new do
|
@@ -98,12 +371,12 @@ end
|
|
98
371
|
message.attachments['sheldon.jpeg'] = File.read('2.jpeg')
|
99
372
|
|
100
373
|
message.deliver
|
101
|
-
# => #<Mail::Message:70185826686240, Multipart: true, Headers: <From: leonard@bigbangtheory.com>, <To: sheldon@bigbangtheory.com>, <Message-ID: ba644cc1-b5b1-4bcb-aaf8-2f290b5aad80>, <Subject: Have you seen these pictures of yours?>, <Content-Type: multipart/mixed; boundary=--==_mimepart_5121f9f1ec653_12c53fd569035ad817726>>
|
374
|
+
# => #<Mail::Message:70185826686240, Multipart: true, Headers: <From: leonard@bigbangtheory.com>, <To: sheldon@bigbangtheory.com>, <Message-ID: ba644cc1-b5b1-4bcb-aaf8-2f290b5aad80>, <Subject: Have you seen these pictures of yours?>, <Content-Type: multipart/mixed; boundary=--==_mimepart_5121f9f1ec653_12c53fd569035ad817726>>
|
102
375
|
```
|
103
376
|
|
104
|
-
|
377
|
+
## Multipart message
|
105
378
|
|
106
|
-
You can send multipart messages containing both text and HTML using Postmark gem.
|
379
|
+
You can send multipart messages containing both text and HTML using the Postmark gem.
|
107
380
|
|
108
381
|
``` ruby
|
109
382
|
require 'rubygems'
|
@@ -135,7 +408,7 @@ message.deliver
|
|
135
408
|
# => #<Mail::Message:70355901588620, Multipart: true, Headers: <From: sheldon@bigbangtheory.com>, <To: leonard@bigbangtheory.com>, <Message-ID: cadba131-f6d6-4cfc-9892-16ee738ba54c>, <Subject: Re: Anything Can Happen Thursday>, <Content-Type: multipart/alternative; boundary=--==_mimepart_50ef7a6234a69_a4c73ffd01035adc207b8>>
|
136
409
|
```
|
137
410
|
|
138
|
-
|
411
|
+
## Tagged message
|
139
412
|
|
140
413
|
Postmark also lets you tag your messages.
|
141
414
|
|
@@ -152,85 +425,85 @@ message = Mail.new do
|
|
152
425
|
body 'I couldn\'t sleep knowing that just outside my bedroom is ' \
|
153
426
|
'our living room and just outside our living room is that ' \
|
154
427
|
'hallway and immediately adjacent to that hallway is this!'
|
428
|
+
tag 'confidential'
|
155
429
|
|
156
430
|
delivery_method Mail::Postmark, :api_key => 'your-postmark-api-key'
|
157
431
|
end
|
158
432
|
|
159
|
-
message.tag = 'confidential'
|
160
|
-
|
161
433
|
message.deliver
|
162
434
|
# => #<Mail::Message:70168327829580, Multipart: false, Headers: <From: sheldon@bigbangtheory.com>, <To: penny@bigbangtheory.com>, <Message-ID: af2570fd-3481-4b45-8b27-a249806d891a>, <Subject: Re: You cleaned my apartment???>, <TAG: confidential>>
|
163
435
|
```
|
164
436
|
|
165
|
-
|
437
|
+
## Sending in batches
|
166
438
|
|
167
|
-
You
|
168
|
-
|
169
|
-
[use to retrieve bounces](http://blog.postmarkapp.com/post/24970994681/using-messageid-to-retrieve-bounces)
|
170
|
-
later. This example shows you how to access Message-ID of a sent email message.
|
439
|
+
You can also send `Mail::Message` objects in batches. Create an instance of
|
440
|
+
`Postmark::ApiClient` as described in "Communicating with the API" section.
|
171
441
|
|
172
442
|
``` ruby
|
173
|
-
|
174
|
-
# ...
|
175
|
-
message.deliver
|
443
|
+
messages = []
|
176
444
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
445
|
+
messages << Mail.new do
|
446
|
+
from 'sheldon@bigbangtheory.com'
|
447
|
+
to 'Leonard Hofstadter <leonard@bigbangtheory.com>'
|
448
|
+
subject 'Re: Come on, Sheldon. It will be fun.'
|
449
|
+
body 'That\'s what you said about the Green Lantern movie. You' \
|
450
|
+
'were 114 minutes of wrong.'
|
451
|
+
end
|
182
452
|
|
183
|
-
|
453
|
+
messages << Mail.new do
|
454
|
+
from 'sheldon@bigbangtheory.com'
|
455
|
+
to 'Penny <penny@bigbangtheory.com>'
|
456
|
+
subject 'Re: You cleaned my apartment???'
|
457
|
+
body 'I couldn\'t sleep knowing that just outside my bedroom is ' \
|
458
|
+
'our living room and just outside our living room is that ' \
|
459
|
+
'hallway and immediately adjacent to that hallway is this!'
|
460
|
+
tag 'confidential'
|
461
|
+
end
|
184
462
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
library for all your new projects.
|
463
|
+
client.deliver_messages(messages)
|
464
|
+
# => [{:to=>"leonard@bigbangtheory.com", :submitted_at=>"2013-05-10T01:59:29.830486-04:00", :message_id=>"8ad0e8b0-xxxx-xxxx-951d-223c581bb467", :error_code=>0, :message=>"OK"}, {:to=>"penny@bigbangtheory.com", :submitted_at=>"2013-05-10T01:59:29.830486-04:00", :message_id=>"33c6240c-xxxx-xxxx-b0df-40bdfcf4e0f7", :error_code=>0, :message=>"OK"}]
|
465
|
+
```
|
189
466
|
|
190
|
-
|
191
|
-
every From email you specify. From can also accept array of addresses.
|
467
|
+
After delivering a batch you can check on each message’s delivery status:
|
192
468
|
|
193
469
|
``` ruby
|
194
|
-
|
195
|
-
|
196
|
-
require 'tmail'
|
197
|
-
require 'json'
|
470
|
+
messages.first.delivered?
|
471
|
+
# => true
|
198
472
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
message.from = "leonard@bigbangtheory.com"
|
203
|
-
message.to = "Sheldon Cooper <sheldon@bigbangtheory.com>"
|
204
|
-
message.subject = "Hi Sheldon!"
|
205
|
-
message.content_type = "text/html"
|
206
|
-
message.body = "Hello my friend!"
|
473
|
+
messages.all?(&:delivered)
|
474
|
+
# => true
|
475
|
+
```
|
207
476
|
|
208
|
-
|
209
|
-
message["CUSTOM-HEADER"] = "my custom header value"
|
477
|
+
Or even get a related Postmark response:
|
210
478
|
|
211
|
-
|
212
|
-
|
479
|
+
``` ruby
|
480
|
+
messages.first.postmark_response
|
481
|
+
# => {"To"=>"leonard@bigbangtheory.com", "SubmittedAt"=>"2013-05-10T01:59:29.830486-04:00", "MessageID"=>"8ad0e8b0-xxxx-xxxx-951d-223c581bb467", "ErrorCode"=>0, "Message"=>"OK"}
|
482
|
+
```
|
213
483
|
|
214
|
-
|
215
|
-
message.postmark_attachments = [File.open("/path"), File.open("/path")]
|
484
|
+
## Accessing Postmark Message-ID
|
216
485
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
"ContentType" => "application/pdf"
|
222
|
-
}]
|
486
|
+
You might want to save identifiers of messages you send. Postmark provides you
|
487
|
+
with a unique Message-ID, which you can
|
488
|
+
[use to retrieve bounces](http://blog.postmarkapp.com/post/24970994681/using-messageid-to-retrieve-bounces)
|
489
|
+
later. This example shows you how to access the Message-ID of a sent email message.
|
223
490
|
|
224
|
-
|
225
|
-
message
|
491
|
+
``` ruby
|
492
|
+
message = Mail.new
|
493
|
+
# ...
|
494
|
+
message.deliver
|
226
495
|
|
227
|
-
|
496
|
+
message['Message-ID']
|
497
|
+
# => cadba131-f6d6-4cfc-9892-16ee738ba54c
|
498
|
+
message.message_id
|
499
|
+
# => "cadba131-f6d6-4cfc-9892-16ee738ba54c"
|
228
500
|
```
|
229
501
|
|
230
|
-
|
502
|
+
# Exploring Other Gem Features
|
231
503
|
|
232
|
-
|
233
|
-
|
504
|
+
To provide an interface similar to ActiveRecord for bounces, the Postmark gem adds
|
505
|
+
`Postmark::Bounce` class. This class uses the shared `Postmark::ApiClient` instance
|
506
|
+
configured through the Postmark module.
|
234
507
|
|
235
508
|
``` ruby
|
236
509
|
require 'rubygems'
|
@@ -241,10 +514,6 @@ require 'json'
|
|
241
514
|
Postmark.response_parser_class = :Json
|
242
515
|
Postmark.api_key = 'your-postmark-api-key'
|
243
516
|
|
244
|
-
# Delivery stats
|
245
|
-
Postmark.delivery_stats
|
246
|
-
# => {"InactiveMails"=>1, "Bounces"=>[{"Name"=>"All", "Count"=>1}, {"Type"=>"HardBounce", "Name"=>"Hard bounce", "Count"=>1}]}
|
247
|
-
|
248
517
|
# Get bounces information: (array of bounce objects)
|
249
518
|
Postmark::Bounce.all
|
250
519
|
# => [#<Postmark::Bounce:0x007ff09c04ae18 @id=580516117, @email="sheldon@bigbangtheory.com", @bounced_at=2012-10-21 00:01:56 +0800, @type="HardBounce", @name=nil, @details="smtp;550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient's email address for typos or unnecessary spaces. Learn more at http://support.google.com/mail/bin/answer.py?answer=6596 c13si5382730vcw.23", @tag=nil, @dump_available=false, @inactive=true, @can_activate=true, @message_id="876d40fe-ab2a-4925-9d6f-8d5e4f4926f5", @subject="Re: What, to you, is a large crowd?">]
|
@@ -260,24 +529,15 @@ bounce.activate # reactivate hard bounce
|
|
260
529
|
# => #<Postmark::Bounce:0x007ff09c04ae18 @id=580516117, @email="sheldon@bigbangtheory.com", @bounced_at=2012-10-21 00:01:56 +0800, @type="HardBounce", @name=nil, @details="smtp;550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient's email address for typos or unnecessary spaces. Learn more at http://support.google.com/mail/bin/answer.py?answer=6596 c13si5382730vcw.23", @tag=nil, @dump_available=false, @inactive=true, @can_activate=true, @message_id="876d40fe-ab2a-4925-9d6f-8d5e4f4926f5", @subject="Re: What, to you, is a large crowd?">
|
261
530
|
```
|
262
531
|
|
263
|
-
## Security
|
264
|
-
|
265
|
-
To use SSL encryption when sending email configure the library as follows:
|
266
|
-
|
267
|
-
``` ruby
|
268
|
-
Postmark.secure = true
|
269
|
-
```
|
270
|
-
|
271
532
|
## Requirements
|
272
533
|
|
273
|
-
|
274
|
-
|
275
|
-
If you plan using it in a rails project, check out the
|
534
|
+
You will need a Postmark account, server and sender signature set up to use it.
|
535
|
+
If you plan using it in a Rails project, check out the
|
276
536
|
[postmark-rails](https://github.com/wildbit/postmark-rails/) gem, which
|
277
537
|
is meant to integrate with ActionMailer.
|
278
538
|
|
279
539
|
The plugin will try to use ActiveSupport Json if it is already included. If not,
|
280
|
-
it will attempt using the built-in
|
540
|
+
it will attempt using the built-in Ruby Json library.
|
281
541
|
|
282
542
|
You can also explicitly specify which one to be used, using
|
283
543
|
|