Stick to idiomatic naming conventions

This commit is contained in:
Dirkjan Ochtman 2022-11-21 15:25:59 -08:00
parent 263c2c16cd
commit 351990b95e
5 changed files with 157 additions and 159 deletions

View File

@ -10,7 +10,7 @@ use nom::{
IResult,
};
use crate::parse::Ldh_str;
use crate::parse::ldh_str;
/// address-literal = "[" (
/// IPv4-address-literal /
@ -23,9 +23,9 @@ pub fn address_literal(input: &[u8]) -> IResult<&[u8], &str> {
tag(b"["),
map_res(
alt((
IPv4_address_literal,
IPv6_address_literal,
General_address_literal,
ipv4_address_literal,
ipv6_address_literal,
general_address_literal,
)),
std::str::from_utf8,
),
@ -34,8 +34,8 @@ pub fn address_literal(input: &[u8]) -> IResult<&[u8], &str> {
}
/// IPv4-address-literal = Snum 3("." Snum)
pub fn IPv4_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((Snum, count(tuple((tag(b"."), Snum)), 3)));
pub fn ipv4_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((snum, count(tuple((tag(b"."), snum)), 3)));
let (remaining, parsed) = recognize(parser)(input)?;
@ -45,13 +45,13 @@ pub fn IPv4_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
/// Representing a decimal integer value in the range 0 through 255
///
/// Snum = 1*3DIGIT
pub fn Snum(input: &[u8]) -> IResult<&[u8], &[u8]> {
pub fn snum(input: &[u8]) -> IResult<&[u8], &[u8]> {
take_while_m_n(1, 3, is_digit)(input)
}
/// IPv6-address-literal = "IPv6:" IPv6-addr
pub fn IPv6_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((tag_no_case(b"IPv6:"), IPv6_addr));
pub fn ipv6_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((tag_no_case(b"IPv6:"), ipv6_addr));
let (remaining, parsed) = recognize(parser)(input)?;
@ -59,8 +59,8 @@ pub fn IPv6_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
pub fn IPv6_addr(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = alt((IPv6_full, IPv6_comp, IPv6v4_full, IPv6v4_comp));
pub fn ipv6_addr(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = alt((ipv6_full, ipv6_comp, ipv6v4_full, ipv6v4_comp));
let (remaining, parsed) = recognize(parser)(input)?;
@ -68,8 +68,8 @@ pub fn IPv6_addr(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// IPv6-full = IPv6-hex 7(":" IPv6-hex)
pub fn IPv6_full(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((IPv6_hex, count(tuple((tag(b":"), IPv6_hex)), 7)));
pub fn ipv6_full(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((ipv6_hex, count(tuple((tag(b":"), ipv6_hex)), 7)));
let (remaining, parsed) = recognize(parser)(input)?;
@ -77,7 +77,7 @@ pub fn IPv6_full(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// IPv6-hex = 1*4HEXDIG
pub fn IPv6_hex(input: &[u8]) -> IResult<&[u8], &[u8]> {
pub fn ipv6_hex(input: &[u8]) -> IResult<&[u8], &[u8]> {
take_while_m_n(1, 4, is_hex_digit)(input)
}
@ -85,16 +85,16 @@ pub fn IPv6_hex(input: &[u8]) -> IResult<&[u8], &[u8]> {
/// No more than 6 groups in addition to the "::" may be present.
///
/// IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::" [IPv6-hex *5(":" IPv6-hex)]
pub fn IPv6_comp(input: &[u8]) -> IResult<&[u8], &[u8]> {
pub fn ipv6_comp(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((
opt(tuple((
IPv6_hex,
many_m_n(0, 5, tuple((tag(b":"), IPv6_hex))),
ipv6_hex,
many_m_n(0, 5, tuple((tag(b":"), ipv6_hex))),
))),
tag(b"::"),
opt(tuple((
IPv6_hex,
many_m_n(0, 5, tuple((tag(b":"), IPv6_hex))),
ipv6_hex,
many_m_n(0, 5, tuple((tag(b":"), ipv6_hex))),
))),
));
@ -104,12 +104,12 @@ pub fn IPv6_comp(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
pub fn IPv6v4_full(input: &[u8]) -> IResult<&[u8], &[u8]> {
pub fn ipv6v4_full(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((
IPv6_hex,
count(tuple((tag(b":"), IPv6_hex)), 5),
ipv6_hex,
count(tuple((tag(b":"), ipv6_hex)), 5),
tag(b":"),
IPv4_address_literal,
ipv4_address_literal,
));
let (remaining, parsed) = recognize(parser)(input)?;
@ -123,19 +123,19 @@ pub fn IPv6v4_full(input: &[u8]) -> IResult<&[u8], &[u8]> {
/// IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
/// [IPv6-hex *3(":" IPv6-hex) ":"]
/// IPv4-address-literal
pub fn IPv6v4_comp(input: &[u8]) -> IResult<&[u8], &[u8]> {
pub fn ipv6v4_comp(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((
opt(tuple((
IPv6_hex,
many_m_n(0, 3, tuple((tag(b":"), IPv6_hex))),
ipv6_hex,
many_m_n(0, 3, tuple((tag(b":"), ipv6_hex))),
))),
tag(b"::"),
opt(tuple((
IPv6_hex,
many_m_n(0, 3, tuple((tag(b":"), IPv6_hex))),
ipv6_hex,
many_m_n(0, 3, tuple((tag(b":"), ipv6_hex))),
tag(b":"),
))),
IPv4_address_literal,
ipv4_address_literal,
));
let (remaining, parsed) = recognize(parser)(input)?;
@ -144,8 +144,8 @@ pub fn IPv6v4_comp(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// General-address-literal = Standardized-tag ":" 1*dcontent
pub fn General_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((Standardized_tag, tag(b":"), take_while1(is_dcontent)));
pub fn general_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((standardized_tag, tag(b":"), take_while1(is_dcontent)));
let (remaining, parsed) = recognize(parser)(input)?;
@ -155,8 +155,8 @@ pub fn General_address_literal(input: &[u8]) -> IResult<&[u8], &[u8]> {
/// Standardized-tag MUST be specified in a Standards-Track RFC and registered with IANA
///
/// Standardized-tag = Ldh-str
pub fn Standardized_tag(input: &[u8]) -> IResult<&[u8], &[u8]> {
Ldh_str(input)
pub fn standardized_tag(input: &[u8]) -> IResult<&[u8], &[u8]> {
ldh_str(input)
}
/// Printable US-ASCII excl. "[", "\", "]"

View File

@ -9,7 +9,7 @@ use nom::{
};
use crate::{
parse::{address::address_literal, base64, Atom, Domain, Quoted_string, String},
parse::{address::address_literal, atom, base64, domain, quoted_string, string},
types::{Command, DomainOrAddress, Parameter},
};
@ -28,7 +28,7 @@ pub fn helo(input: &[u8]) -> IResult<&[u8], Command> {
tag_no_case(b"HELO"),
tag(" "),
alt((
map(Domain, |domain| DomainOrAddress::Domain(domain.into())),
map(domain, |domain| DomainOrAddress::Domain(domain.into())),
map(address_literal, |address| {
DomainOrAddress::Address(address.into())
}),
@ -47,7 +47,7 @@ pub fn ehlo(input: &[u8]) -> IResult<&[u8], Command> {
tag_no_case(b"EHLO"),
tag(" "),
alt((
map(Domain, |domain| DomainOrAddress::Domain(domain.into())),
map(domain, |domain| DomainOrAddress::Domain(domain.into())),
map(address_literal, |address| {
DomainOrAddress::Address(address.into())
}),
@ -65,8 +65,8 @@ pub fn mail(input: &[u8]) -> IResult<&[u8], Command> {
let mut parser = tuple((
tag_no_case(b"MAIL FROM:"),
opt(tag(" ")), // Out-of-tag(" ")ec, but Outlook does it ...
Reverse_path,
opt(preceded(tag(" "), Mail_parameters)),
reverse_path,
opt(preceded(tag(" "), mail_parameters)),
tag("\r\n"),
));
@ -82,7 +82,7 @@ pub fn mail(input: &[u8]) -> IResult<&[u8], Command> {
}
/// Mail-parameters = esmtp-param *(tag(" ") esmtp-param)
pub fn Mail_parameters(input: &[u8]) -> IResult<&[u8], Vec<Parameter>> {
pub fn mail_parameters(input: &[u8]) -> IResult<&[u8], Vec<Parameter>> {
separated_list1(tag(" "), esmtp_param)(input)
}
@ -138,13 +138,13 @@ pub fn rcpt(input: &[u8]) -> IResult<&[u8], Command> {
opt(tag(" ")), // Out-of-tag(" ")ec, but Outlook does it ...
alt((
map_res(
recognize(tuple((tag_no_case("<Postmaster@"), Domain, tag(">")))),
recognize(tuple((tag_no_case("<Postmaster@"), domain, tag(">")))),
std::str::from_utf8,
),
map_res(tag_no_case("<Postmaster>"), std::str::from_utf8),
Forward_path,
forward_path,
)),
opt(preceded(tag(" "), Rcpt_parameters)),
opt(preceded(tag(" "), rcpt_parameters)),
tag("\r\n"),
));
@ -160,7 +160,7 @@ pub fn rcpt(input: &[u8]) -> IResult<&[u8], Command> {
}
/// Rcpt-parameters = esmtp-param *(tag(" ") esmtp-param)
pub fn Rcpt_parameters(input: &[u8]) -> IResult<&[u8], Vec<Parameter>> {
pub fn rcpt_parameters(input: &[u8]) -> IResult<&[u8], Vec<Parameter>> {
separated_list1(tag(" "), esmtp_param)(input)
}
@ -176,7 +176,7 @@ pub fn rset(input: &[u8]) -> IResult<&[u8], Command> {
/// vrfy = "VRFY" tag(" ") String CRLF
pub fn vrfy(input: &[u8]) -> IResult<&[u8], Command> {
let mut parser = tuple((tag_no_case(b"VRFY"), tag(" "), String, tag("\r\n")));
let mut parser = tuple((tag_no_case(b"VRFY"), tag(" "), string, tag("\r\n")));
let (remaining, (_, _, data, _)) = parser(input)?;
@ -190,7 +190,7 @@ pub fn vrfy(input: &[u8]) -> IResult<&[u8], Command> {
/// expn = "EXPN" tag(" ") String CRLF
pub fn expn(input: &[u8]) -> IResult<&[u8], Command> {
let mut parser = tuple((tag_no_case(b"EXPN"), tag(" "), String, tag("\r\n")));
let mut parser = tuple((tag_no_case(b"EXPN"), tag(" "), string, tag("\r\n")));
let (remaining, (_, _, data, _)) = parser(input)?;
@ -201,7 +201,7 @@ pub fn expn(input: &[u8]) -> IResult<&[u8], Command> {
pub fn help(input: &[u8]) -> IResult<&[u8], Command> {
let mut parser = tuple((
tag_no_case(b"HELP"),
opt(preceded(tag(" "), String)),
opt(preceded(tag(" "), string)),
tag("\r\n"),
));
@ -219,7 +219,7 @@ pub fn help(input: &[u8]) -> IResult<&[u8], Command> {
pub fn noop(input: &[u8]) -> IResult<&[u8], Command> {
let mut parser = tuple((
tag_no_case(b"NOOP"),
opt(preceded(tag(" "), String)),
opt(preceded(tag(" "), string)),
tag("\r\n"),
));
@ -240,7 +240,7 @@ pub fn quit(input: &[u8]) -> IResult<&[u8], Command> {
pub fn starttls(input: &[u8]) -> IResult<&[u8], Command> {
value(
Command::StartTLS,
Command::StartTls,
tuple((tag_no_case(b"STARTTLS"), tag("\r\n"))),
)(input)
}
@ -293,21 +293,21 @@ pub fn auth_plain(input: &[u8]) -> IResult<&[u8], Command> {
// ----- 4.1.2. Command Argument Syntax (RFC 5321) -----
/// Reverse-path = Path / "<>"
pub fn Reverse_path(input: &[u8]) -> IResult<&[u8], &str> {
alt((Path, value("", tag("<>"))))(input)
pub fn reverse_path(input: &[u8]) -> IResult<&[u8], &str> {
alt((path, value("", tag("<>"))))(input)
}
/// Forward-path = Path
pub fn Forward_path(input: &[u8]) -> IResult<&[u8], &str> {
Path(input)
pub fn forward_path(input: &[u8]) -> IResult<&[u8], &str> {
path(input)
}
// Path = "<" [ A-d-l ":" ] Mailbox ">"
pub fn Path(input: &[u8]) -> IResult<&[u8], &str> {
pub fn path(input: &[u8]) -> IResult<&[u8], &str> {
delimited(
tag(b"<"),
map_res(
recognize(tuple((opt(tuple((A_d_l, tag(b":")))), Mailbox))),
recognize(tuple((opt(tuple((a_d_l, tag(b":")))), mailbox))),
std::str::from_utf8,
),
tag(b">"),
@ -318,8 +318,8 @@ pub fn Path(input: &[u8]) -> IResult<&[u8], &str> {
/// ; Note that this form, the so-called "source
/// ; route", MUST BE accepted, SHOULD NOT be
/// ; generated, and SHOULD be ignored.
pub fn A_d_l(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = separated_list1(tag(b","), At_domain);
pub fn a_d_l(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = separated_list1(tag(b","), at_domain);
let (remaining, parsed) = recognize(parser)(input)?;
@ -327,8 +327,8 @@ pub fn A_d_l(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// At-domain = "@" Domain
pub fn At_domain(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((tag(b"@"), Domain));
pub fn at_domain(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((tag(b"@"), domain));
let (remaining, parsed) = recognize(parser)(input)?;
@ -336,8 +336,8 @@ pub fn At_domain(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// Mailbox = Local-part "@" ( Domain / address-literal )
pub fn Mailbox(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((Local_part, tag(b"@"), alt((Domain, address_literal))));
pub fn mailbox(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((local_part, tag(b"@"), alt((domain, address_literal))));
let (remaining, parsed) = recognize(parser)(input)?;
@ -346,14 +346,14 @@ pub fn Mailbox(input: &[u8]) -> IResult<&[u8], &[u8]> {
/// Local-part = Dot-string / Quoted-string
/// ; MAY be case-sensitive
pub fn Local_part(input: &[u8]) -> IResult<&[u8], &[u8]> {
alt((recognize(Dot_string), recognize(Quoted_string)))(input)
pub fn local_part(input: &[u8]) -> IResult<&[u8], &[u8]> {
alt((recognize(dot_string), recognize(quoted_string)))(input)
}
/// Dot-string = Atom *("." Atom)
pub fn Dot_string(input: &[u8]) -> IResult<&[u8], &str> {
pub fn dot_string(input: &[u8]) -> IResult<&[u8], &str> {
map_res(
recognize(separated_list1(tag(b"."), Atom)),
recognize(separated_list1(tag(b"."), atom)),
std::str::from_utf8,
)(input)
}

View File

@ -1,5 +1,3 @@
#![allow(non_snake_case)]
use std::{borrow::Cow, str::from_utf8};
use nom::{
@ -44,15 +42,15 @@ pub fn number(input: &[u8]) -> IResult<&[u8], u32> {
// -------------------------------------------------------------------------------------------------
/// String = Atom / Quoted-string
pub fn String(input: &[u8]) -> IResult<&[u8], AtomOrQuoted> {
pub fn string(input: &[u8]) -> IResult<&[u8], AtomOrQuoted> {
alt((
map(Atom, |atom| AtomOrQuoted::Atom(atom.into())),
map(Quoted_string, |quoted| AtomOrQuoted::Quoted(quoted.into())),
map(atom, |atom| AtomOrQuoted::Atom(atom.into())),
map(quoted_string, |quoted| AtomOrQuoted::Quoted(quoted.into())),
))(input)
}
/// Atom = 1*atext
pub fn Atom(input: &[u8]) -> IResult<&[u8], &str> {
pub fn atom(input: &[u8]) -> IResult<&[u8], &str> {
map_res(take_while1(is_atext), std::str::from_utf8)(input)
}
@ -77,11 +75,11 @@ pub fn is_atext(byte: u8) -> bool {
}
/// Quoted-string = DQUOTE *QcontentSMTP DQUOTE
pub fn Quoted_string(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
pub fn quoted_string(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
map(
delimited(
tag("\""),
map_res(recognize(many0(QcontentSMTP)), std::str::from_utf8),
map_res(recognize(many0(q_content_smtp)), std::str::from_utf8),
tag("\""),
),
unescape_quoted,
@ -89,8 +87,8 @@ pub fn Quoted_string(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
}
/// QcontentSMTP = qtextSMTP / quoted-pairSMTP
pub fn QcontentSMTP(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = alt((take_while_m_n(1, 1, is_qtextSMTP), quoted_pairSMTP));
pub fn q_content_smtp(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = alt((take_while_m_n(1, 1, is_qtext_smtp), quoted_pair_smtp));
let (remaining, parsed) = recognize(parser)(input)?;
@ -101,7 +99,7 @@ pub fn QcontentSMTP(input: &[u8]) -> IResult<&[u8], &[u8]> {
/// without blackslash-quoting except double-quote and the backslash itself.
///
/// qtextSMTP = %d32-33 / %d35-91 / %d93-126
pub fn is_qtextSMTP(byte: u8) -> bool {
pub fn is_qtext_smtp(byte: u8) -> bool {
matches!(byte, 32..=33 | 35..=91 | 93..=126)
}
@ -110,7 +108,7 @@ pub fn is_qtextSMTP(byte: u8) -> bool {
/// quoted-pairSMTP = %d92 %d32-126
///
/// FIXME: How should e.g. "\a" be interpreted?
pub fn quoted_pairSMTP(input: &[u8]) -> IResult<&[u8], &[u8]> {
pub fn quoted_pair_smtp(input: &[u8]) -> IResult<&[u8], &[u8]> {
//fn is_value(byte: u8) -> bool {
// matches!(byte, 32..=126)
//}
@ -130,7 +128,7 @@ pub fn quoted_pairSMTP(input: &[u8]) -> IResult<&[u8], &[u8]> {
// -------------------------------------------------------------------------------------------------
/// Domain = sub-domain *("." sub-domain)
pub fn Domain(input: &[u8]) -> IResult<&[u8], &str> {
pub fn domain(input: &[u8]) -> IResult<&[u8], &str> {
let parser = separated_list1(tag(b"."), sub_domain);
let (remaining, parsed) = map_res(recognize(parser), std::str::from_utf8)(input)?;
@ -140,7 +138,7 @@ pub fn Domain(input: &[u8]) -> IResult<&[u8], &str> {
/// sub-domain = Let-dig [Ldh-str]
pub fn sub_domain(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = tuple((take_while_m_n(1, 1, is_Let_dig), opt(Ldh_str)));
let parser = tuple((take_while_m_n(1, 1, is_let_dig), opt(ldh_str)));
let (remaining, parsed) = recognize(parser)(input)?;
@ -148,16 +146,16 @@ pub fn sub_domain(input: &[u8]) -> IResult<&[u8], &[u8]> {
}
/// Let-dig = ALPHA / DIGIT
pub fn is_Let_dig(byte: u8) -> bool {
pub fn is_let_dig(byte: u8) -> bool {
is_alphabetic(byte) || is_digit(byte)
}
/// Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
pub fn Ldh_str(input: &[u8]) -> IResult<&[u8], &[u8]> {
pub fn ldh_str(input: &[u8]) -> IResult<&[u8], &[u8]> {
let parser = many0(alt((
take_while_m_n(1, 1, is_alphabetic),
take_while_m_n(1, 1, is_digit),
recognize(tuple((tag(b"-"), take_while_m_n(1, 1, is_Let_dig)))),
recognize(tuple((tag(b"-"), take_while_m_n(1, 1, is_let_dig)))),
)));
let (remaining, parsed) = recognize(parser)(input)?;

View File

@ -11,7 +11,7 @@ use nom::{
};
use crate::{
parse::{address::address_literal, number, Domain},
parse::{address::address_literal, domain, number},
types::{AuthMechanism, Capability, ReplyCode, Response, TextString},
};
@ -19,12 +19,12 @@ use crate::{
/// ( "220-" (Domain / address-literal) [ SP textstring ] CRLF
/// *( "220-" [ textstring ] CRLF )
/// "220" [ SP textstring ] CRLF )
pub fn Greeting(input: &[u8]) -> IResult<&[u8], Response> {
pub fn greeting(input: &[u8]) -> IResult<&[u8], Response> {
let mut parser = alt((
map(
tuple((
tag(b"220 "),
alt((Domain, address_literal)),
alt((domain, address_literal)),
opt(preceded(tag(" "), textstring)),
tag("\r\n"),
)),
@ -38,7 +38,7 @@ pub fn Greeting(input: &[u8]) -> IResult<&[u8], Response> {
map(
tuple((
tag(b"220-"),
alt((Domain, address_literal)),
alt((domain, address_literal)),
opt(preceded(tag(" "), textstring)),
tag("\r\n"),
many0(delimited(tag(b"220-"), opt(textstring), tag("\r\n"))),
@ -94,11 +94,11 @@ pub(crate) fn is_text_string_byte(byte: u8) -> bool {
/// Reply-line = *( Reply-code "-" [ textstring ] CRLF )
/// Reply-code [ SP textstring ] CRLF
pub fn Reply_lines(input: &[u8]) -> IResult<&[u8], Response> {
pub fn reply_lines(input: &[u8]) -> IResult<&[u8], Response> {
let mut parser = map(
tuple((
many0(tuple((Reply_code, tag(b"-"), opt(textstring), tag("\r\n")))),
Reply_code,
many0(tuple((reply_code, tag(b"-"), opt(textstring), tag("\r\n")))),
reply_code,
opt(tuple((tag(" "), textstring))),
tag("\r\n"),
)),
@ -129,7 +129,7 @@ pub fn Reply_lines(input: &[u8]) -> IResult<&[u8], Response> {
/// 2345
/// 012345
/// 0123456789
pub fn Reply_code(input: &[u8]) -> IResult<&[u8], ReplyCode> {
pub fn reply_code(input: &[u8]) -> IResult<&[u8], ReplyCode> {
// FIXME: do not accept all codes.
map_res(
map_res(
@ -153,7 +153,7 @@ pub fn ehlo_ok_rsp(input: &[u8]) -> IResult<&[u8], Response> {
map(
tuple((
tag(b"250 "),
Domain,
domain,
opt(preceded(tag(" "), ehlo_greet)),
tag("\r\n"),
)),
@ -166,7 +166,7 @@ pub fn ehlo_ok_rsp(input: &[u8]) -> IResult<&[u8], Response> {
map(
tuple((
tag(b"250-"),
Domain,
domain,
opt(preceded(tag(" "), ehlo_greet)),
tag("\r\n"),
many0(delimited(tag(b"250-"), ehlo_line, tag("\r\n"))),
@ -220,34 +220,34 @@ pub fn ehlo_line(input: &[u8]) -> IResult<&[u8], Capability> {
));
alt((
value(Capability::EXPN, tag_no_case("EXPN")),
value(Capability::Expn, tag_no_case("EXPN")),
value(Capability::Help, tag_no_case("HELP")),
value(Capability::EightBitMIME, tag_no_case("8BITMIME")),
value(Capability::EightBitMime, tag_no_case("8BITMIME")),
map(preceded(tag_no_case("SIZE "), number), Capability::Size),
value(Capability::Chunking, tag_no_case("CHUNKING")),
value(Capability::BinaryMIME, tag_no_case("BINARYMIME")),
value(Capability::BinaryMime, tag_no_case("BINARYMIME")),
value(Capability::Checkpoint, tag_no_case("CHECKPOINT")),
value(Capability::DeliverBy, tag_no_case("DELIVERBY")),
value(Capability::Pipelining, tag_no_case("PIPELINING")),
value(Capability::DSN, tag_no_case("DSN")),
value(Capability::ETRN, tag_no_case("ETRN")),
value(Capability::Dsn, tag_no_case("DSN")),
value(Capability::Etrn, tag_no_case("ETRN")),
value(
Capability::EnhancedStatusCodes,
tag_no_case("ENHANCEDSTATUSCODES"),
),
value(Capability::StartTLS, tag_no_case("STARTTLS")),
value(Capability::StartTls, tag_no_case("STARTTLS")),
// FIXME: NO-SOLICITING
value(Capability::MTRK, tag_no_case("MTRK")),
value(Capability::ATRN, tag_no_case("ATRN")),
value(Capability::Mtrk, tag_no_case("MTRK")),
value(Capability::Atrn, tag_no_case("ATRN")),
map(auth, |(_, _, mechanisms)| Capability::Auth(mechanisms)),
value(Capability::BURL, tag_no_case("BURL")),
value(Capability::Burl, tag_no_case("BURL")),
// FIXME: FUTURERELEASE
// FIXME: CONPERM
// FIXME: CONNEG
value(Capability::SMTPUTF8, tag_no_case("SMTPUTF8")),
value(Capability::SmtpUtf8, tag_no_case("SMTPUTF8")),
// FIXME: MT-PRIORITY
value(Capability::RRVS, tag_no_case("RRVS")),
value(Capability::RequireTLS, tag_no_case("REQUIRETLS")),
value(Capability::Rrvs, tag_no_case("RRVS")),
value(Capability::RequireTls, tag_no_case("REQUIRETLS")),
map(other, |(keyword, params)| Capability::Other {
keyword: keyword.into(),
params: params
@ -287,12 +287,12 @@ pub fn auth_mechanism(input: &[u8]) -> IResult<&[u8], AuthMechanism> {
alt((
value(AuthMechanism::Login, tag_no_case("LOGIN")),
value(AuthMechanism::Plain, tag_no_case("PLAIN")),
value(AuthMechanism::CramMD5, tag_no_case("CRAM-MD5")),
value(AuthMechanism::CramSHA1, tag_no_case("CRAM-SHA1")),
value(AuthMechanism::DigestMD5, tag_no_case("DIGEST-MD5")),
value(AuthMechanism::ScramMD5, tag_no_case("SCRAM-MD5")),
value(AuthMechanism::GSSAPI, tag_no_case("GSSAPI")),
value(AuthMechanism::NTLM, tag_no_case("NTLM")),
value(AuthMechanism::CramMd5, tag_no_case("CRAM-MD5")),
value(AuthMechanism::CramSha1, tag_no_case("CRAM-SHA1")),
value(AuthMechanism::DigestMd5, tag_no_case("DIGEST-MD5")),
value(AuthMechanism::ScramMd5, tag_no_case("SCRAM-MD5")),
value(AuthMechanism::GssApi, tag_no_case("GSSAPI")),
value(AuthMechanism::Ntlm, tag_no_case("NTLM")),
map(ehlo_param, |param| AuthMechanism::Other(param.to_string())),
))(input)
}
@ -305,12 +305,12 @@ mod test {
use crate::types::AuthMechanism;
#[test]
fn test_Greeting() {
let greeting = b"220-example.org ESMTP Fake 4.93 #2 Thu, 16 Jul 2020 07:30:16 -0400\r\n\
fn test_greeting() {
let buf = b"220-example.org ESMTP Fake 4.93 #2 Thu, 16 Jul 2020 07:30:16 -0400\r\n\
220-We do not authorize the use of this system to transport unsolicited,\r\n\
220 and/or bulk e-mail.\r\n";
let (rem, out) = Greeting(greeting).unwrap();
let (rem, out) = greeting(buf).unwrap();
assert_eq!(rem, b"");
assert_eq!(
out,
@ -344,17 +344,17 @@ and/or bulk e-mail."
capabilities: vec![
Capability::Auth(vec![
AuthMechanism::Login,
AuthMechanism::CramMD5,
AuthMechanism::CramMd5,
AuthMechanism::Plain
]),
Capability::Auth(vec![
AuthMechanism::Login,
AuthMechanism::CramMD5,
AuthMechanism::CramMd5,
AuthMechanism::Plain
]),
Capability::StartTLS,
Capability::StartTls,
Capability::Size(12345),
Capability::EightBitMIME,
Capability::EightBitMime,
],
}
);

View File

@ -89,7 +89,7 @@ pub enum Command {
/// mail transaction will be aborted.
Quit,
// Extensions
StartTLS,
StartTls,
// AUTH LOGIN
AuthLogin(Option<String>),
// AUTH PLAIN
@ -149,7 +149,7 @@ impl Command {
Command::Noop { .. } => "NOOP",
Command::Quit => "QUIT",
// Extensions
Command::StartTLS => "STARTTLS",
Command::StartTls => "STARTTLS",
// TODO: SMTP AUTH LOGIN
Command::AuthLogin(_) => "AUTHLOGIN",
// TODO: SMTP AUTH PLAIN
@ -233,7 +233,7 @@ impl Command {
Quit => writer.write_all(b"QUIT")?,
// ----- Extensions -----
// starttls = "STARTTLS" CRLF
StartTLS => writer.write_all(b"STARTTLS")?,
StartTls => writer.write_all(b"STARTTLS")?,
// auth_login_command = "AUTH LOGIN" [SP username] CRLF
AuthLogin(None) => {
writer.write_all(b"AUTH LOGIN")?;
@ -316,7 +316,7 @@ pub enum Response {
impl Response {
pub fn parse_greeting(input: &[u8]) -> IResult<&[u8], Self> {
crate::parse::response::Greeting(input)
crate::parse::response::greeting(input)
}
pub fn greeting<D, T>(domain: D, text: T) -> Response
@ -335,7 +335,7 @@ impl Response {
}
pub fn parse_other(input: &[u8]) -> IResult<&[u8], Self> {
crate::parse::response::Reply_lines(input)
crate::parse::response::reply_lines(input)
}
pub fn ehlo<D, G>(domain: D, greet: Option<G>, capabilities: Vec<Capability>) -> Response
@ -465,13 +465,13 @@ pub enum Capability {
/// Expand the mailing list [RFC821]
/// Command description updated by [RFC5321]
EXPN,
Expn,
/// Supply helpful information [RFC821]
/// Command description updated by [RFC5321]
Help,
/// SMTP and Submit transport of 8bit MIME content [RFC6152]
EightBitMIME,
EightBitMime,
/// Message size declaration [RFC1870]
Size(u32),
@ -480,7 +480,7 @@ pub enum Capability {
Chunking,
/// Binary MIME [RFC3030]
BinaryMIME,
BinaryMime,
/// Checkpoint/Restart [RFC1845]
Checkpoint,
@ -492,34 +492,34 @@ pub enum Capability {
Pipelining,
/// Delivery Status Notification [RFC3461]
DSN,
Dsn,
/// Extended Turn [RFC1985]
/// SMTP [RFC5321] only. Not for use on Submit port 587.
ETRN,
Etrn,
/// Enhanced Status Codes [RFC2034]
EnhancedStatusCodes,
/// Start TLS [RFC3207]
StartTLS,
StartTls,
/// Notification of no soliciting [RFC3865]
// NoSoliciting,
/// Message Tracking [RFC3885]
MTRK,
Mtrk,
/// Authenticated TURN [RFC2645]
/// SMTP [RFC5321] only. Not for use on Submit port 587.
ATRN,
Atrn,
/// Authentication [RFC4954]
Auth(Vec<AuthMechanism>),
/// Remote Content [RFC4468]
/// Submit [RFC6409] only. Not for use with SMTP on port 25.
BURL,
Burl,
/// Future Message Release [RFC4865]
// FutureRelease,
@ -531,16 +531,16 @@ pub enum Capability {
// ConNeg,
/// Internationalized email address [RFC6531]
SMTPUTF8,
SmtpUtf8,
/// Priority Message Handling [RFC6710]
// MTPRIORITY,
/// Require Recipient Valid Since [RFC7293]
RRVS,
Rrvs,
/// Require TLS [RFC8689]
RequireTLS,
RequireTls,
// Observed ...
// TIME,
@ -557,21 +557,21 @@ pub enum Capability {
impl Capability {
pub fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
match self {
Capability::EXPN => writer.write_all(b"EXPN"),
Capability::Expn => writer.write_all(b"EXPN"),
Capability::Help => writer.write_all(b"HELP"),
Capability::EightBitMIME => writer.write_all(b"8BITMIME"),
Capability::EightBitMime => writer.write_all(b"8BITMIME"),
Capability::Size(number) => writer.write_all(format!("SIZE {}", number).as_bytes()),
Capability::Chunking => writer.write_all(b"CHUNKING"),
Capability::BinaryMIME => writer.write_all(b"BINARYMIME"),
Capability::BinaryMime => writer.write_all(b"BINARYMIME"),
Capability::Checkpoint => writer.write_all(b"CHECKPOINT"),
Capability::DeliverBy => writer.write_all(b"DELIVERBY"),
Capability::Pipelining => writer.write_all(b"PIPELINING"),
Capability::DSN => writer.write_all(b"DSN"),
Capability::ETRN => writer.write_all(b"ETRN"),
Capability::Dsn => writer.write_all(b"DSN"),
Capability::Etrn => writer.write_all(b"ETRN"),
Capability::EnhancedStatusCodes => writer.write_all(b"ENHANCEDSTATUSCODES"),
Capability::StartTLS => writer.write_all(b"STARTTLS"),
Capability::MTRK => writer.write_all(b"MTRK"),
Capability::ATRN => writer.write_all(b"ATRN"),
Capability::StartTls => writer.write_all(b"STARTTLS"),
Capability::Mtrk => writer.write_all(b"MTRK"),
Capability::Atrn => writer.write_all(b"ATRN"),
Capability::Auth(mechanisms) => {
if let Some((tail, head)) = mechanisms.split_last() {
writer.write_all(b"AUTH ")?;
@ -586,10 +586,10 @@ impl Capability {
writer.write_all(b"AUTH")
}
}
Capability::BURL => writer.write_all(b"BURL"),
Capability::SMTPUTF8 => writer.write_all(b"SMTPUTF8"),
Capability::RRVS => writer.write_all(b"RRVS"),
Capability::RequireTLS => writer.write_all(b"REQUIRETLS"),
Capability::Burl => writer.write_all(b"BURL"),
Capability::SmtpUtf8 => writer.write_all(b"SMTPUTF8"),
Capability::Rrvs => writer.write_all(b"RRVS"),
Capability::RequireTls => writer.write_all(b"REQUIRETLS"),
Capability::Other { keyword, params } => {
if let Some((tail, head)) = params.split_last() {
writer.write_all(keyword.as_bytes())?;
@ -773,13 +773,13 @@ impl From<ReplyCode> for u16 {
pub enum AuthMechanism {
Plain,
Login,
GSSAPI,
GssApi,
CramMD5,
CramSHA1,
ScramMD5,
DigestMD5,
NTLM,
CramMd5,
CramSha1,
ScramMd5,
DigestMd5,
Ntlm,
Other(String),
}
@ -789,13 +789,13 @@ impl AuthMechanism {
match self {
AuthMechanism::Plain => writer.write_all(b"PLAIN"),
AuthMechanism::Login => writer.write_all(b"LOGIN"),
AuthMechanism::GSSAPI => writer.write_all(b"GSSAPI"),
AuthMechanism::GssApi => writer.write_all(b"GSSAPI"),
AuthMechanism::CramMD5 => writer.write_all(b"CRAM-MD5"),
AuthMechanism::CramSHA1 => writer.write_all(b"CRAM-SHA1"),
AuthMechanism::ScramMD5 => writer.write_all(b"SCRAM-MD5"),
AuthMechanism::DigestMD5 => writer.write_all(b"DIGEST-MD5"),
AuthMechanism::NTLM => writer.write_all(b"NTLM"),
AuthMechanism::CramMd5 => writer.write_all(b"CRAM-MD5"),
AuthMechanism::CramSha1 => writer.write_all(b"CRAM-SHA1"),
AuthMechanism::ScramMd5 => writer.write_all(b"SCRAM-MD5"),
AuthMechanism::DigestMd5 => writer.write_all(b"DIGEST-MD5"),
AuthMechanism::Ntlm => writer.write_all(b"NTLM"),
AuthMechanism::Other(other) => writer.write_all(other.as_bytes()),
}
@ -912,7 +912,7 @@ mod tests {
Response::Ehlo {
domain: "example.org".into(),
greet: Some("...".into()),
capabilities: vec![Capability::StartTLS],
capabilities: vec![Capability::StartTls],
},
b"250-example.org ...\r\n250 STARTTLS\r\n".as_ref(),
),
@ -920,7 +920,7 @@ mod tests {
Response::Ehlo {
domain: "example.org".into(),
greet: Some("...".into()),
capabilities: vec![Capability::StartTLS, Capability::Size(12345)],
capabilities: vec![Capability::StartTls, Capability::Size(12345)],
},
b"250-example.org ...\r\n250-STARTTLS\r\n250 SIZE 12345\r\n".as_ref(),
),