diff --git a/Cargo.lock b/Cargo.lock index a9d4ac751..f976394a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,18 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "addr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "psl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rental 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "adler32" version = "1.0.3" @@ -460,7 +447,6 @@ dependencies = [ name = "deltachat" version = "1.0.0-alpha.3" dependencies = [ - "addr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1569,39 +1555,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "psl" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "psl-codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "psl-codegen" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "psl-lexer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "sequence_trie 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "psl-lexer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "publicsuffix" version = "1.5.2" @@ -1844,25 +1797,6 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rental" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rental-impl 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rental-impl" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "reqwest" version = "0.9.19" @@ -2040,11 +1974,6 @@ name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "sequence_trie" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "serde" version = "1.0.98" @@ -2679,7 +2608,6 @@ dependencies = [ ] [metadata] -"checksum addr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22199dd03e5cff19ede8c2b835c93460f998b4716e225d06d740d925ceac5d75" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" "checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" @@ -2846,9 +2774,6 @@ dependencies = [ "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum psl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0fcd4da9d98f254ad641dd081207cc14fcbec95dd58ee62ffc9b96f0684fd6c2" -"checksum psl-codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06f94f31e4f36b42e21b831d20bf0efc805b2155624697fb86f987b666518c3b" -"checksum psl-lexer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cf84fe23023e855b9a9d038a1b08d5c438d3961d2ced6c2b2358b29fbf74a63" "checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" @@ -2875,8 +2800,6 @@ dependencies = [ "checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" "checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum rental 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "01916ebd9fc2e81978a5dc9542a2fa47f5bb2ca3402e14c7cc42d6e3c5123e1f" -"checksum rental-impl 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "82260d54cf2cbe9608df161f7e7c98e81fae702aa13af9e4d5d39dc2ffb25ab6" "checksum reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0777154c2c3eb54f5c480db01de845652d941e47191277cc673634c3853939" "checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" "checksum rsa 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6ad8d3632f6745bb671c8637e2aa44015537c5e384789d2ea3235739301ed1e0" @@ -2895,7 +2818,6 @@ dependencies = [ "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum sequence_trie 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee22067b7ccd072eeb64454b9c6e1b33b61cd0d49e895fd48676a184580e0c3" "checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113" "checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" diff --git a/Cargo.toml b/Cargo.toml index e3672d45b..2e6b1139c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ rustyline = "4.1.0" lazy_static = "1.3.0" regex = "1.1.6" rusqlite = { version = "0.20", features = ["bundled"] } -addr = "0.2.0" r2d2_sqlite = "0.12.0" r2d2 = "0.8.5" strum = "0.15.0" diff --git a/src/contact.rs b/src/contact.rs index 0891449ef..9b2f9da5b 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -909,20 +909,7 @@ pub fn get_first_name<'a>(full_name: &'a str) -> &'a str { /// Returns false if addr is an invalid address, otherwise true. pub fn may_be_valid_addr(addr: &str) -> bool { - if addr.is_empty() { - return false; - } - - let at = addr.find('@').unwrap_or_default(); - if at < 1 { - return false; - } - let dot = addr.find('.').unwrap_or_default(); - if dot < 1 || dot > addr.len() - 3 || dot < at + 2 { - return false; - } - - true + addr.parse::().is_ok() } pub fn addr_normalize(addr: &str) -> &str { diff --git a/src/dc_configure.rs b/src/dc_configure.rs index 744c559e0..4a0f4ba0f 100644 --- a/src/dc_configure.rs +++ b/src/dc_configure.rs @@ -186,13 +186,13 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j ok_to_continue0 = true; } if ok_to_continue0 { - let parsed: addr::Result = param.addr.parse(); + let parsed: Result = param.addr.parse(); let mut ok_to_continue7 = false; if parsed.is_err() { error!(context, 0, "Bad email-address."); } else { let parsed = parsed.unwrap(); - let param_domain = parsed.host(); + let param_domain = parsed.domain; let param_addr_urlencoded = utf8_percent_encode(¶m.addr, NON_ALPHANUMERIC).to_string(); diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 857a4033a..d18cd3d69 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -1,6 +1,8 @@ use std::borrow::Cow; use std::ffi::{CStr, CString}; +use std::fmt; use std::fs; +use std::str::FromStr; use std::time::SystemTime; use chrono::{Local, TimeZone}; @@ -1556,6 +1558,69 @@ pub fn time() -> i64 { .as_secs() as i64 } +/// Very simple email address wrapper. +/// +/// Represents an email address, right now just the `name@domain` portion. +/// +/// # Example +/// +/// ``` +/// use deltachat::dc_tools::EmailAddress; +/// let email = match EmailAddress::new("someone@example.com") { +/// Ok(addr) => addr, +/// Err(e) => panic!("Error parsing address, error was {}", e), +/// }; +/// assert_eq!(&email.local, "someone"); +/// assert_eq!(&email.domain, "example.com"); +/// assert_eq!(email.to_string(), "someone@example.com"); +/// ``` +#[derive(Debug, PartialEq, Clone)] +pub struct EmailAddress { + pub local: String, + pub domain: String, +} + +impl EmailAddress { + pub fn new(input: &str) -> Result { + input.parse::() + } +} + +impl fmt::Display for EmailAddress { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}@{}", self.local, self.domain) + } +} + +impl FromStr for EmailAddress { + type Err = Error; + + /// Performs a dead-simple parse of an email address. + fn from_str(input: &str) -> Result { + ensure!(!input.is_empty(), "empty string is not valid"); + let parts: Vec<&str> = input.rsplitn(2, '@').collect(); + + ensure!(parts.len() > 1, "missing '@' character"); + let local = parts[1]; + let domain = parts[0]; + + ensure!( + !local.is_empty(), + "empty string is not valid for local part" + ); + ensure!(domain.len() > 3, "domain is too short"); + + let dot = domain.find('.'); + ensure!(dot.is_some(), "invalid domain"); + ensure!(dot.unwrap() < domain.len() - 2, "invalid domain"); + + Ok(EmailAddress { + local: local.to_string(), + domain: domain.to_string(), + }) + } +} + #[cfg(test)] mod tests { use super::*; @@ -2115,4 +2180,31 @@ mod tests { let grpid = dc_extract_grpid_from_rfc724_mid(mid); assert_eq!(grpid, Some("1234567890123456")); } + + #[test] + fn test_emailaddress_parse() { + assert_eq!(EmailAddress::new("").is_ok(), false); + assert_eq!( + EmailAddress::new("user@domain.tld").unwrap(), + EmailAddress { + local: "user".into(), + domain: "domain.tld".into(), + } + ); + assert_eq!(EmailAddress::new("uuu").is_ok(), false); + assert_eq!(EmailAddress::new("dd.tt").is_ok(), false); + assert_eq!(EmailAddress::new("tt.dd@uu").is_ok(), false); + assert_eq!(EmailAddress::new("u@d").is_ok(), false); + assert_eq!(EmailAddress::new("u@d.").is_ok(), false); + assert_eq!(EmailAddress::new("u@d.t").is_ok(), false); + assert_eq!( + EmailAddress::new("u@d.tt").unwrap(), + EmailAddress { + local: "u".into(), + domain: "d.tt".into(), + } + ); + assert_eq!(EmailAddress::new("u@.tt").is_ok(), false); + assert_eq!(EmailAddress::new("@d.tt").is_ok(), false); + } }