postmark 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +4 -0
- data/README.md +20 -0
- data/VERSION +1 -1
- data/lib/postmark/api_client.rb +57 -1
- data/lib/postmark/version.rb +1 -1
- data/spec/unit/postmark/api_client_spec.rb +256 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17d7c0c5ea350fd8902efaa8e8334dff894fe215
|
4
|
+
data.tar.gz: 17f7871d1544d69b7cf16d75c4ba260048de182c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38df57ae61ce36c80870832444d017083e1bff043901823eb675384ae25df1366f420170abf41059a7601d7a6a2c7e26866a15abf8c5b98fa7fa30b7d8cbeeb8
|
7
|
+
data.tar.gz: 4dcacb79aec065cf65445da357f0b3e275911da17881291124dacd70b0bccacb1a3d69b4779f34f010692b7667710a0e0b6c8214a00af557b65d86746fc0a499
|
data/CHANGELOG.rdoc
CHANGED
data/README.md
CHANGED
@@ -160,6 +160,22 @@ client.deliver(from: 'sheldon@bigbangtheory.com',
|
|
160
160
|
# => {: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"}
|
161
161
|
```
|
162
162
|
|
163
|
+
## Sending a templated email
|
164
|
+
|
165
|
+
If you have a [template created](https://github.com/wildbit/postmark-gem/wiki/The-Templates-API-support) in Postmark you can send an email using that template.
|
166
|
+
|
167
|
+
``` ruby
|
168
|
+
client.deliver_with_template(from: 'sheldon@bigbangtheory.com',
|
169
|
+
to: 'Penny <penny@bigbangtheory.com>',
|
170
|
+
template_id: 123,
|
171
|
+
template_model: {
|
172
|
+
name: 'Penny',
|
173
|
+
message: 'Bazinga!'
|
174
|
+
})
|
175
|
+
|
176
|
+
# => {: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"}
|
177
|
+
```
|
178
|
+
|
163
179
|
## Sending in batches
|
164
180
|
|
165
181
|
While Postmark is focused on transactional email, we understand that developers
|
@@ -544,6 +560,10 @@ Postmark allows you to automatically scale your sending infrastructure with the
|
|
544
560
|
|
545
561
|
If you ever need to access your messages or their metadata (i.e. open tracking info), [the Messages API](https://github.com/wildbit/postmark-gem/wiki/The-Messages-API-support) is a great place to start.
|
546
562
|
|
563
|
+
## The Templates API Support
|
564
|
+
|
565
|
+
[The Templates API](https://github.com/wildbit/postmark-gem/wiki/The-Templates-API-support) can be used to fully manage your templates.
|
566
|
+
|
547
567
|
## ActiveModel-like Interface For Bounces
|
548
568
|
|
549
569
|
To provide an interface similar to ActiveModel for bounces, the Postmark gem adds
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0
|
data/lib/postmark/api_client.rb
CHANGED
@@ -165,6 +165,62 @@ module Postmark
|
|
165
165
|
format_response http_client.put("server", serialize(data))
|
166
166
|
end
|
167
167
|
|
168
|
+
def get_templates(options = {})
|
169
|
+
load_batch('templates', 'Templates', options)
|
170
|
+
end
|
171
|
+
|
172
|
+
def templates(options = {})
|
173
|
+
find_each('templates', 'Templates', options)
|
174
|
+
end
|
175
|
+
|
176
|
+
def get_template(id)
|
177
|
+
format_response http_client.get("templates/#{id}")
|
178
|
+
end
|
179
|
+
|
180
|
+
def create_template(attributes = {})
|
181
|
+
data = serialize(HashHelper.to_postmark(attributes))
|
182
|
+
|
183
|
+
format_response http_client.post('templates', data)
|
184
|
+
end
|
185
|
+
|
186
|
+
def update_template(id, attributes = {})
|
187
|
+
data = serialize(HashHelper.to_postmark(attributes))
|
188
|
+
|
189
|
+
format_response http_client.put("templates/#{id}", data)
|
190
|
+
end
|
191
|
+
|
192
|
+
def delete_template(id)
|
193
|
+
format_response http_client.delete("templates/#{id}")
|
194
|
+
end
|
195
|
+
|
196
|
+
def validate_template(attributes = {})
|
197
|
+
data = serialize(HashHelper.to_postmark(attributes))
|
198
|
+
response = format_response(http_client.post('templates/validate', data))
|
199
|
+
|
200
|
+
response.each do |k, v|
|
201
|
+
next unless v.is_a?(Hash) && k != :suggested_template_model
|
202
|
+
|
203
|
+
response[k] = HashHelper.to_ruby(v)
|
204
|
+
|
205
|
+
if response[k].has_key?(:validation_errors)
|
206
|
+
ruby_hashes = response[k][:validation_errors].map do |err|
|
207
|
+
HashHelper.to_ruby(err)
|
208
|
+
end
|
209
|
+
response[k][:validation_errors] = ruby_hashes
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
response
|
214
|
+
end
|
215
|
+
|
216
|
+
def deliver_with_template(attributes = {})
|
217
|
+
data = serialize(MessageHelper.to_postmark(attributes))
|
218
|
+
|
219
|
+
with_retries do
|
220
|
+
format_response http_client.post('email/withTemplate', data)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
168
224
|
protected
|
169
225
|
|
170
226
|
def in_batches(messages)
|
@@ -195,4 +251,4 @@ module Postmark
|
|
195
251
|
end
|
196
252
|
|
197
253
|
end
|
198
|
-
end
|
254
|
+
end
|
data/lib/postmark/version.rb
CHANGED
@@ -572,4 +572,259 @@ describe Postmark::ApiClient do
|
|
572
572
|
end
|
573
573
|
end
|
574
574
|
|
575
|
-
|
575
|
+
describe '#get_templates' do
|
576
|
+
let(:http_client) { subject.http_client }
|
577
|
+
let(:response) do
|
578
|
+
{
|
579
|
+
'TotalCount' => 31,
|
580
|
+
'Templates' => [
|
581
|
+
{
|
582
|
+
'Active' => true,
|
583
|
+
'TemplateId' => 123,
|
584
|
+
'Name' => 'ABC'
|
585
|
+
},
|
586
|
+
{
|
587
|
+
'Active' => true,
|
588
|
+
'TemplateId' => 456,
|
589
|
+
'Name' => 'DEF'
|
590
|
+
}
|
591
|
+
]
|
592
|
+
}
|
593
|
+
end
|
594
|
+
|
595
|
+
it 'gets templates info and converts it to ruby format' do
|
596
|
+
http_client.should_receive(:get).with('templates', :offset => 0, :count => 2).and_return(response)
|
597
|
+
|
598
|
+
count, templates = subject.get_templates(:count => 2)
|
599
|
+
|
600
|
+
expect(count).to eq(31)
|
601
|
+
expect(templates.first[:template_id]).to eq(123)
|
602
|
+
expect(templates.first[:name]).to eq('ABC')
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
describe '#templates' do
|
607
|
+
it 'returns an Enumerator' do
|
608
|
+
expect(subject.templates).to be_kind_of(Enumerable)
|
609
|
+
end
|
610
|
+
|
611
|
+
it 'requests data at /templates' do
|
612
|
+
allow(subject.http_client).to receive(:get).
|
613
|
+
with('templates', an_instance_of(Hash)).
|
614
|
+
and_return('TotalCount' => 1, 'Templates' => [{}])
|
615
|
+
expect(subject.templates.first(5).count).to eq(1)
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
describe '#get_template' do
|
620
|
+
let(:http_client) { subject.http_client }
|
621
|
+
let(:response) do
|
622
|
+
{
|
623
|
+
'Name' => 'Template Name',
|
624
|
+
'TemplateId' => 123,
|
625
|
+
'Subject' => 'Subject',
|
626
|
+
'HtmlBody' => 'Html',
|
627
|
+
'TextBody' => 'Text',
|
628
|
+
'AssociatedServerId' => 456,
|
629
|
+
'Active' => true
|
630
|
+
}
|
631
|
+
end
|
632
|
+
|
633
|
+
it 'gets single template and converts it to ruby format' do
|
634
|
+
http_client.should_receive(:get).with('templates/123').and_return(response)
|
635
|
+
|
636
|
+
template = subject.get_template('123')
|
637
|
+
|
638
|
+
expect(template[:name]).to eq('Template Name')
|
639
|
+
expect(template[:template_id]).to eq(123)
|
640
|
+
expect(template[:html_body]).to eq('Html')
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
describe '#create_template' do
|
645
|
+
let(:http_client) { subject.http_client }
|
646
|
+
let(:response) do
|
647
|
+
{
|
648
|
+
'TemplateId' => 123,
|
649
|
+
'Name' => 'template name',
|
650
|
+
'Active' => true
|
651
|
+
}
|
652
|
+
end
|
653
|
+
|
654
|
+
it 'performs a POST request to /templates with the given attributes' do
|
655
|
+
expected_json = { 'Name' => 'template name' }.to_json
|
656
|
+
|
657
|
+
http_client.should_receive(:post).with('templates', expected_json).and_return(response)
|
658
|
+
|
659
|
+
template = subject.create_template(:name => 'template name')
|
660
|
+
|
661
|
+
expect(template[:name]).to eq('template name')
|
662
|
+
expect(template[:template_id]).to eq(123)
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
describe '#update_template' do
|
667
|
+
let(:http_client) { subject.http_client }
|
668
|
+
let(:response) do
|
669
|
+
{
|
670
|
+
'TemplateId' => 123,
|
671
|
+
'Name' => 'template name',
|
672
|
+
'Active' => true
|
673
|
+
}
|
674
|
+
end
|
675
|
+
|
676
|
+
it 'performs a PUT request to /templates with the given attributes' do
|
677
|
+
expected_json = { 'Name' => 'template name' }.to_json
|
678
|
+
|
679
|
+
http_client.should_receive(:put).with('templates/123', expected_json).and_return(response)
|
680
|
+
|
681
|
+
template = subject.update_template(123, :name => 'template name')
|
682
|
+
|
683
|
+
expect(template[:name]).to eq('template name')
|
684
|
+
expect(template[:template_id]).to eq(123)
|
685
|
+
end
|
686
|
+
end
|
687
|
+
|
688
|
+
describe '#delete_template' do
|
689
|
+
let(:http_client) { subject.http_client }
|
690
|
+
let(:response) do
|
691
|
+
{
|
692
|
+
'ErrorCode' => 0,
|
693
|
+
'Message' => 'Template 123 removed.'
|
694
|
+
}
|
695
|
+
end
|
696
|
+
|
697
|
+
it 'performs a DELETE request to /templates/:id' do
|
698
|
+
http_client.should_receive(:delete).with('templates/123').and_return(response)
|
699
|
+
|
700
|
+
resp = subject.delete_template(123)
|
701
|
+
|
702
|
+
expect(resp[:error_code]).to eq(0)
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
describe '#validate_template' do
|
707
|
+
let(:http_client) { subject.http_client }
|
708
|
+
|
709
|
+
context 'when template is valid' do
|
710
|
+
let(:response) do
|
711
|
+
{
|
712
|
+
'AllContentIsValid' => true,
|
713
|
+
'HtmlBody' => {
|
714
|
+
'ContentIsValid' => true,
|
715
|
+
'ValidationErrors' => [],
|
716
|
+
'RenderedContent' => '<html><head></head><body>MyName_Value</body></html>'
|
717
|
+
},
|
718
|
+
'TextBody' => {
|
719
|
+
'ContentIsValid' => true,
|
720
|
+
'ValidationErrors' => [],
|
721
|
+
'RenderedContent' => 'MyName_Value'
|
722
|
+
},
|
723
|
+
'Subject' => {
|
724
|
+
'ContentIsValid' => true,
|
725
|
+
'ValidationErrors' => [],
|
726
|
+
'RenderedContent' => 'MyName_Value'
|
727
|
+
},
|
728
|
+
'SuggestedTemplateModel' => {
|
729
|
+
'MyName' => 'MyName_Value'
|
730
|
+
}
|
731
|
+
}
|
732
|
+
end
|
733
|
+
|
734
|
+
it 'performs a POST request and returns unmodified suggested template model' do
|
735
|
+
expected_template_json = {
|
736
|
+
'HtmlBody' => '{{MyName}}',
|
737
|
+
'TextBody' => '{{MyName}}',
|
738
|
+
'Subject' => '{{MyName}}'
|
739
|
+
}.to_json
|
740
|
+
|
741
|
+
http_client.should_receive(:post).with('templates/validate', expected_template_json).and_return(response)
|
742
|
+
|
743
|
+
resp = subject.validate_template(:html_body => '{{MyName}}',
|
744
|
+
:text_body => '{{MyName}}',
|
745
|
+
:subject => '{{MyName}}')
|
746
|
+
|
747
|
+
expect(resp[:all_content_is_valid]).to be_true
|
748
|
+
expect(resp[:html_body][:content_is_valid]).to be_true
|
749
|
+
expect(resp[:html_body][:validation_errors]).to be_empty
|
750
|
+
expect(resp[:suggested_template_model]['MyName']).to eq('MyName_Value')
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
context 'when template is invalid' do
|
755
|
+
let(:response) do
|
756
|
+
{
|
757
|
+
'AllContentIsValid' => false,
|
758
|
+
'HtmlBody' => {
|
759
|
+
'ContentIsValid' => false,
|
760
|
+
'ValidationErrors' => [
|
761
|
+
{
|
762
|
+
'Message' => 'The \'each\' block being opened requires a model path to be specified in the form \'{#each <name>}\'.',
|
763
|
+
'Line' => 1,
|
764
|
+
'CharacterPosition' => 1
|
765
|
+
}
|
766
|
+
],
|
767
|
+
'RenderedContent' => nil
|
768
|
+
},
|
769
|
+
'TextBody' => {
|
770
|
+
'ContentIsValid' => true,
|
771
|
+
'ValidationErrors' => [],
|
772
|
+
'RenderedContent' => 'MyName_Value'
|
773
|
+
},
|
774
|
+
'Subject' => {
|
775
|
+
'ContentIsValid' => true,
|
776
|
+
'ValidationErrors' => [],
|
777
|
+
'RenderedContent' => 'MyName_Value'
|
778
|
+
},
|
779
|
+
'SuggestedTemplateModel' => nil
|
780
|
+
}
|
781
|
+
end
|
782
|
+
|
783
|
+
it 'performs a POST request and returns validation errors' do
|
784
|
+
expected_template_json = {
|
785
|
+
'HtmlBody' => '{{#each}}',
|
786
|
+
'TextBody' => '{{MyName}}',
|
787
|
+
'Subject' => '{{MyName}}'
|
788
|
+
}.to_json
|
789
|
+
|
790
|
+
http_client.should_receive(:post).with('templates/validate', expected_template_json).and_return(response)
|
791
|
+
|
792
|
+
resp = subject.validate_template(:html_body => '{{#each}}',
|
793
|
+
:text_body => '{{MyName}}',
|
794
|
+
:subject => '{{MyName}}')
|
795
|
+
|
796
|
+
expect(resp[:all_content_is_valid]).to be_false
|
797
|
+
expect(resp[:text_body][:content_is_valid]).to be_true
|
798
|
+
expect(resp[:html_body][:content_is_valid]).to be_false
|
799
|
+
expect(resp[:html_body][:validation_errors].first[:character_position]).to eq(1)
|
800
|
+
expect(resp[:html_body][:validation_errors].first[:message]).to eq('The \'each\' block being opened requires a model path to be specified in the form \'{#each <name>}\'.')
|
801
|
+
end
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
describe "#deliver_with_template" do
|
806
|
+
let(:email) { Postmark::MessageHelper.to_postmark(message_hash) }
|
807
|
+
let(:email_json) { Postmark::Json.encode(email) }
|
808
|
+
let(:http_client) { subject.http_client }
|
809
|
+
let(:response) { {"MessageID" => 42} }
|
810
|
+
|
811
|
+
it 'converts message hash to Postmark format and posts it to /email/withTemplate' do
|
812
|
+
http_client.should_receive(:post).with('email/withTemplate', email_json) { response }
|
813
|
+
subject.deliver_with_template(message_hash)
|
814
|
+
end
|
815
|
+
|
816
|
+
it 'retries 3 times' do
|
817
|
+
2.times do
|
818
|
+
http_client.should_receive(:post).and_raise(Postmark::InternalServerError)
|
819
|
+
end
|
820
|
+
http_client.should_receive(:post) { response }
|
821
|
+
expect { subject.deliver_with_template(message_hash) }.not_to raise_error
|
822
|
+
end
|
823
|
+
|
824
|
+
it 'converts response to ruby format' do
|
825
|
+
http_client.should_receive(:post).with('email/withTemplate', email_json) { response }
|
826
|
+
r = subject.deliver_with_template(message_hash)
|
827
|
+
r.should have_key(:message_id)
|
828
|
+
end
|
829
|
+
end
|
830
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postmark
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Petyo Ivanov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-08-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
141
|
version: 1.3.7
|
142
142
|
requirements: []
|
143
143
|
rubyforge_project:
|
144
|
-
rubygems_version: 2.
|
144
|
+
rubygems_version: 2.4.5
|
145
145
|
signing_key:
|
146
146
|
specification_version: 4
|
147
147
|
summary: Official Postmark API wrapper.
|