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§

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.

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.

returns a opt. reference to the ehlo data stored from the last ehlo call

converts the Connection into an Io instance

This is only need when implementing custom Cmd’s

shutdown the connection without sending quit

sends quit to the server and then shuts down the socket

The socked is shut down independent of wether or not sending quit failed, while sending quit should not cause any logic error if it does it’s not returned by this method.

open a connection to an smtp server using given configuration

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.

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).

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 an std::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§

Formats the value using the given formatter. Read more
Converts to this type from the input type.

create a new Connection from a Io instance

The Io instance should contain a Socket which is still alive.

Converts to this type from the input type.

create a new Connection from a Socket instance

The Socket instance should contain a socket which is still alive.

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.