Repository: certbot/certbot

Issue:
User friendlyness fail : letsencrypt does not re-prompt if invalid email domain is keyed in
Issue: If an invalid email DOMAIN is entered, the program simply aborts without attempting to retry prompt.

Platform: OS X (10.11.3)
Version: letsencrypt 0.4.2

Command used:
/Users/admin/.local/share/letsencrypt/bin/letsencrypt run --test-cert -w /Users/admin/test-cert  -d example.com -d www.example.com --config-dir /usr/local/etc/letsencrypt --work-dir /Users/admin/tmp --logs-dir /Users/admin/test-cert-logs

Prompt:
Enter email address (used for urgent notices and lost key recovery)  
me@here.blahblahblah

An unexpected error occurred:
The provided email for a registration was invalid :: DNS problem: NXDOMAIN looking up MX for {invalid domain}
Please see the logfiles in /Users/admin/test-cert-logs for more details.

(with --debug)
Traceback (most recent call last):
  File "/Users/admin/.local/share/letsencrypt/bin/letsencrypt", line 11, in <module>
    sys.exit(main())
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/letsencrypt/cli.py", line 1993, in main
    return config.func(config, plugins)
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/letsencrypt/cli.py", line 661, in run
    le_client = _init_le_client(config, authenticator, installer)
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/letsencrypt/cli.py", line 207, in _init_le_client
    acc, acme = _determine_account(config)
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/letsencrypt/cli.py", line 192, in _determine_account
    config, account_storage, tos_cb=_tos_cb)
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/letsencrypt/client.py", line 118, in register
    regr = perform_registration(acme, config)
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/letsencrypt/client.py", line 148, in perform_registration
    return acme.register(messages.NewRegistration.from_data(email=config.email))
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/acme/client.py", line 98, in register
    response = self.net.post(self.directory[new_reg], new_reg)
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/acme/client.py", line 652, in post
    return self._check_response(response, content_type=content_type)
  File "/Users/admin/.local/share/letsencrypt/lib/python2.7/site-packages/acme/client.py", line 568, in _check_response
    raise messages.Error.from_json(jobj)
Error: urn:acme:error:invalidEmail :: The provided email for a registration was invalid :: DNS problem: NXDOMAIN looking up MX for {invalid domain}



Discussion:
Verified this problem. The client is supposed to prompt the user again without exiting. The issue is that the error is not being detected properly. I'll submit a PR for this today.


Resolving patch:
diff --git a/letsencrypt/client.py b/letsencrypt/client.py
--- a/letsencrypt/client.py
+++ b/letsencrypt/client.py
@@ -146,8 +146,7 @@ def perform_registration(acme, config):
     try:
         return acme.register(messages.NewRegistration.from_data(email=config.email))
     except messages.Error as e:
-        err = repr(e)
-        if "MX record" in err or "Validation of contact mailto" in err:
+        if e.typ == "urn:acme:error:invalidEmail":
             config.namespace.email = display_ops.get_email(more=True, invalid=True)
             return perform_registration(acme, config)
         else:


Test patch:
diff --git a/letsencrypt/tests/client_test.py b/letsencrypt/tests/client_test.py
--- a/letsencrypt/tests/client_test.py
+++ b/letsencrypt/tests/client_test.py
@@ -63,8 +63,8 @@ def test_it(self):
     @mock.patch("letsencrypt.client.display_ops.get_email")
     def test_email_retry(self, _rep, mock_get_email):
         from acme import messages
-        msg = "Validation of contact mailto:sousaphone@improbablylongggstring.tld failed"
-        mx_err = messages.Error(detail=msg, typ="malformed", title="title")
+        msg = "DNS problem: NXDOMAIN looking up MX for example.com"
+        mx_err = messages.Error(detail=msg, typ="urn:acme:error:invalidEmail")
         with mock.patch("letsencrypt.client.acme_client.Client") as mock_client:
             mock_client().register.side_effect = [mx_err, mock.MagicMock()]
             self._call()