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