postmark 1.8.1 → 1.21.3

Sign up to get free protection for your applications and to get access to all the features.
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