From 6fff515e81f30e8febcdf162eb8e5a833afc03e6 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Tue, 20 Jun 2023 10:19:23 -0700 Subject: [PATCH] http injection: normalize newlines in generated content Otherwise we can end up with protocol errors when trying to send the resultant messages out via SMTP. --- crates/kumod/src/http_server/inject_v1.rs | 37 ++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/crates/kumod/src/http_server/inject_v1.rs b/crates/kumod/src/http_server/inject_v1.rs index 2810b120..0bc1fed5 100644 --- a/crates/kumod/src/http_server/inject_v1.rs +++ b/crates/kumod/src/http_server/inject_v1.rs @@ -381,6 +381,28 @@ impl InjectV1Request { } } +pub fn normalize_crlf(input: &str) -> String { + let mut normalized = String::with_capacity(input.len()); + let mut prev = ' '; + for c in input.chars() { + if c == '\r' { + normalized.push_str("\r\n"); + prev = c; + continue; + } + if c == '\n' { + if prev != '\r' { + normalized.push_str("\r\n"); + } + prev = c; + continue; + } + prev = c; + normalized.push(c); + } + normalized +} + async fn process_recipient<'a>( config: &mut LuaConfig, sender: &EnvelopeAddress, @@ -394,6 +416,11 @@ async fn process_recipient<'a>( .with_context(|| format!("recipient email {}", recip.email))?; let generated = compiled.expand_for_recip(recip, &request.substitutions, &request.content)?; + + // Ensure that there are no bare LF in the message, as that will + // confuse SMTP delivery! + let normalized = normalize_crlf(&generated); + // build into a Message let id = SpoolId::new(); let message = message::Message::new_dirty( @@ -401,7 +428,7 @@ async fn process_recipient<'a>( sender.clone(), recip_addr, serde_json::json!({}), - Arc::new(generated.into_bytes().into_boxed_slice()), + Arc::new(normalized.into_bytes().into_boxed_slice()), )?; message.set_meta("http_auth", auth.summarize())?; @@ -620,4 +647,12 @@ Some( k9::assert_equal!(parsed.text_body_count(), 1); k9::assert_equal!(parsed.attachment_count(), 1); } + + #[test] + fn test_normalize_crlf() { + k9::assert_equal!( + normalize_crlf("foo\r\nbar\nwoot\rdouble-r\r\rend"), + "foo\r\nbar\r\nwoot\r\ndouble-r\r\n\r\nend" + ); + } }