Stop using the regex crate for parsing addresses (#776)

This commit is contained in:
Paolo Barbolini
2022-06-03 15:39:57 +02:00
committed by GitHub
parent b33dd562fc
commit e4006518fe
2 changed files with 41 additions and 16 deletions

View File

@@ -20,7 +20,7 @@ maintenance = { status = "actively-developed" }
[dependencies]
idna = "0.2"
once_cell = "1"
once_cell = { version = "1", optional = true }
tracing = { version = "0.1.16", default-features = false, features = ["std"], optional = true } # feature
# builder
@@ -29,7 +29,6 @@ mime = { version = "0.3.4", optional = true }
fastrand = { version = "1.4", optional = true }
quoted_printable = { version = "0.4", optional = true }
base64 = { version = "0.13", optional = true }
regex = { version = "1", default-features = false, features = ["std", "unicode-case"] }
email-encoding = { git = "https://github.com/lettre/email-encoding.git", rev = "ac7ab8630b8d012ade63869c89b2855e27b3ce7a", optional = true }
# file transport
@@ -67,6 +66,7 @@ tokio1_rustls = { package = "tokio-rustls", version = "0.23", optional = true }
sha2 = { version = "0.10", optional = true }
rsa = { version = "0.6.0", optional = true }
ed25519-dalek = { version = "1.0.1", optional = true }
regex = { version = "1", default-features = false, features = ["std"], optional = true }
# email formats
email_address = { version = "0.2.1", default-features = false }
@@ -95,7 +95,7 @@ mime03 = ["mime"]
file-transport = ["uuid"]
file-transport-envelope = ["serde", "serde_json", "file-transport"]
sendmail-transport = []
smtp-transport = ["base64", "nom", "socket2"]
smtp-transport = ["base64", "nom", "socket2", "once_cell"]
pool = ["futures-util"]
@@ -109,7 +109,7 @@ tokio1 = ["tokio1_crate", "async-trait", "futures-io", "futures-util"]
tokio1-native-tls = ["tokio1", "native-tls", "tokio1_native_tls_crate"]
tokio1-rustls-tls = ["tokio1", "rustls-tls", "tokio1_rustls"]
dkim = ["base64", "sha2", "rsa", "ed25519-dalek"]
dkim = ["base64", "sha2", "rsa", "ed25519-dalek", "regex", "once_cell"]
[package.metadata.docs.rs]
all-features = true

View File

@@ -10,8 +10,6 @@ use std::{
use email_address::EmailAddress;
use idna::domain_to_ascii;
use once_cell::sync::Lazy;
use regex::Regex;
/// Represents an email address with a user and a domain name.
///
@@ -56,9 +54,6 @@ pub struct Address {
at_start: usize,
}
// 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());
impl Address {
/// Creates a new email address from a user and domain.
///
@@ -132,16 +127,19 @@ impl Address {
}
fn check_domain_ascii(domain: &str) -> Result<(), AddressError> {
// Domain
if EmailAddress::is_valid_domain(domain) {
return Ok(());
}
if let Some(caps) = LITERAL_RE.captures(domain) {
if let Some(cap) = caps.get(1) {
if cap.as_str().parse::<IpAddr>().is_ok() {
return Ok(());
}
}
// IP
let ip = domain
.strip_prefix('[')
.and_then(|ip| ip.strip_suffix(']'))
.unwrap_or(domain);
if ip.parse::<IpAddr>().is_ok() {
return Ok(());
}
Err(AddressError::InvalidDomain)
@@ -259,7 +257,7 @@ mod tests {
use super::*;
#[test]
fn parse_address() {
fn ascii_address() {
let addr_str = "something@example.com";
let addr = Address::from_str(addr_str).unwrap();
let addr2 = Address::new("something", "example.com").unwrap();
@@ -268,7 +266,34 @@ mod tests {
assert_eq!(addr.domain(), "example.com");
assert_eq!(addr2.user(), "something");
assert_eq!(addr2.domain(), "example.com");
}
#[test]
fn ascii_address_ipv4() {
let addr_str = "something@1.1.1.1";
let addr = Address::from_str(addr_str).unwrap();
let addr2 = Address::new("something", "1.1.1.1").unwrap();
assert_eq!(addr, addr2);
assert_eq!(addr.user(), "something");
assert_eq!(addr.domain(), "1.1.1.1");
assert_eq!(addr2.user(), "something");
assert_eq!(addr2.domain(), "1.1.1.1");
}
#[test]
fn ascii_address_ipv6() {
let addr_str = "something@[2606:4700:4700::1111]";
let addr = Address::from_str(addr_str).unwrap();
let addr2 = Address::new("something", "[2606:4700:4700::1111]").unwrap();
assert_eq!(addr, addr2);
assert_eq!(addr.user(), "something");
assert_eq!(addr.domain(), "[2606:4700:4700::1111]");
assert_eq!(addr2.user(), "something");
assert_eq!(addr2.domain(), "[2606:4700:4700::1111]");
}
#[test]
fn check_parts() {
assert!(Address::check_user("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").is_err());
assert!(
Address::check_domain("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com").is_err()