diff options
Diffstat (limited to 'src/smtp.rs')
| -rw-r--r-- | src/smtp.rs | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/smtp.rs b/src/smtp.rs index 2ab79f8..00e2ae8 100644 --- a/src/smtp.rs +++ b/src/smtp.rs @@ -31,6 +31,7 @@ impl SmtpServer { state: SessionState::default(), client_host: String::new(), from: None, + to: Vec::new(), }; spawn(session.run(stream)); } @@ -43,6 +44,7 @@ struct SessionHandler { state: SessionState, client_host: String, from: Option<String>, + to: Vec<String>, } impl SessionHandler { @@ -84,6 +86,7 @@ impl SessionHandler { match &command { Command::HELO(hostname) => self.helo(hostname).await, Command::MAIL(from) => self.mail(from).await, + Command::RCPT(to) => self.rcpt(to).await, } } @@ -92,6 +95,7 @@ impl SessionHandler { self.client_host = String::from(hostname); self.state = SessionState::Normal; self.from = None; + self.to.clear(); Ok(Reply::Completed(String::from(SERVER_NAME))) } @@ -103,12 +107,29 @@ impl SessionHandler { } self.from = Some(String::from(from)); + self.to.clear(); self.state = SessionState::MailTransaction; Ok(Reply::Completed(String::from("Ok"))) } + + /// TODO: Validate email addresses + /// Only after having started a mail transaction + async fn rcpt(&mut self, to: &str) -> Result<Reply> { + if self.state != SessionState::MailTransaction { + return Ok(Reply::BadSequence); + } + + if to.is_empty() { + return Ok(Reply::InvalidParameter); + } + + self.to.push(String::from(to)); + Ok(Reply::Completed(String::from("Ok"))) + } } +#[derive(PartialEq)] enum SessionState { WaitingHelo, MailTransaction, @@ -126,6 +147,7 @@ enum Reply { Completed(String), InvalidCommand, InvalidParameter, + BadSequence, } impl ToString for Reply { @@ -135,6 +157,7 @@ impl ToString for Reply { Reply::Completed(hostname) => format!("250 {}", hostname), Reply::InvalidCommand => format!("500 Command not recognized"), Reply::InvalidParameter => format!("501 Parameter error"), + Reply::BadSequence => format!("503 Bad sequence of commands"), } } } @@ -142,6 +165,7 @@ impl ToString for Reply { enum Command { HELO(String), MAIL(String), + RCPT(String), } impl TryFrom<&str> for Command { @@ -160,6 +184,12 @@ impl TryFrom<&str> for Command { return Ok(Command::MAIL(String::from(from))); } + if value.len() >= 9 && value.to_lowercase().starts_with("rcpt to:<") && value.contains('>') + { + let to = &value[9..value.find('>').unwrap()]; + return Ok(Command::RCPT(String::from(to))); + } + Err(anyhow::format_err!("Invalid command")) } } |
