File: error.rb

package info (click to toggle)
ruby-postmark 1.25.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 480 kB
  • sloc: ruby: 5,413; makefile: 4
file content (137 lines) | stat: -rw-r--r-- 3,349 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
require 'postmark/deprecations'

module Postmark
  class Error < ::StandardError; end

  class HttpClientError < Error
    def retry?
      true
    end
  end

  class HttpServerError < Error
    attr_accessor :status_code, :parsed_body, :body

    alias_method :full_response, :parsed_body

    def self.build(status_code, body)
      parsed_body = Postmark::Json.decode(body) rescue {}

      case status_code
      when '401'
        InvalidApiKeyError.new(401, body, parsed_body)
      when '422'
        ApiInputError.build(body, parsed_body)
      when '500'
        InternalServerError.new(500, body, parsed_body)
      else
        UnexpectedHttpResponseError.new(status_code, body, parsed_body)
      end
    end

    def initialize(status_code = 500, body = '', parsed_body = {})
      self.parsed_body = parsed_body
      self.status_code = status_code.to_i
      self.body = body
      message = parsed_body.fetch('Message', "The Postmark API responded with HTTP status #{status_code}.")

      super(message)
    end

    def retry?
      5 == status_code / 100
    end
  end

  class ApiInputError < HttpServerError
    INACTIVE_RECIPIENT = 406
    INVALID_EMAIL_REQUEST = 300

    attr_accessor :error_code

    def self.build(body, parsed_body)
      error_code = parsed_body['ErrorCode'].to_i

      case error_code
      when INACTIVE_RECIPIENT
        InactiveRecipientError.new(error_code, body, parsed_body)
      when INVALID_EMAIL_REQUEST
        InvalidEmailRequestError.new(error_code, body, parsed_body)
      else
        new(error_code, body, parsed_body)
      end
    end

    def initialize(error_code = nil, body = '', parsed_body = {})
      self.error_code = error_code.to_i
      super(422, body, parsed_body)
    end

    def retry?
      false
    end
  end

  class InvalidEmailRequestError < ApiInputError; end

  class InactiveRecipientError < ApiInputError
    attr_reader :recipients

    PATTERNS = [
      /Found inactive addresses: (.+?)\. Inactive/,
      /these inactive addresses: (.+?)\.?$/
    ].freeze

    def self.parse_recipients(message)
      PATTERNS.each do |p|
        _, recipients = p.match(message).to_a
        next unless recipients
        return recipients.split(', ')
      end

      []
    end

    def initialize(*args)
      super
      @recipients = parse_recipients || []
    end

    private

    def parse_recipients
      return unless parsed_body && !parsed_body.empty?

      self.class.parse_recipients(parsed_body['Message'])
    end
  end

  class InvalidTemplateError < Error
    attr_reader :postmark_response

    def initialize(response)
      @postmark_response = response
      super('Failed to render the template. Please check #postmark_response on this error for details.')
    end
  end

  class TimeoutError < Error
    def retry?
      true
    end
  end

  class MailAdapterError < Postmark::Error; end
  class UnknownMessageType < Error; end
  class InvalidApiKeyError < HttpServerError; end
  class InternalServerError < HttpServerError; end
  class UnexpectedHttpResponseError < HttpServerError; end

  # Backwards compatible aliases
  Deprecations.add_constants(
    :DeliveryError => Error,
    :InvalidMessageError => ApiInputError,
    :UnknownError => UnexpectedHttpResponseError,
    :InvalidEmailAddressError => InvalidEmailRequestError
  )
end