mirror of
https://github.com/instant-labs/instant-smtp.git
synced 2025-02-17 23:42:09 +00:00
Improve fields of Command enum.
This commit is contained in:
parent
b8448a8889
commit
facfa4d7ea
@ -40,7 +40,12 @@ pub fn helo(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
|
|
||||||
let (remaining, (_, _, data, _)) = parser(input)?;
|
let (remaining, (_, _, data, _)) = parser(input)?;
|
||||||
|
|
||||||
Ok((remaining, Command::Helo(data.into())))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Command::Helo {
|
||||||
|
fqdn_or_address_literal: data.into(),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ehlo = "EHLO" SP ( Domain / address-literal ) CRLF
|
/// ehlo = "EHLO" SP ( Domain / address-literal ) CRLF
|
||||||
@ -54,7 +59,12 @@ pub fn ehlo(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
|
|
||||||
let (remaining, (_, _, data, _)) = parser(input)?;
|
let (remaining, (_, _, data, _)) = parser(input)?;
|
||||||
|
|
||||||
Ok((remaining, Command::Ehlo(data.into())))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Command::Ehlo {
|
||||||
|
fqdn_or_address_literal: data.into(),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// mail = "MAIL FROM:" Reverse-path [SP Mail-parameters] CRLF
|
/// mail = "MAIL FROM:" Reverse-path [SP Mail-parameters] CRLF
|
||||||
@ -72,8 +82,8 @@ pub fn mail(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Command::Mail {
|
Command::Mail {
|
||||||
data: data.into(),
|
reverse_path: data.into(),
|
||||||
params: maybe_params.map(|params| params.into()),
|
parameters: maybe_params.map(|params| params.into()),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -101,8 +111,8 @@ pub fn rcpt(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Command::Rcpt {
|
Command::Rcpt {
|
||||||
data: data.into(),
|
forward_path: data.into(),
|
||||||
params: maybe_params.map(|params| params.into()),
|
parameters: maybe_params.map(|params| params.into()),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -131,7 +141,12 @@ pub fn vrfy(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
|
|
||||||
let (remaining, (_, _, data, _)) = parser(input)?;
|
let (remaining, (_, _, data, _)) = parser(input)?;
|
||||||
|
|
||||||
Ok((remaining, Command::Vrfy(data.into())))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Command::Vrfy {
|
||||||
|
user_or_mailbox: data.into(),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// expn = "EXPN" SP String CRLF
|
/// expn = "EXPN" SP String CRLF
|
||||||
@ -140,7 +155,12 @@ pub fn expn(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
|
|
||||||
let (remaining, (_, _, data, _)) = parser(input)?;
|
let (remaining, (_, _, data, _)) = parser(input)?;
|
||||||
|
|
||||||
Ok((remaining, Command::Expn(data.into())))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Command::Expn {
|
||||||
|
mailing_list: data.into(),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// help = "HELP" [ SP String ] CRLF
|
/// help = "HELP" [ SP String ] CRLF
|
||||||
@ -149,7 +169,12 @@ pub fn help(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
|
|
||||||
let (remaining, (_, maybe_data, _)) = parser(input)?;
|
let (remaining, (_, maybe_data, _)) = parser(input)?;
|
||||||
|
|
||||||
Ok((remaining, Command::Help(maybe_data.map(|data| data.into()))))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Command::Help {
|
||||||
|
argument: maybe_data.map(|data| data.into()),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// noop = "NOOP" [ SP String ] CRLF
|
/// noop = "NOOP" [ SP String ] CRLF
|
||||||
@ -158,7 +183,12 @@ pub fn noop(input: &[u8]) -> IResult<&[u8], Command> {
|
|||||||
|
|
||||||
let (remaining, (_, maybe_data, _)) = parser(input)?;
|
let (remaining, (_, maybe_data, _)) = parser(input)?;
|
||||||
|
|
||||||
Ok((remaining, Command::Noop(maybe_data.map(|data| data.into()))))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Command::Noop {
|
||||||
|
argument: maybe_data.map(|data| data.into()),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// quit = "QUIT" CRLF
|
/// quit = "QUIT" CRLF
|
||||||
@ -512,14 +542,24 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_ehlo() {
|
fn test_ehlo() {
|
||||||
let (rem, parsed) = ehlo(b"EHLO [123.123.123.123]\r\n???").unwrap();
|
let (rem, parsed) = ehlo(b"EHLO [123.123.123.123]\r\n???").unwrap();
|
||||||
assert_eq!(parsed, Command::Ehlo(b"123.123.123.123".to_vec()));
|
assert_eq!(
|
||||||
|
parsed,
|
||||||
|
Command::Ehlo {
|
||||||
|
fqdn_or_address_literal: b"123.123.123.123".to_vec()
|
||||||
|
}
|
||||||
|
);
|
||||||
assert_eq!(rem, b"???");
|
assert_eq!(rem, b"???");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_helo() {
|
fn test_helo() {
|
||||||
let (rem, parsed) = helo(b"HELO example.com\r\n???").unwrap();
|
let (rem, parsed) = helo(b"HELO example.com\r\n???").unwrap();
|
||||||
assert_eq!(parsed, Command::Helo(b"example.com".to_vec()));
|
assert_eq!(
|
||||||
|
parsed,
|
||||||
|
Command::Helo {
|
||||||
|
fqdn_or_address_literal: b"example.com".to_vec()
|
||||||
|
}
|
||||||
|
);
|
||||||
assert_eq!(rem, b"???");
|
assert_eq!(rem, b"???");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,8 +569,8 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parsed,
|
parsed,
|
||||||
Command::Mail {
|
Command::Mail {
|
||||||
data: b"<userx@y.foo.org>".to_vec(),
|
reverse_path: b"<userx@y.foo.org>".to_vec(),
|
||||||
params: None
|
parameters: None
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(rem, b"???");
|
assert_eq!(rem, b"???");
|
||||||
|
137
src/types.rs
137
src/types.rs
@ -1,23 +1,86 @@
|
|||||||
use crate::escape;
|
use crate::escape;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Ehlo(Vec<u8>),
|
Ehlo {
|
||||||
Helo(Vec<u8>),
|
fqdn_or_address_literal: Vec<u8>,
|
||||||
|
},
|
||||||
|
Helo {
|
||||||
|
fqdn_or_address_literal: Vec<u8>,
|
||||||
|
},
|
||||||
Mail {
|
Mail {
|
||||||
data: Vec<u8>,
|
reverse_path: Vec<u8>,
|
||||||
params: Option<Vec<u8>>,
|
parameters: Option<Vec<u8>>,
|
||||||
},
|
},
|
||||||
Rcpt {
|
Rcpt {
|
||||||
data: Vec<u8>,
|
forward_path: Vec<u8>,
|
||||||
params: Option<Vec<u8>>,
|
parameters: Option<Vec<u8>>,
|
||||||
},
|
},
|
||||||
Data,
|
Data,
|
||||||
Rset,
|
Rset,
|
||||||
Vrfy(Vec<u8>),
|
/// This command asks the receiver to confirm that the argument
|
||||||
Expn(Vec<u8>),
|
/// identifies a user or mailbox. If it is a user name, information is
|
||||||
Help(Option<Vec<u8>>),
|
/// returned as specified in Section 3.5.
|
||||||
Noop(Option<Vec<u8>>),
|
///
|
||||||
|
/// This command has no effect on the reverse-path buffer, the forward-
|
||||||
|
/// path buffer, or the mail data buffer.
|
||||||
|
Vrfy {
|
||||||
|
user_or_mailbox: Vec<u8>,
|
||||||
|
},
|
||||||
|
/// This command asks the receiver to confirm that the argument
|
||||||
|
/// identifies a mailing list, and if so, to return the membership of
|
||||||
|
/// that list. If the command is successful, a reply is returned
|
||||||
|
/// containing information as described in Section 3.5. This reply will
|
||||||
|
/// have multiple lines except in the trivial case of a one-member list.
|
||||||
|
///
|
||||||
|
/// This command has no effect on the reverse-path buffer, the forward-
|
||||||
|
/// path buffer, or the mail data buffer, and it may be issued at any
|
||||||
|
/// time.
|
||||||
|
Expn {
|
||||||
|
mailing_list: Vec<u8>,
|
||||||
|
},
|
||||||
|
/// This command causes the server to send helpful information to the
|
||||||
|
/// client. The command MAY take an argument (e.g., any command name)
|
||||||
|
/// and return more specific information as a response.
|
||||||
|
///
|
||||||
|
/// SMTP servers SHOULD support HELP without arguments and MAY support it
|
||||||
|
/// with arguments.
|
||||||
|
///
|
||||||
|
/// This command has no effect on the reverse-path buffer, the forward-
|
||||||
|
/// path buffer, or the mail data buffer, and it may be issued at any
|
||||||
|
/// time.
|
||||||
|
Help {
|
||||||
|
argument: Option<Vec<u8>>,
|
||||||
|
},
|
||||||
|
/// This command does not affect any parameters or previously entered
|
||||||
|
/// commands. It specifies no action other than that the receiver send a
|
||||||
|
/// "250 OK" reply.
|
||||||
|
///
|
||||||
|
/// If a parameter string is specified, servers SHOULD ignore it.
|
||||||
|
///
|
||||||
|
/// This command has no effect on the reverse-path buffer, the forward-
|
||||||
|
/// path buffer, or the mail data buffer, and it may be issued at any
|
||||||
|
/// time.
|
||||||
|
Noop {
|
||||||
|
argument: Option<Vec<u8>>,
|
||||||
|
},
|
||||||
|
/// This command specifies that the receiver MUST send a "221 OK" reply,
|
||||||
|
/// and then close the transmission channel.
|
||||||
|
///
|
||||||
|
/// The receiver MUST NOT intentionally close the transmission channel
|
||||||
|
/// until it receives and replies to a QUIT command (even if there was an
|
||||||
|
/// error). The sender MUST NOT intentionally close the transmission
|
||||||
|
/// channel until it sends a QUIT command, and it SHOULD wait until it
|
||||||
|
/// receives the reply (even if there was an error response to a previous
|
||||||
|
/// command). If the connection is closed prematurely due to violations
|
||||||
|
/// of the above or system or network failure, the server MUST cancel any
|
||||||
|
/// pending transaction, but not undo any previously completed
|
||||||
|
/// transaction, and generally MUST act as if the command or transaction
|
||||||
|
/// in progress had received a temporary error (i.e., a 4yz response).
|
||||||
|
///
|
||||||
|
/// The QUIT command may be issued at any time. Any current uncompleted
|
||||||
|
/// mail transaction will be aborted.
|
||||||
Quit,
|
Quit,
|
||||||
// Extensions
|
// Extensions
|
||||||
StartTLS,
|
StartTLS,
|
||||||
@ -30,16 +93,16 @@ pub enum Command {
|
|||||||
impl Command {
|
impl Command {
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Command::Ehlo(_) => "EHLO",
|
Command::Ehlo { .. } => "EHLO",
|
||||||
Command::Helo(_) => "HELO",
|
Command::Helo { .. } => "HELO",
|
||||||
Command::Mail { .. } => "MAIL",
|
Command::Mail { .. } => "MAIL",
|
||||||
Command::Rcpt { .. } => "RCPT",
|
Command::Rcpt { .. } => "RCPT",
|
||||||
Command::Data => "DATA",
|
Command::Data => "DATA",
|
||||||
Command::Rset => "RSET",
|
Command::Rset => "RSET",
|
||||||
Command::Vrfy(_) => "VRFY",
|
Command::Vrfy { .. } => "VRFY",
|
||||||
Command::Expn(_) => "EXPN",
|
Command::Expn { .. } => "EXPN",
|
||||||
Command::Help(_) => "HELP",
|
Command::Help { .. } => "HELP",
|
||||||
Command::Noop(_) => "NOOP",
|
Command::Noop { .. } => "NOOP",
|
||||||
Command::Quit => "QUIT",
|
Command::Quit => "QUIT",
|
||||||
// Extensions
|
// Extensions
|
||||||
Command::StartTLS => "STARTTLS",
|
Command::StartTLS => "STARTTLS",
|
||||||
@ -51,34 +114,46 @@ impl Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: try to derive(Debug) instead
|
||||||
impl std::fmt::Debug for Command {
|
impl std::fmt::Debug for Command {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
use Command::*;
|
use Command::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Ehlo(data) => write!(f, "Ehlo({})", escape(data)),
|
Ehlo {
|
||||||
Helo(data) => write!(f, "Helo({})", escape(data)),
|
fqdn_or_address_literal,
|
||||||
|
} => write!(f, "Ehlo({})", escape(fqdn_or_address_literal)),
|
||||||
|
Helo {
|
||||||
|
fqdn_or_address_literal,
|
||||||
|
} => write!(f, "Helo({})", escape(fqdn_or_address_literal)),
|
||||||
Mail {
|
Mail {
|
||||||
data: path,
|
reverse_path: path,
|
||||||
params: None,
|
parameters: None,
|
||||||
} => write!(f, "Mail({})", escape(path)),
|
} => write!(f, "Mail({})", escape(path)),
|
||||||
Mail {
|
Mail {
|
||||||
data: path,
|
reverse_path: path,
|
||||||
params: Some(params),
|
parameters: Some(params),
|
||||||
} => write!(f, "Mail({}, {})", escape(path), escape(params)),
|
} => write!(f, "Mail({}, {})", escape(path), escape(params)),
|
||||||
Rcpt { data, params: None } => write!(f, "Rcpt({})", escape(data)),
|
|
||||||
Rcpt {
|
Rcpt {
|
||||||
data,
|
forward_path: data,
|
||||||
params: Some(params),
|
parameters: None,
|
||||||
|
} => write!(f, "Rcpt({})", escape(data)),
|
||||||
|
Rcpt {
|
||||||
|
forward_path: data,
|
||||||
|
parameters: Some(params),
|
||||||
} => write!(f, "Rcpt({}, {})", escape(data), escape(params)),
|
} => write!(f, "Rcpt({}, {})", escape(data), escape(params)),
|
||||||
Data => write!(f, "Data"),
|
Data => write!(f, "Data"),
|
||||||
Rset => write!(f, "Rset"),
|
Rset => write!(f, "Rset"),
|
||||||
Vrfy(data) => write!(f, "Vrfy({})", escape(data)),
|
Vrfy { user_or_mailbox } => write!(f, "Vrfy({})", escape(user_or_mailbox)),
|
||||||
Expn(data) => write!(f, "Expn({})", escape(data)),
|
Expn { mailing_list } => write!(f, "Expn({})", escape(mailing_list)),
|
||||||
Help(None) => write!(f, "Help"),
|
Help { argument: None } => write!(f, "Help"),
|
||||||
Help(Some(data)) => write!(f, "Help({})", escape(data)),
|
Help {
|
||||||
Noop(None) => write!(f, "Noop"),
|
argument: Some(data),
|
||||||
Noop(Some(data)) => write!(f, "Noop({})", escape(data)),
|
} => write!(f, "Help({})", escape(data)),
|
||||||
|
Noop { argument: None } => write!(f, "Noop"),
|
||||||
|
Noop {
|
||||||
|
argument: Some(data),
|
||||||
|
} => write!(f, "Noop({})", escape(data)),
|
||||||
Quit => write!(f, "Quit"),
|
Quit => write!(f, "Quit"),
|
||||||
// Extensions
|
// Extensions
|
||||||
StartTLS => write!(f, "StartTLS"),
|
StartTLS => write!(f, "StartTLS"),
|
||||||
|
Loading…
Reference in New Issue
Block a user