diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7728c8d..6e9dbc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,8 @@ name: CI on: push: - branches: [ master ] + branches: [ 'master' ] pull_request: - branches: [ master ] jobs: tests: @@ -12,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3'] + ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3', '3.4'] steps: - uses: actions/checkout@v4 diff --git a/.rubocop.yml b/.rubocop.yml index 6e0df8a..6c031db 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,2 @@ -inherit_from: .rubocop_todo.yml - inherit_gem: rubocop-cache-ventures: rubocop.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml deleted file mode 100644 index ffb0488..0000000 --- a/.rubocop_todo.yml +++ /dev/null @@ -1,7 +0,0 @@ -# This configuration was generated by -# `rubocop --auto-gen-config --exclude-limit 10000` -# on 2024-03-18 16:04:55 UTC using RuboCop version 1.62.1. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. diff --git a/.ruby-version b/.ruby-version index 15a2799..f989260 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.0 +3.4.4 diff --git a/Gemfile b/Gemfile index 9fed709..b736565 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ -source "https://rubygems.org" +source 'https://rubygems.org' # Specify your gem's dependencies in emailable-ruby.gemspec gemspec diff --git a/README.md b/README.md index 9eac84e..a94049a 100644 --- a/README.md +++ b/README.md @@ -30,17 +30,26 @@ Or install it yourself as: ## Usage -The library needs to be configured with your account's API key which is -available in your [Emailable Dashboard](https://app.emailable.com/api). Set -`Emailable.api_key` to its value: +### Authentication -### Setup +The Emailable API requires either an API key or an access token for +authentication. API keys can be created and managed in the +[Emailable Dashboard](https://app.emailable.com/api). + +An API key can be set globally for the Emailable client: + +```ruby +Emailable.api_key = 'your_api_key' +``` + +Or, you can specify an `api_key` or an `access_token` with each request: ```ruby -require 'emailable' +# set api_key at request time +Emailable.verify(api_key: 'your_api_key') -# set api key -Emailable.api_key = 'live_...' +# set access_token at request time +Emailable.verify(access_token: 'your_access_token') ``` ### Verification diff --git a/emailable.gemspec b/emailable.gemspec index 86ab291..d9bd82e 100644 --- a/emailable.gemspec +++ b/emailable.gemspec @@ -15,9 +15,9 @@ Gem::Specification.new do |s| s.email = 'support@emailable.com' s.license = 'MIT' s.metadata = { - "bug_tracker_uri" => "https://github.com/emailable/emailable-ruby/issues", - "documentation_uri" => "https://docs.emailable.com/?ruby", - "source_code_uri" => "https://github.com/emailable/emailable-ruby" + 'bug_tracker_uri' => 'https://github.com/emailable/emailable-ruby/issues', + 'documentation_uri' => 'https://emailable.com/docs/api/?ruby', + 'source_code_uri' => 'https://github.com/emailable/emailable-ruby' } s.files = `git ls-files`.split("\n") @@ -29,8 +29,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'bundler' s.add_development_dependency 'rake', '~> 13.0' - s.add_development_dependency 'pry' - s.add_development_dependency 'awesome_print' + s.add_development_dependency 'amazing_print' s.add_development_dependency 'minitest', '~> 5.0' s.add_development_dependency 'minitest-reporters' s.add_development_dependency 'activemodel' diff --git a/lib/emailable.rb b/lib/emailable.rb index 0dabd90..5d2cbb4 100644 --- a/lib/emailable.rb +++ b/lib/emailable.rb @@ -32,7 +32,7 @@ def verify(email, parameters = {}) parameters[:email] = email client = Emailable::Client.new - response = client.request(:get, 'verify', parameters) + response = client.request(:post, 'verify', parameters) if response.status == 249 raise Emailable::TimeoutError.new(response.body) @@ -41,9 +41,9 @@ def verify(email, parameters = {}) end end - def account + def account(parameters = {}) client = Emailable::Client.new - response = client.request(:get, 'account') + response = client.request(:get, 'account', parameters) Account.new(response.body) end diff --git a/lib/emailable/client.rb b/lib/emailable/client.rb index 7e2cc54..a61369f 100644 --- a/lib/emailable/client.rb +++ b/lib/emailable/client.rb @@ -17,18 +17,24 @@ def initialize end def request(method, endpoint, params = {}) - begin - tries ||= 3 + api_key = params.delete(:api_key) + access_token = params.delete(:access_token) - uri = URI("#{@base_url}/#{endpoint}") - params[:api_key] = Emailable.api_key + uri = URI("#{@base_url}/#{endpoint}") + headers = { + 'Authorization': "Bearer #{Emailable.api_key || api_key || access_token}", + 'Content-Type': 'application/json' + } + begin + tries ||= 3 http_response = if method == :get - uri.query = URI.encode_www_form(params) - @connection.get(uri) + uri.query = URI.encode_www_form(params) unless params.empty? + request = Net::HTTP::Get.new(uri, headers) + @connection.request(request) elsif method == :post - request = Net::HTTP::Post.new(uri, 'Content-Type': 'application/json') + request = Net::HTTP::Post.new(uri, headers) request.body = params.to_json @connection.request(request) end @@ -65,7 +71,7 @@ def create_connection(uri) if connection.respond_to?(:write_timeout=) connection.write_timeout = Emailable.write_timeout end - connection.use_ssl = uri.scheme == "https" + connection.use_ssl = uri.scheme == 'https' connection end diff --git a/lib/emailable/email_validator.rb b/lib/emailable/email_validator.rb index a430bd0..18a1d0e 100644 --- a/lib/emailable/email_validator.rb +++ b/lib/emailable/email_validator.rb @@ -18,7 +18,7 @@ def validate_each(record, attribute, value) 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 "\ + raise ArgumentError, ':states must be an array of symbols containing '\ "any or all of :#{allowed_states.join(', :')}" end @@ -29,7 +29,7 @@ def validate_each(record, attribute, value) timeout = options.fetch(:timeout, 3) unless timeout.is_a?(Integer) && timeout > 1 - raise ArgumentError, ":timeout must be an Integer greater than 1" + raise ArgumentError, ':timeout must be an Integer greater than 1' end return if record.errors[attribute].present? diff --git a/test/authentication_test.rb b/test/authentication_test.rb new file mode 100644 index 0000000..7ec2f82 --- /dev/null +++ b/test/authentication_test.rb @@ -0,0 +1,27 @@ +require 'test_helper' + +class AuthenticationTest < Minitest::Test + + def setup + @api_key = 'test_7aff7fc0142c65f86a00' + @email = 'jarrett@emailable.com' + @emails = ['jarrett@emailable.com', 'support@emailable.com'] + end + + def test_global_api_key_authentication + Emailable.api_key = @api_key + + refute_nil Emailable.verify(@email).domain + refute_nil Emailable.account.owner_email + refute_nil bid = Emailable::Batch.new(@emails).verify + refute_nil Emailable::Batch.new(bid).status.id + end + + def test_request_time_api_key_authentication + refute_nil Emailable.verify(@email, api_key: @api_key).domain + refute_nil Emailable.account(api_key: @api_key).owner_email + refute_nil bid = Emailable::Batch.new(@emails).verify(api_key: @api_key) + refute_nil Emailable::Batch.new(bid).status(api_key: @api_key).id + end + +end diff --git a/test/email_validator_test.rb b/test/email_validator_test.rb index 96c9394..f0b6541 100644 --- a/test/email_validator_test.rb +++ b/test/email_validator_test.rb @@ -1,4 +1,3 @@ -require 'active_model' require 'test_helper' class EmailValidatorTest < Minitest::Test diff --git a/test/test_helper.rb b/test/test_helper.rb index 1e1c196..4660ea3 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,6 +1,6 @@ +require 'active_model' require 'emailable' -require 'pry' require 'minitest/autorun' require 'minitest/reporters' Minitest::Reporters.use! [