Return the addr-spec portion of an email address. Raises ValueError for invalid addresses, including CR/NL injection. If force_ascii is True, apply IDNA encoding to non-ASCII domains, and raise ValueError for non-ASCII local-parts (which can't be encoded). O
(self, address, force_ascii=True)
| 202 | return True |
| 203 | |
| 204 | def prep_address(self, address, force_ascii=True): |
| 205 | """ |
| 206 | Return the addr-spec portion of an email address. Raises ValueError for |
| 207 | invalid addresses, including CR/NL injection. |
| 208 | |
| 209 | If force_ascii is True, apply IDNA encoding to non-ASCII domains, and |
| 210 | raise ValueError for non-ASCII local-parts (which can't be encoded). |
| 211 | Otherwise, leave Unicode characters unencoded (e.g., for sending with |
| 212 | SMTPUTF8). |
| 213 | """ |
| 214 | address = force_str(address) |
| 215 | parsed = AddressHeader.value_parser(address) |
| 216 | defects = set(str(defect) for defect in parsed.all_defects) |
| 217 | # Django allows local mailboxes like "From: webmaster" (#15042). |
| 218 | defects.discard("addr-spec local part with no domain") |
| 219 | if not force_ascii: |
| 220 | # PY315: Non-ASCII local-part is valid with SMTPUTF8. This check |
| 221 | # can be removed once the minimum supported Python version is 3.15 |
| 222 | # (so the fix for https://github.com/python/cpython/issues/81074 |
| 223 | # is in all supported versions). |
| 224 | defects.discard("local-part contains non-ASCII characters)") |
| 225 | if defects: |
| 226 | raise ValueError(f"Invalid address {address!r}: {'; '.join(defects)}") |
| 227 | |
| 228 | mailboxes = parsed.all_mailboxes |
| 229 | if len(mailboxes) != 1: |
| 230 | raise ValueError(f"Invalid address {address!r}: must be a single address") |
| 231 | |
| 232 | mailbox = mailboxes[0] |
| 233 | if force_ascii and mailbox.domain and not mailbox.domain.isascii(): |
| 234 | # Re-compose an addr-spec with the IDNA encoded domain. |
| 235 | domain = punycode(mailbox.domain) |
| 236 | return str(Address(username=mailbox.local_part, domain=domain)) |
| 237 | else: |
| 238 | return mailbox.addr_spec |