1 use crate::{handle_starttls::handle_starttls, storage::MessageStorage};
2 use tokio::{
3 io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter},
4 net::TcpStream,
5 };
6
7 pub async fn handle_unsecured_session(stream: &mut TcpStream, storage: Option<MessageStorage>) -> anyhow::Result<()> {
8 let (reader, writer) = stream.split();
9 let mut reader = BufReader::new(reader);
10 let mut writer = BufWriter::new(writer);
11 let mut is_tls = false;
12 let mut line = String::new();
13 while reader.read_line(&mut line).await? != 0 {
14 let space_pos = line.find(" ").unwrap_or(line.len());
15 let (command, _) = line.split_at(space_pos);
16
17 match command.trim().to_uppercase().as_ref() {
18 "EHLO" | "HELO" => {
19 writer.write_all(b"250-windmill Hello\r\n").await?;
20 writer.write_all(b"250-STARTTLS\r\n").await?;
21 writer.write_all(b"250 What you've got?\r\n").await?;
22 writer.flush().await?;
23 }
24 "STARTTLS" => {
25 writer.write_all(b"220 GO ON\r\n").await?;
26 writer.flush().await?;
27 is_tls = true;
28 break;
29 }
30 "QUIT" => {
31 writer.write_all(b"221 Have a nice day!\r\n").await?;
32 writer.flush().await?;
33 break;
34 }
35 "NOOP" => {
36 writer.write_all(b"250 OK\r\n").await?;
37 writer.flush().await?;
38 }
39 "MAIL" | "RCPT" | "DATA" | "RSET" => {
40 writer
41 .write_all(b"530 Must issue a STARTTLS command first\r\n")
42 .await?;
43 writer.flush().await?;
44 }
45 _ => {
46 writer.write_all(b"500 Unknown command\r\n").await?;
47 writer.flush().await?;
48 }
49 }
50
51 line.clear();
52 }
53
54 if is_tls {
55 handle_starttls(stream, storage).await?;
56 }
57
58 Ok(())
59 }