loqate 0.6.0 → 0.7.0

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.
@@ -0,0 +1,149 @@
1
+ require 'loqate/address/address'
2
+ require 'loqate/address/detailed_address'
3
+ require 'loqate/error'
4
+ require 'loqate/client'
5
+ require 'loqate/result'
6
+ require 'loqate/mappers/error_mapper'
7
+ require 'loqate/mappers/generic_mapper'
8
+
9
+ module Loqate
10
+ module Address
11
+ # Address Verification consists of two main API requests: a Find request is used to narrow down a possible
12
+ # list of addresses; and a Retrieve request is used to retrieve a fully formatted address.
13
+ #
14
+ # A typical address search is made up of a series of Find requests, followed by a Retrieve based on the
15
+ # user selection. Choose a service below to find out how to use each request.
16
+ #
17
+ class Gateway
18
+ FIND_ENDPOINT = '/Capture/Interactive/Find/v1.00/json3.ws'.freeze
19
+ RETRIEVE_ENDPOINT = '/Capture/Interactive/Retrieve/v1.00/json3.ws'.freeze
20
+
21
+ include Result::Mixin
22
+
23
+ # Creates an address gateway
24
+ #
25
+ # @param [Client] client The client responsible for the HTTP interactions
26
+ #
27
+ def initialize(client)
28
+ @client = client
29
+ @mapper = Mappers::GenericMapper.new
30
+ @error_mapper = Mappers::ErrorMapper.new
31
+ end
32
+
33
+ # Find addresses and places.
34
+ #
35
+ # @param [Hash] options The options to find an address or a list of addresses.
36
+ # @option options [String] :text The search text to find. Ideally a postcode or the start of the address.
37
+ # @option options [String] countries A comma separated list of ISO 2 or 3 character country codes to limit
38
+ # the search within.
39
+ # @option options [String] origin A starting location for the search. This can be the name or ISO 2 or 3
40
+ # character code of a country, WGS84 coordinates (comma separated) or IP address to search from.
41
+ # @option options [String] container A container for the search. This should only be another Id previously
42
+ # returned from this service when the Type of the result was not 'Address'.
43
+ # @option options [Integer] limit The maximum number of results to return.
44
+ # @option options [String] language The preferred language for results. This should be a 2 or 4 character
45
+ # language code e.g. (en, fr, en-gb, en-us etc).
46
+ #
47
+ # @example Retrieving an address in the UK
48
+ # address = address_gateway.find(countries: 'GB', text: 'Scrubs Lane')
49
+ #
50
+ # @return [Result] A result wrapping a list of addresses
51
+ #
52
+ def find(options)
53
+ response = client.get(FIND_ENDPOINT, options)
54
+
55
+ response.errors? && build_error_from(response.items.first) || build_addresses_from(response.items)
56
+ end
57
+
58
+ # Returns the full address details based on the id.
59
+ #
60
+ # @param [Hash] options The options to retrieve the address.
61
+ # @option options [String] :id The Id from a Find method to retrieve the details for.
62
+ # @option options [String] :field_1_format Format of a custom address field.
63
+ # @option options [String] :field_2_format Format of a custom address field.
64
+ # @option options [String] :field_3_format Format of a custom address field.
65
+ # @option options [String] :field_4_format Format of a custom address field.
66
+ # @option options [String] :field_5_format Format of a custom address field.
67
+ #
68
+ # @example Retrieving the details of an address
69
+ # detailed_address = gateway.retrieve(id: 'GB|RM|ENG|6RB-NW10')
70
+ #
71
+ # @return [Result] A result wrapping a detailed address
72
+ #
73
+ def retrieve(options)
74
+ response = client.get(RETRIEVE_ENDPOINT, options)
75
+
76
+ response.errors? && build_error_from(response.items.first) || build_detailed_address_from(response.items.first)
77
+ end
78
+
79
+ # Find addresses and places.
80
+ #
81
+ # @param [Hash] options The options to find an address or a list of addresses.
82
+ # @option options [String] :text The search text to find. Ideally a postcode or the start of the address.
83
+ # @option options [String] countries A comma separated list of ISO 2 or 3 character country codes to limit
84
+ # the search within.
85
+ # @option options [String] origin A starting location for the search. This can be the name or ISO 2 or 3
86
+ # character code of a country, WGS84 coordinates (comma separated) or IP address to search from.
87
+ # @option options [String] container A container for the search. This should only be another Id previously
88
+ # returned from this service when the Type of the result was not 'Address'.
89
+ # @option options [Integer] limit The maximum number of results to return.
90
+ # @option options [String] language The preferred language for results. This should be a 2 or 4 character
91
+ # language code e.g. (en, fr, en-gb, en-us etc).
92
+ #
93
+ # @example Retrieving addresses in the UK
94
+ # addresses = address_gateway.find!(countries: 'GB', text: 'Scrubs Lane')
95
+ #
96
+ # @raise [Error] If the result is not a success
97
+ #
98
+ # @return [Array<Address>] A list of addresses
99
+ #
100
+ def find!(options)
101
+ unwrap_result_or_raise { find(options) }
102
+ end
103
+
104
+ # Returns the full address details based on the id.
105
+ #
106
+ # @param [Hash] options The options to retrieve the address.
107
+ # @option options [String] :id The Id from a Find method to retrieve the details for.
108
+ # @option options [String] :field_1_format Format of a custom address field.
109
+ # @option options [String] :field_2_format Format of a custom address field.
110
+ # @option options [String] :field_3_format Format of a custom address field.
111
+ # @option options [String] :field_4_format Format of a custom address field.
112
+ # @option options [String] :field_5_format Format of a custom address field.
113
+ #
114
+ # @example Retrieving the details of an address
115
+ # detailed_address = gateway.retrieve!(id: 'GB|RM|ENG|6RB-NW10')
116
+ #
117
+ # @raise [Error] If the result is not a success
118
+ #
119
+ # @return [DetailedAddress] A detailed address
120
+ #
121
+ def retrieve!(options)
122
+ unwrap_result_or_raise { retrieve(options) }
123
+ end
124
+
125
+ private
126
+
127
+ # @api private
128
+ attr_reader :client, :mapper, :error_mapper
129
+
130
+ # @api private
131
+ def build_error_from(item)
132
+ error = error_mapper.map_one(item)
133
+ Failure(error)
134
+ end
135
+
136
+ # @api private
137
+ def build_addresses_from(items)
138
+ address = mapper.map(items, Address)
139
+ Success(address)
140
+ end
141
+
142
+ # @api private
143
+ def build_detailed_address_from(item)
144
+ detailed_address = mapper.map_one(item, DetailedAddress)
145
+ Success(detailed_address)
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,68 @@
1
+ module Loqate
2
+ module Email
3
+ # Result of a batch email address validation.
4
+ class BatchEmailValidation < Dry::Struct::Value
5
+ Status = Types::Strict::String.enum('Valid', 'Invalid', 'Unknown', 'Accept_All')
6
+
7
+ # Valid - The email address is valid
8
+ # Invalid - The email address is invalid and shouldn't be accepted
9
+ # Unknown - Unable to complete the verification process (normally due to SMTP timeout)
10
+ # Accept_All - The mail server is set to accept all verification requests so full verification isn't possible
11
+ #
12
+ # @return ['Valid', 'Invalid', 'Unknown', 'Accept_All']
13
+ #
14
+ attribute :status, Status
15
+
16
+ # The email address that verification was attempted on.
17
+ #
18
+ # @return [String]
19
+ #
20
+ attribute :email_address, Types::Strict::String
21
+
22
+ # The account portion of the email address provided.
23
+ #
24
+ # @return [String
25
+ #
26
+ attribute :account, Types::Strict::String
27
+
28
+ # The domain portion of the email address provided.
29
+ #
30
+ # @return [String]
31
+ #
32
+ attribute :domain, Types::Strict::String
33
+
34
+ # Whether the email address provided is a disposable mailbox (some companies create temporary mailboxes
35
+ # which shouldn't be used for marketing communications).
36
+ #
37
+ # @return [Boolean]
38
+ #
39
+ attribute :is_disposible, Types::Strict::Bool
40
+
41
+ # Whether the email address provided is a system mailbox (e.g. sales@, support@, accounts@ etc).
42
+ #
43
+ # @return [Boolean]
44
+ #
45
+ attribute :is_system_mailbox, Types::Strict::Bool
46
+
47
+ # Whether the email was fully validated (including the account portion).
48
+ def valid?
49
+ status == 'Valid'
50
+ end
51
+
52
+ # Whether the email is invalid and shouldn't be accepted.
53
+ def invalid?
54
+ status == 'Invalid'
55
+ end
56
+
57
+ # Whether the email wasn't verified (normally due to SMTP timeout)
58
+ def unknown?
59
+ status == 'Unknown'
60
+ end
61
+
62
+ # Whether the email could be verified
63
+ def unverified?
64
+ status == 'Accept_All'
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,83 @@
1
+ module Loqate
2
+ module Email
3
+ # Result of a email address validation.
4
+ class EmailValidation < Dry::Struct::Value
5
+ ResponseCode = Types::Strict::String.enum('Valid', 'Valid_CatchAll', 'Invalid', 'Timeout')
6
+
7
+ # Valid - The email address has been fully validated (including the account portion)
8
+ # Valid_CatchAll - The domain has been validated but the account could not be validated
9
+ # Invalid - The email address is invalid and shouldn't be accepted
10
+ # Timeout - The validation could not be completed within the timeout specified (try increasing the timeout value)
11
+ #
12
+ # @return ['Valid', 'Valid_CatchAll', 'Invalid', 'Timeout']
13
+ #
14
+ attribute :response_code, ResponseCode
15
+
16
+ # A textual description of the ResponseCode returned
17
+ #
18
+ # @return [String]
19
+ #
20
+ attribute :response_message, Types::Strict::String
21
+
22
+ # The email address that verification was attempted on.
23
+ #
24
+ # @return [String]
25
+ #
26
+ attribute :email_address, Types::Strict::String
27
+
28
+ # The account portion of the email address provided.
29
+ #
30
+ # @return [String
31
+ #
32
+ attribute :user_account, Types::Strict::String
33
+
34
+ # The domain portion of the email address provided.
35
+ #
36
+ # @return [String]
37
+ #
38
+ attribute :domain, Types::Strict::String
39
+
40
+ # Whether the email address provided is a disposable mailbox (some companies create temporary mailboxes
41
+ # which shouldn't be used for marketing communications).
42
+ #
43
+ # @return [Boolean]
44
+ #
45
+ attribute :is_disposable_or_temporary, Types::Strict::Bool
46
+
47
+ # True if we recognise the email address against known lists of complainers and/or the email address has been
48
+ # used to defraud.
49
+ #
50
+ # @return [Boolean]
51
+ #
52
+ attribute :is_complainer_or_fraud_risk, Types::Strict::Bool
53
+
54
+ # The duration (in seconds) that the email validation took (maximum timeout enforced at 15 seconds).
55
+ # We recommend a high timeout (at least 5 seconds) value as it will minimise the number of "Timeout"
56
+ # responses returned.
57
+ #
58
+ # @return [Float]
59
+ #
60
+ attribute :duration, Types::Strict::Float
61
+
62
+ # Whether the email was fully validated (including the account portion).
63
+ def valid?
64
+ response_code == 'Valid'
65
+ end
66
+
67
+ # Whether the domain has been validated but the account hasn't.
68
+ def valid_domain?
69
+ response_code == 'Valid' || response_code == 'Valid_CatchAll'
70
+ end
71
+
72
+ # Whether the email is invalid and shouldn't be accepted.
73
+ def invalid?
74
+ response_code == 'Invalid'
75
+ end
76
+
77
+ # Whether the validation could not be completed within the timeout specified.
78
+ def timeout?
79
+ response_code == 'Timeout'
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,124 @@
1
+ require 'loqate/client'
2
+ require 'loqate/result'
3
+ require 'loqate/email/email_validation'
4
+ require 'loqate/email/batch_email_validation'
5
+ require 'loqate/mappers/error_mapper'
6
+ require 'loqate/mappers/generic_mapper'
7
+
8
+ module Loqate
9
+ module Email
10
+ # Validates the existence of email addresses.
11
+ #
12
+ class Gateway
13
+ BATCH_VALIDATE_ENDPOINT = '/EmailValidation/Batch/Validate/v1.20/json3.ws'.freeze
14
+ VALIDATE_ENDPOINT = '/EmailValidation/Interactive/Validate/v2.00/json3.ws'.freeze
15
+
16
+ include Result::Mixin
17
+
18
+ # Creates an email gateway.
19
+ #
20
+ # @param [Client] client The client responsible for the HTTP interactions
21
+ #
22
+ def initialize(client)
23
+ @client = client
24
+ @mapper = Mappers::GenericMapper.new
25
+ @error_mapper = Mappers::ErrorMapper.new
26
+ end
27
+
28
+ # Verifies the existence of an email address.
29
+ #
30
+ # @param [Hash] options The options to validate an email address.
31
+ # @option options [String] :email The email address to verify.
32
+ # @option options [Integer] :timeout The time (in milliseconds) you want to give for the validation attempt to be
33
+ # executed within. Value must be between 1 and 15000 (values outside of these ranges will fallback to the
34
+ # default of 15000).
35
+ #
36
+ # @example
37
+ # email_validation = email_gateway.validate(email: 'spam@example.com')
38
+ #
39
+ # @return [Result] A result wrapping an email address validation
40
+ #
41
+ def validate(options)
42
+ response = client.get(VALIDATE_ENDPOINT, options)
43
+
44
+ response.errors? && build_error_from(response.items.first) || build_email_validation_from(response.items.first)
45
+ end
46
+
47
+ # Verifies the existence of an email address.
48
+ #
49
+ # @param [Hash] options The options to validate an email address.
50
+ # @option options [String] :email The email address to verify.
51
+ # @option options [Integer] :timeout The time (in milliseconds) you want to give for the validation attempt to be
52
+ # executed within. Value must be between 1 and 15000 (values outside of these ranges will fallback to the
53
+ # default of 15000).
54
+ #
55
+ # @example
56
+ # email_validation = email_gateway.validate!(email: 'spam@example.com')
57
+ #
58
+ # @raise [Error] If the result is not a success
59
+ #
60
+ # @return [EmailValidation> An email address validation
61
+ #
62
+ def validate!(options)
63
+ unwrap_result_or_raise { validate(options) }
64
+ end
65
+
66
+ # Verifies up to 100 emails per batch.
67
+ #
68
+ # @param [Hash] options The options to validate an email address.
69
+ # @option options [Array<String>] :emails The email addresses to verify. Maximum 100 records.
70
+ #
71
+ # @example
72
+ # result = email_gateway.batch_validate(emails: %w[spam@example.com example@example.com])
73
+ # result.value # => [#<Loqate::Email::BatchEmailValidation status="Invalid" ...]
74
+ #
75
+ # @return [Result] A result wrapping a list of email address validations
76
+ #
77
+ def batch_validate(options)
78
+ options[:emails] = options[:emails].join(',') if options[:emails]
79
+ response = client.get(BATCH_VALIDATE_ENDPOINT, options)
80
+
81
+ response.errors? && build_error_from(response.items.first) || build_email_validations_from(response.items)
82
+ end
83
+
84
+ # Verifies up to 100 emails per batch.
85
+ #
86
+ # @param [Hash] options The options to validate an email address.
87
+ # @option options [Array<String>] :emails The email addresses to verify. Maximum 100 records.
88
+ #
89
+ # @example
90
+ # email_validations = email_gateway.batch_validate!(emails: %w[spam@example.com example@example.com])
91
+ #
92
+ # @raise [Error] If the result is not a success
93
+ #
94
+ # @return [Array<BatchEmailValidation>] A list of email address validations
95
+ #
96
+ def batch_validate!(options)
97
+ unwrap_result_or_raise { batch_validate(options) }
98
+ end
99
+
100
+ private
101
+
102
+ # @api private
103
+ attr_reader :client, :mapper, :error_mapper
104
+
105
+ # @api private
106
+ def build_error_from(item)
107
+ error = error_mapper.map_one(item)
108
+ Failure(error)
109
+ end
110
+
111
+ # @api private
112
+ def build_email_validation_from(item)
113
+ email_validation = mapper.map_one(item, EmailValidation)
114
+ Success(email_validation)
115
+ end
116
+
117
+ # @api private
118
+ def build_email_validations_from(item)
119
+ email_validation = mapper.map(item, BatchEmailValidation)
120
+ Success(email_validation)
121
+ end
122
+ end
123
+ end
124
+ end
@@ -1,7 +1,7 @@
1
- require 'loqate/address_gateway'
1
+ require 'loqate/address/gateway'
2
2
  require 'loqate/bank/gateway'
3
- require 'loqate/email_gateway'
4
- require 'loqate/phone_gateway'
3
+ require 'loqate/email/gateway'
4
+ require 'loqate/phone/gateway'
5
5
 
6
6
  module Loqate
7
7
  # Acts as a single point of entry for a defined group of API's.
@@ -28,31 +28,31 @@ module Loqate
28
28
 
29
29
  # Gateway to the Address APIs.
30
30
  #
31
- # @return [AddressGateway] An instance of an address gateway.
31
+ # @return [Address::Gateway] An instance of an address gateway.
32
32
  #
33
33
  def address
34
- @address ||= AddressGateway.new(client)
34
+ @address ||= Address::Gateway.new(client)
35
35
  end
36
36
 
37
37
  # Gateway to the Phone number API.
38
38
  #
39
- # @return [PhoneGateway] An instance of a phone gateway.
39
+ # @return [Phone::Gateway] An instance of a phone gateway.
40
40
  #
41
41
  def phone
42
- @phone ||= PhoneGateway.new(client)
42
+ @phone ||= Phone::Gateway.new(client)
43
43
  end
44
44
 
45
45
  # Gateway to the Email verification APIs.
46
46
  #
47
- # @return [EmailGateway] An instance of an email gateway.
47
+ # @return [Email::Gateway] An instance of an email gateway.
48
48
  #
49
49
  def email
50
- @email ||= EmailGateway.new(client)
50
+ @email ||= Email::Gateway.new(client)
51
51
  end
52
52
 
53
53
  # Gateway to the Bank verification APIs.
54
54
  #
55
- # @return [BankGateway] An instance of a bank gateway.
55
+ # @return [Bank::Gateway] An instance of a bank gateway.
56
56
  #
57
57
  def bank
58
58
  @bank ||= Bank::Gateway.new(client)