mod common; pub use common::*; use byte_strings::c_str; use indymilter::MacroStage; use indymilter_test::*; use spamassassin_milter::*; /// A spam message is rejected with an SMTP error reply. #[tokio::test] async fn reject_spam() { let config = configure_spamc(Config::builder()) .reject_spam(true) .reply_code("554".into()) .reply_text("Not allowed!".into()) .spamc_args([format!("--port={SPAMD_PORT}")]) .build(); let server = spawn_mock_spamd_server(SPAMD_PORT, |spam| { Err(spam.replacen("\r\n\r\n", "\r\nX-Spam-Flag: YES\r\n\r\n", 1)) }) .await .unwrap(); let milter = SpamAssassinMilter::spawn(LOCALHOST, config).await.unwrap(); let mut conn = TestConnection::open(milter.addr()).await.unwrap(); let status = conn.connect("client.gluet.ch", [123, 123, 123, 123]).await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.helo("mail.gluet.ch").await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.mail([""]).await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.rcpt([""]).await.unwrap(); assert_eq!(status, Status::Continue); conn.macros( MacroStage::Data, [ ("i", "1234567ABC"), ("j", "localhost"), ("_", "client.gluet.ch [123.123.123.123]"), ("{tls_version}", "TLSv1.2"), ("v", "Postfix 3.3.0"), ], ) .await .unwrap(); let status = conn.data().await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.header("From", "from@gluet.ch").await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.header("To", "to@gluet.ch").await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.header("Subject", "Test message").await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.header("Message-ID", rand_msg_id()).await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.header("Date", current_date()).await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.eoh().await.unwrap(); assert_eq!(status, Status::Continue); let status = conn.body(&b"Test message body"[..]).await.unwrap(); assert_eq!(status, Status::Continue); let (_, status) = conn.eom().await.unwrap(); assert_eq!( status, Status::Reject { message: Some(c_str!("554 5.7.1 Not allowed!").into()), } ); conn.close().await.unwrap(); milter.shutdown().await.unwrap(); server.await.unwrap().unwrap(); }