postmark 1.8.1 → 1.21.3

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 (49) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +8 -5
  4. data/CHANGELOG.rdoc +86 -0
  5. data/CONTRIBUTING.md +18 -0
  6. data/Gemfile +6 -5
  7. data/LICENSE +1 -1
  8. data/README.md +34 -607
  9. data/RELEASE.md +12 -0
  10. data/VERSION +1 -1
  11. data/gemfiles/Gemfile.legacy +5 -4
  12. data/lib/postmark.rb +1 -18
  13. data/lib/postmark/account_api_client.rb +55 -1
  14. data/lib/postmark/api_client.rb +145 -17
  15. data/lib/postmark/bounce.rb +0 -4
  16. data/lib/postmark/client.rb +12 -4
  17. data/lib/postmark/error.rb +127 -0
  18. data/lib/postmark/handlers/mail.rb +10 -4
  19. data/lib/postmark/helpers/message_helper.rb +4 -0
  20. data/lib/postmark/http_client.rb +20 -32
  21. data/lib/postmark/mail_message_converter.rb +18 -5
  22. data/lib/postmark/message_extensions/mail.rb +83 -8
  23. data/lib/postmark/version.rb +1 -1
  24. data/postmark.gemspec +1 -1
  25. data/postmark.png +0 -0
  26. data/spec/integration/account_api_client_spec.rb +42 -10
  27. data/spec/integration/api_client_hashes_spec.rb +32 -49
  28. data/spec/integration/api_client_messages_spec.rb +33 -52
  29. data/spec/integration/api_client_resources_spec.rb +12 -44
  30. data/spec/integration/mail_delivery_method_spec.rb +21 -23
  31. data/spec/spec_helper.rb +4 -7
  32. data/spec/support/custom_matchers.rb +44 -0
  33. data/spec/support/shared_examples.rb +16 -16
  34. data/spec/unit/postmark/account_api_client_spec.rb +239 -45
  35. data/spec/unit/postmark/api_client_spec.rb +792 -406
  36. data/spec/unit/postmark/bounce_spec.rb +40 -62
  37. data/spec/unit/postmark/client_spec.rb +0 -6
  38. data/spec/unit/postmark/error_spec.rb +231 -0
  39. data/spec/unit/postmark/handlers/mail_spec.rb +59 -27
  40. data/spec/unit/postmark/helpers/hash_helper_spec.rb +5 -6
  41. data/spec/unit/postmark/helpers/message_helper_spec.rb +60 -11
  42. data/spec/unit/postmark/http_client_spec.rb +76 -61
  43. data/spec/unit/postmark/inbound_spec.rb +34 -34
  44. data/spec/unit/postmark/inflector_spec.rb +11 -13
  45. data/spec/unit/postmark/json_spec.rb +2 -2
  46. data/spec/unit/postmark/mail_message_converter_spec.rb +250 -81
  47. data/spec/unit/postmark/message_extensions/mail_spec.rb +249 -38
  48. data/spec/unit/postmark_spec.rb +37 -37
  49. metadata +41 -11
@@ -1,3 +1,3 @@
1
1
  module Postmark
2
- VERSION = '1.8.1'
2
+ VERSION = '1.21.3'
3
3
  end
data/postmark.gemspec CHANGED
@@ -33,8 +33,8 @@ Gem::Specification.new do |s|
33
33
 
34
34
  s.required_rubygems_version = ">= 1.3.7"
35
35
 
36
- s.add_dependency "rake"
37
36
  s.add_dependency "json"
38
37
 
39
38
  s.add_development_dependency "mail"
39
+ s.add_development_dependency "rake"
40
40
  end
data/postmark.png ADDED
Binary file
@@ -8,12 +8,9 @@ describe 'Account API client usage' do
8
8
  let(:unique_token) { rand(36**32).to_s(36) }
9
9
  let(:unique_from_email) { ENV['POSTMARK_CI_SENDER'].gsub(/(\+.+)?@/, "+#{unique_token}@") }
10
10
 
11
- it 'can be used to manage senders' do
12
- new_sender = nil
13
-
11
+ it 'manage senders' do
14
12
  # create & count
15
- new_sender = subject.create_sender(:name => 'Integration Test',
16
- :from_email => unique_from_email)
13
+ new_sender = subject.create_sender(:name => 'Integration Test', :from_email => unique_from_email)
17
14
  expect(subject.get_senders_count).to be > 0
18
15
 
19
16
  # get
@@ -31,8 +28,9 @@ describe 'Account API client usage' do
31
28
  expect(updated_sender[:name]).to eq('New Name')
32
29
  expect(updated_sender[:id]).to eq(new_sender[:id])
33
30
 
31
+
34
32
  # spf
35
- expect(subject.verified_sender_spf?(new_sender[:id])).to be_true
33
+ expect(subject.verified_sender_spf?(new_sender[:id])).to be true
36
34
 
37
35
  # resend
38
36
  expect { subject.resend_sender_confirmation(new_sender[:id]) }.not_to raise_error
@@ -46,9 +44,44 @@ describe 'Account API client usage' do
46
44
  expect { subject.delete_sender(new_sender[:id]) }.not_to raise_error
47
45
  end
48
46
 
49
- it 'can be used to manage servers' do
50
- new_server = nil
47
+ it 'manage domains' do
48
+ domain_name = "#{unique_token}-gem-integration.test"
49
+ return_path = "return.#{domain_name}"
50
+ updated_return_path = "updated-return.#{domain_name}"
51
+
52
+ # create & count
53
+ new_domain = subject.create_domain(:name => domain_name,
54
+ :return_path_domain => return_path)
55
+ expect(subject.get_domains_count).to be > 0
56
+
57
+ # get
58
+ expect(subject.get_domain(new_domain[:id])[:id]).to eq(new_domain[:id])
59
+
60
+ # list
61
+ domains = subject.get_domains(:count => 50)
62
+ expect(domains.map { |d| d[:id] }).to include(new_domain[:id])
63
+
64
+ # collection
65
+ expect(subject.domains.map { |d| d[:id] }).to include(new_domain[:id])
66
+
67
+ # update
68
+ updated_domain = subject.update_domain(new_domain[:id], :return_path_domain => updated_return_path)
69
+ expect(updated_domain[:return_path_domain]).to eq(updated_return_path)
70
+ expect(updated_domain[:id]).to eq(new_domain[:id])
71
+
72
+ # spf
73
+ expect(subject.verified_domain_spf?(new_domain[:id])).to be true
51
74
 
75
+ # dkim
76
+ expect { subject.rotate_domain_dkim(new_domain[:id]) }.
77
+ to raise_error(Postmark::InvalidMessageError,
78
+ 'This DKIM is already being renewed.')
79
+
80
+ # delete
81
+ expect { subject.delete_domain(new_domain[:id]) }.not_to raise_error
82
+ end
83
+
84
+ it 'manage servers' do
52
85
  # create & count
53
86
  new_server = subject.create_server(:name => "server-#{unique_token}",
54
87
  :color => 'red')
@@ -72,5 +105,4 @@ describe 'Account API client usage' do
72
105
  # delete
73
106
  expect { subject.delete_server(new_server[:id]) }.not_to raise_error
74
107
  end
75
-
76
- end
108
+ end
@@ -1,19 +1,16 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Sending messages as Ruby hashes with Postmark::ApiClient" do
4
- let(:postmark_message_id_format) { /\w{8}\-\w{4}-\w{4}-\w{4}-\w{12}/ }
5
- let(:api_client) {
6
- Postmark::ApiClient.new('POSTMARK_API_TEST',
7
- :http_open_timeout => 15,
8
- :http_read_timeout => 15)
9
- }
4
+ let(:message_id_format) {/<.+@.+>/}
5
+ let(:postmark_message_id_format) {/\w{8}\-\w{4}-\w{4}-\w{4}-\w{12}/}
6
+ let(:api_client) {Postmark::ApiClient.new('POSTMARK_API_TEST', :http_open_timeout => 15, :http_read_timeout => 15)}
10
7
 
11
8
  let(:message) {
12
9
  {
13
- :from => "sender@postmarkapp.com",
14
- :to => "recipient@postmarkapp.com",
15
- :subject => "Mail::Message object",
16
- :text_body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " \
10
+ :from => "sender@postmarkapp.com",
11
+ :to => "recipient@postmarkapp.com",
12
+ :subject => "Mail::Message object",
13
+ :text_body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " \
17
14
  "sed do eiusmod tempor incididunt ut labore et dolore " \
18
15
  "magna aliqua."
19
16
  }
@@ -21,8 +18,8 @@ describe "Sending messages as Ruby hashes with Postmark::ApiClient" do
21
18
 
22
19
  let(:message_with_no_body) {
23
20
  {
24
- :from => "sender@postmarkapp.com",
25
- :to => "recipient@postmarkapp.com",
21
+ :from => "sender@postmarkapp.com",
22
+ :to => "recipient@postmarkapp.com",
26
23
  }
27
24
  }
28
25
 
@@ -32,74 +29,60 @@ describe "Sending messages as Ruby hashes with Postmark::ApiClient" do
32
29
  end
33
30
  }
34
31
 
35
- let(:message_with_invalid_to) {
36
- {
37
- :from => "sender@postmarkapp.com",
38
- :to => "@postmarkapp.com"
39
- }
40
- }
41
-
42
- let(:valid_messages) { [message, message.dup] }
43
- let(:partially_valid_messages) { [message, message.dup, message_with_no_body] }
44
- let(:invalid_messages) { [message_with_no_body, message_with_no_body.dup] }
32
+ let(:message_with_invalid_to) {{:from => "sender@postmarkapp.com", :to => "@postmarkapp.com"}}
33
+ let(:valid_messages) {[message, message.dup]}
34
+ let(:partially_valid_messages) {[message, message.dup, message_with_no_body]}
35
+ let(:invalid_messages) {[message_with_no_body, message_with_no_body.dup]}
45
36
 
46
- context "message by message" do
47
- it 'delivers a plain text message' do
48
- api_client.deliver(message).should have_key(:message_id)
37
+ context "single message" do
38
+ it 'plain text message' do
39
+ expect(api_client.deliver(message)).to have_key(:message_id)
49
40
  end
50
41
 
51
- it 'updates a message object with Message-ID' do
52
- api_client.deliver(message)[:message_id].
53
- should =~ postmark_message_id_format
42
+ it 'message with attachment' do
43
+ expect(api_client.deliver(message_with_attachment)).to have_key(:message_id)
54
44
  end
55
45
 
56
- it 'returns full Postmark response' do
57
- api_client.deliver(message).should be_a Hash
46
+ it 'response Message-ID' do
47
+ expect(api_client.deliver(message)[:message_id]).to be =~ postmark_message_id_format
58
48
  end
59
49
 
60
- it 'delivers a message with attachment' do
61
- api_client.deliver(message_with_attachment).
62
- should have_key(:message_id)
50
+ it 'response is Hash' do
51
+ expect(api_client.deliver(message)).to be_a Hash
63
52
  end
64
53
 
65
54
  it 'fails to deliver a message without body' do
66
- expect { api_client.deliver(message_with_no_body) }.
67
- to raise_error(Postmark::InvalidMessageError)
55
+ expect {api_client.deliver(message_with_no_body)}.to raise_error(Postmark::InvalidMessageError)
68
56
  end
69
57
 
70
58
  it 'fails to deliver a message with invalid To address' do
71
- expect { api_client.deliver(message_with_invalid_to) }.
72
- to raise_error(Postmark::InvalidMessageError)
59
+ expect {api_client.deliver(message_with_invalid_to)}.to raise_error(Postmark::InvalidMessageError)
73
60
  end
74
61
  end
75
62
 
76
- context "in batches" do
77
- it 'returns as many responses as many messages were sent' do
78
- api_client.deliver_in_batches(valid_messages).count.should == valid_messages.count
63
+ context "batch message" do
64
+ it 'response messages count' do
65
+ expect(api_client.deliver_in_batches(valid_messages).count).to eq valid_messages.count
79
66
  end
80
67
 
81
- context "given custom max_batch_size" do
68
+ context "custom max_batch_size" do
82
69
  before do
83
70
  api_client.max_batch_size = 1
84
71
  end
85
72
 
86
- it 'returns as many responses as many messages were sent' do
87
- api_client.deliver_in_batches(valid_messages).count.should == valid_messages.count
73
+ it 'response message count' do
74
+ expect(api_client.deliver_in_batches(valid_messages).count).to eq valid_messages.count
88
75
  end
89
76
  end
90
77
 
91
78
  it 'partially delivers a batch of partially valid Mail::Message objects' do
92
79
  response = api_client.deliver_in_batches(partially_valid_messages)
93
- expect(response).to satisfy { |r| r.count { |mr| mr[:error_code].to_i.zero? } == 2 }
80
+ expect(response).to satisfy {|r| r.count {|mr| mr[:error_code].to_i.zero?} == 2}
94
81
  end
95
82
 
96
83
  it "doesn't deliver a batch of invalid Mail::Message objects" do
97
84
  response = api_client.deliver_in_batches(invalid_messages)
98
-
99
- expect(response).to satisfy { |r| r.all? { |mr| !!mr[:error_code] } }
85
+ expect(response).to satisfy {|r| r.all? {|mr| !!mr[:error_code]}}
100
86
  end
101
87
  end
102
-
103
-
104
-
105
88
  end
@@ -2,11 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe "Sending Mail::Messages with Postmark::ApiClient" do
4
4
  let(:postmark_message_id_format) { /\w{8}\-\w{4}-\w{4}-\w{4}-\w{12}/ }
5
- let(:api_client) {
6
- Postmark::ApiClient.new('POSTMARK_API_TEST',
7
- :http_open_timeout => 15,
8
- :http_read_timeout => 15)
9
- }
5
+ let(:api_client) { Postmark::ApiClient.new('POSTMARK_API_TEST', :http_open_timeout => 15, :http_read_timeout => 15) }
10
6
 
11
7
  let(:message) {
12
8
  Mail.new do
@@ -25,11 +21,7 @@ describe "Sending Mail::Messages with Postmark::ApiClient" do
25
21
  end
26
22
  }
27
23
 
28
- let(:message_with_attachment) {
29
- message.tap do |msg|
30
- msg.attachments["test.gif"] = File.read(empty_gif_path)
31
- end
32
- }
24
+ let(:message_with_attachment) { message.tap { |msg| msg.attachments["test.gif"] = File.read(empty_gif_path) } }
33
25
 
34
26
  let(:message_with_invalid_to) {
35
27
  Mail.new do
@@ -50,90 +42,79 @@ describe "Sending Mail::Messages with Postmark::ApiClient" do
50
42
  end
51
43
  end
52
44
 
53
- context "message by message" do
54
- it 'delivers a plain text message' do
55
- api_client.deliver_message(message).should have_key(:message_id)
45
+ context "single message" do
46
+ it 'plain text message' do
47
+ expect(api_client.deliver_message(message)).to have_key(:message_id)
56
48
  end
57
49
 
58
- it 'updates a message object with Message-ID' do
59
- api_client.deliver_message(message)[:message_id].
60
- should =~ postmark_message_id_format
50
+ it 'message with attachment' do
51
+ expect(api_client.deliver_message(message_with_attachment)).to have_key(:message_id)
61
52
  end
62
53
 
63
- it 'returns full Postmark response' do
64
- api_client.deliver_message(message).should be_a Hash
54
+ it 'response Message-ID' do
55
+ expect(api_client.deliver_message(message)[:message_id]).to be =~ postmark_message_id_format
65
56
  end
66
57
 
67
- it 'delivers a message with attachment' do
68
- api_client.deliver_message(message_with_attachment).
69
- should have_key(:message_id)
58
+ it 'response is Hash' do
59
+ expect(api_client.deliver_message(message)).to be_a Hash
70
60
  end
71
61
 
72
62
  it 'fails to deliver a message without body' do
73
- expect { api_client.deliver_message(message_with_no_body) }.
74
- to raise_error(Postmark::InvalidMessageError)
63
+ expect { api_client.deliver_message(message_with_no_body) }.to raise_error(Postmark::InvalidMessageError)
75
64
  end
76
65
 
77
66
  it 'fails to deliver a message with invalid To address' do
78
- expect { api_client.deliver_message(message_with_invalid_to) }.
79
- to raise_error(Postmark::InvalidMessageError)
67
+ expect { api_client.deliver_message(message_with_invalid_to) }.to raise_error(Postmark::InvalidMessageError)
80
68
  end
81
69
  end
82
70
 
83
- context "in batches" do
84
- it 'delivers a batch of valid Mail::Message objects' do
71
+ context "batch message" do
72
+ it 'response - valid Mail::Message objects' do
85
73
  expect { api_client.deliver_messages(valid_messages) }.
86
- to change{valid_messages.all? { |m| m.delivered? }}.
87
- to true
74
+ to change{valid_messages.all? { |m| m.delivered? }}.to true
88
75
  end
89
76
 
90
- it 'updates delivered messages with Message-IDs' do
77
+ it 'response - valid X-PM-Message-Ids' do
91
78
  api_client.deliver_messages(valid_messages)
92
-
93
- expect(valid_messages.all? { |m| m.message_id =~ postmark_message_id_format }).
94
- to be_true
79
+ expect(valid_messages.all? { |m| m['X-PM-Message-Id'].to_s =~ postmark_message_id_format }).to be true
95
80
  end
96
81
 
97
- it 'updates delivered messages with related Postmark responses' do
82
+ it 'response - valid response objects' do
98
83
  api_client.deliver_messages(valid_messages)
99
-
100
- expect(valid_messages.all? { |m| m.postmark_response["To"] == m.to[0] }).
101
- to be_true
84
+ expect(valid_messages.all? { |m| m.postmark_response["To"] == m.to[0] }).to be true
102
85
  end
103
86
 
104
- it 'returns as many responses as many messages were sent' do
105
- api_client.deliver_messages(valid_messages).count.should == valid_messages.count
87
+ it 'response - message responses count' do
88
+ expect(api_client.deliver_messages(valid_messages).count).to eq valid_messages.count
106
89
  end
107
90
 
108
- context "given custom max_batch_size" do
91
+ context "custom max_batch_size" do
109
92
  before do
110
93
  api_client.max_batch_size = 1
111
94
  end
112
95
 
113
- it 'updates delivered messages with related Postmark responses' do
96
+ it 'response - valid response objects' do
114
97
  api_client.deliver_messages(valid_messages)
115
-
116
- expect(valid_messages.all? { |m| m.postmark_response["To"] == m.to[0] }).
117
- to be_true
98
+ expect(valid_messages.all? { |m| m.postmark_response["To"] == m.to[0] }).to be true
118
99
  end
119
100
 
120
- it 'returns as many responses as many messages were sent' do
121
- api_client.deliver_messages(valid_messages).count.should == valid_messages.count
101
+ it 'response - message responses count' do
102
+ expect(api_client.deliver_messages(valid_messages).count).to eq valid_messages.count
122
103
  end
123
104
  end
124
105
 
125
106
  it 'partially delivers a batch of partially valid Mail::Message objects' do
126
107
  expect { api_client.deliver_messages(partially_valid_messages) }.
127
- to change{partially_valid_messages.select { |m| m.delivered? }.count}.
128
- to 2
108
+ to change{partially_valid_messages.select { |m| m.delivered? }.count}.to 2
129
109
  end
130
110
 
131
111
  it "doesn't deliver a batch of invalid Mail::Message objects" do
132
- expect { api_client.deliver_messages(invalid_messages) }.
133
- to change{invalid_messages.all? { |m| m.delivered? == false }}.
134
- to true
112
+ aggregate_failures do
113
+ expect { api_client.deliver_messages(invalid_messages) }.
114
+ to change{invalid_messages.all? { |m| m.delivered? == false }}.to true
135
115
 
136
- invalid_messages.should satisfy { |ms| ms.all? { |m| !!m.postmark_response }}
116
+ expect(invalid_messages).to satisfy { |ms| ms.all? { |m| !!m.postmark_response }}
117
+ end
137
118
  end
138
119
  end
139
120
  end
@@ -1,46 +1,20 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Accessing server resources using the API' do
4
-
5
- let(:api_client) {
6
- Postmark::ApiClient.new(ENV['POSTMARK_API_KEY'], :http_open_timeout => 15)
7
- }
8
- let(:recipient) { ENV['POSTMARK_CI_RECIPIENT'] }
4
+ let(:api_client) {Postmark::ApiClient.new(ENV['POSTMARK_API_KEY'], :http_open_timeout => 15)}
5
+ let(:recipient) {ENV['POSTMARK_CI_RECIPIENT']}
9
6
  let(:message) {
10
7
  {
11
- :from => "tema+ci@wildbit.com",
12
- :to => recipient,
13
- :subject => "Mail::Message object",
14
- :text_body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " \
8
+ :from => ENV['POSTMARK_CI_SENDER'],
9
+ :to => recipient,
10
+ :subject => "Mail::Message object",
11
+ :text_body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " \
15
12
  "sed do eiusmod tempor incididunt ut labore et dolore " \
16
13
  "magna aliqua."
17
14
  }
18
15
  }
19
16
 
20
- context 'Triggers API' do
21
-
22
- let(:unique_token) { rand(36**32).to_s(36) }
23
-
24
- it 'can be used to manage tag triggers via the API' do
25
- trigger = api_client.create_trigger(:tags,
26
- :match_name => "gemtest_#{unique_token}",
27
- :track_opens => true)
28
- api_client.update_trigger(:tags,
29
- trigger[:id],
30
- :match_name => "pre_#{trigger[:match_name]}")
31
- updated = api_client.get_trigger(:tags, trigger[:id])
32
-
33
- expect(updated[:id]).to eq(trigger[:id])
34
- expect(updated[:match_name]).not_to eq(trigger[:id])
35
- expect(api_client.triggers(:tags).map { |t| t[:id] }).to include(trigger[:id])
36
-
37
- api_client.delete_trigger(:tags, trigger[:id])
38
- end
39
-
40
- end
41
-
42
17
  context 'Messages API' do
43
-
44
18
  def with_retries(max_retries = 20, wait_seconds = 3)
45
19
  yield
46
20
  rescue => e
@@ -55,17 +29,13 @@ describe 'Accessing server resources using the API' do
55
29
 
56
30
  it 'is possible to send a message and access its details via the Messages API' do
57
31
  response = api_client.deliver(message)
58
- message = with_retries {
59
- api_client.get_message(response[:message_id])
60
- }
32
+ message = with_retries {api_client.get_message(response[:message_id])}
61
33
  expect(message[:recipients]).to include(recipient)
62
34
  end
63
35
 
64
36
  it 'is possible to send a message and dump it via the Messages API' do
65
37
  response = api_client.deliver(message)
66
- dump = with_retries {
67
- api_client.dump_message(response[:message_id])
68
- }
38
+ dump = with_retries {api_client.dump_message(response[:message_id])}
69
39
  expect(dump[:body]).to include('Mail::Message object')
70
40
  end
71
41
 
@@ -74,15 +44,13 @@ describe 'Accessing server resources using the API' do
74
44
  expect {
75
45
  with_retries {
76
46
  messages = api_client.get_messages(:recipient => recipient,
77
- :fromemail => message[:from],
78
- :subject => message[:subject])
79
- unless messages.map { |m| m[:message_id] }.include?(response[:message_id])
47
+ :fromemail => message[:from],
48
+ :subject => message[:subject])
49
+ unless messages.map {|m| m[:message_id]}.include?(response[:message_id])
80
50
  raise 'Message not found'
81
51
  end
82
52
  }
83
53
  }.not_to raise_error
84
54
  end
85
-
86
55
  end
87
-
88
- end
56
+ end