pub trait Config: Send + Sync {
type Protocol: for<'resp> Protocol<'resp>;
type ConnectionUserMeta: Send;
type MailUserMeta: Send;
Show 32 methods
// Required methods
fn hostname(
&self,
conn_meta: &ConnectionMetadata<Self::ConnectionUserMeta>,
) -> &str;
fn tls_accept<'life0, 'life1, 'async_trait, IO>(
&'life0 self,
io: IO,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Result<Duplex<Pin<Box<dyn Send + AsyncRead>>, Pin<Box<dyn Send + AsyncWrite>>>>> + Send + 'async_trait>>
where IO: 'static + Unpin + Send + AsyncRead + AsyncWrite + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn new_mail<'life0, 'life1, 'async_trait>(
&'life0 self,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Self::MailUserMeta> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn filter_from<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
from: Option<Email>,
meta: &'life1 mut MailMetadata<Self::MailUserMeta>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<Option<Email>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn filter_to<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
to: Email,
meta: &'life1 mut MailMetadata<Self::MailUserMeta>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<Email>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn handle_mail<'resp, 'life0, 'life1, 'async_trait, R>(
&'resp self,
stream: &'life0 mut EscapedDataReader<'life1, R>,
meta: MailMetadata<Self::MailUserMeta>,
conn_meta: &'resp mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = <Self::Protocol as Protocol<'resp>>::HandleMailReturnType> + Send + 'async_trait>>
where R: Send + Unpin + AsyncRead + 'async_trait,
Self: 'resp + 'async_trait,
'resp: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided methods
fn welcome_banner(
&self,
conn_meta: &ConnectionMetadata<Self::ConnectionUserMeta>,
) -> &str { ... }
fn welcome_banner_reply(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn hello_banner(
&self,
conn_meta: &ConnectionMetadata<Self::ConnectionUserMeta>,
) -> &str { ... }
fn filter_hello<'life0, 'life1, 'async_trait>(
&'life0 self,
is_extended: bool,
hostname: Hostname,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<HelloInfo>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn can_do_tls(
&self,
conn_meta: &ConnectionMetadata<Self::ConnectionUserMeta>,
) -> bool { ... }
fn filter_data<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
meta: &'life1 mut MailMetadata<Self::MailUserMeta>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn handle_rset<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
meta: &'life1 mut Option<MailMetadata<Self::MailUserMeta>>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn handle_starttls<'life0, 'life1, 'async_trait>(
&'life0 self,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn handle_expn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn handle_vrfy<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn handle_help<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
subject: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn handle_noop<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
string: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn handle_quit<'life0, 'life1, 'async_trait>(
&'life0 self,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn already_did_hello(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn mail_before_hello(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn already_in_mail(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn rcpt_before_mail(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn data_before_rcpt(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn data_before_mail(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn starttls_unsupported(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn command_unrecognized(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn pipeline_forbidden_after_starttls(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn line_too_long(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn handle_mail_did_not_call_complete(
&self,
conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Reply { ... }
fn reply_write_timeout(&self) -> Duration { ... }
fn command_read_timeout(&self) -> Duration { ... }
}
Required Associated Types§
type Protocol: for<'resp> Protocol<'resp>
type ConnectionUserMeta: Send
type MailUserMeta: Send
Required Methods§
Sourcefn hostname(
&self,
conn_meta: &ConnectionMetadata<Self::ConnectionUserMeta>,
) -> &str
fn hostname( &self, conn_meta: &ConnectionMetadata<Self::ConnectionUserMeta>, ) -> &str
Note: this function is only ever used for the default implementations of
other functions in this trait. As such, it is OK to leave it
unimplemented!()
if other functions are implemented.
Sourcefn tls_accept<'life0, 'life1, 'async_trait, IO>(
&'life0 self,
io: IO,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Result<Duplex<Pin<Box<dyn Send + AsyncRead>>, Pin<Box<dyn Send + AsyncWrite>>>>> + Send + 'async_trait>>where
IO: 'static + Unpin + Send + AsyncRead + AsyncWrite + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn tls_accept<'life0, 'life1, 'async_trait, IO>(
&'life0 self,
io: IO,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Result<Duplex<Pin<Box<dyn Send + AsyncRead>>, Pin<Box<dyn Send + AsyncWrite>>>>> + Send + 'async_trait>>where
IO: 'static + Unpin + Send + AsyncRead + AsyncWrite + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Note: if you don’t want to implement TLS, you should override
can_do_tls
to return false
so that STARTTLS is not advertized. This
being said, returning an error here should have the same result in
practice, except clients will try STARTTLS and fail
fn new_mail<'life0, 'life1, 'async_trait>(
&'life0 self,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Self::MailUserMeta> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn filter_from<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
from: Option<Email>,
meta: &'life1 mut MailMetadata<Self::MailUserMeta>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<Option<Email>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn filter_to<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
to: Email,
meta: &'life1 mut MailMetadata<Self::MailUserMeta>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<Email>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Sourcefn handle_mail<'resp, 'life0, 'life1, 'async_trait, R>(
&'resp self,
stream: &'life0 mut EscapedDataReader<'life1, R>,
meta: MailMetadata<Self::MailUserMeta>,
conn_meta: &'resp mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = <Self::Protocol as Protocol<'resp>>::HandleMailReturnType> + Send + 'async_trait>>
fn handle_mail<'resp, 'life0, 'life1, 'async_trait, R>( &'resp self, stream: &'life0 mut EscapedDataReader<'life1, R>, meta: MailMetadata<Self::MailUserMeta>, conn_meta: &'resp mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Pin<Box<dyn Future<Output = <Self::Protocol as Protocol<'resp>>::HandleMailReturnType> + Send + 'async_trait>>
handle_mail
is an async function that returns either a single decision
in the case of the SMTP protocol, or an async stream of decisions in the
case of the LMTP protocol.
For LMTP: there must be one such decision for each RCPT TO command that succeeded (i.e. for each accepted recipient), which allows to indicate that the message could be stored in the mailbox of some users, but not in that of other users. This can happen for instance if their mail quota is used up. The lifetimes of the borrow on the mail’s data stream is limited to the duration of the async call; this reference may not be retained by the returned stream. The async function must consume the entire data stream before returning its stream of responses. The recommended implementation of this function would start by reading the message’s content to a temporary file, and then produce a stream that writes the message to all of the mailboxes one after the other.
Note: the EscapedDataReader has an inner buffer size of
RDBUF_SIZE
, which means that reads should not happen
with more than this buffer size.
Also, note that there is no timeout applied here, so the implementation of this function is responsible for making sure that the client does not just stop sending anything to DOS the system.
Provided Methods§
Note: this function is only ever used for the default implementations of
other functions in this trait. As such, it is OK to leave it
unimplemented!()
if other functions are implemented.
Note: this function is only ever used for the default implementations of
other functions in this trait. As such, it is OK to leave it
unimplemented!()
if other functions are implemented.
fn filter_hello<'life0, 'life1, 'async_trait>(
&'life0 self,
is_extended: bool,
hostname: Hostname,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<HelloInfo>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn can_do_tls( &self, conn_meta: &ConnectionMetadata<Self::ConnectionUserMeta>, ) -> bool
fn filter_data<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
meta: &'life1 mut MailMetadata<Self::MailUserMeta>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn handle_rset<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
meta: &'life1 mut Option<MailMetadata<Self::MailUserMeta>>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn handle_starttls<'life0, 'life1, 'async_trait>(
&'life0 self,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn handle_expn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn handle_vrfy<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn handle_help<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
subject: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn handle_noop<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
string: MaybeUtf8<&'life1 str>,
conn_meta: &'life2 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn handle_quit<'life0, 'life1, 'async_trait>(
&'life0 self,
conn_meta: &'life1 mut ConnectionMetadata<Self::ConnectionUserMeta>,
) -> Pin<Box<dyn Future<Output = Decision<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn already_did_hello( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn mail_before_hello( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn already_in_mail( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn rcpt_before_mail( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn data_before_rcpt( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn data_before_mail( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn starttls_unsupported( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn command_unrecognized( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn pipeline_forbidden_after_starttls( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn line_too_long( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn handle_mail_did_not_call_complete( &self, conn_meta: &mut ConnectionMetadata<Self::ConnectionUserMeta>, ) -> Reply
fn reply_write_timeout(&self) -> Duration
fn command_read_timeout(&self) -> Duration
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.