diff --git a/tests/trace.rs b/tests/trace.rs new file mode 100644 index 0000000..34384f7 --- /dev/null +++ b/tests/trace.rs @@ -0,0 +1,203 @@ +use nom::FindSubstring; +use smtp_codec::{ + parse::{ + command::command, + response::{ehlo_ok_rsp, Greeting, Reply_line}, + }, + types::Command, +}; + +fn parse_trace(mut trace: &[u8]) { + let (rem, greeting) = Greeting(trace).unwrap(); + println!("S: {:?}", greeting); + trace = rem; + + loop { + if trace.is_empty() { + break; + } + + let (rem, cmd) = command(trace).unwrap(); + println!("C: {:?}", cmd); + trace = rem; + + match cmd { + Command::Ehlo { .. } => { + let (rem, rsp) = ehlo_ok_rsp(trace).unwrap(); + println!("S: {:?}", rsp); + trace = rem; + } + Command::Data { .. } => { + let (rem, rsp) = Reply_line(trace).unwrap(); + println!("S: {:?}", rsp); + trace = rem; + + let pos = trace.find_substring("\r\n.\r\n").unwrap(); + let (data, rem) = trace.split_at(pos + 5); + println!("C (data): <{}>", std::str::from_utf8(data).unwrap()); + trace = rem; + + let (rem, rsp) = Reply_line(trace).unwrap(); + println!("S: {:?}", rsp); + trace = rem; + } + _ => { + let (rem, rsp) = Reply_line(trace).unwrap(); + println!("S: {:?}", rsp); + trace = rem; + } + } + } +} + +#[test] +/// D.1. A Typical SMTP Transaction Scenario +fn test_trace_d_1() { + let trace = b"\ +220 foo.com Simple Mail Transfer Service Ready\r +EHLO bar.com\r +250-foo.com greets bar.com\r +250-8BITMIME\r +250-SIZE\r +250-DSN\r +250 HELP\r +MAIL FROM:\r +250 OK\r +RCPT TO:\r +250 OK\r +RCPT TO:\r +550 No such user here\r +RCPT TO:\r +250 OK\r +DATA\r +354 Start mail input; end with .\r +Blah blah blah...\r +...etc. etc. etc.\r +.\r +250 OK\r +QUIT\r +221 foo.com Service closing transmission channel\r +"; + + parse_trace(trace); +} + +#[test] +/// D.2. Aborted SMTP Transaction Scenario +fn test_trace_d_2() { + let trace = b"\ +220 foo.com Simple Mail Transfer Service Ready\r +EHLO bar.com\r +250-foo.com greets bar.com\r +250-8BITMIME\r +250-SIZE\r +250-DSN\r +250 HELP\r +MAIL FROM:\r +250 OK\r +RCPT TO:\r +250 OK\r +RCPT TO:\r +550 No such user here\r +RSET\r +250 OK\r +QUIT\r +221 foo.com Service closing transmission channel\r +"; + + parse_trace(trace); +} + +#[test] +/// D.3. Relayed Mail Scenario +fn test_trace_d_3() { + let step_1 = b"\ +220 foo.com Simple Mail Transfer Service Ready\r +EHLO bar.com\r +250-foo.com greets bar.com\r +250-8BITMIME\r +250-SIZE\r +250-DSN\r +250 HELP\r +MAIL FROM:\r +250 OK\r +RCPT TO:\r +250 OK\r +DATA\r +354 Start mail input; end with .\r +Date: Thu, 21 May 1998 05:33:29 -0700\r +From: John Q. Public \r +Subject: The Next Meeting of the Board\r +To: Jones@xyz.com\r +\r +Bill:\r +The next meeting of the board of directors will be\r +on Tuesday.\r +John.\r +.\r +250 OK\r +QUIT\r +221 foo.com Service closing transmission channel\r +"; + + let step_2 = b"\ +220 xyz.com Simple Mail Transfer Service Ready\r +EHLO foo.com\r +250 xyz.com is on the air\r +MAIL FROM:\r +250 OK\r +RCPT TO:\r +250 OK\r +DATA\r +354 Start mail input; end with .\r +Received: from bar.com by foo.com ; Thu, 21 May 1998\r + 05:33:29 -0700\r +Date: Thu, 21 May 1998 05:33:22 -0700\r +From: John Q. Public \r +Subject: The Next Meeting of the Board\r +To: Jones@xyz.com\r +\r +Bill:\r +The next meeting of the board of directors will be\r +on Tuesday.\r + John.\r +.\r +250 OK\r +QUIT\r +221 foo.com Service closing transmission channel\r +"; + + parse_trace(step_1); + parse_trace(step_2); +} + +#[test] +/// D.4. Verifying and Sending Scenario +fn test_trace_d_4() { + let trace = b"\ +220 foo.com Simple Mail Transfer Service Ready\r +EHLO bar.com\r +250-foo.com greets bar.com\r +250-8BITMIME\r +250-SIZE\r +250-DSN\r +250-VRFY\r +250 HELP\r +VRFY Crispin\r +250 Mark Crispin \r +MAIL FROM:\r +250 OK\r +RCPT TO:\r +250 OK\r +DATA\r +354 Start mail input; end with .\r +Blah blah blah...\r +...etc. etc. etc.\r +.\r +250 OK\r +QUIT\r +221 foo.com Service closing transmission channel\r +"; + + parse_trace(trace); +}