Re: Passing unicode to Email validator

Leandro Lucarella <[email protected]> Wed, 15 Oct 2008 15:39:13 -0300
Newsgroups gmane.comp.python.formencode
Message-ID <[email protected]>
Ian Bicking, el 15 de octubre a las 10:49 me escribiste:
> > Should Email validator first check if the domain is valid ASCII? (at least
> > if IDN[1] are not supported by pyDNS).
> 
> Yes, that seems reasonable.  I suppose it could also use the punycode 
> encoding.  I think that all IDNs are is punycode-encoded unicode, right?

This is what Wikipedia says at least =)

Here is a patch that implements IDNA support.

> > Should I send a patch? Or you think this is a pyDNS bug?
> > 
> > [1] http://en.wikipedia.org/wiki/Internationalized_domain_name
> 
> Yes, probably pyDNS should handle this more gracefully as well.

I'll try to contact pyDNS author to see if he can add IDNA support to it.

Thanks.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
Come on, now,
I hear you're feeling down.
Well I can ease your pain
Get you on your feet again.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

_______________________________________________
FormEncode-discuss mailing list
FormEncode-discuss-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/formencode-discuss
0001-Use-punycode-encoding-to-resolve-the-domain-in-Email.patch (text/x-diff, 4 KB)
>From 210f0a361e8dd0dcd60d192065fda8de3d115562 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella <[email protected]>
Date: Wed, 15 Oct 2008 13:42:25 -0300
Subject: [PATCH] Use punycode encoding to resolve the domain in Email validator

When trying to resolve a domain (via the resolve_domain option for the Email
validator), and the e-mail address is a unicode string (even when it only
contains ASCII characters) pyDNS goes crazy, and raises almost random
unicode errors. To avoid this, we encode the domain using punycode[1] first,
which it seems to be the encoding used for IDNA[2].

This patch does some identation fixes too.

[1] http://en.wikipedia.org/wiki/Punycode
[2] http://en.wikipedia.org/wiki/Internationalized_domain_name
---
 formencode/validators.py |   24 ++++++++++++++++--------
 1 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/formencode/validators.py b/formencode/validators.py
index 04587b9..564953e 100644
--- a/formencode/validators.py
+++ b/formencode/validators.py
@@ -47,6 +47,7 @@ import fieldstorage
 
 try:
     import DNS
+    from encodings import idna
     DNS.DiscoverNameServers()
     have_dns=True
 except ImportError:
@@ -1301,6 +1302,7 @@ class Email(FancyValidator):
         '[email protected]'
         >>> e.to_python('o*[email protected]')
         'o*[email protected]'
+        >>> # NOTE: If you do not have PyDNS installed this examples won't work:
         >>> e = Email(resolve_domain=True)
         >>> e.resolve_domain
         True
@@ -1308,11 +1310,16 @@ class Email(FancyValidator):
         '[email protected]'
         >>> e.to_python('test-gifGjc5/[email protected]')
         'test-gifGjc5/[email protected]'
-        >>> # NOTE: If you do not have PyDNS installed this example won't work:
+        >>> e.to_python((u'test@t\u016bdali\u0146.lv')
+        u'test@t\u016bdali\u0146.lv'
         >>> e.to_python('test-uihjHT2Oh7lHgoOn0jT6HnyRXQViASWaYGFN1R+/[email protected]')
         Traceback (most recent call last):
             ...
         Invalid: The domain of the email address does not exist (the portion after the @: thisdomaindoesnotexistithinkforsure.com)
+        >>> e.to_python(u'test@thisdomaindoesnotexistithinkforsure\xe1.com')
+        Traceback (most recent call last):
+            ...
+        Invalid: The domain of the email address does not exist (the portion after the @: thisdomaindoesnotexistithinkforsure\xe1.com)
         >>> e = Email(not_empty=False)
         >>> e.to_python('')
 
@@ -1364,22 +1371,23 @@ class Email(FancyValidator):
                 self.message('badUsername', state,
                              username=username),
                 value, state)
-        if not self.domainRE.search(domain):
+        idna_domain = '.'.join([idna.ToASCII(l) for l in domain.split('.')])
+        if not self.domainRE.search(idna_domain):
             raise Invalid(
                 self.message('badDomain', state,
                              domain=domain),
                 value, state)
         if self.resolve_domain:
             assert have_dns, "pyDNS should be available"
-	    try:
-                a=DNS.DnsRequest(domain, qtype='mx').req().answers
+            try:
+                a=DNS.DnsRequest(idna_domain, qtype='mx').req().answers
                 if not a:
-                    a=DNS.DnsRequest(domain, qtype='a').req().answers
+                    a=DNS.DnsRequest(idna_domain, qtype='a').req().answers
                 dnsdomains=[x['data'] for x in a]
-	    except (socket.error, DNS.DNSError), e:
+            except (socket.error, DNS.DNSError), e:
 		raise Invalid(
-		    self.message('socketError', state, error=e),
-		    value, state)
+                    self.message('socketError', state, error=e),
+                    value, state)
             if not dnsdomains:
                 raise Invalid(
                     self.message('domainDoesNotExist', state,
-- 
1.5.6.5