Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ History
``phone_was_verification_successful``, and ``phone_verification_time``
inputs to the ``/billing`` and ``/shipping`` request objects. They describe
the most recent verification of the phone number.
* Added the ``verification_time`` and ``was_verification_successful`` inputs
to the ``/email`` request object. They describe the most recent
verification of the email address.
* The RFC 3339 check on ``/event/time`` and ``phone_verification_time`` now
rejects more values that the web service rejects, such as February 30,
hour 24, an offset of 24 hours or more, and a lowercase ``t`` or ``z``.
Expand Down
4 changes: 3 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ Score, Insights and Factors Example
>>> },
>>> 'email': {
>>> 'address': '977577b140bfb7c516e4746204fbdb01',
>>> 'domain': 'maxmind.com'
>>> 'domain': 'maxmind.com',
>>> 'verification_time': '2026-10-01T14:25:00Z',
>>> 'was_verification_successful': True,
>>> },
>>> 'billing': {
>>> 'first_name': 'Jane',
Expand Down
2 changes: 2 additions & 0 deletions src/minfraud/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,8 @@ def _uri(s: str) -> str:
"email": {
"address": _email_or_md5,
"domain": _hostname,
"verification_time": _rfc3339_datetime,
"was_verification_successful": bool,
},
"event": {
"party": _event_party,
Expand Down
4 changes: 3 additions & 1 deletion tests/data/full-transaction-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
},
"email": {
"address": "977577b140bfb7c516e4746204fbdb01",
"domain": "maxmind.com"
"domain": "maxmind.com",
"verification_time": "2026-10-01T14:25:00Z",
"was_verification_successful": true
},
"billing": {
"first_name": "First",
Expand Down
13 changes: 13 additions & 0 deletions tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,19 @@ def test_domain(self) -> None:
for bad in ("bad ", " bad.com"):
self.check_invalid_transaction({"email": {"domain": bad}})

def test_verification_time(self) -> None:
for good in GOOD_TIMES:
self.check_transaction({"email": {"verification_time": good}})
for bad in BAD_TIMES:
self.check_invalid_transaction({"email": {"verification_time": bad}})

def test_verification_time_not_string(self) -> None:
for bad in NON_STRING_TIMES:
self.check_invalid_transaction({"email": {"verification_time": bad}})

def test_was_verification_successful(self) -> None:
self.check_bool("email", "was_verification_successful")


class TestEvent(ValidationBase, unittest.TestCase):
def test_party(self) -> None:
Expand Down
10 changes: 9 additions & 1 deletion tests/test_webservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ def test_200_with_email_hashing(self) -> None:
"email": {
"address": "977577b140bfb7c516e4746204fbdb01",
"domain": "maxmind.com",
"verification_time": "2026-10-01T14:25:00Z",
"was_verification_successful": False,
},
},
).respond_with_data(
Expand All @@ -292,7 +294,13 @@ def test_200_with_email_hashing(self) -> None:
status=200,
)

request = {"email": {"address": "Test+ignore@maxmind.com"}}
request = {
"email": {
"address": "Test+ignore@maxmind.com",
"verification_time": "2026-10-01T14:25:00Z",
"was_verification_successful": False,
},
}
self.run_client(getattr(self.client, self.type)(request, hash_email=True))

# This was fixed in https://github.com/maxmind/minfraud-api-python/pull/78
Expand Down
Loading