Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/validators/email.py: 80%

15 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:08 +0000

1"""eMail.""" 

2# -*- coding: utf-8 -*- 

3 

4# standard 

5import re 

6 

7# local 

8from .hostname import hostname 

9from .utils import validator 

10 

11 

12@validator 

13def email( 

14 value: str, 

15 /, 

16 *, 

17 ipv6_address: bool = False, 

18 ipv4_address: bool = False, 

19 simple_host: bool = False, 

20 rfc_1034: bool = False, 

21 rfc_2782: bool = False, 

22): 

23 """Validate an email address. 

24 

25 This was inspired from [Django's email validator][1]. 

26 Also ref: [RFC 1034][2], [RFC 5321][3] and [RFC 5322][4]. 

27 

28 [1]: https://github.com/django/django/blob/main/django/core/validators.py#L174 

29 [2]: https://www.rfc-editor.org/rfc/rfc1034 

30 [3]: https://www.rfc-editor.org/rfc/rfc5321 

31 [4]: https://www.rfc-editor.org/rfc/rfc5322 

32 

33 Examples: 

34 >>> email('someone@example.com') 

35 # Output: True 

36 >>> email('bogus@@') 

37 # Output: ValidationFailure(email=email, args={'value': 'bogus@@'}) 

38 

39 Args: 

40 value: 

41 eMail string to validate. 

42 ipv6_address: 

43 When the domain part is an IPv6 address. 

44 ipv4_address: 

45 When the domain part is an IPv4 address. 

46 simple_host: 

47 When the domain part is a simple hostname. 

48 rfc_1034: 

49 Allow trailing dot in domain name. 

50 Ref: [RFC 1034](https://www.rfc-editor.org/rfc/rfc1034). 

51 rfc_2782: 

52 Domain name is of type service record. 

53 Ref: [RFC 2782](https://www.rfc-editor.org/rfc/rfc2782). 

54 

55 Returns: 

56 (Literal[True]): 

57 If `value` is a valid eMail. 

58 (ValidationFailure): 

59 If `value` is an invalid eMail. 

60 

61 > *New in version 0.1.0*. 

62 """ 

63 if not value or value.count("@") != 1: 

64 return False 

65 

66 username_part, domain_part = value.rsplit("@", 1) 

67 

68 if len(username_part) > 64 or len(domain_part) > 253: 

69 # ref: RFC 1034 and 5231 

70 return False 

71 

72 if ipv6_address or ipv4_address: 

73 if domain_part.startswith("[") and domain_part.endswith("]"): 

74 # ref: RFC 5321 

75 domain_part = domain_part.lstrip("[").rstrip("]") 

76 else: 

77 return False 

78 

79 return ( 

80 bool( 

81 hostname( 

82 domain_part, 

83 skip_ipv6_addr=not ipv6_address, 

84 skip_ipv4_addr=not ipv4_address, 

85 may_have_port=False, 

86 maybe_simple=simple_host, 

87 rfc_1034=rfc_1034, 

88 rfc_2782=rfc_2782, 

89 ) 

90 ) 

91 if re.match( 

92 # dot-atom 

93 r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$" 

94 # quoted-string 

95 + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"$)', 

96 username_part, 

97 re.IGNORECASE, 

98 ) 

99 else False 

100 )