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