1# Copyright (C) 2007-2020 by the Free Software Foundation, Inc. 2# 3# This file is part of GNU Mailman. 4# 5# GNU Mailman is free software: you can redistribute it and/or modify it under 6# the terms of the GNU General Public License as published by the Free 7# Software Foundation, either version 3 of the License, or (at your option) 8# any later version. 9# 10# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT 11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13# more details. 14# 15# You should have received a copy of the GNU General Public License along with 16# GNU Mailman. If not, see <https://www.gnu.org/licenses/>. 17 18"""Interface for email address related information.""" 19 20from mailman.interfaces.errors import MailmanError 21from public import public 22from zope.interface import Attribute, Interface 23 24 25@public 26class EmailError(MailmanError): 27 """A generic text email address-related error occurred.""" 28 29 def __init__(self, email): 30 super().__init__() 31 self.email = email 32 33 def __str__(self): 34 return self.email 35 36 37@public 38class AddressError(MailmanError): 39 """A generic IAddress-related error occurred.""" 40 41 def __init__(self, address): 42 super().__init__() 43 self.address = address 44 45 def __str__(self): 46 return str(self.address) 47 48 49@public 50class ExistingAddressError(AddressError): 51 """The given email address already exists.""" 52 53 54@public 55class AddressAlreadyLinkedError(AddressError): 56 """The address is already linked to a user.""" 57 58 59@public 60class AddressNotLinkedError(AddressError): 61 """The address is not linked to the user.""" 62 63 64@public 65class InvalidEmailAddressError(EmailError): 66 """Email address is invalid.""" 67 68 69@public 70class AddressVerificationEvent: 71 """Triggered when an address gets verified or unverified.""" 72 73 def __init__(self, address): 74 self.address = address 75 76 def __str__(self): 77 return '<{} {} {}>'.format( 78 self.__class__.__name__, 79 self.address.email, 80 ('unverified' if self.address.verified_on is None 81 else self.address.verified_on)) 82 83 84@public 85class IAddress(Interface): 86 """Email address related information.""" 87 88 email = Attribute( 89 """Read-only text email address.""") 90 91 original_email = Attribute( 92 """Read-only original case-preserved email address. 93 94 For almost all intents and purposes, email addresses in Mailman are 95 case insensitive, however because RFC 2821 allows for case sensitive 96 local parts, Mailman preserves the case of the original email address 97 when delivering a message to the user. 98 99 `original_email` will be the same as `email` if the original email 100 address was all lower case. Otherwise `original_email` will be the 101 case preserved email address; `email` will always be lower case. 102 """) 103 104 display_name = Attribute( 105 """Optional display name associated with the email address.""") 106 107 registered_on = Attribute( 108 """The date and time at which this email address was registered. 109 110 Registeration is really the date at which this address became known to 111 us. It may have been explicitly registered by a user, or it may have 112 been implicitly registered, e.g. by showing up in a nonmember 113 posting.""") 114 115 verified_on = Attribute( 116 """The date and time at which this email address was validated, or 117 None if the email address has not yet been validated. The specific 118 method of validation is not defined here.""") 119 120 preferences = Attribute( 121 """This address's preferences.""") 122 123 124@public 125class IEmailValidator(Interface): 126 """An email validator.""" 127 128 def is_valid(email): 129 """Check if an email address if valid. 130 131 :param email: A text email address. 132 :type email: str 133 :return: A flag indicating whether the email address is okay or not. 134 :rtype: bool 135 """ 136 137 def validate(email): 138 """Validate an email address. 139 140 :param email: A text email address. 141 :type email: str 142 :raise InvalidEmailAddressError: when `email` is deemed invalid. 143 """ 144