use std::sync::atomic::Ordering;
use std::time::{SystemTime, UNIX_EPOCH};
use super::MSG_ID_COUNTER;
pub(super) fn generate_message_id(domain: &str) -> String {
let hex = generate_unique_hex();
format!("{hex}@{domain}")
}
pub(super) fn generate_boundary() -> String {
let hex = generate_unique_hex();
format!("----=_Part_{hex}")
}
pub(super) fn generate_boundary_not_in(content: &[u8]) -> String {
for _ in 0..10 {
let boundary = generate_boundary();
if !contains_boundary(content, &boundary) {
return boundary;
}
}
for _ in 0..100 {
let count = MSG_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
let boundary = format!("----=_Part_fallback_{count:016x}");
if !contains_boundary(content, &boundary) {
return boundary;
}
}
loop {
let count = MSG_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
let boundary = format!("----=_Part_fallback_{count:016x}");
if !contains_boundary(content, &boundary) {
return boundary;
}
}
}
pub(super) fn contains_boundary(content: &[u8], boundary: &str) -> bool {
let boundary_bytes = boundary.as_bytes();
content
.windows(boundary_bytes.len())
.any(|w| w == boundary_bytes)
}
fn generate_unique_hex() -> String {
let mut buf = [0u8; 16];
if read_urandom(&mut buf).is_ok() {
return buf.iter().fold(String::with_capacity(32), |mut s, b| {
use std::fmt::Write;
let _ = write!(s, "{b:02x}");
s
});
}
#[allow(clippy::cast_possible_truncation)]
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64;
let count = MSG_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
let pid = u64::from(std::process::id());
format!("{nanos:016x}{pid:08x}{count:08x}")
}
fn read_urandom(buf: &mut [u8]) -> std::io::Result<()> {
use std::io::Read;
let mut f = std::fs::File::open("/dev/urandom")?;
f.read_exact(buf)
}