Repository navigation
STF-2006: Add email verification inputs #476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -161,15 +161,17 @@ Score, Insights and Factors Example | |
| >>> 'shop_id': 's2123', | ||
| >>> 'type': 'purchase', | ||
| >>> 'transaction_id': 'txn3134133', | ||
| >>> 'time': '2014-04-12T23:20:50.052+00:00' | ||
| >>> 'time': '2026-10-05T23:20:50.052+00:00' | ||
| >>> }, | ||
| >>> 'account': { | ||
| >>> 'user_id': '3132', | ||
| >>> 'username_md5': '570a90bfbf8c7eab5dc5d4e26832d5b1' | ||
| >>> }, | ||
| >>> 'email': { | ||
| >>> 'address': '977577b140bfb7c516e4746204fbdb01', | ||
| >>> 'domain': 'maxmind.com' | ||
| >>> 'domain': 'maxmind.com', | ||
| >>> 'verification_time': '2026-10-01T14:25:00Z', | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: in this example, The phone Suggested fix: use verification times before the event time, or move 🤖 Comment by Claude Opus 5.5.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reply by Claude Opus 5.5 on Greg's behalf. Fixed in 4145164. The example event time is now 2026-10-05, after every verification time. This also fixes the phone examples. |
||
| >>> 'was_verification_successful': True, | ||
| >>> }, | ||
| >>> 'billing': { | ||
| >>> 'first_name': 'Jane', | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,6 +82,12 @@ def check_bool(self, obj: str, key: str) -> None: | |
| for bad in ("", 0, "True"): | ||
| self.check_invalid_transaction({obj: {key: bad}}) | ||
|
|
||
| def check_rfc3339_time(self, obj: str, key: str) -> None: | ||
| for good in GOOD_TIMES: | ||
| self.check_transaction({obj: {key: good}}) | ||
| for bad in BAD_TIMES + NON_STRING_TIMES: | ||
| self.check_invalid_transaction({obj: {key: bad}}) | ||
|
|
||
| def setup_report(self, report: dict[str, Any]) -> None: | ||
| if "ip_address" not in report: | ||
| report["ip_address"] = "1.2.3.4" | ||
|
|
@@ -186,18 +192,7 @@ def test_phone_was_verification_successful(self) -> None: | |
| self.check_bool(self.type, "phone_was_verification_successful") | ||
|
|
||
| def test_phone_verification_time(self) -> None: | ||
| for good in GOOD_TIMES: | ||
| self.check_transaction({self.type: {"phone_verification_time": good}}) | ||
| for bad in BAD_TIMES: | ||
| self.check_invalid_transaction( | ||
| {self.type: {"phone_verification_time": bad}}, | ||
| ) | ||
|
|
||
| def test_phone_verification_time_not_string(self) -> None: | ||
| for bad in NON_STRING_TIMES: | ||
| self.check_invalid_transaction( | ||
| {self.type: {"phone_verification_time": bad}}, | ||
| ) | ||
| self.check_rfc3339_time(self.type, "phone_verification_time") | ||
|
|
||
|
|
||
| class TestBillingAddress(AddressBase): | ||
|
|
@@ -371,6 +366,12 @@ def test_domain(self) -> None: | |
| for bad in ("bad ", " bad.com"): | ||
| self.check_invalid_transaction({"email": {"domain": bad}}) | ||
|
|
||
| def test_verification_time(self) -> None: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: these two tests are the third copy of the If someone later adds a new list of bad values to one copy, the other fields do not get that coverage. Each new RFC 3339 input also needs two more copied methods. Suggested fix: add a 🤖 Comment by Claude Opus 5.5.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reply by Claude Opus 5.5 on Greg's behalf. Fixed in 0b20a07. A |
||
| self.check_rfc3339_time("email", "verification_time") | ||
|
|
||
| def test_was_verification_successful(self) -> None: | ||
| self.check_bool("email", "was_verification_successful") | ||
|
|
||
|
|
||
| class TestEvent(ValidationBase, unittest.TestCase): | ||
| def test_party(self) -> None: | ||
|
|
@@ -386,14 +387,7 @@ def test_shop_id(self) -> None: | |
| self.check_transaction_str_type("event", "shop_id") | ||
|
|
||
| def test_time(self) -> None: | ||
| for good in GOOD_TIMES: | ||
| self.check_transaction({"event": {"time": good}}) | ||
| for bad in BAD_TIMES: | ||
| self.check_invalid_transaction({"event": {"time": bad}}) | ||
|
|
||
| def test_time_not_string(self) -> None: | ||
| for bad in NON_STRING_TIMES: | ||
| self.check_invalid_transaction({"event": {"time": bad}}) | ||
| self.check_rfc3339_time("event", "time") | ||
|
|
||
| def test_time_impossible_date_message(self) -> None: | ||
| transaction: dict[str, Any] = {"event": {"time": "2026-02-30T10:00:00Z"}} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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( | ||
|
|
@@ -292,7 +294,13 @@ def test_200_with_email_hashing(self) -> None: | |
| status=200, | ||
| ) | ||
|
|
||
| request = {"email": {"address": "Test+ignore@maxmind.com"}} | ||
| request = { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: this test now is the only check that If a later change to Suggested fix: add a row to 🤖 Comment by Claude Opus 5.5.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reply by Claude Opus 5.5 on Greg's behalf. Fixed in 463ab2c. |
||
| "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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this bullet does not say that
verification_timemust be an RFC 3339 string. Python users can easily pass adatetimeobject.For example,
{"email": {"verification_time": datetime.now(timezone.utc)}}fails validation withInvalidRequestError(NON_STRING_TIMESin the tests confirms this). Withvalidate=False, it fails with a JSON serializationTypeError. This client has no per-field docstrings, so HISTORY.rst and the README are the only places that can state the format. The phone bullet above has the same gap forphone_verification_time.Suggested fix: add a sentence such as "
verification_timemust be an RFC 3339 date-time string."🤖 Comment by Claude Opus 5.5.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure it's necessary