1use crate::backend::Backend;
2use crate::conn::Conn;
3use crate::parse::parse_cmd;
4use std::sync::Arc;
5use std::time::Duration;
6
7use anyhow::Result;
8
9use tokio::net::TcpListener;
10use tokio_rustls::TlsAcceptor;
11
12
13pub struct Server<B: Backend> {
16 pub addr: String,
17 pub tls_acceptor: Option<TlsAcceptor>,
18
19 pub domain: String,
20 pub max_recipients: usize,
21 pub max_message_bytes: usize,
22 pub max_line_length: usize,
23 pub allow_insecure_auth: bool,
24 pub strict: bool,
25
26 pub read_timeout: Duration,
27 pub write_timeout: Duration,
28
29 pub enable_smtputf8: bool,
30 pub enable_requiretls: bool,
31 pub enable_binarymime: bool,
32
33 pub backend: B,
34
35 pub caps: Vec<String>,
36
37 }
41
42impl<B: Backend> Server<B> {
43 pub fn new(be: B) -> Self {
44 return Server{
45 addr: String::new(),
46 tls_acceptor: None,
47 domain: String::new(),
48 max_recipients: 0,
49 max_message_bytes: 0,
50 max_line_length: 2000,
51 allow_insecure_auth: true,
52 strict: false,
53 read_timeout: Duration::from_secs(0),
54 write_timeout: Duration::from_secs(0),
55 enable_smtputf8: false,
56 enable_requiretls: false,
57 enable_binarymime: false,
58 backend: be,
59 caps: vec!["PIPELINING".to_string(), "8BITMIME".to_string(), "ENHANCEDSTATUSCODES".to_string(), "CHUNKING".to_string()],
60 }
62 }
63
64 pub async fn serve(self: Arc<Self>, l: TcpListener) -> Result<()> {
65 loop {
66 match l.accept().await {
67 Ok((stream, _)) => {
68 let server = self.clone();
69 println!("New connection");
70 tokio::spawn(async move {
71 if let Err(err) = server.handle_conn(Conn::new(stream, server.max_line_length)).await {
72 println!("Error333: {}", err);
73 }
74 });
75 }
76 Err(e) => {
77 println!("Error444: {}", e);
78 }
79 }
80 }
81 }
82
83 pub async fn handle_conn(&self, mut c: Conn<B>) -> Result<()> {
84 c.greet(self.domain.clone()).await;
85
86 loop {
87 let mut line = String::new();
88 match c.read_line(&mut line, self).await {
89 Ok(0) => {
90 println!("Connection closed");
91 c.stream.get_mut().write_response(221, [2,4,0], &["Connection closed, bye"]).await;
92 return Ok(());
93 }
94 Ok(_) => {
95 match parse_cmd(line) {
96 Ok((cmd, arg)) => {
97 c.handle(cmd, arg, self).await;
98 }
99 Err(err) => {
100 println!("Error222: {}", err);
101 c.stream.get_mut().write_response(501, [5,5,2], &["Bad command"]).await;
102 continue;
103 }
104 }
105 }
106 Err(err) => {
107 println!("Connection error: {}", err);
108 c.stream.get_mut().write_response(221, [2,4,0], &["Connection error, sorry"]).await;
109 return Err(err.into());
110 }
111 }
112 }
113 }
114
115 pub async fn listen_and_serve(self) -> Result<()> {
116 let l = TcpListener::bind(&self.addr).await?;
117 Arc::new(self).serve(l).await
118 }
119
120 }