Skip to content

Commit

Permalink
Added Email Verification support (#7)
Browse files Browse the repository at this point in the history
* Added email verification support

* Added tests for email verification

* Renamed files

* Updated readme for email verification

* Version bump

* Updated Table of contents

* Fixed post to get in verification api

* Changed post to get in test
  • Loading branch information
nithinsubhash authored Dec 17, 2020
1 parent b9a444f commit 16117d7
Show file tree
Hide file tree
Showing 10 changed files with 578 additions and 98 deletions.
531 changes: 434 additions & 97 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion fullcontact/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
]

__name__ = "python-fullcontact"
__version__ = "2.1.0"
__version__ = "2.1.1"
__author__ = "FullContact"
__author_email__ = "pypy@fullcontact.com"
__description__ = "Client library for FullContact V3 Enrich and Resolve APIs"
Expand Down
2 changes: 2 additions & 0 deletions fullcontact/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .api.resolve_api import ResolveApi as _ResolveApi
from .api.tags_api import TagsApi as _TagsApi
from .api.audience_api import AudienceApi as _AudienceApi
from .api.verification_api import VerificationApi as _EmailVerificationApi
from .config.client_config import ClientConfig as _ClientConfig


Expand Down Expand Up @@ -43,3 +44,4 @@ def __init__(self,
self.identity = _ResolveApi(client_config, headers)
self.tags = _TagsApi(client_config, headers)
self.audience = _AudienceApi(client_config, headers)
self.verification = _EmailVerificationApi(client_config, headers)
50 changes: 50 additions & 0 deletions fullcontact/api/verification_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from concurrent.futures import Future

from .base.base_api import BaseApi
from ..response.verification_response import EmailVerificationResponse
from ..schema.verification_schema import EmailVerificationRequestSchema


class VerificationApi(BaseApi):
_BASE_URL = "https://api.fullcontact.com/v2/"

_email_verification_endpoint = "verification/email"
_email_verification_request = EmailVerificationRequestSchema()
_email_verification_response = EmailVerificationResponse

def email(self, email: str, headers: dict = None) -> _email_verification_response:
r"""
Send a GET request to FullContact email verification API with the email
:param email: The email to be verified
:param headers: additional_headers to be passed. Authorization and Content-Type
are added automatically.
:return: requests.Response wrapped in _email_verification_response
"""
return self._validate_and_get_from_api(
self._email_verification_request,
self._email_verification_response,
self._email_verification_endpoint,
{
"email": email
},
headers
)

def email_async(self, email: str, headers: dict = None) -> Future:
r"""
Send a GET request to FullContact email verification API with the email asynchronously
:param email: The email to be verified
:param headers: additional_headers to be passed. Authorization and Content-Type
are added automatically.
:return: Future object. result() will return a requests.Response
wrapped in _email_verification_response
"""
return self.config.get_executor().submit(
self.email,
email,
headers
)
5 changes: 5 additions & 0 deletions fullcontact/response/verification_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .base.base import BaseApiResponse


class EmailVerificationResponse(BaseApiResponse):
pass
8 changes: 8 additions & 0 deletions fullcontact/schema/verification_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from .base.schema_base import BaseRequestSchema


class EmailVerificationRequestSchema(BaseRequestSchema):
schema_name = "Email Verification"
email: str

required_fields = ("email",)
3 changes: 3 additions & 0 deletions tests/resources/api_requests/verification_email_positive.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"email": "marquitaross006@gmail.com"
}
22 changes: 22 additions & 0 deletions tests/resources/api_responses/verification_email_positive.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"status": 200,
"requestId": "5b334bae-e205-423f-8a13-be669ad67806",
"emails": {
"marquitaross006@gmail.com": {
"message": "Valid email address",
"address": "marquitaross006@gmail.com",
"username": "marquitaross006",
"domain": "gmail.com",
"corrected": false,
"attributes": {
"validSyntax": true,
"deliverable": true,
"catchall": false,
"risky": false,
"disposable": false
},
"person": "https://api.fullcontact.com/v2/person.json?email=marquitaross006@gmail.com&apiKey=",
"sendSafely": true
}
}
}
51 changes: 51 additions & 0 deletions tests/test_email_verification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pytest

from fullcontact import FullContactClient
from fullcontact.config.client_config import Session
from .utils.error_messages import ErrorMessages
from .utils.mock_request import MockRequest
from .utils.mock_response import MockResponse

REQUEST_TYPE = "verification"
METHOD_EMAIL = "email"
SCENARIO_POSITIVE = "positive"


# MOCK API CALLS #######################################################################################################

@pytest.fixture
def mock_good_response(monkeypatch):
def mock_get(*args, **kwargs):
return MockResponse.get_mock_response(
REQUEST_TYPE,
method=METHOD_EMAIL,
test_scenario=SCENARIO_POSITIVE
)

monkeypatch.setattr(Session, "get", mock_get)


########################################################################################################################


class TestVerificationApi(object):

def setup(self):
self.fullcontact_client = FullContactClient(MockRequest.MOCK_TOKEN)

# Empty query provided)
def test_empty_query(self):
with pytest.raises(TypeError) as fc_exception:
self.fullcontact_client.verification.email()

assert str(fc_exception.value).startswith(ErrorMessages.VERIFICATION_EMAIL_MISSING_ARGUMENT)

# Send a good request
def test_good_requests(self, mock_good_response):
query = MockRequest.get_mock_request(REQUEST_TYPE, METHOD_EMAIL, SCENARIO_POSITIVE)
expected_result = MockResponse.get_mock_response(
REQUEST_TYPE, METHOD_EMAIL, SCENARIO_POSITIVE
)
result = self.fullcontact_client.verification.email(**query)
assert result.is_successful and \
result.get_status_code() == expected_result.status_code
2 changes: 2 additions & 0 deletions tests/utils/error_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ class ErrorMessages(object):

AUDIENCE_CREATE_MISSING_ARGUMENT = "create() missing 2 required positional arguments: 'webhookUrl' and 'tags'"
AUDIENCE_DOWNLOAD_MISSING_ARGUMENT = "download() missing 1 required positional argument: 'requestId'"

VERIFICATION_EMAIL_MISSING_ARGUMENT = "email() missing 1 required positional argument: 'email'"

0 comments on commit 16117d7

Please sign in to comment.