Skip to content

Commit 16117d7

Browse files
Added Email Verification support (#7)
* 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
1 parent b9a444f commit 16117d7

File tree

10 files changed

+578
-98
lines changed

10 files changed

+578
-98
lines changed

README.md

Lines changed: 434 additions & 97 deletions
Large diffs are not rendered by default.

fullcontact/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
]
99

1010
__name__ = "python-fullcontact"
11-
__version__ = "2.1.0"
11+
__version__ = "2.1.1"
1212
__author__ = "FullContact"
1313
__author_email__ = "[email protected]"
1414
__description__ = "Client library for FullContact V3 Enrich and Resolve APIs"

fullcontact/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .api.resolve_api import ResolveApi as _ResolveApi
66
from .api.tags_api import TagsApi as _TagsApi
77
from .api.audience_api import AudienceApi as _AudienceApi
8+
from .api.verification_api import VerificationApi as _EmailVerificationApi
89
from .config.client_config import ClientConfig as _ClientConfig
910

1011

@@ -43,3 +44,4 @@ def __init__(self,
4344
self.identity = _ResolveApi(client_config, headers)
4445
self.tags = _TagsApi(client_config, headers)
4546
self.audience = _AudienceApi(client_config, headers)
47+
self.verification = _EmailVerificationApi(client_config, headers)

fullcontact/api/verification_api.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from concurrent.futures import Future
2+
3+
from .base.base_api import BaseApi
4+
from ..response.verification_response import EmailVerificationResponse
5+
from ..schema.verification_schema import EmailVerificationRequestSchema
6+
7+
8+
class VerificationApi(BaseApi):
9+
_BASE_URL = "https://api.fullcontact.com/v2/"
10+
11+
_email_verification_endpoint = "verification/email"
12+
_email_verification_request = EmailVerificationRequestSchema()
13+
_email_verification_response = EmailVerificationResponse
14+
15+
def email(self, email: str, headers: dict = None) -> _email_verification_response:
16+
r"""
17+
Send a GET request to FullContact email verification API with the email
18+
19+
:param email: The email to be verified
20+
:param headers: additional_headers to be passed. Authorization and Content-Type
21+
are added automatically.
22+
23+
:return: requests.Response wrapped in _email_verification_response
24+
"""
25+
return self._validate_and_get_from_api(
26+
self._email_verification_request,
27+
self._email_verification_response,
28+
self._email_verification_endpoint,
29+
{
30+
"email": email
31+
},
32+
headers
33+
)
34+
35+
def email_async(self, email: str, headers: dict = None) -> Future:
36+
r"""
37+
Send a GET request to FullContact email verification API with the email asynchronously
38+
39+
:param email: The email to be verified
40+
:param headers: additional_headers to be passed. Authorization and Content-Type
41+
are added automatically.
42+
43+
:return: Future object. result() will return a requests.Response
44+
wrapped in _email_verification_response
45+
"""
46+
return self.config.get_executor().submit(
47+
self.email,
48+
email,
49+
headers
50+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from .base.base import BaseApiResponse
2+
3+
4+
class EmailVerificationResponse(BaseApiResponse):
5+
pass
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from .base.schema_base import BaseRequestSchema
2+
3+
4+
class EmailVerificationRequestSchema(BaseRequestSchema):
5+
schema_name = "Email Verification"
6+
email: str
7+
8+
required_fields = ("email",)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"email": "[email protected]"
3+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"status": 200,
3+
"requestId": "5b334bae-e205-423f-8a13-be669ad67806",
4+
"emails": {
5+
6+
"message": "Valid email address",
7+
"address": "[email protected]",
8+
"username": "marquitaross006",
9+
"domain": "gmail.com",
10+
"corrected": false,
11+
"attributes": {
12+
"validSyntax": true,
13+
"deliverable": true,
14+
"catchall": false,
15+
"risky": false,
16+
"disposable": false
17+
},
18+
"person": "https://api.fullcontact.com/v2/[email protected]&apiKey=",
19+
"sendSafely": true
20+
}
21+
}
22+
}

tests/test_email_verification.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import pytest
2+
3+
from fullcontact import FullContactClient
4+
from fullcontact.config.client_config import Session
5+
from .utils.error_messages import ErrorMessages
6+
from .utils.mock_request import MockRequest
7+
from .utils.mock_response import MockResponse
8+
9+
REQUEST_TYPE = "verification"
10+
METHOD_EMAIL = "email"
11+
SCENARIO_POSITIVE = "positive"
12+
13+
14+
# MOCK API CALLS #######################################################################################################
15+
16+
@pytest.fixture
17+
def mock_good_response(monkeypatch):
18+
def mock_get(*args, **kwargs):
19+
return MockResponse.get_mock_response(
20+
REQUEST_TYPE,
21+
method=METHOD_EMAIL,
22+
test_scenario=SCENARIO_POSITIVE
23+
)
24+
25+
monkeypatch.setattr(Session, "get", mock_get)
26+
27+
28+
########################################################################################################################
29+
30+
31+
class TestVerificationApi(object):
32+
33+
def setup(self):
34+
self.fullcontact_client = FullContactClient(MockRequest.MOCK_TOKEN)
35+
36+
# Empty query provided)
37+
def test_empty_query(self):
38+
with pytest.raises(TypeError) as fc_exception:
39+
self.fullcontact_client.verification.email()
40+
41+
assert str(fc_exception.value).startswith(ErrorMessages.VERIFICATION_EMAIL_MISSING_ARGUMENT)
42+
43+
# Send a good request
44+
def test_good_requests(self, mock_good_response):
45+
query = MockRequest.get_mock_request(REQUEST_TYPE, METHOD_EMAIL, SCENARIO_POSITIVE)
46+
expected_result = MockResponse.get_mock_response(
47+
REQUEST_TYPE, METHOD_EMAIL, SCENARIO_POSITIVE
48+
)
49+
result = self.fullcontact_client.verification.email(**query)
50+
assert result.is_successful and \
51+
result.get_status_code() == expected_result.status_code

tests/utils/error_messages.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ class ErrorMessages(object):
2222

2323
AUDIENCE_CREATE_MISSING_ARGUMENT = "create() missing 2 required positional arguments: 'webhookUrl' and 'tags'"
2424
AUDIENCE_DOWNLOAD_MISSING_ARGUMENT = "download() missing 1 required positional argument: 'requestId'"
25+
26+
VERIFICATION_EMAIL_MISSING_ARGUMENT = "email() missing 1 required positional argument: 'email'"

0 commit comments

Comments
 (0)