From d5dfe979a1d2d9b198ffcc67c1eb401c1adeebcb Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 12 May 2020 19:43:05 +0200 Subject: [PATCH 1/5] Be a bit more restrictive on email addresses --- src/contact.rs | 25 +++++++++++++++++++++++++ src/dc_tools.rs | 26 ++++++++++++-------------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/contact.rs b/src/contact.rs index 0fff01025a..1c74662c74 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -3,6 +3,8 @@ use async_std::path::PathBuf; use deltachat_derive::*; use itertools::Itertools; +use lazy_static::lazy_static; +use regex::Regex; use crate::aheader::EncryptPreference; use crate::chat::ChatId; @@ -1528,4 +1530,27 @@ mod tests { assert!(addr_cmp(" aa@aa.ORG ", "AA@AA.ORG")); assert!(addr_cmp(" mailto:AA@AA.ORG", "Aa@Aa.orG")); } + + #[test] + fn test_name_in_address() { + let t = dummy_context(); + + let contact_id = Contact::create(&t.ctx, "", "").unwrap(); + let contact = Contact::load_from_db(&t.ctx, contact_id).unwrap(); + assert_eq!(contact.get_name(), ""); + assert_eq!(contact.get_addr(), "dave@example.org"); + + let contact_id = Contact::create(&t.ctx, "", "Mueller, Dave ").unwrap(); + let contact = Contact::load_from_db(&t.ctx, contact_id).unwrap(); + assert_eq!(contact.get_name(), "Dave Mueller"); + assert_eq!(contact.get_addr(), "dave@example.org"); + + assert!(Contact::create(&t.ctx, "", "dslk@sadklj.dk>").is_err()); + assert!(Contact::create(&t.ctx, "", "dskjfdslksadklj.dk").is_err()); + assert!(Contact::create(&t.ctx, "", "dskjfdslk@sadklj.dk>").is_err()); + assert!(Contact::create(&t.ctx, "", "dskjf@dslk@sadkljdk").is_err()); + assert!(Contact::create(&t.ctx, "", "dskjf dslk@d.e").is_err()); + assert!(Contact::create(&t.ctx, "", ", addr: impl Into) -> InvalidEmailError { - InvalidEmailError { - message: msg.into(), - addr: addr.into(), - } - } -} - /// Very simple email address wrapper. /// /// Represents an email address, right now just the `name@domain` portion. @@ -530,17 +521,24 @@ impl FromStr for EmailAddress { /// Performs a dead-simple parse of an email address. fn from_str(input: &str) -> Result { - if input.is_empty() { - return Err(InvalidEmailError::new("empty string is not valid", input)); - } - let parts: Vec<&str> = input.rsplitn(2, '@').collect(); - let err = |msg: &str| { Err(InvalidEmailError { message: msg.to_string(), addr: input.to_string(), }) }; + if input.is_empty() { + return err("empty string is not valid"); + } + let parts: Vec<&str> = input.rsplitn(2, '@').collect(); + + if input + .chars() + .any(|c| c.is_whitespace() || c == '<' || c == '>') + { + return err("Email must not contain whitespaces, '>' or '<'"); + } + match &parts[..] { [domain, local] => { if local.is_empty() { From 10430eb004545c7f7358e695c413f897b11abfd8 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 12 May 2020 20:08:05 +0200 Subject: [PATCH 2/5] Sanizize mail & addr in extra function, improve test --- src/contact.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/contact.rs b/src/contact.rs index 1c74662c74..5310f8feca 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -240,6 +240,8 @@ impl Contact { "Cannot create contact with empty address" ); + let (name, addr) = sanitize_name_and_addr(name, addr); + let (contact_id, sth_modified) = Contact::add_or_lookup(context, name, addr, Origin::ManuallyCreated).await?; let blocked = Contact::is_blocked_load(context, contact_id).await; @@ -1030,6 +1032,24 @@ pub fn addr_normalize(addr: &str) -> &str { norm } +fn sanitize_name_and_addr(name: impl AsRef, addr: impl AsRef) -> (String, String) { + lazy_static! { + static ref ADDR_WITH_NAME_REGEX: Regex = Regex::new("(.*)<(.*)>").unwrap(); + } + if let Some(captures) = ADDR_WITH_NAME_REGEX.captures(addr.as_ref()) { + ( + if name.as_ref().is_empty() { + normalize_name(&captures[1]) + } else { + name.as_ref().to_string() + }, + captures[2].to_string(), + ) + } else { + (name.as_ref().to_string(), addr.as_ref().to_string()) + } +} + async fn set_block_contact(context: &Context, contact_id: u32, new_blocking: bool) { if contact_id <= DC_CONTACT_ID_LAST_SPECIAL { return; @@ -1204,6 +1224,10 @@ mod tests { assert_eq!(may_be_valid_addr("u@d.tt"), true); assert_eq!(may_be_valid_addr("u@.tt"), false); assert_eq!(may_be_valid_addr("@d.tt"), false); + assert_eq!(may_be_valid_addr(""), false); + assert_eq!(may_be_valid_addr("as@sd.de>"), false); + assert_eq!(may_be_valid_addr("ask dkl@dd.tt"), false); } #[test] From 533a7c6880f034adcd7ff94e8b90327145ee081e Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 14 May 2020 10:25:46 +0200 Subject: [PATCH 3/5] Improve test --- src/contact.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/contact.rs b/src/contact.rs index 5310f8feca..36b1f8d64c 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -1569,6 +1569,11 @@ mod tests { assert_eq!(contact.get_name(), "Dave Mueller"); assert_eq!(contact.get_addr(), "dave@example.org"); + let contact_id = Contact::create(&t.ctx, "name1", "name2 ").unwrap(); + let contact = Contact::load_from_db(&t.ctx, contact_id).unwrap(); + assert_eq!(contact.get_name(), "name1"); + assert_eq!(contact.get_addr(), "dave@example.org"); + assert!(Contact::create(&t.ctx, "", "dslk@sadklj.dk>").is_err()); assert!(Contact::create(&t.ctx, "", "dskjfdslksadklj.dk").is_err()); From 4b927883e58d56435142d8a1b8999a48e2585322 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 19 May 2020 17:36:12 +0200 Subject: [PATCH 4/5] Update mailparse --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f79e9bd52e..6028ded0aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ bitflags = "1.1.0" debug_stub_derive = "0.3.0" sanitize-filename = "0.2.1" stop-token = { version = "0.1.1", features = ["unstable"] } -mailparse = "0.12.0" +mailparse = "0.12.1" encoded-words = { git = "https://github.com/async-email/encoded-words", branch="master" } native-tls = "0.2.3" image = { version = "0.22.4", default-features=false, features = ["gif_codec", "jpeg", "ico", "png_codec", "pnm", "webp", "bmp"] } From b9c21e7ea61cd7007b7ad143b9055822a605262f Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 29 May 2020 15:52:39 +0200 Subject: [PATCH 5/5] Adapt to async --- src/contact.rs | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/contact.rs b/src/contact.rs index 36b1f8d64c..a62b58ddc7 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -1555,31 +1555,49 @@ mod tests { assert!(addr_cmp(" mailto:AA@AA.ORG", "Aa@Aa.orG")); } - #[test] - fn test_name_in_address() { - let t = dummy_context(); + #[async_std::test] + async fn test_name_in_address() { + let t = dummy_context().await; - let contact_id = Contact::create(&t.ctx, "", "").unwrap(); - let contact = Contact::load_from_db(&t.ctx, contact_id).unwrap(); + let contact_id = Contact::create(&t.ctx, "", "") + .await + .unwrap(); + let contact = Contact::load_from_db(&t.ctx, contact_id).await.unwrap(); assert_eq!(contact.get_name(), ""); assert_eq!(contact.get_addr(), "dave@example.org"); - let contact_id = Contact::create(&t.ctx, "", "Mueller, Dave ").unwrap(); - let contact = Contact::load_from_db(&t.ctx, contact_id).unwrap(); + let contact_id = Contact::create(&t.ctx, "", "Mueller, Dave ") + .await + .unwrap(); + let contact = Contact::load_from_db(&t.ctx, contact_id).await.unwrap(); assert_eq!(contact.get_name(), "Dave Mueller"); assert_eq!(contact.get_addr(), "dave@example.org"); - let contact_id = Contact::create(&t.ctx, "name1", "name2 ").unwrap(); - let contact = Contact::load_from_db(&t.ctx, contact_id).unwrap(); + let contact_id = Contact::create(&t.ctx, "name1", "name2 ") + .await + .unwrap(); + let contact = Contact::load_from_db(&t.ctx, contact_id).await.unwrap(); assert_eq!(contact.get_name(), "name1"); assert_eq!(contact.get_addr(), "dave@example.org"); - assert!(Contact::create(&t.ctx, "", "dslk@sadklj.dk>").is_err()); - assert!(Contact::create(&t.ctx, "", "dskjfdslksadklj.dk").is_err()); - assert!(Contact::create(&t.ctx, "", "dskjfdslk@sadklj.dk>").is_err()); - assert!(Contact::create(&t.ctx, "", "dskjf@dslk@sadkljdk").is_err()); - assert!(Contact::create(&t.ctx, "", "dskjf dslk@d.e").is_err()); - assert!(Contact::create(&t.ctx, "", "dslk@sadklj.dk>") + .await + .is_err()); + assert!(Contact::create(&t.ctx, "", "dskjfdslksadklj.dk") + .await + .is_err()); + assert!(Contact::create(&t.ctx, "", "dskjfdslk@sadklj.dk>") + .await + .is_err()); + assert!(Contact::create(&t.ctx, "", "dskjf@dslk@sadkljdk") + .await + .is_err()); + assert!(Contact::create(&t.ctx, "", "dskjf dslk@d.e").await.is_err()); + assert!(Contact::create(&t.ctx, "", "