lettre/transport/mod.rs
1//! ## Transports for sending emails
2//!
3//! This module contains `Transport`s for sending emails. A `Transport` implements a high-level API
4//! for sending emails. It automatically manages the underlying resources and doesn't require any
5//! specific knowledge of email protocols in order to be used.
6//!
7//! ### Getting started
8//!
9//! Sending emails from your programs requires using an email relay, as client libraries are not
10//! designed to handle email delivery by themselves. Depending on your infrastructure, your relay
11//! could be:
12//!
13//! * a service from your Cloud or hosting provider
14//! * an email server ([MTA] for Mail Transfer Agent, like Postfix or Exchange), running either
15//! locally on your servers or accessible over the network
16//! * a dedicated external service, like Mailchimp, Mailgun, etc.
17//!
18//! In most cases, the best option is to:
19//!
20//! * Use the [`SMTP`] transport, with the [`relay`] builder (or one of its async counterparts)
21//! with your server's hostname. They provide modern and secure defaults.
22//! * Use the [`credentials`] method of the builder to pass your credentials.
23//!
24//! These should be enough to safely cover most use cases.
25//!
26//! ### Available transports
27//!
28//! The following transports are available:
29//!
30//! | Module | Protocol | Sync API | Async API | Description |
31//! | ------------ | -------- | --------------------- | -------------------------- | ------------------------------------------------------- |
32//! | [`smtp`] | SMTP | [`SmtpTransport`] | [`AsyncSmtpTransport`] | Uses the SMTP protocol to send emails to a relay server |
33//! | [`sendmail`] | Sendmail | [`SendmailTransport`] | [`AsyncSendmailTransport`] | Uses the `sendmail` command to send emails |
34//! | [`file`] | File | [`FileTransport`] | [`AsyncFileTransport`] | Saves the email as an `.eml` file |
35//! | [`stub`] | Debug | [`StubTransport`] | [`AsyncStubTransport`] | Drops the email - Useful for debugging |
36//!
37//! ## Building an email
38//!
39//! Emails can either be built though [`Message`], which is a typed API for constructing emails
40//! (find out more about it by going over the [`message`][crate::message] module),
41//! or via external means.
42//!
43//! [`Message`]s can be sent via [`Transport::send`] or [`AsyncTransport::send`], while messages
44//! built without lettre's [`message`][crate::message] APIs can be sent via [`Transport::send_raw`]
45//! or [`AsyncTransport::send_raw`].
46//!
47//! ## Brief example
48//!
49//! This example shows how to build an email and send it via an SMTP relay server.
50//! It is in no way a complete example, but it shows how to get started with lettre.
51//! More examples can be found by looking at the specific modules, linked in the _Module_ column
52//! of the [table above](#transports-for-sending-emails).
53//!
54//! ```rust,no_run
55//! # use std::error::Error;
56//! #
57//! # #[cfg(all(feature = "builder", feature = "smtp-transport"))]
58//! # fn main() -> Result<(), Box<dyn Error>> {
59//! use lettre::{
60//! message::header::ContentType, transport::smtp::authentication::Credentials, Message,
61//! SmtpTransport, Transport,
62//! };
63//!
64//! let email = Message::builder()
65//! .from("NoBody <nobody@domain.tld>".parse()?)
66//! .reply_to("Yuin <yuin@domain.tld>".parse()?)
67//! .to("Hei <hei@domain.tld>".parse()?)
68//! .subject("Happy new year")
69//! .header(ContentType::TEXT_PLAIN)
70//! .body(String::from("Be happy!"))?;
71//!
72//! let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());
73//!
74//! // Open a remote connection to the SMTP relay server
75//! let mailer = SmtpTransport::relay("smtp.gmail.com")?
76//! .credentials(creds)
77//! .build();
78//!
79//! // Send the email
80//! match mailer.send(&email) {
81//! Ok(_) => println!("Email sent successfully!"),
82//! Err(e) => panic!("Could not send email: {e:?}"),
83//! }
84//! # Ok(())
85//! # }
86//! # #[cfg(not(all(feature = "builder", feature = "smtp-transport")))]
87//! # fn main() {}
88//! ```
89//!
90//! [MTA]: https://en.wikipedia.org/wiki/Message_transfer_agent
91//! [`SMTP`]: crate::transport::smtp
92//! [`relay`]: crate::SmtpTransport::relay
93//! [`starttls_relay`]: crate::SmtpTransport::starttls_relay
94//! [`credentials`]: crate::transport::smtp::SmtpTransportBuilder::credentials
95//! [`Message`]: crate::Message
96//! [`file`]: self::file
97//! [`SmtpTransport`]: crate::SmtpTransport
98//! [`AsyncSmtpTransport`]: crate::AsyncSmtpTransport
99//! [`SendmailTransport`]: crate::SendmailTransport
100//! [`AsyncSendmailTransport`]: crate::AsyncSendmailTransport
101//! [`FileTransport`]: crate::FileTransport
102//! [`AsyncFileTransport`]: crate::AsyncFileTransport
103//! [`StubTransport`]: crate::transport::stub::StubTransport
104//! [`AsyncStubTransport`]: crate::transport::stub::AsyncStubTransport
105
106#[cfg(any(feature = "async-std1", feature = "tokio1"))]
107use async_trait::async_trait;
108
109use crate::Envelope;
110#[cfg(feature = "builder")]
111use crate::Message;
112
113#[cfg(feature = "file-transport")]
114#[cfg_attr(docsrs, doc(cfg(feature = "file-transport")))]
115pub mod file;
116#[cfg(feature = "sendmail-transport")]
117#[cfg_attr(docsrs, doc(cfg(feature = "sendmail-transport")))]
118pub mod sendmail;
119#[cfg(feature = "smtp-transport")]
120#[cfg_attr(docsrs, doc(cfg(feature = "smtp-transport")))]
121pub mod smtp;
122pub mod stub;
123
124/// Blocking Transport method for emails
125pub trait Transport {
126 /// Response produced by the Transport
127 type Ok;
128 /// Error produced by the Transport
129 type Error;
130
131 /// Sends the email
132 #[cfg(feature = "builder")]
133 #[cfg_attr(docsrs, doc(cfg(feature = "builder")))]
134 fn send(&self, message: &Message) -> Result<Self::Ok, Self::Error> {
135 #[cfg(feature = "tracing")]
136 tracing::trace!("starting to send an email");
137
138 let raw = message.formatted();
139 self.send_raw(message.envelope(), &raw)
140 }
141
142 fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
143
144 /// Shuts down the transport. Future calls to [`Self::send`] and
145 /// [`Self::send_raw`] might fail.
146 fn shutdown(&self) {}
147}
148
149/// Async Transport method for emails
150#[cfg(any(feature = "tokio1", feature = "async-std1"))]
151#[cfg_attr(docsrs, doc(cfg(any(feature = "tokio1", feature = "async-std1"))))]
152#[async_trait]
153pub trait AsyncTransport {
154 /// Response produced by the Transport
155 type Ok;
156 /// Error produced by the Transport
157 type Error;
158
159 /// Sends the email
160 #[cfg(feature = "builder")]
161 #[cfg_attr(docsrs, doc(cfg(feature = "builder")))]
162 // TODO take &Message
163 async fn send(&self, message: Message) -> Result<Self::Ok, Self::Error> {
164 #[cfg(feature = "tracing")]
165 tracing::trace!("starting to send an email");
166
167 let raw = message.formatted();
168 let envelope = message.envelope();
169 self.send_raw(envelope, &raw).await
170 }
171
172 async fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
173
174 /// Shuts down the transport. Future calls to [`Self::send`] and
175 /// [`Self::send_raw`] might fail.
176 async fn shutdown(&self) {}
177}