postmark 0.9.19 → 1.0.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.
- 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
|
+
[](https://travis-ci.org/wildbit/postmark-gem) [](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
|
|