Skip to content

Commit

Permalink
Merge branch 'release/2.0.0'
Browse files Browse the repository at this point in the history
* release/2.0.0:
  Updated readme, changed slow requests to return a BlazeVerify::Timeout error.
  Updated translations to not be namedspaced and also made it so we send accept_all to the API only when necessary.
  Added options validation to validator and additional test coverage.
  Added email_validator_test
  Added active record validator, removed faraday version restriction and updated readme.
  • Loading branch information
jclusso committed Nov 13, 2020
2 parents d040687 + 5a116e1 commit 2d6f965
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 38 deletions.
32 changes: 25 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
PATH
remote: .
specs:
blazeverify (1.3.1)
faraday (~> 0.13)
blazeverify (1.3.2)
faraday
faraday_middleware
net-http-persistent

GEM
remote: https://rubygems.org/
specs:
activemodel (6.0.3.4)
activesupport (= 6.0.3.4)
activesupport (6.0.3.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
ansi (1.5.0)
awesome_print (1.8.0)
builder (3.2.3)
coderay (1.1.2)
connection_pool (2.2.2)
faraday (0.17.0)
concurrent-ruby (1.1.7)
connection_pool (2.2.3)
faraday (1.1.0)
multipart-post (>= 1.2, < 3)
faraday_middleware (0.13.1)
faraday (>= 0.7.4, < 1.0)
ruby2_keywords
faraday_middleware (1.0.0)
faraday (~> 1.0)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
method_source (0.9.2)
minitest (5.11.3)
minitest-reporters (1.3.6)
Expand All @@ -26,18 +38,24 @@ GEM
minitest (>= 5.0)
ruby-progressbar
multipart-post (2.1.1)
net-http-persistent (3.1.0)
net-http-persistent (4.0.0)
connection_pool (~> 2.2)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rake (13.0.1)
ruby-progressbar (1.10.1)
ruby2_keywords (0.0.2)
thread_safe (0.3.6)
tzinfo (1.2.8)
thread_safe (~> 0.1)
zeitwerk (2.4.1)

PLATFORMS
ruby

DEPENDENCIES
activemodel
awesome_print
blazeverify!
bundler
Expand Down
48 changes: 37 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

This is the official ruby wrapper for the Blaze Verify API.

It also includes an Active Record (Rails) validator to verify email attributes.

## Documentation

See the [Ruby API docs](https://blazeverify.com/docs/api/?ruby).
Expand Down Expand Up @@ -47,18 +49,14 @@ BlazeVerify.verify('[email protected]')

#### Slow Email Server Handling

Some email servers are slow to respond. As a result the timeout may be reached
Some email servers are slow to respond. As a result, the timeout may be reached
before we are able to complete the verification process. If this happens, the
verification will continue in the background on our servers. We recommend
sleeping for at least one second and trying your request again. Re-requesting
the same verification with the same options will not impact your credit
allocation within a 5 minute window.

```ruby
{
"message" => "Your request is taking longer than normal. Please send your request again."
}
```
verification will continue in the background on our servers, and a
`BlazeVerify::TimeoutError` will be raised. We recommend sleeping for at least
one second and trying your request again. Re-requesting the same verification
with the same options will not impact your credit allocation within a 5 minute
window. You can test this behavior using a test key and the special
email `[email protected]`.

### Batch Verification

Expand Down Expand Up @@ -98,6 +96,34 @@ batch.status.reason_counts
batch.complete?
```

### Active Record Validator

Define a validator on an Active Record model for your email attribute(s).
It'll validate the attribute only when it's present and has changed.

#### Options

* `smtp`, `timeout`: Passed directly to API as options.
* `states`: An array of states you'd like to be considered valid.
* `free`, `role`, `disposable`, `accept_all`: If you'd like any of these to be valid.

```ruby
validates :email, email: {
smtp: true, states: %i[deliverable risky unknown],
free: true, role: true, disposable: false, accept_all: true, timeout: 3
}
```

#### Access Verification Result

You can define an `attr_accessor` with the following format to gain
access to the verification result.

```ruby
# [attribute_name]_verification_result
attr_accessor :email_verification_result
```

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Expand Down
3 changes: 2 additions & 1 deletion blazeverify.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Gem::Specification.new do |s|
end
s.require_paths = ['lib']

s.add_dependency 'faraday', '~> 0.13'
s.add_dependency 'faraday'
s.add_dependency 'faraday_middleware'
s.add_dependency 'net-http-persistent'
s.add_development_dependency 'bundler'
Expand All @@ -36,4 +36,5 @@ Gem::Specification.new do |s|
s.add_development_dependency 'awesome_print'
s.add_development_dependency 'minitest', '~> 5.0'
s.add_development_dependency 'minitest-reporters'
s.add_development_dependency 'activemodel'
end
10 changes: 10 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
en:
errors:
messages:
undeliverable: is undeliverable
risky: is risky
unknown: is unknown
free: is a free address
role: is a role address
disposable: is a disposable address
accept_all: is an accept-all address
27 changes: 26 additions & 1 deletion lib/blazeverify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
require 'blazeverify/resources/account'
require 'blazeverify/resources/batch_status'
require 'blazeverify/resources/verification'
if defined?(ActiveModel)
require 'blazeverify/email_validator'
I18n.load_path += Dir.glob(File.expand_path('../../config/locales/**/*', __FILE__))
end

module BlazeVerify
@max_network_retries = 1
Expand All @@ -26,7 +30,9 @@ def verify(email, smtp: nil, accept_all: nil, timeout: nil)
response = client.request(:get, 'verify', opts)

if response.status == 249
response.body
raise BlazeVerify::TimeoutError.new(
code: response.status, message: response.body
)
else
Verification.new(response.body)
end
Expand All @@ -37,4 +43,23 @@ def account
response = client.request(:get, 'account')
Account.new(response.body)
end


class Error < StandardError
attr_accessor :code, :message

def initialize(code: nil, message: nil)
@code = code
@message = message
end
end
class BadRequestError < Error; end
class UnauthorizedError < Error; end
class PaymentRequiredError < Error; end
class ForbiddenError < Error; end
class NotFoundError < Error; end
class TooManyRequestsError < Error; end
class InternalServerError < Error; end
class ServiceUnavailableError < Error; end
class TimeoutError < Error; end
end
17 changes: 0 additions & 17 deletions lib/blazeverify/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,4 @@ def self.should_retry?(error, num_retries)
false
end
end

class Error < StandardError
attr_accessor :code, :message

def initialize(code: nil, message: nil)
@code = code
@message = message
end
end
class BadRequestError < Error; end
class UnauthorizedError < Error; end
class PaymentRequiredError < Error; end
class ForbiddenError < Error; end
class NotFoundError < Error; end
class TooManyRequestsError < Error; end
class InternalServerError < Error; end
class ServiceUnavailableError < Error; end
end
70 changes: 70 additions & 0 deletions lib/blazeverify/email_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# ActiveRecord validator for validating an email address with Blaze Verify
#
# Usage:
# validates :email, presence: true, email: {
# smtp: true, states: %i[deliverable risky unknown],
# free: true, role: true, disposable: false, accept_all: true,
# timeout: 3
# }
#
# Define an attr_accessor to access verification results.
# attr_accessor :email_verification_result
#
class EmailValidator < ActiveModel::EachValidator

def validate_each(record, attribute, value)
smtp = boolean_option_or_raise_error(:smtp, true)

states = options.fetch(:states, %i(deliverable risky unknown))
allowed_states = %i[deliverable undeliverable risky unknown]
unless (states - allowed_states).empty?
raise ArgumentError, ":states must be an array of symbols containing "\
"any or all of :#{allowed_states.join(', :')}"
end

free = boolean_option_or_raise_error(:free, true)
role = boolean_option_or_raise_error(:role, true)
disposable = boolean_option_or_raise_error(:disposable, false)
accept_all = boolean_option_or_raise_error(:accept_all, true)

timeout = options.fetch(:timeout, 3)
unless timeout.is_a?(Integer) && timeout > 1
raise ArgumentError, ":timeout must be an Integer greater than 1"
end

return if record.errors[attribute].present?
return unless value.present?
return unless record.changes[attribute].present?

api_options = { timeout: timeout, smtp: smtp }
api_options[:accept_all] = true unless accept_all
ev = BlazeVerify.verify(value, api_options)

result_accessor = "#{attribute}_verification_result"
if record.respond_to?(result_accessor)
record.instance_variable_set("@#{result_accessor}", ev)
end

error ||= ev.state.to_sym unless states.include?(ev.state.to_sym)
error ||= :free if ev.free? && !free
error ||= :role if ev.role? && !role
error ||= :disposable if ev.disposable? && !disposable
error ||= :accept_all if ev.accept_all? && !accept_all

record.errors.add(attribute, error) if error
rescue BlazeVerify::Error
# silence errors
end

private

def boolean_option_or_raise_error(name, default)
option = options.fetch(name, default)
unless [true, false].include?(option)
raise ArgumentError, ":#{name} must by a Boolean"
end

option
end

end
2 changes: 1 addition & 1 deletion lib/blazeverify/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module BlazeVerify
VERSION = '1.3.1'
VERSION = '2.0.0'
end
6 changes: 6 additions & 0 deletions test/blazeverify_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,10 @@ def test_name_and_gender
end
end

def test_slow_verification
assert_raises(BlazeVerify::TimeoutError) do
BlazeVerify.verify('[email protected]')
end
end

end
Loading

0 comments on commit 2d6f965

Please sign in to comment.