fix(all): Fix doc tests in website (#375)
This commit is contained in:
9
.github/workflows/test.yml
vendored
9
.github/workflows/test.yml
vendored
@@ -24,7 +24,8 @@ jobs:
|
|||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --no-default-features --features=native-tls
|
args: --no-default-features --features=native-tls,builder,r2d2,smtp-transport,file-transport,sendmail-transport
|
||||||
|
- run: rm target/debug/deps/liblettre-*
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
@@ -68,7 +69,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: -- -D warnings
|
args: -- -D warnings
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
name: Coverage
|
name: Coverage
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -85,8 +86,8 @@ jobs:
|
|||||||
command: test
|
command: test
|
||||||
args: --no-fail-fast
|
args: --no-fail-fast
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: '0'
|
CARGO_INCREMENTAL: "0"
|
||||||
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads'
|
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads"
|
||||||
- id: coverage
|
- id: coverage
|
||||||
uses: actions-rs/grcov@v0.1
|
uses: actions-rs/grcov@v0.1
|
||||||
- name: Coveralls upload
|
- name: Coveralls upload
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ webpki = { version = "^0.21", optional = true }
|
|||||||
criterion = "^0.3"
|
criterion = "^0.3"
|
||||||
env_logger = "^0.7"
|
env_logger = "^0.7"
|
||||||
glob = "^0.3"
|
glob = "^0.3"
|
||||||
|
walkdir = "^2"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
harness = false
|
harness = false
|
||||||
@@ -46,12 +47,11 @@ name = "transport_smtp"
|
|||||||
[features]
|
[features]
|
||||||
builder = ["email", "mime", "time", "base64", "uuid"]
|
builder = ["email", "mime", "time", "base64", "uuid"]
|
||||||
connection-pool = ["r2d2"]
|
connection-pool = ["r2d2"]
|
||||||
default = ["file-transport", "smtp-transport", "sendmail-transport", "ssl-rustls", "builder"]
|
default = ["file-transport", "smtp-transport", "sendmail-transport", "rustls-tls", "builder"]
|
||||||
file-transport = ["serde", "serde_json"]
|
file-transport = ["serde", "serde_json"]
|
||||||
|
rustls-tls = ["webpki", "rustls"]
|
||||||
sendmail-transport = []
|
sendmail-transport = []
|
||||||
smtp-transport = ["bufstream", "base64", "nom", "hostname"]
|
smtp-transport = ["bufstream", "base64", "nom", "hostname"]
|
||||||
ssl-native = ["native-tls"]
|
|
||||||
ssl-rustls = ["rustls", "webpki"]
|
|
||||||
unstable = []
|
unstable = []
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ lettre = "0.9"
|
|||||||
```rust,no_run
|
```rust,no_run
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::{SmtpClient, Transport, Email, mime::TEXT_PLAIN};
|
use lettre::{SmtpClient, Transport, Email, builder::mime::TEXT_PLAIN};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::{error::Error as LettreError, EmailAddress, Envelope, SendableEmail};
|
use crate::{error::Error as LettreError, EmailAddress, Envelope, SendableEmail};
|
||||||
pub use email::{Address, Header, Mailbox, MimeMessage, MimeMultipartType};
|
pub use email::{Address, Header, Mailbox, MimeMessage, MimeMultipartType};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
pub use mime;
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ pub mod sendmail;
|
|||||||
pub mod smtp;
|
pub mod smtp;
|
||||||
pub mod stub;
|
pub mod stub;
|
||||||
|
|
||||||
|
#[cfg(feature = "builder")]
|
||||||
|
pub use crate::builder::Email;
|
||||||
use crate::error::EmailResult;
|
use crate::error::EmailResult;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
#[cfg(feature = "file-transport")]
|
#[cfg(feature = "file-transport")]
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
use crate::smtp::client::mock::MockStream;
|
use crate::smtp::client::mock::MockStream;
|
||||||
use crate::smtp::error::Error;
|
use crate::smtp::error::Error;
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
use native_tls::{Protocol, TlsConnector, TlsStream};
|
use native_tls::{TlsConnector, TlsStream};
|
||||||
#[cfg(feature = "rustls")]
|
#[cfg(feature = "rustls")]
|
||||||
use rustls::{ClientConfig, ClientSession};
|
use rustls::{ClientConfig, ClientSession};
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use std::net::{Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, TcpStream};
|
use std::net::{Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, TcpStream};
|
||||||
|
#[cfg(feature = "rustls")]
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -45,12 +46,6 @@ impl ClientTlsParameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accepted protocols by default.
|
|
||||||
/// This removes TLS 1.0 and 1.1 compared to tls-native defaults.
|
|
||||||
/// This is also rustls' default behavior
|
|
||||||
#[cfg(feature = "native-tls")]
|
|
||||||
const DEFAULT_TLS_MIN_PROTOCOL: Protocol = Protocol::Tlsv12;
|
|
||||||
|
|
||||||
/// Represents the different types of underlying network streams
|
/// Represents the different types of underlying network streams
|
||||||
pub enum NetworkStream {
|
pub enum NetworkStream {
|
||||||
/// Plain TCP stream
|
/// Plain TCP stream
|
||||||
@@ -161,7 +156,7 @@ impl Connector for NetworkStream {
|
|||||||
.connector
|
.connector
|
||||||
.connect(context.domain.as_ref(), tcp_stream)
|
.connect(context.domain.as_ref(), tcp_stream)
|
||||||
.map(|tls| NetworkStream::Tls(Box::new(tls)))
|
.map(|tls| NetworkStream::Tls(Box::new(tls)))
|
||||||
.map_err(|e| io::Error::new(ErrorKind::Other, e)),
|
.map_err(|e| Error::Io(io::Error::new(ErrorKind::Other, e))),
|
||||||
#[cfg(feature = "rustls")]
|
#[cfg(feature = "rustls")]
|
||||||
Some(context) => {
|
Some(context) => {
|
||||||
let domain = webpki::DNSNameRef::try_from_ascii_str(&context.domain)?;
|
let domain = webpki::DNSNameRef::try_from_ascii_str(&context.domain)?;
|
||||||
@@ -183,7 +178,7 @@ impl Connector for NetworkStream {
|
|||||||
.connect(tls_parameters.domain.as_ref(), stream.try_clone().unwrap())
|
.connect(tls_parameters.domain.as_ref(), stream.try_clone().unwrap())
|
||||||
{
|
{
|
||||||
Ok(tls_stream) => NetworkStream::Tls(Box::new(tls_stream)),
|
Ok(tls_stream) => NetworkStream::Tls(Box::new(tls_stream)),
|
||||||
Err(err) => return Err(io::Error::new(ErrorKind::Other, err)),
|
Err(err) => return Err(Error::Io(io::Error::new(ErrorKind::Other, err))),
|
||||||
},
|
},
|
||||||
#[cfg(feature = "rustls")]
|
#[cfg(feature = "rustls")]
|
||||||
NetworkStream::Tcp(ref mut stream) => {
|
NetworkStream::Tcp(ref mut stream) => {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ pub enum Error {
|
|||||||
/// Parsing error
|
/// Parsing error
|
||||||
Parsing(nom::error::ErrorKind),
|
Parsing(nom::error::ErrorKind),
|
||||||
/// Invalid hostname
|
/// Invalid hostname
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
InvalidDNSName(webpki::InvalidDNSNameError),
|
InvalidDNSName(webpki::InvalidDNSNameError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ impl StdError for Error {
|
|||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
Tls(ref err) => err.description(),
|
Tls(ref err) => err.description(),
|
||||||
Parsing(ref err) => err.description(),
|
Parsing(ref err) => err.description(),
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
InvalidDNSName(ref err) => err.description(),
|
InvalidDNSName(ref err) => err.description(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,6 +126,7 @@ impl From<FromUtf8Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
impl From<webpki::InvalidDNSNameError> for Error {
|
impl From<webpki::InvalidDNSNameError> for Error {
|
||||||
fn from(err: webpki::InvalidDNSNameError) -> Error {
|
fn from(err: webpki::InvalidDNSNameError) -> Error {
|
||||||
InvalidDNSName(err)
|
InvalidDNSName(err)
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ use crate::smtp::authentication::{
|
|||||||
Credentials, Mechanism, DEFAULT_ENCRYPTED_MECHANISMS, DEFAULT_UNENCRYPTED_MECHANISMS,
|
Credentials, Mechanism, DEFAULT_ENCRYPTED_MECHANISMS, DEFAULT_UNENCRYPTED_MECHANISMS,
|
||||||
};
|
};
|
||||||
use crate::smtp::client::net::ClientTlsParameters;
|
use crate::smtp::client::net::ClientTlsParameters;
|
||||||
#[cfg(feature = "native-tls")]
|
|
||||||
use crate::smtp::client::net::DEFAULT_TLS_MIN_PROTOCOL;
|
|
||||||
use crate::smtp::client::InnerClient;
|
use crate::smtp::client::InnerClient;
|
||||||
use crate::smtp::commands::*;
|
use crate::smtp::commands::*;
|
||||||
use crate::smtp::error::{Error, SmtpResult};
|
use crate::smtp::error::{Error, SmtpResult};
|
||||||
@@ -26,7 +24,9 @@ use crate::smtp::extension::{ClientId, Extension, MailBodyParameter, MailParamet
|
|||||||
use crate::{SendableEmail, Transport};
|
use crate::{SendableEmail, Transport};
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
use native_tls::TlsConnector;
|
use native_tls::{Protocol, TlsConnector};
|
||||||
|
#[cfg(feature = "rustls")]
|
||||||
|
use rustls::ClientConfig;
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -51,6 +51,12 @@ pub const SUBMISSION_PORT: u16 = 587;
|
|||||||
/// Default submission over TLS port
|
/// Default submission over TLS port
|
||||||
pub const SUBMISSIONS_PORT: u16 = 465;
|
pub const SUBMISSIONS_PORT: u16 = 465;
|
||||||
|
|
||||||
|
/// Accepted protocols by default.
|
||||||
|
/// This removes TLS 1.0 and 1.1 compared to tls-native defaults.
|
||||||
|
/// This is also rustls' default behavior
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
const DEFAULT_TLS_MIN_PROTOCOL: Protocol = Protocol::Tlsv12;
|
||||||
|
|
||||||
/// How to apply TLS to a client connection
|
/// How to apply TLS to a client connection
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
@@ -150,6 +156,16 @@ impl SmtpClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls")]
|
||||||
|
pub fn new_simple(domain: &str) -> Result<SmtpClient, Error> {
|
||||||
|
let tls_parameters = ClientTlsParameters::new(domain.to_string(), ClientConfig::new());
|
||||||
|
|
||||||
|
SmtpClient::new(
|
||||||
|
(domain, SUBMISSIONS_PORT),
|
||||||
|
ClientSecurity::Wrapper(tls_parameters),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new local SMTP client to port 25
|
/// Creates a new local SMTP client to port 25
|
||||||
pub fn new_unencrypted_localhost() -> Result<SmtpClient, Error> {
|
pub fn new_unencrypted_localhost() -> Result<SmtpClient, Error> {
|
||||||
SmtpClient::new(("localhost", SMTP_PORT), ClientSecurity::None)
|
SmtpClient::new(("localhost", SMTP_PORT), ClientSecurity::None)
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
use glob::glob;
|
use std::env::{self, consts::EXE_EXTENSION};
|
||||||
use std::env;
|
|
||||||
use std::env::consts::EXE_EXTENSION;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn book_test() {
|
fn book_test() {
|
||||||
let mut book_path = env::current_dir().unwrap();
|
skeptic_test(Path::new("README.md"));
|
||||||
book_path.push(
|
|
||||||
Path::new(file!())
|
|
||||||
.parent()
|
|
||||||
.unwrap()
|
|
||||||
.parent()
|
|
||||||
.unwrap()
|
|
||||||
.join("../website/content/sending-messages"),
|
|
||||||
); // For some reasons, calling .parent() once more gives us None...
|
|
||||||
|
|
||||||
for md in glob(&format!("{}/*.md", book_path.to_str().unwrap())).unwrap() {
|
for entry in WalkDir::new("website").into_iter().filter(|e| {
|
||||||
skeptic_test(&md.unwrap());
|
e.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.path()
|
||||||
|
.extension()
|
||||||
|
.map(|ex| ex == "md")
|
||||||
|
.unwrap_or(false)
|
||||||
|
}) {
|
||||||
|
skeptic_test(entry.unwrap().path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ The `email` part builds email messages. For now, it does not support attachments
|
|||||||
An email is built using an `EmailBuilder`. The simplest email could be:
|
An email is built using an `EmailBuilder`. The simplest email could be:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate lettre_email;
|
# #[cfg(feature = "builder")]
|
||||||
|
# {
|
||||||
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre_email::Email;
|
use lettre::Email;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Create an email
|
// Create an email
|
||||||
@@ -22,9 +24,10 @@ fn main() {
|
|||||||
.subject("Hi, Hello world")
|
.subject("Hi, Hello world")
|
||||||
.alternative("<h2>Hi, Hello world.</h2>", "Hi, Hello world.")
|
.alternative("<h2>Hi, Hello world.</h2>", "Hi, Hello world.")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assert!(email.is_ok());
|
assert!(email.is_ok());
|
||||||
}
|
}
|
||||||
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
When the `build` method is called, the `EmailBuilder` will add the missing headers (like
|
When the `build` method is called, the `EmailBuilder` will add the missing headers (like
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ The file transport writes the emails to the given directory. The name of the fil
|
|||||||
It can be useful for testing purposes, or if you want to keep track of sent messages.
|
It can be useful for testing purposes, or if you want to keep track of sent messages.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #[cfg(feature = "file-transport")]
|
||||||
|
# {
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
use std::env::temp_dir;
|
use std::env::temp_dir;
|
||||||
@@ -23,10 +25,11 @@ fn main() {
|
|||||||
"id".to_string(),
|
"id".to_string(),
|
||||||
"Hello world".to_string().into_bytes(),
|
"Hello world".to_string().into_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = sender.send(email);
|
let result = sender.send(email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
Example result in `/tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt`:
|
Example result in `/tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt`:
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
The sendmail transport sends the email using the local sendmail command.
|
The sendmail transport sends the email using the local sendmail command.
|
||||||
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
|
# #[cfg(feature = "sendmail-transport")]
|
||||||
|
# {
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::sendmail::SendmailTransport;
|
use lettre::sendmail::SendmailTransport;
|
||||||
@@ -17,9 +19,10 @@ fn main() {
|
|||||||
"id".to_string(),
|
"id".to_string(),
|
||||||
"Hello world".to_string().into_bytes(),
|
"Hello world".to_string().into_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut sender = SendmailTransport::new();
|
let mut sender = SendmailTransport::new();
|
||||||
let result = sender.send(email);
|
let result = sender.send(email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
# }
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ The relay server can be the local email server, a specific host or a third-party
|
|||||||
This is the most basic example of usage:
|
This is the most basic example of usage:
|
||||||
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
|
# #[cfg(feature = "smtp-transport")]
|
||||||
|
# {
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::{SendableEmail, EmailAddress, Transport, Envelope, SmtpClient};
|
use lettre::{SendableEmail, EmailAddress, Transport, Envelope, SmtpClient};
|
||||||
@@ -31,20 +33,23 @@ fn main() {
|
|||||||
"id".to_string(),
|
"id".to_string(),
|
||||||
"Hello world".to_string().into_bytes(),
|
"Hello world".to_string().into_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Open a local connection on port 25
|
// Open a local connection on port 25
|
||||||
let mut mailer =
|
let mut mailer =
|
||||||
SmtpClient::new_unencrypted_localhost().unwrap().transport();
|
SmtpClient::new_unencrypted_localhost().unwrap().transport();
|
||||||
// Send the email
|
// Send the email
|
||||||
let result = mailer.send(email);
|
let result = mailer.send(email);
|
||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Complete example
|
#### Complete example
|
||||||
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
|
# #[cfg(feature = "smtp-transport")]
|
||||||
|
# {
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::smtp::authentication::{Credentials, Mechanism};
|
use lettre::smtp::authentication::{Credentials, Mechanism};
|
||||||
@@ -61,7 +66,7 @@ fn main() {
|
|||||||
"id1".to_string(),
|
"id1".to_string(),
|
||||||
"Hello world".to_string().into_bytes(),
|
"Hello world".to_string().into_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let email_2 = SendableEmail::new(
|
let email_2 = SendableEmail::new(
|
||||||
Envelope::new(
|
Envelope::new(
|
||||||
Some(EmailAddress::new("user@localhost".to_string()).unwrap()),
|
Some(EmailAddress::new("user@localhost".to_string()).unwrap()),
|
||||||
@@ -70,7 +75,7 @@ fn main() {
|
|||||||
"id2".to_string(),
|
"id2".to_string(),
|
||||||
"Hello world a second time".to_string().into_bytes(),
|
"Hello world a second time".to_string().into_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Connect to a remote server on a custom port
|
// Connect to a remote server on a custom port
|
||||||
let mut mailer = SmtpClient::new_simple("server.tld").unwrap()
|
let mut mailer = SmtpClient::new_simple("server.tld").unwrap()
|
||||||
// Set the name sent during EHLO/HELO, default is `localhost`
|
// Set the name sent during EHLO/HELO, default is `localhost`
|
||||||
@@ -83,22 +88,25 @@ fn main() {
|
|||||||
.authentication_mechanism(Mechanism::Plain)
|
.authentication_mechanism(Mechanism::Plain)
|
||||||
// Enable connection reuse
|
// Enable connection reuse
|
||||||
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited).transport();
|
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited).transport();
|
||||||
|
|
||||||
let result_1 = mailer.send(email_1);
|
let result_1 = mailer.send(email_1);
|
||||||
assert!(result_1.is_ok());
|
assert!(result_1.is_ok());
|
||||||
|
|
||||||
// The second email will use the same connection
|
// The second email will use the same connection
|
||||||
let result_2 = mailer.send(email_2);
|
let result_2 = mailer.send(email_2);
|
||||||
assert!(result_2.is_ok());
|
assert!(result_2.is_ok());
|
||||||
|
|
||||||
// Explicitly close the SMTP transaction as we enabled connection reuse
|
// Explicitly close the SMTP transaction as we enabled connection reuse
|
||||||
mailer.close();
|
mailer.close();
|
||||||
}
|
}
|
||||||
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
You can specify custom TLS settings:
|
You can specify custom TLS settings:
|
||||||
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
|
# #[cfg(feature = "native-tls")]
|
||||||
|
# {
|
||||||
extern crate native_tls;
|
extern crate native_tls;
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
@@ -144,6 +152,7 @@ fn main() {
|
|||||||
|
|
||||||
mailer.close();
|
mailer.close();
|
||||||
}
|
}
|
||||||
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Lower level
|
#### Lower level
|
||||||
@@ -152,6 +161,8 @@ You can also send commands, here is a simple email transaction without
|
|||||||
error handling:
|
error handling:
|
||||||
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
|
# #[cfg(feature = "smtp-transport")]
|
||||||
|
# {
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::EmailAddress;
|
use lettre::EmailAddress;
|
||||||
@@ -175,5 +186,5 @@ fn main() {
|
|||||||
let _ = email_client.message(Box::new("Test email".as_bytes()));
|
let _ = email_client.message(Box::new("Test email".as_bytes()));
|
||||||
let _ = email_client.command(QuitCommand);
|
let _ = email_client.command(QuitCommand);
|
||||||
}
|
}
|
||||||
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ fn main() {
|
|||||||
"id".to_string(),
|
"id".to_string(),
|
||||||
"Hello world".to_string().into_bytes(),
|
"Hello world".to_string().into_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut sender = StubTransport::new_positive();
|
let mut sender = StubTransport::new_positive();
|
||||||
let result = sender.send(email);
|
let result = sender.send(email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|||||||
Reference in New Issue
Block a user