@@ -51,8 +51,11 @@ from email_validator import validate_email, EmailNotValidError
5151email = " my+address@mydomain.tld"
5252
5353try :
54- v = validate_email(email) # validate and get info
55- email = v[" email" ] # replace with normalized form
54+ # Validate.
55+ valid = validate_email(email)
56+
57+ # Update with the normalized form.
58+ email = valid.email
5659except EmailNotValidError as e:
5760 # email is not valid, exception message is human-readable
5861 print (str (e))
@@ -72,7 +75,7 @@ server. If you know ahead of time that SMTPUTF8 is not supported then
7275addresses that would require SMTPUTF8** :
7376
7477``` python
75- v = validate_email(email, allow_smtputf8 = False )
78+ valid = validate_email(email, allow_smtputf8 = False )
7679```
7780
7881Overview
@@ -83,17 +86,18 @@ takes an email address (either a `str` or ASCII `bytes`) and:
8386
8487- Raises a ` EmailNotValidError ` with a helpful, human-readable error
8588 message explaining why the email address is not valid, or
86- - Returns a dict with information about the deliverability of the
87- email address .
89+ - Returns an object with a normalized form of the email address and
90+ other information about it .
8891
8992When an email address is not valid, ` validate_email ` raises either an
9093` EmailSyntaxError ` if the form of the address is invalid or an
9194` EmailUndeliverableError ` if the domain name does not resolve. Both
9295exception classes are subclasses of ` EmailNotValidError ` , which in turn
9396is a subclass of ` ValueError ` .
9497
95- But when an email address is valid, a dict is returned containing
96- information that might aid deliverability (see below).
98+ But when an email address is valid, an object is returned containing
99+ a normalized form of the email address (which you should use!) and
100+ other information.
97101
98102The validator doesn't permit obsoleted forms of email addresses that no
99103one uses anymore even though they are still valid and deliverable, since
@@ -167,17 +171,17 @@ This will cause the validation function to raise a `EmailSyntaxError` if
167171delivery would require SMTPUTF8. That's just in those cases where
168172non-ASCII characters appear before the @-sign. If you do not set
169173` allow_smtputf8=False ` , you can also check the value of the ` smtputf8 `
170- field in the returned dict .
174+ field in the returned object .
171175
172176If your mail submission library doesn't support Unicode at all --- even
173177in the domain part of the address --- then immediately prior to mail
174178submission you must replace the email address with its ASCII-ized form.
175- This library gives you back the ASCII-ized form in the ` email_ascii `
176- field in the returned dict , which you can get like this:
179+ This library gives you back the ASCII-ized form in the ` ascii_email `
180+ field in the returned object , which you can get like this:
177181
178182``` python
179- v = validate_email(email, allow_smtputf8 = False )
180- email = v[ ' email_ascii ' ]
183+ valid = validate_email(email, allow_smtputf8 = False )
184+ email = valid.ascii_email
181185```
182186
183187The local part is left alone (if it has internationalized characters
@@ -204,8 +208,10 @@ validation provides the correctly normalized form of the given email
204208address:
205209
206210``` python
207- v = validate_email(email)
208- email = v[' email' ]
211+ valid = validate_email(" me@Domain.com" )
212+ email = valid.ascii_email
213+ print (email)
214+ # prints: me@domain.com
209215```
210216
211217Because you may get an email address in a variety of forms, you ought to
@@ -233,132 +239,112 @@ in the domain part, and possibly other
233239Examples
234240--------
235241
236- For the email address ` test@example.org ` , the returned dict is:
242+ For the email address ` test@joshdata.me ` , the returned object is:
237243
238244``` python
239- {
240- " email" : " test@example.org" ,
241- " email_ascii" : " test@example.org" ,
242- " local" : " test" ,
243- " domain" : " example.org" ,
244- " domain_i18n" : " example.org" ,
245-
246- " smtputf8" : false,
247-
248- " mx" : [
249- [
250- 0 ,
251- " 93.184.216.34"
252- ]
253- ],
254- " mx-fallback" : " A"
255- }
245+ ValidatedEmail(
246+ email = ' test@joshdata.me' ,
247+ local_part = ' test' ,
248+ domain = ' joshdata.me' ,
249+ ascii_email = ' test@joshdata.me' ,
250+ ascii_local_part = ' test' ,
251+ ascii_domain = ' joshdata.me' ,
252+ smtputf8 = False ,
253+ mx = [(10 , ' box.occams.info' )],
254+ mx_fallback_type = None )
256255```
257256
258- For the fictitious address ` example@良好Mail.中国 ` , which has an
259- internationalized domain but ASCII local part, the returned dict is:
257+ For the fictitious address ` example@ツ.life ` , which has an
258+ internationalized domain but ASCII local part, the returned object is:
260259
261260``` python
262- {
263- " email" : " example@良好mail.中国" ,
264- " email_ascii" : " example@xn--mail-p86gl01s.xn--fiqs8s" ,
265- " local" : " example" ,
266- " domain" : " xn--mail-p86gl01s.xn--fiqs8s" ,
267- " domain_i18n" : " 良好mail.中国" ,
268-
269- " smtputf8" : false,
270-
271- " mx" : [
272- [
273- 0 ,
274- " 218.241.116.40"
275- ]
276- ],
277- " mx-fallback" : " A"
278- }
261+ ValidatedEmail(
262+ email = ' example@ツ.life' ,
263+ local_part = ' example' ,
264+ domain = ' ツ.life' ,
265+ ascii_email = ' example@xn--bdk.life' ,
266+ ascii_local_part = ' example' ,
267+ ascii_domain = ' xn--bdk.life' ,
268+ smtputf8 = False )
269+
279270```
280271
281272Note that ` smtputf8 ` is ` False ` even though the domain part is
282273internationalized because
283274[ SMTPUTF8] ( https://tools.ietf.org/html/rfc6531 ) is only needed if the
284275local part of the address is internationalized (the domain part can be
285- converted to IDNA ASCII). Also note that the ` email ` and ` domain_i18n `
276+ converted to IDNA ASCII). Also note that the ` email ` and ` domain `
286277fields provide a normalized form of the email address and domain name
287278(casefolding and Unicode normalization as required by IDNA 2008).
288279
289- For the fictitious address ` 树大@occams.info ` , which has an
290- internationalized local part, the returned dict is:
280+ For the fictitious address ` ツ-test@joshdata.me ` , which has an
281+ internationalized local part, the returned object is:
291282
292283``` python
293- {
294- " email" : " 树大@occams.info" ,
295- " local" : " 树大" ,
296- " domain" : " occams.info" ,
297- " domain_i18n" : " occams.info" ,
298-
299- " smtputf8" : true,
300-
301- " mx" : [
302- [
303- 10 ,
304- " box.occams.info"
305- ]
306- ],
307- " mx-fallback" : false
308- }
284+ ValidatedEmail(
285+ email = ' ツ-test@joshdata.me' ,
286+ local_part = ' ツ-test' ,
287+ domain = ' joshdata.me' ,
288+ ascii_email = None ,
289+ ascii_local_part = None ,
290+ ascii_domain = ' joshdata.me' ,
291+ smtputf8 = True )
309292```
310293
311- Now ` smtputf8 ` is ` True ` and ` email_ascii ` is missing because the local
312- part of the address is internationalized. The ` local ` and ` email ` fields
294+ Now ` smtputf8 ` is ` True ` and ` ascii_email ` is ` None ` because the local
295+ part of the address is internationalized. The ` local_part ` and ` email ` fields
313296return the normalized form of the address: certain Unicode characters
314297(such as angstrom and ohm) may be replaced by other equivalent code
315298points (a-with-ring and omega).
316299
317300Return value
318301------------
319302
320- When an email address passes validation, the fields in the returned dict
303+ When an email address passes validation, the fields in the returned object
321304are:
322305
323306` email ` : The canonical form of the email address, mostly useful for
324- display purposes. This merely combines the ` local ` and ` domain_i18n `
307+ display purposes. This merely combines the ` local_part ` and ` domain `
325308 fields (see below).
326309
327- ` email_ascii ` : If present , an ASCII-only form of the email address by replacing the
310+ ` ascii_email ` : If set , an ASCII-only form of the email address by replacing the
328311 domain part with [ IDNA ASCII] ( https://tools.ietf.org/html/rfc5891 ) .
329312 This field will be present when an ASCII-only form of the email
330313 address exists (including if the email address is already ASCII). If
331314 the local part of the email address contains internationalized
332- characters, ` email_ascii ` will not be present.
315+ characters, ` ascii_email ` will be ` None ` . If set, it merely combines
316+ ` ascii_local_part ` and ` ascii_domain ` .
333317
334- ` local ` : The local part of the given email address (before the @-sign) with
318+ ` local_part ` : The local part of the given email address (before the @-sign) with
335319 Unicode NFC normalization applied.
336320
337- ` domain ` : The [ IDNA ASCII] ( https://tools.ietf.org/html/rfc5891 ) -encoded form
338- of the domain part of the given email address (after the @-sign), as
339- it would be transmitted on the wire.
321+ ` ascii_local_part ` : If set, the local part, which is composed of ASCII characters only.
340322
341- ` domain_i18n ` : The canonical internationalized form of the domain part of the
323+ ` domain ` : The canonical internationalized form of the domain part of the
342324 address, by round-tripping through IDNA ASCII. If the returned
343325 string contains non-ASCII characters, either the
344- [ SMTPUTF8] ( https://tools.ietf.org/html/rfc6531 ) feature of MTAs will
345- be required to transmit the message or else the email address's
346- domain part must be converted to IDNA ASCII first (given in the
347- returned ` domain ` field).
326+ [ SMTPUTF8] ( https://tools.ietf.org/html/rfc6531 ) feature of your
327+ mail relay will be required to transmit the message or else the
328+ email address's domain part must be converted to IDNA ASCII first
329+ (given in the returned ` domain ` field).
330+
331+ ` ascii_domain ` : The [ IDNA ASCII] ( https://tools.ietf.org/html/rfc5891 ) -encoded form
332+ of the domain part of the given email address (after the @-sign), as
333+ it would be transmitted on the wire.
348334
349335` smtputf8 ` : A boolean indicating that the
350- [ SMTPUTF8] ( https://tools.ietf.org/html/rfc6531 ) feature of MTAs will
351- be required to transmit messages to this address because the local
352- part of the address has non-ASCII characters (the local part cannot
353- be IDNA-encoded). If ` allow_smtputf8=False ` is passed as an
354- argument, this flag will always be false because an exception is
355- raised if it would have been true.
336+ [ SMTPUTF8] ( https://tools.ietf.org/html/rfc6531 ) feature of your
337+ mail relay will be required to transmit messages to this address
338+ because the local part of the address has non-ASCII characters (the
339+ local part cannot be IDNA-encoded). If ` allow_smtputf8=False ` is
340+ passed as an argument, this flag will always be false because an
341+ exception is raised if it would have been true.
356342
357343` mx ` : A list of (priority, domain) tuples of MX records specified in the
358344 DNS for the domain (see [ RFC 5321 section
359345 5] ( https://tools.ietf.org/html/rfc5321#section-5 ) ).
360346
361- ` mx-fallback ` : ` None ` if an ` MX ` record is found. If no MX records are actually
347+ ` mx_fallback_type ` : ` None ` if an ` MX ` record is found. If no MX records are actually
362348 specified in DNS and instead are inferred, through an obsolete
363349 mechanism, from A or AAAA records, the value is the type of DNS
364350 record used instead (` A ` or ` AAAA ` ).
@@ -406,5 +392,5 @@ To release:
406392 rm -rf dist
407393 python3 setup.py bdist_wheel
408394 twine upload dist/*
409- git tag v1.0.XXX
395+ git tag v1.0.XXX # replace with version in setup.py
410396 git push --tags
0 commit comments