smtp_server_types/
reply.rs

1use smtp_message::{EnhancedReplyCode, MaybeUtf8, Reply, ReplyCode};
2
3#[inline]
4pub fn welcome_banner(hostname: &str, banner: &str) -> Reply {
5    Reply {
6        code: ReplyCode::SERVICE_READY,
7        ecode: None,
8        text: vec![MaybeUtf8::Utf8(String::from(hostname) + " " + banner)],
9    }
10}
11
12/// Usual value for returning “Okay” from `filter_hello`
13#[inline]
14pub fn okay_hello(
15    is_extended: bool,
16    local_hostname: &str,
17    banner: &str,
18    can_do_tls: bool,
19) -> Reply {
20    let mut built_banner = String::from(local_hostname);
21    if !banner.is_empty() {
22        built_banner += " ";
23        built_banner += banner;
24    }
25    let mut text = vec![MaybeUtf8::Utf8(built_banner)];
26    if is_extended {
27        text.push(MaybeUtf8::Ascii("8BITMIME".into()));
28        text.push(MaybeUtf8::Ascii("ENHANCEDSTATUSCODES".into()));
29        text.push(MaybeUtf8::Ascii("PIPELINING".into()));
30        text.push(MaybeUtf8::Ascii("SMTPUTF8".into()));
31        if can_do_tls {
32            text.push(MaybeUtf8::Ascii("STARTTLS".into()));
33        }
34    }
35    Reply {
36        code: ReplyCode::OKAY,
37        ecode: None,
38        text,
39    }
40}
41
42#[inline]
43pub fn okay(ecode: EnhancedReplyCode<&'static str>) -> Reply<&'static str> {
44    Reply {
45        code: ReplyCode::OKAY,
46        ecode: Some(ecode),
47        text: vec![MaybeUtf8::Ascii("Okay")],
48    }
49}
50
51/// Usual value for returning “Okay” from `filter_from`
52#[inline]
53pub fn okay_from() -> Reply<&'static str> {
54    okay(EnhancedReplyCode::SUCCESS_UNDEFINED)
55}
56
57/// Usual value for returning “Okay” from `filter_to`
58#[inline]
59pub fn okay_to() -> Reply<&'static str> {
60    okay(EnhancedReplyCode::SUCCESS_DEST_VALID)
61}
62
63/// Usual value for returning “Okay” from `filter_data`
64#[inline]
65pub fn okay_data() -> Reply<&'static str> {
66    Reply {
67        code: ReplyCode::START_MAIL_INPUT,
68        ecode: None,
69        text: vec![MaybeUtf8::Ascii("Start mail input; end with <CRLF>.<CRLF>")],
70    }
71}
72
73/// Usual value for returning “Okay” from `handle_mail`
74#[inline]
75pub fn okay_mail() -> Reply<&'static str> {
76    okay(EnhancedReplyCode::SUCCESS_UNDEFINED)
77}
78
79/// Usual value for returning “Okay” from `handle_starttls`
80#[inline]
81pub fn okay_starttls() -> Reply<&'static str> {
82    Reply {
83        code: ReplyCode::SERVICE_READY,
84        ecode: Some(EnhancedReplyCode::SUCCESS_UNDEFINED),
85        text: vec![MaybeUtf8::Ascii("Ready to start TLS")],
86    }
87}
88
89/// Usual value for returning “Okay” from `handle_rset`
90#[inline]
91pub fn okay_rset() -> Reply<&'static str> {
92    okay(EnhancedReplyCode::SUCCESS_UNDEFINED)
93}
94
95/// Usual value for ignoring the request but returning “Okay” from `handle_vrfy`
96#[inline]
97pub fn ignore_vrfy() -> Reply<&'static str> {
98    Reply {
99        code: ReplyCode::CANNOT_VRFY_BUT_PLEASE_TRY,
100        ecode: Some(EnhancedReplyCode::SUCCESS_DEST_VALID),
101        text: vec![MaybeUtf8::Ascii(
102            "Cannot VRFY user, but will accept message and attempt delivery",
103        )],
104    }
105}
106
107/// Usual value for ignoring the request but returning a generic message from
108/// `handle_help`
109#[inline]
110pub fn ignore_help() -> Reply<&'static str> {
111    Reply {
112        code: ReplyCode::HELP_MESSAGE,
113        ecode: Some(EnhancedReplyCode::SUCCESS_UNDEFINED),
114        text: vec![MaybeUtf8::Ascii("See https://tools.ietf.org/html/rfc5321")],
115    }
116}
117
118/// Usual value for returning “Okay” from `handle_noop`
119#[inline]
120pub fn okay_noop() -> Reply<&'static str> {
121    okay(EnhancedReplyCode::SUCCESS_UNDEFINED)
122}
123
124/// Usual value for returning “Okay” from `handle_quit`
125#[inline]
126pub fn okay_quit() -> Reply<&'static str> {
127    Reply {
128        code: ReplyCode::CLOSING_CHANNEL,
129        ecode: Some(EnhancedReplyCode::SUCCESS_UNDEFINED),
130        text: vec![MaybeUtf8::Utf8("Bye")],
131    }
132}
133
134/// Usual value for returning “Okay” from `already_did_hello`,
135/// `mail_before_hello`, `already_in_mail`, `rcpt_before_mail`,
136/// `data_before_rcpt` and `data_before_mail`
137#[inline]
138pub fn bad_sequence() -> Reply<&'static str> {
139    Reply {
140        code: ReplyCode::BAD_SEQUENCE,
141        ecode: Some(EnhancedReplyCode::PERMANENT_INVALID_COMMAND),
142        text: vec![MaybeUtf8::Ascii("Bad sequence of commands")],
143    }
144}
145
146#[inline]
147pub fn command_unimplemented() -> Reply<&'static str> {
148    Reply {
149        code: ReplyCode::COMMAND_UNIMPLEMENTED,
150        ecode: Some(EnhancedReplyCode::PERMANENT_INVALID_COMMAND),
151        text: vec![MaybeUtf8::Ascii("Command not implemented")],
152    }
153}
154
155#[inline]
156pub fn command_unrecognized() -> Reply<&'static str> {
157    Reply {
158        code: ReplyCode::COMMAND_UNRECOGNIZED,
159        ecode: Some(EnhancedReplyCode::PERMANENT_INVALID_COMMAND),
160        text: vec![MaybeUtf8::Ascii("Command not recognized")],
161    }
162}
163
164#[inline]
165pub fn command_not_supported() -> Reply<&'static str> {
166    Reply {
167        code: ReplyCode::COMMAND_UNIMPLEMENTED,
168        ecode: Some(EnhancedReplyCode::PERMANENT_INVALID_COMMAND),
169        text: vec![MaybeUtf8::Ascii("Command not supported")],
170    }
171}
172
173#[inline]
174pub fn pipeline_forbidden_after_starttls() -> Reply<&'static str> {
175    Reply {
176        code: ReplyCode::BAD_SEQUENCE,
177        ecode: Some(EnhancedReplyCode::PERMANENT_INVALID_COMMAND),
178        text: vec![MaybeUtf8::Ascii("Pipelining after starttls is forbidden")],
179    }
180}
181
182#[inline]
183pub fn line_too_long() -> Reply<&'static str> {
184    Reply {
185        code: ReplyCode::COMMAND_UNRECOGNIZED,
186        ecode: Some(EnhancedReplyCode::PERMANENT_UNDEFINED),
187        text: vec![MaybeUtf8::Ascii("Line too long")],
188    }
189}
190
191#[inline]
192pub fn internal_server_error() -> Reply<&'static str> {
193    Reply {
194        code: ReplyCode::LOCAL_ERROR,
195        ecode: Some(EnhancedReplyCode::TRANSIENT_UNDEFINED),
196        text: vec![MaybeUtf8::Ascii("Internal server error")],
197    }
198}
199
200#[inline]
201pub fn handle_mail_did_not_call_complete() -> Reply<&'static str> {
202    Reply {
203        code: ReplyCode::LOCAL_ERROR,
204        ecode: Some(EnhancedReplyCode::TRANSIENT_SYSTEM_INCORRECTLY_CONFIGURED),
205        text: vec![MaybeUtf8::Ascii("System incorrectly configured")],
206    }
207}