neo_email/client_message.rs
1use std::fmt::Debug;
2
3use serde::{Deserialize, Serialize};
4
5use super::{command::Commands, errors::SMTPError};
6
7/// # Client Message
8///
9/// This struct represents a message from the client to the server.
10/// It contains the command and the data.
11/// Usually they are like this:
12///
13/// ```
14/// HELO example.com
15/// MAIL FROM: <...>
16/// RCPT TO: <...>
17/// DATA
18/// ...
19/// ```
20#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
21pub struct ClientMessage<T> {
22 /// The command that the client is sending.
23 pub command: Commands,
24 /// The data that the client is sending.
25 pub data: T,
26}
27
28/// # Client Message
29///
30/// This implementation is for the ClientMessage struct.
31impl<T> ClientMessage<T> {
32 /// # From Bytes
33 ///
34 /// This function converts a byte array to a ClientMessage struct.
35 pub fn from_bytes<'a>(bytes: Vec<u8>) -> Result<ClientMessage<T>, SMTPError>
36 where
37 // The data must be able to be converted from a Vec<u8>
38 T: std::convert::From<std::string::String> + Debug,
39 {
40 // Convert bytes to string
41 let message = match String::from_utf8(bytes.to_vec()) {
42 Ok(cmd) => cmd,
43 // If it fails, return an error
44 Err(_) => {
45 return Err(SMTPError::ParseError(
46 "Cannot convert to String from bytes".to_owned(),
47 ))
48 }
49 };
50
51 // Split the message by spaces
52 let mut parts = message.split(" ");
53
54 // Get the command
55 let cmd = match parts.next() {
56 Some(cmd) => cmd.to_string(),
57 None => {
58 // If there is no command, return an error
59 return Err(SMTPError::ParseError(
60 "Invalid Message, Message doesn't contain COMMAND".to_owned(),
61 ));
62 }
63 };
64
65 // Rejoin with spaces
66 let data = parts.collect::<Vec<&str>>().join(" ");
67 // remove \r\n
68 let data = data.trim_end_matches("\r\n").to_string();
69 // Convert the command to a Commands enum
70 let command = Commands::from_bytes(cmd.as_bytes());
71 // Return the ClientMessage
72 Ok(ClientMessage {
73 command,
74 data: data.into(),
75 })
76 }
77}