use email_address crate for checking formats (#763)

The email_address crate is more strict in validating user and domain
parts of email addresses. For example, it verifies the total size
of the local part, which the current method does not, and this has
caused upstream servers to fail to accept an email.
This commit is contained in:
André Cruz
2022-05-26 18:21:14 +01:00
committed by GitHub
parent ca5cb3f8f7
commit e6b4529896
2 changed files with 11 additions and 13 deletions

View File

@@ -67,6 +67,9 @@ sha2 = { version = "0.10", optional = true }
rsa = { version = "0.6.0", optional = true }
ed25519-dalek = { version = "1.0.1", optional = true }
# email formats
email_address = { version = "0.2.1", default-features = false }
[dev-dependencies]
criterion = "0.3"
tracing-subscriber = "0.3"

View File

@@ -8,6 +8,7 @@ use std::{
str::FromStr,
};
use email_address::EmailAddress;
use idna::domain_to_ascii;
use once_cell::sync::Lazy;
use regex::Regex;
@@ -55,17 +56,6 @@ pub struct Address {
at_start: usize,
}
// Regex from the specs
// https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
// It will mark esoteric email addresses like quoted string as invalid
static USER_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^(?i)[a-z0-9.!#$%&'*+/=?^_`{|}~-]+\z").unwrap());
static DOMAIN_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(
r"(?i)^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$",
)
.unwrap()
});
// literal form, ipv4 or ipv6 address (SMTP 4.1.3)
static LITERAL_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?i)\[([A-f0-9:\.]+)\]\z").unwrap());
@@ -126,7 +116,7 @@ impl Address {
}
pub(super) fn check_user(user: &str) -> Result<(), AddressError> {
if USER_RE.is_match(user) {
if EmailAddress::is_valid_local_part(user) {
Ok(())
} else {
Err(AddressError::InvalidUser)
@@ -142,7 +132,7 @@ impl Address {
}
fn check_domain_ascii(domain: &str) -> Result<(), AddressError> {
if DOMAIN_RE.is_match(domain) {
if EmailAddress::is_valid_domain(domain) {
return Ok(());
}
@@ -278,5 +268,10 @@ mod tests {
assert_eq!(addr.domain(), "example.com");
assert_eq!(addr2.user(), "something");
assert_eq!(addr2.domain(), "example.com");
assert!(Address::check_user("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").is_err());
assert!(
Address::check_domain("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com").is_err()
);
}
}