diff options
| -rw-r--r-- | src/main.rs | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/src/main.rs b/src/main.rs index d511632..da2e715 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,8 @@ use tokio::net::UnixStream; struct Config { token: &'static str, lmtp: &'static str, - bind: &'static str + rcpt: Option<&'static str>, + bind: &'static str, } #[tokio::main] @@ -23,6 +24,10 @@ async fn main() -> anyhow::Result<()> { token: std::env::var("INGEST_TOKEN")?.leak(), lmtp: std::env::var("LMTP_SOCK")?.leak(), bind: std::env::var("LISTEN_ADDR").unwrap_or_else(|_| "127.0.0.1:8080".into()).leak(), + rcpt: match std::env::var("LMTP_RCPT") { + Ok(s) => Some(s.leak()), + Err(_) => None, + }, })); let app = Router::new() @@ -47,7 +52,7 @@ async fn inject( let from = header(&headers, "x-envelope-from"); let to = header(&headers, "x-envelope-to"); - match lmtp_deliver(&cfg.lmtp, from, to, &body).await { + match lmtp_deliver(cfg, from, to, &body).await { Ok(_) => StatusCode::NO_CONTENT, Err((true, m)) => { tracing::warn!("permanent: {m}"); @@ -73,12 +78,12 @@ fn valid_token(h: &HeaderMap, expected: &str) -> bool { } async fn lmtp_deliver( - deliver_to: &str, + cfg: &Config, from: &str, to: &str, msg: &[u8], ) -> Result<(), (bool, String)> { - let stream = UnixStream::connect(deliver_to).await.map_err(|e| (false, e.to_string()))?; + let stream = UnixStream::connect(cfg.lmtp).await.map_err(|e| (false, e.to_string()))?; let (rd, mut wr) = stream.into_split(); let mut rd = BufReader::new(rd); let mut line = String::new(); @@ -106,15 +111,20 @@ async fn lmtp_deliver( }}; } + let rcpt = cfg.rcpt.unwrap_or(to); + expect!("220"); io!(wr.write_all(b"LHLO alpha\r\n")); expect!("250"); io!(wr.write_all(format!("MAIL FROM:<{from}>\r\n").as_bytes())); expect!("250"); - io!(wr.write_all(format!("RCPT TO:<{to}>\r\n").as_bytes())); + io!(wr.write_all(format!("RCPT TO:<{rcpt}>\r\n").as_bytes())); expect!("250"); io!(wr.write_all(b"DATA\r\n")); expect!("354"); + if cfg.rcpt.is_some() { + io!(wr.write_all(format!("X-Original-To: {to}\r\n").as_bytes())); + } for chunk in msg.split_inclusive(|&b| b == b'\n') { if chunk.first() == Some(&b'.') { |
