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.
- checksums.yaml +4 -4
- data/.yardstick.yml +96 -96
- data/CHANGELOG.md +5 -0
- data/README.md +8 -40
- data/ROADMAP.md +1 -1
- data/lib/loqate/address/address.rb +37 -0
- data/lib/loqate/address/detailed_address.rb +85 -0
- data/lib/loqate/address/gateway.rb +149 -0
- data/lib/loqate/email/batch_email_validation.rb +68 -0
- data/lib/loqate/email/email_validation.rb +83 -0
- data/lib/loqate/email/gateway.rb +124 -0
- data/lib/loqate/gateway.rb +10 -10
- data/lib/loqate/phone/gateway.rb +84 -0
- data/lib/loqate/phone/phone_number_validation.rb +69 -0
- data/lib/loqate/version.rb +1 -1
- metadata +9 -9
- data/lib/loqate/address.rb +0 -35
- data/lib/loqate/address_gateway.rb +0 -147
- data/lib/loqate/batch_email_validation.rb +0 -66
- data/lib/loqate/detailed_address.rb +0 -83
- data/lib/loqate/email_gateway.rb +0 -122
- data/lib/loqate/email_validation.rb +0 -81
- data/lib/loqate/phone_gateway.rb +0 -82
- data/lib/loqate/phone_number_validation.rb +0 -67
@@ -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
|
data/lib/loqate/gateway.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'loqate/
|
1
|
+
require 'loqate/address/gateway'
|
2
2
|
require 'loqate/bank/gateway'
|
3
|
-
require 'loqate/
|
4
|
-
require 'loqate/
|
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 [
|
31
|
+
# @return [Address::Gateway] An instance of an address gateway.
|
32
32
|
#
|
33
33
|
def address
|
34
|
-
@address ||=
|
34
|
+
@address ||= Address::Gateway.new(client)
|
35
35
|
end
|
36
36
|
|
37
37
|
# Gateway to the Phone number API.
|
38
38
|
#
|
39
|
-
# @return [
|
39
|
+
# @return [Phone::Gateway] An instance of a phone gateway.
|
40
40
|
#
|
41
41
|
def phone
|
42
|
-
@phone ||=
|
42
|
+
@phone ||= Phone::Gateway.new(client)
|
43
43
|
end
|
44
44
|
|
45
45
|
# Gateway to the Email verification APIs.
|
46
46
|
#
|
47
|
-
# @return [
|
47
|
+
# @return [Email::Gateway] An instance of an email gateway.
|
48
48
|
#
|
49
49
|
def email
|
50
|
-
@email ||=
|
50
|
+
@email ||= Email::Gateway.new(client)
|
51
51
|
end
|
52
52
|
|
53
53
|
# Gateway to the Bank verification APIs.
|
54
54
|
#
|
55
|
-
# @return [
|
55
|
+
# @return [Bank::Gateway] An instance of a bank gateway.
|
56
56
|
#
|
57
57
|
def bank
|
58
58
|
@bank ||= Bank::Gateway.new(client)
|