The email module of Python through 3.11.3 incorrectly parses e-mail addresses that contain a special character. The wrong portion of an RFC2822 header is identified as the value of the addr-spec. In some applications, an attacker can bypass a protection mechanism in which application access is granted only after verifying receipt of e-mail to a specific domain (e.g., only @company.example.com addresses may be used for signup). This occurs in email/_parseaddr.py in recent versions of Python.
# Bug report

I have discovered a way to cause `email.utils.parsaddr()` and `email.utils.getaddresses()` to erroneously return the Real Name portion of a RFC 2822 Address Header in the Email Address portion of the returned tuple. This vulnerability enables me to bypass security systems which allow or deny access or actions based on the email address.

Example one, this is an issue if the system should only allow for accounts to be created for email addresses which are part of a whitelist e.g. only government emails, or a blacklist e.g. block `attacker@example.com`. If ether `parseaddr()` or `getaddresses()` is used to parse the Address Header and the Email Address part of the returned tuple is checked ageist the whitelist/blacklist, it would be checking the value in the Real Name part of of the Address Header instead of the Email Address. Then, to finish account registration the system sends the reply to the full Address Header, which is normally the case, the reply would be sent to the actual Email Address and not the Real Name part of the header.

This is similar to the type of attack which was used to exploit the French governments Tchap chat system a few years back.

Tchap: The super (not) secure app of the French government
https://medium.com/@fs0c131y/tchap-the-super-not-secure-app-of-the-french-government-84b31517d144

Example two, this would also be an issue if an email security system is written in Python and uses `parseaddr()` or `getaddresses()` to parse the Address Header of incoming email and then checks the Email Address part of the tuple against a whitelist/blacklist. I can use this vulnerability to trick that system into checking the Real Name part of the Address Header instead of the actual Email Address which would have been blocked. Then after this, the email system which actually replies to the email dose not use Python's `parseaddr()` or `getaddresses()` functions to get the email address, or simply uses the full Address Header to send a reply.

For all of these test cases Golang returns a Parsing Error, but all versions of Python including Python 2, Python 3, and the most resent version in Github all result in the Real Name part of the address being returned in the Email Address part of the tuple.

**NOTE: This issue has been assigned: CVE-2023-27043
Link: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-27043**

**[VulnerabilityType Other]
CWE-1286: Improper Validation of Syntactic Correctness of Input**

I have been in communication with security@python.org about this issue, and was told they are fine with addressing this issue publicly. Additionally, I have created a PR which will detect these parsing errors and return an empty tuple to indicate a parsing error instead of returning the erroneous output.

Example Script to show this erroneous output:
```
from email.utils import parseaddr
rfc2822_ADDRESS = "Thomas Dwyer<tdwyer@example.org>"
print("Valid RFC2822 Address Parse Output")
parseaddr(rfc2822_ADDRESS)
print()
print("Test output...")
print()
specials = '()<>@,:;.\"[]'
a = "alice@example.org"
b = "<bob@example.org>"
for i in specials:
    c = a + i + b
    print(c)
    parseaddr(c)
```

Example Golang program which shows that Golang returns a parsing error:
```
package main

import (
 "fmt"
 "net/mail"
)

func main() {
   fmt.Println((&mail.AddressParser{}).Parse("Thomas Dwyer <thomas@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("thomas@example.org"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org(<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org)<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org<<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org><bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org@<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org,bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org:<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org;<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org.<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse(`alice@example.org"<bob@example.org>`))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org[<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org]<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org<bob@example.org>"))
}
```


# Your environment

- CPython versions tested on: All versions of Python

<!-- gh-linked-prs -->
### Linked PRs
* gh-102990
* gh-105127
* gh-105128
* gh-106612
* gh-108250
* gh-111116
<!-- /gh-linked-prs -->

[CVE-2023-27043] Parsing errors in email/_parseaddr.py lead to incorrect value in email address part of tuple
This is a GitHub Issue
repo:cpython
owner:python
Title : [CVE-2023-27043] Parsing errors in email/_parseaddr.py lead to incorrect value in email address part of tuple
Issue date:

--- start body ---
# Bug report

I have discovered a way to cause `email.utils.parsaddr()` and `email.utils.getaddresses()` to erroneously return the Real Name portion of a RFC 2822 Address Header in the Email Address portion of the returned tuple. This vulnerability enables me to bypass security systems which allow or deny access or actions based on the email address.

Example one, this is an issue if the system should only allow for accounts to be created for email addresses which are part of a whitelist e.g. only government emails, or a blacklist e.g. block `attacker@example.com`. If ether `parseaddr()` or `getaddresses()` is used to parse the Address Header and the Email Address part of the returned tuple is checked ageist the whitelist/blacklist, it would be checking the value in the Real Name part of of the Address Header instead of the Email Address. Then, to finish account registration the system sends the reply to the full Address Header, which is normally the case, the reply would be sent to the actual Email Address and not the Real Name part of the header.

This is similar to the type of attack which was used to exploit the French governments Tchap chat system a few years back.

Tchap: The super (not) secure app of the French government
https://medium.com/@fs0c131y/tchap-the-super-not-secure-app-of-the-french-government-84b31517d144

Example two, this would also be an issue if an email security system is written in Python and uses `parseaddr()` or `getaddresses()` to parse the Address Header of incoming email and then checks the Email Address part of the tuple against a whitelist/blacklist. I can use this vulnerability to trick that system into checking the Real Name part of the Address Header instead of the actual Email Address which would have been blocked. Then after this, the email system which actually replies to the email dose not use Python's `parseaddr()` or `getaddresses()` functions to get the email address, or simply uses the full Address Header to send a reply.

For all of these test cases Golang returns a Parsing Error, but all versions of Python including Python 2, Python 3, and the most resent version in Github all result in the Real Name part of the address being returned in the Email Address part of the tuple.

**NOTE: This issue has been assigned: CVE-2023-27043
Link: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-27043**

**[VulnerabilityType Other]
CWE-1286: Improper Validation of Syntactic Correctness of Input**

I have been in communication with security@python.org about this issue, and was told they are fine with addressing this issue publicly. Additionally, I have created a PR which will detect these parsing errors and return an empty tuple to indicate a parsing error instead of returning the erroneous output.

Example Script to show this erroneous output:
```
from email.utils import parseaddr
rfc2822_ADDRESS = "Thomas Dwyer<tdwyer@example.org>"
print("Valid RFC2822 Address Parse Output")
parseaddr(rfc2822_ADDRESS)
print()
print("Test output...")
print()
specials = '()<>@,:;.\"[]'
a = "alice@example.org"
b = "<bob@example.org>"
for i in specials:
    c = a + i + b
    print(c)
    parseaddr(c)
```

Example Golang program which shows that Golang returns a parsing error:
```
package main

import (
 "fmt"
 "net/mail"
)

func main() {
   fmt.Println((&mail.AddressParser{}).Parse("Thomas Dwyer <thomas@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("thomas@example.org"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org(<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org)<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org<<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org><bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org@<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org,bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org:<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org;<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org.<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse(`alice@example.org"<bob@example.org>`))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org[<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org]<bob@example.org>"))
   fmt.Println((&mail.AddressParser{}).Parse("alice@example.org<bob@example.org>"))
}
```


# Your environment

- CPython versions tested on: All versions of Python

<!-- gh-linked-prs -->
### Linked PRs
* gh-102990
* gh-105127
* gh-105128
* gh-106612
* gh-108250
* gh-111116
<!-- /gh-linked-prs -->

--- end body ---
