Struct new_tokio_smtp::Connection
source · pub struct Connection { /* private fields */ }
Expand description
The basic Connection
type representing an (likely) open smtp connection
It’s only likely open as the server could disconnect at any time. But it guaranteed that the last time a command was send over the server did respond with a valid smtp response (through not necessary with a successful one, e.g. the mailbox from a MAIL command might have been rejected or similar)
Normally the only think done with this type is to construct it with
the connect
method, call the send
method or the quit
method (
or the send_mail
cmd if the future is enabled). All other methods
of it are mainly for implementor of the Cmd
trait.
Implementations§
source§impl Connection
impl Connection
sourcepub fn send<C: Cmd>(
self,
cmd: C
) -> impl Future<Item = (Connection, SmtpResult), Error = Error>
pub fn send<C: Cmd>(
self,
cmd: C
) -> impl Future<Item = (Connection, SmtpResult), Error = Error>
send a command to the smtp server
This consumes the connection (as it might be modified, recrated or killed by the command) and returns a future resolving to the result of sending the command.
Example
use futures::future::{self, Future};
use new_tokio_smtp::{command, Connection, ReversePath, ForwardPath};
let fut = future
::lazy(|| mock_create_connection())
.and_then(|con| {
con.send(command::Mail::new(
ReversePath::from_unchecked("test@sender.test")))
})
.and_then(|(con, smtp_result)| {
// using `ctx_and_then`, or `chain` from would make
// thinks more simple (`future_ext::ResultWithContextExt`)
if let Err(err) = smtp_result {
panic!("server says no {}", err)
}
con.send(command::Recipient::new(
ForwardPath::from_unchecked("test@receiver.test")))
})
.and_then(|(con, smtp_result)| {
if let Err(err) = smtp_result {
panic!("server says no {}", err)
}
con.send(command::Data::from_buf(concat!(
"Date: Thu, 14 Jun 2018 11:22:18 +0000\r\n",
"From: Sendu <test@sender.test>\r\n",
"\r\n",
"...\r\n"
)))
})
.and_then(|(con, smtp_result)| {
if let Err(err) = smtp_result {
panic!("server says no {}", err)
}
con.quit()
});
// ... this are tokio using operation make sure there is
// a running tokio instance/runtime/event loop
mock_run_with_tokio(fut);
Logic Failure
A logic failure is a case where the command was successfully send over smtp and a response was successfully received but the response code indicates that the command could not be executed on the smtp server. For example because the mailbox/mail address was rejected.
As long as no connection failure happens the returned future will
resolve to an tuble of the (now again usable) Connection
instance
and a SmtpResult
which is either a Response
or a LogicError
.
The ctx_and_then
or the future_ext::ResultWithContextExt
trait
can be used to chain send
calls in a way that the next call is only
run if there was no error at all (neither connection nor logic error).
Connection Failure
If the connection fails (e.g. the internet connection is interrupted)
the future will resolve to an io::Error
and the connection is gone.
sourcepub fn has_capability<C>(&self, cap: C) -> boolwhere
C: AsRef<str>,
pub fn has_capability<C>(&self, cap: C) -> boolwhere
C: AsRef<str>,
returns true if the capability is known to be supported, false else wise
The capability is know to be supported if the connection has EhloData and it was in the ehlo data (as a ehlo-keyword in one of the ehlo-lines after the first response line).
If the connection has no ehlo data or the capability is not in the ehlo data false is returned.
sourcepub fn ehlo_data(&self) -> Option<&EhloData>
pub fn ehlo_data(&self) -> Option<&EhloData>
returns a opt. reference to the ehlo data stored from the last ehlo call
sourcepub fn into_inner(self) -> Io
pub fn into_inner(self) -> Io
converts the Connection
into an Io
instance
This is only need when implementing custom Cmd
’s
source§impl Connection
impl Connection
sourcepub fn connect<S, A>(
config: ConnectionConfig<A, S>
) -> impl Future<Item = Connection, Error = ConnectingFailed> + Sendwhere
S: SetupTls,
A: Cmd + Send,
pub fn connect<S, A>(
config: ConnectionConfig<A, S>
) -> impl Future<Item = Connection, Error = ConnectingFailed> + Sendwhere
S: SetupTls,
A: Cmd + Send,
open a connection to an smtp server using given configuration
source§impl Connection
impl Connection
sourcepub fn send_mail(
self,
envelop: MailEnvelop
) -> impl Future<Item = (Connection, MailSendResult), Error = Error> + Send
pub fn send_mail(
self,
envelop: MailEnvelop
) -> impl Future<Item = (Connection, MailSendResult), Error = Error> + Send
Sends a mail specified through MailEnvelop
through this connection.
If any command fails sending is stopped and RSET
is send to the server
to reset the current mail transaction.
see the module level documentation/README or example dir for example about how to use this.
sourcepub fn send_all_mails<E, M>(con: Connection, mails: M) -> SendAllMails<M>where
E: From<GeneralError>,
M: Iterator<Item = Result<MailEnvelop, E>>,
pub fn send_all_mails<E, M>(con: Connection, mails: M) -> SendAllMails<M>where
E: From<GeneralError>,
M: Iterator<Item = Result<MailEnvelop, E>>,
Sends all mails from mails through the connection.
The connection is moved into the SendAllMails
adapter
and can be retrieved from there.
Alternatively SendAllMails.quit_on_completion
can be used to make the adapter call quite once
all mails are send.
Or SendAllMails.on_completion
can be used if
you need to do something else with the same connection
(like putting it back into a connection pool).
sourcepub fn connect_send_quit<A, E, I, T>(
config: ConnectionConfig<A, T>,
mails: I
) -> impl Stream<Item = (), Error = E>where
A: Cmd,
E: From<GeneralError>,
I: IntoIterator<Item = Result<MailEnvelop, E>>,
T: SetupTls,
pub fn connect_send_quit<A, E, I, T>(
config: ConnectionConfig<A, T>,
mails: I
) -> impl Stream<Item = (), Error = E>where
A: Cmd,
E: From<GeneralError>,
I: IntoIterator<Item = Result<MailEnvelop, E>>,
T: SetupTls,
Creates a new connection, sends all mails and then closes the connection
- if sending a mail fails because of
LogicError
it will still try to send the other mails. - If sending a mail fails because of an I/O-Error causing the connection to be lost the remaining
Mails will fail with
GeneralError::Io
with anstd::io::ErrorKind::NoConnection
error.
This function accepts an IntoIterable
(instead of a Stream
) as all mails
should already be available when the connection os opened.
It also expects Result
’s instead of just mails, as mails normally have to
be encoded which can fail (and is not part of the crate). With this its easier
to adapt it to functionality which e.g. takes a vector of data and creates and
sends mails from it returning a vector of results. Be aware of std::iter::once
which provides a handy way to just pass in a single mail envelop.
As any future/stream this has to be polled to drive it to completion, i.e. even if you don’t care about the results you have to poll the future and then the stream it resolves to.
Example (where to find it)
Take a look at the send_mail
module documentation for an usage example.
To send a single mail std::iter::once as one
can be used:
Connection::connect_send_quit(config, one(mail))
To get back a Vec
of results you can use:
stream.then(|result| Ok(result)).collect()
Which is only needed as futures v0.1
Stream::collect
method is
conceptually broken. (Stream
’s are a sequence of results in futures,
which continuos independent of any error result, but collect
is written
as if streams short circuit once a error is it which is just wrong.)
use std::iter::once as one;
// note that the map_err is only needed as `!` isn't stable yet
let fut = Connection::connect_send_quit(config, one(mail))
//Stream::collect is conceptually broken in futures v0.1
.then(|res| Result::Ok::<_, ()>(res))
.collect();
Trait Implementations§
source§impl Debug for Connection
impl Debug for Connection
source§impl From<Connection> for Io
impl From<Connection> for Io
source§fn from(con: Connection) -> Self
fn from(con: Connection) -> Self
source§impl From<Io> for Connection
impl From<Io> for Connection
create a new Connection
from a Io
instance
The Io
instance should contain a Socket
which
is still alive.