diff --git a/Cargo.toml b/Cargo.toml index 739086b..74a4818 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,11 +33,11 @@ nom = { version = "5", optional = true } once_cell = "1" quoted_printable = { version = "0.4", optional = true } r2d2 = { version = "0.8", optional = true } +rand = { version = "0.7", optional = true, default-features = false } regex = "1" rustls = { version = "0.17", optional = true } serde = { version = "1", optional = true, features = ["derive"] } serde_json = { version = "1", optional = true } -textnonce = { version = "0.7", optional = true } uuid = { version = "0.8", features = ["v4"] } webpki = { version = "0.21", optional = true } webpki-roots = { version = "0.19", optional = true } @@ -54,7 +54,7 @@ name = "transport_smtp" [features] async = ["async-std", "async-trait", "async-attributes"] -builder = ["mime", "base64", "hyperx", "textnonce", "quoted_printable"] +builder = ["mime", "base64", "hyperx", "rand", "quoted_printable"] default = ["file-transport", "smtp-transport", "rustls-tls", "hostname", "r2d2", "sendmail-transport", "builder"] file-transport = ["serde", "serde_json"] rustls-tls = ["webpki", "webpki-roots", "rustls"] diff --git a/src/message/mimebody.rs b/src/message/mimebody.rs index 9e4a34d..9f012f0 100644 --- a/src/message/mimebody.rs +++ b/src/message/mimebody.rs @@ -4,7 +4,7 @@ use crate::message::{ EmailFormat, }; use mime::Mime; -use textnonce::TextNonce; +use rand::Rng; /// MIME part variants /// @@ -194,11 +194,19 @@ pub enum MultiPartKind { Related, } +/// Create a random MIME boundary. +fn make_boundary() -> String { + rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(68) + .collect() +} + impl MultiPartKind { fn to_mime>(self, boundary: Option) -> Mime { let boundary = boundary .map(|s| s.as_ref().into()) - .unwrap_or_else(|| TextNonce::sized(68).unwrap().into_string()); + .unwrap_or_else(make_boundary); use self::MultiPartKind::*; format!( @@ -601,4 +609,20 @@ mod test { "int main() { return 0; }\r\n", "--F2mTKN843loAAAAA8porEdAjCKhArPxGeahYoZYSftse1GT/84tup+O0bs8eueVuAlMK--\r\n")); } + + #[test] + fn test_make_boundary() { + let mut boundaries = std::collections::HashSet::with_capacity(10); + for _ in 0..1000 { + boundaries.insert(make_boundary()); + } + + // Ensure there are no duplicates + assert_eq!(1000, boundaries.len()); + + // Ensure correct length + for boundary in boundaries { + assert_eq!(68, boundary.len()); + } + } }