diff --git a/email_validator/__main__.py b/email_validator/__main__.py index 107b08b..1d0d779 100644 --- a/email_validator/__main__.py +++ b/email_validator/__main__.py @@ -33,10 +33,15 @@ def main(dns_resolver: Optional[_Resolver] = None) -> None: 'ALLOW_DISPLAY_NAME', 'GLOBALLY_DELIVERABLE', 'CHECK_DELIVERABILITY', 'TEST_ENVIRONMENT'): if varname in os.environ: - options[varname.lower()] = bool(os.environ[varname]) + # bool() would make any non-empty string True, so e.g. + # CHECK_DELIVERABILITY=false would enable the check. + options[varname.lower()] = os.environ[varname].strip().lower() not in ('', '0', 'false', 'no', 'off') for varname in ('DEFAULT_TIMEOUT',): if varname in os.environ: - options[varname.lower()] = float(os.environ[varname]) + # DEFAULT_TIMEOUT is a module-level default read by + # caching_resolver(), not a keyword argument of validate_email. + import email_validator + email_validator.DEFAULT_TIMEOUT = int(os.environ[varname]) if len(sys.argv) == 1: # Validate the email addresses passed line-by-line on STDIN. diff --git a/tests/test_main.py b/tests/test_main.py index b8c6583..5bc7d91 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -81,6 +81,43 @@ def test_main_multi_input(monkeypatch: pytest.MonkeyPatch, capsys: pytest.Captur assert test_cases[3] in stdout +@pytest.mark.parametrize('value', ['false', 'False', 'FALSE', '0', 'no', 'off', ' ']) +def test_main_falsy_boolean_option_from_env(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], value: str) -> None: + # Options are set from environment variables of the same name in upper + # case. A falsy value there must turn the option off, not on. + import json + test_email = 'test@xkxufoekjvjfjeodlfmdfjcu.com' # this domain does not exist in DNS + monkeypatch.setenv('CHECK_DELIVERABILITY', value) + monkeypatch.setattr('sys.argv', ['email_validator', test_email]) + validator_command_line_tool(dns_resolver=RESOLVER) + stdout, _ = capsys.readouterr() + assert json.loads(str(stdout))["normalized"] == test_email + + +@pytest.mark.parametrize('value', ['false', 'False', '0', 'no', 'off', ' ']) +def test_main_falsy_test_environment_from_env(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], value: str) -> None: + # test_environment off means the reserved "test" domain names are rejected. + monkeypatch.setenv('TEST_ENVIRONMENT', value) + monkeypatch.setattr('sys.argv', ['email_validator', 'me@foo.test']) + validator_command_line_tool(dns_resolver=RESOLVER) + stdout, _ = capsys.readouterr() + assert stdout == 'The part after the @-sign is a special-use or reserved name that cannot be used with email.\n' + + +def test_main_default_timeout_from_env(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: + import json + import email_validator + test_email = 'google@google.com' + # Set up the restore of the module-level default, which main() overwrites. + monkeypatch.setattr('email_validator.DEFAULT_TIMEOUT', email_validator.DEFAULT_TIMEOUT) + monkeypatch.setenv('DEFAULT_TIMEOUT', '5') + monkeypatch.setattr('sys.argv', ['email_validator', test_email]) + validator_command_line_tool(dns_resolver=RESOLVER) + stdout, _ = capsys.readouterr() + assert json.loads(str(stdout))["normalized"] == test_email + assert email_validator.DEFAULT_TIMEOUT == 5 + + def test_bytes_input() -> None: input_email = b"testaddr@example.tld" valid_email = validate_email(input_email, check_deliverability=False)