Use nightly rustfmt features to improve code style (#734)
* format_code_in_doc_comments * imports_granularity * group_imports * Add ci job
This commit is contained in:
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -13,7 +13,7 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
rustfmt:
|
rustfmt:
|
||||||
name: rustfmt / stable
|
name: rustfmt / nightly-2022-02-11
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
run: |
|
run: |
|
||||||
rustup update --no-self-update stable
|
rustup default nightly-2022-02-11
|
||||||
rustup component add rustfmt
|
rustup component add rustfmt
|
||||||
|
|
||||||
- name: cargo fmt
|
- name: cargo fmt
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
// This line is only to make it compile from lettre's examples folder,
|
// This line is only to make it compile from lettre's examples folder,
|
||||||
// since it uses Rust 2018 crate renaming to import tokio.
|
// since it uses Rust 2018 crate renaming to import tokio.
|
||||||
// Won't be needed in user's code.
|
// Won't be needed in user's code.
|
||||||
use tokio1_crate as tokio;
|
|
||||||
|
|
||||||
use lettre::{
|
use lettre::{
|
||||||
transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message,
|
transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message,
|
||||||
Tokio1Executor,
|
Tokio1Executor,
|
||||||
};
|
};
|
||||||
|
use tokio1_crate as tokio;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
// This line is only to make it compile from lettre's examples folder,
|
// This line is only to make it compile from lettre's examples folder,
|
||||||
// since it uses Rust 2018 crate renaming to import tokio.
|
// since it uses Rust 2018 crate renaming to import tokio.
|
||||||
// Won't be needed in user's code.
|
// Won't be needed in user's code.
|
||||||
use tokio1_crate as tokio;
|
|
||||||
|
|
||||||
use lettre::{
|
use lettre::{
|
||||||
transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message,
|
transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message,
|
||||||
Tokio1Executor,
|
Tokio1Executor,
|
||||||
};
|
};
|
||||||
|
use tokio1_crate as tokio;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
|||||||
3
rustfmt.toml
Normal file
3
rustfmt.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
format_code_in_doc_comments = true
|
||||||
|
imports_granularity = "Crate"
|
||||||
|
group_imports = "StdExternalCrate"
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
//! Representation of an email address
|
//! Representation of an email address
|
||||||
|
|
||||||
use idna::domain_to_ascii;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use regex::Regex;
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
error::Error,
|
error::Error,
|
||||||
@@ -12,6 +9,10 @@ use std::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use idna::domain_to_ascii;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
/// Represents an email address with a user and a domain name.
|
/// Represents an email address with a user and a domain name.
|
||||||
///
|
///
|
||||||
/// This type contains email in canonical form (_user@domain.tld_).
|
/// This type contains email in canonical form (_user@domain.tld_).
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
#[cfg(all(feature = "smtp-transport", feature = "async-std1"))]
|
|
||||||
use futures_util::future::BoxFuture;
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
@@ -12,6 +8,10 @@ use std::path::Path;
|
|||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
#[cfg(all(feature = "smtp-transport", feature = "async-std1"))]
|
||||||
|
use futures_util::future::BoxFuture;
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "smtp-transport",
|
feature = "smtp-transport",
|
||||||
any(feature = "tokio1", feature = "async-std1")
|
any(feature = "tokio1", feature = "async-std1")
|
||||||
|
|||||||
@@ -175,6 +175,8 @@ mod executor;
|
|||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
|
||||||
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
#[cfg(feature = "async-std1")]
|
#[cfg(feature = "async-std1")]
|
||||||
pub use self::executor::AsyncStd1Executor;
|
pub use self::executor::AsyncStd1Executor;
|
||||||
#[cfg(all(any(feature = "tokio1", feature = "async-std1")))]
|
#[cfg(all(any(feature = "tokio1", feature = "async-std1")))]
|
||||||
@@ -211,14 +213,12 @@ pub use crate::transport::sendmail::SendmailTransport;
|
|||||||
any(feature = "tokio1", feature = "async-std1")
|
any(feature = "tokio1", feature = "async-std1")
|
||||||
))]
|
))]
|
||||||
pub use crate::transport::smtp::AsyncSmtpTransport;
|
pub use crate::transport::smtp::AsyncSmtpTransport;
|
||||||
|
#[cfg(feature = "smtp-transport")]
|
||||||
|
pub use crate::transport::smtp::SmtpTransport;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::transport::Transport;
|
pub use crate::transport::Transport;
|
||||||
use crate::{address::Envelope, error::Error};
|
use crate::{address::Envelope, error::Error};
|
||||||
|
|
||||||
#[cfg(feature = "smtp-transport")]
|
|
||||||
pub use crate::transport::smtp::SmtpTransport;
|
|
||||||
use std::error::Error as StdError;
|
|
||||||
|
|
||||||
pub(crate) type BoxError = Box<dyn StdError + Send + Sync>;
|
pub(crate) type BoxError = Box<dyn StdError + Send + Sync>;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ impl Attachment {
|
|||||||
/// # use std::error::Error;
|
/// # use std::error::Error;
|
||||||
/// use std::fs;
|
/// use std::fs;
|
||||||
///
|
///
|
||||||
/// use lettre::message::{Attachment, header::ContentType};
|
/// use lettre::message::{header::ContentType, Attachment};
|
||||||
///
|
///
|
||||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||||
/// let filename = String::from("invoice.pdf");
|
/// let filename = String::from("invoice.pdf");
|
||||||
@@ -64,7 +64,7 @@ impl Attachment {
|
|||||||
/// # use std::error::Error;
|
/// # use std::error::Error;
|
||||||
/// use std::fs;
|
/// use std::fs;
|
||||||
///
|
///
|
||||||
/// use lettre::message::{Attachment, header::ContentType};
|
/// use lettre::message::{header::ContentType, Attachment};
|
||||||
///
|
///
|
||||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||||
/// let content_id = String::from("123");
|
/// let content_id = String::from("123");
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
use crate::message::{
|
use std::{
|
||||||
header::{HeaderName, HeaderValue},
|
borrow::Cow,
|
||||||
Headers, Message,
|
error::Error as StdError,
|
||||||
|
fmt::{self, Display, Write},
|
||||||
|
iter::IntoIterator,
|
||||||
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ed25519_dalek::Signer;
|
use ed25519_dalek::Signer;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::{bytes::Regex as BRegex, Regex};
|
use regex::{bytes::Regex as BRegex, Regex};
|
||||||
use rsa::{pkcs1::FromRsaPrivateKey, Hash, PaddingScheme, RsaPrivateKey};
|
use rsa::{pkcs1::FromRsaPrivateKey, Hash, PaddingScheme, RsaPrivateKey};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::error::Error as StdError;
|
use crate::message::{
|
||||||
use std::fmt::{self, Display, Write};
|
header::{HeaderName, HeaderValue},
|
||||||
use std::iter::IntoIterator;
|
Headers, Message,
|
||||||
use std::time::SystemTime;
|
};
|
||||||
|
|
||||||
/// Describe Dkim Canonicalization to apply to either body or headers
|
/// Describe Dkim Canonicalization to apply to either body or headers
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@@ -381,15 +385,20 @@ pub(super) fn dkim_sign(message: &mut Message, dkim_config: &DkimConfig) {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use std::{
|
||||||
|
io::Write,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
super::header::{HeaderName, HeaderValue},
|
super::{
|
||||||
super::{Header, Message},
|
header::{HeaderName, HeaderValue},
|
||||||
|
Header, Message,
|
||||||
|
},
|
||||||
dkim_canonicalize_body, dkim_canonicalize_header_value, dkim_canonicalize_headers,
|
dkim_canonicalize_body, dkim_canonicalize_header_value, dkim_canonicalize_headers,
|
||||||
DkimCanonicalizationType, DkimConfig, DkimSigningAlgorithm, DkimSigningKey,
|
DkimCanonicalizationType, DkimConfig, DkimSigningAlgorithm, DkimSigningKey,
|
||||||
};
|
};
|
||||||
use crate::StdError;
|
use crate::StdError;
|
||||||
use std::io::Write;
|
|
||||||
use std::process::{Command, Stdio};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct TestHeader(String);
|
struct TestHeader(String);
|
||||||
|
|||||||
@@ -94,11 +94,13 @@ impl Display for ContentTypeErr {
|
|||||||
// -- Serialization and Deserialization --
|
// -- Serialization and Deserialization --
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
mod serde {
|
mod serde {
|
||||||
use serde::de::{self, Deserialize, Deserializer, Visitor};
|
|
||||||
use serde::ser::{Serialize, Serializer};
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use serde::{
|
||||||
|
de::{self, Deserialize, Deserializer, Visitor},
|
||||||
|
ser::{Serialize, Serializer},
|
||||||
|
};
|
||||||
|
|
||||||
use super::ContentType;
|
use super::ContentType;
|
||||||
|
|
||||||
impl Serialize for ContentType {
|
impl Serialize for ContentType {
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
use crate::message::{Mailbox, Mailboxes};
|
use std::fmt::{Formatter, Result as FmtResult};
|
||||||
|
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{Deserializer, Error as DeError, MapAccess, SeqAccess, Visitor},
|
de::{Deserializer, Error as DeError, MapAccess, SeqAccess, Visitor},
|
||||||
ser::Serializer,
|
ser::Serializer,
|
||||||
Deserialize, Serialize,
|
Deserialize, Serialize,
|
||||||
};
|
};
|
||||||
use std::fmt::{Formatter, Result as FmtResult};
|
|
||||||
|
use crate::message::{Mailbox, Mailboxes};
|
||||||
|
|
||||||
impl Serialize for Mailbox {
|
impl Serialize for Mailbox {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -152,9 +154,10 @@ impl<'de> Deserialize<'de> for Mailboxes {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use serde_json::from_str;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::address::Address;
|
use crate::address::Address;
|
||||||
use serde_json::from_str;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_address_string() {
|
fn parse_address_string() {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::address::{Address, AddressError};
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fmt::{Display, Formatter, Result as FmtResult, Write},
|
fmt::{Display, Formatter, Result as FmtResult, Write},
|
||||||
@@ -6,6 +5,8 @@ use std::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::address::{Address, AddressError};
|
||||||
|
|
||||||
/// Represents an email address with an optional name for the sender/recipient.
|
/// Represents an email address with an optional name for the sender/recipient.
|
||||||
///
|
///
|
||||||
/// This type contains email address and the sender/recipient name (_Some Name \<user@domain.tld\>_ or _withoutname@domain.tld_).
|
/// This type contains email address and the sender/recipient name (_Some Name \<user@domain.tld\>_ or _withoutname@domain.tld_).
|
||||||
@@ -410,9 +411,10 @@ fn write_quoted_string_char(f: &mut Formatter<'_>, c: u8) -> FmtResult {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Mailbox;
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use super::Mailbox;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mailbox_format_address_only() {
|
fn mailbox_format_address_only() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use std::io::Write;
|
use std::{io::Write, iter::repeat_with};
|
||||||
|
|
||||||
|
use mime::Mime;
|
||||||
|
|
||||||
use crate::message::{
|
use crate::message::{
|
||||||
header::{self, ContentTransferEncoding, ContentType, Header, Headers},
|
header::{self, ContentTransferEncoding, ContentType, Header, Headers},
|
||||||
EmailFormat, IntoBody,
|
EmailFormat, IntoBody,
|
||||||
};
|
};
|
||||||
use mime::Mime;
|
|
||||||
use std::iter::repeat_with;
|
|
||||||
|
|
||||||
/// MIME part variants
|
/// MIME part variants
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -106,9 +106,10 @@
|
|||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # use std::error::Error;
|
//! # use std::error::Error;
|
||||||
//! use lettre::message::{header, Attachment, Body, Message, MultiPart, SinglePart};
|
|
||||||
//! use std::fs;
|
//! use std::fs;
|
||||||
//!
|
//!
|
||||||
|
//! use lettre::message::{header, Attachment, Body, Message, MultiPart, SinglePart};
|
||||||
|
//!
|
||||||
//! # fn main() -> Result<(), Box<dyn Error>> {
|
//! # fn main() -> Result<(), Box<dyn Error>> {
|
||||||
//! let image = fs::read("docs/lettre.png")?;
|
//! let image = fs::read("docs/lettre.png")?;
|
||||||
//! // this image_body can be cloned and reused between emails.
|
//! // this image_body can be cloned and reused between emails.
|
||||||
@@ -510,16 +511,18 @@ impl Message {
|
|||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use lettre::Message;
|
/// use lettre::{
|
||||||
/// use lettre::message::dkim::{DkimConfig, DkimSigningAlgorithm, DkimSigningKey};
|
/// message::dkim::{DkimConfig, DkimSigningAlgorithm, DkimSigningKey},
|
||||||
|
/// Message,
|
||||||
|
/// };
|
||||||
///
|
///
|
||||||
/// let mut message = Message::builder()
|
/// let mut message = Message::builder()
|
||||||
/// .from("Alice <alice@example.org>".parse().unwrap())
|
/// .from("Alice <alice@example.org>".parse().unwrap())
|
||||||
/// .reply_to("Bob <bob@example.org>".parse().unwrap())
|
/// .reply_to("Bob <bob@example.org>".parse().unwrap())
|
||||||
/// .to("Carla <carla@example.net>".parse().unwrap())
|
/// .to("Carla <carla@example.net>".parse().unwrap())
|
||||||
/// .subject("Hello")
|
/// .subject("Hello")
|
||||||
/// .body("Hi there, it's a test email, with utf-8 chars ë!\n\n\n".to_string())
|
/// .body("Hi there, it's a test email, with utf-8 chars ë!\n\n\n".to_string())
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
/// let key = "-----BEGIN RSA PRIVATE KEY-----
|
/// let key = "-----BEGIN RSA PRIVATE KEY-----
|
||||||
/// MIIEowIBAAKCAQEAt2gawjoybf0mAz0mSX0cq1ah5F9cPazZdCwLnFBhRufxaZB8
|
/// MIIEowIBAAKCAQEAt2gawjoybf0mAz0mSX0cq1ah5F9cPazZdCwLnFBhRufxaZB8
|
||||||
/// NLTdc9xfPIOK8l/xGrN7Nd63J4cTATqZukumczkA46O8YKHwa53pNT6NYwCNtDUL
|
/// NLTdc9xfPIOK8l/xGrN7Nd63J4cTATqZukumczkA46O8YKHwa53pNT6NYwCNtDUL
|
||||||
@@ -548,8 +551,15 @@ impl Message {
|
|||||||
/// I45fbR4l+3D/30WMfZlM6bzZbwPXEnr2s1mirmuQpjumY9wLhK25
|
/// I45fbR4l+3D/30WMfZlM6bzZbwPXEnr2s1mirmuQpjumY9wLhK25
|
||||||
/// -----END RSA PRIVATE KEY-----";
|
/// -----END RSA PRIVATE KEY-----";
|
||||||
/// let signing_key = DkimSigningKey::new(key.to_string(), DkimSigningAlgorithm::Rsa).unwrap();
|
/// let signing_key = DkimSigningKey::new(key.to_string(), DkimSigningAlgorithm::Rsa).unwrap();
|
||||||
/// message.sign(&DkimConfig::default_config("dkimtest".to_string(),"example.org".to_string(),signing_key));
|
/// message.sign(&DkimConfig::default_config(
|
||||||
/// println!("message: {}", std::str::from_utf8(&message.formatted()).unwrap());
|
/// "dkimtest".to_string(),
|
||||||
|
/// "example.org".to_string(),
|
||||||
|
/// signing_key,
|
||||||
|
/// ));
|
||||||
|
/// println!(
|
||||||
|
/// "message: {}",
|
||||||
|
/// std::str::from_utf8(&message.formatted()).unwrap()
|
||||||
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "dkim")]
|
#[cfg(feature = "dkim")]
|
||||||
pub fn sign(&mut self, dkim_config: &DkimConfig) {
|
pub fn sign(&mut self, dkim_config: &DkimConfig) {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
//! Error and result type for file transport
|
//! Error and result type for file transport
|
||||||
|
|
||||||
use crate::BoxError;
|
|
||||||
use std::{error::Error as StdError, fmt};
|
use std::{error::Error as StdError, fmt};
|
||||||
|
|
||||||
|
use crate::BoxError;
|
||||||
|
|
||||||
/// The Errors that may occur when sending an email over SMTP
|
/// The Errors that may occur when sending an email over SMTP
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
inner: Box<Inner>,
|
inner: Box<Inner>,
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
//! #
|
//! #
|
||||||
//! # #[cfg(all(feature = "file-transport", feature = "builder"))]
|
//! # #[cfg(all(feature = "file-transport", feature = "builder"))]
|
||||||
//! # fn main() -> Result<(), Box<dyn Error>> {
|
//! # fn main() -> Result<(), Box<dyn Error>> {
|
||||||
//! use lettre::{FileTransport, Message, Transport};
|
|
||||||
//! use std::env::temp_dir;
|
//! use std::env::temp_dir;
|
||||||
//!
|
//!
|
||||||
|
//! use lettre::{FileTransport, Message, Transport};
|
||||||
|
//!
|
||||||
//! // Write to the local temp directory
|
//! // Write to the local temp directory
|
||||||
//! let sender = FileTransport::new(temp_dir());
|
//! let sender = FileTransport::new(temp_dir());
|
||||||
//! let email = Message::builder()
|
//! let email = Message::builder()
|
||||||
@@ -41,9 +42,10 @@
|
|||||||
//! #
|
//! #
|
||||||
//! # #[cfg(all(feature = "file-transport-envelope", feature = "builder"))]
|
//! # #[cfg(all(feature = "file-transport-envelope", feature = "builder"))]
|
||||||
//! # fn main() -> Result<(), Box<dyn Error>> {
|
//! # fn main() -> Result<(), Box<dyn Error>> {
|
||||||
//! use lettre::{FileTransport, Message, Transport};
|
|
||||||
//! use std::env::temp_dir;
|
//! use std::env::temp_dir;
|
||||||
//!
|
//!
|
||||||
|
//! use lettre::{FileTransport, Message, Transport};
|
||||||
|
//!
|
||||||
//! // Write to the local temp directory
|
//! // Write to the local temp directory
|
||||||
//! let sender = FileTransport::with_envelope(temp_dir());
|
//! let sender = FileTransport::with_envelope(temp_dir());
|
||||||
//! let email = Message::builder()
|
//! let email = Message::builder()
|
||||||
@@ -70,7 +72,8 @@
|
|||||||
//! # #[cfg(all(feature = "tokio1", feature = "file-transport", feature = "builder"))]
|
//! # #[cfg(all(feature = "tokio1", feature = "file-transport", feature = "builder"))]
|
||||||
//! # async fn run() -> Result<(), Box<dyn Error>> {
|
//! # async fn run() -> Result<(), Box<dyn Error>> {
|
||||||
//! use std::env::temp_dir;
|
//! use std::env::temp_dir;
|
||||||
//! use lettre::{AsyncTransport, Tokio1Executor, Message, AsyncFileTransport};
|
//!
|
||||||
|
//! use lettre::{AsyncFileTransport, AsyncTransport, Message, Tokio1Executor};
|
||||||
//!
|
//!
|
||||||
//! // Write to the local temp directory
|
//! // Write to the local temp directory
|
||||||
//! let sender = AsyncFileTransport::<Tokio1Executor>::new(temp_dir());
|
//! let sender = AsyncFileTransport::<Tokio1Executor>::new(temp_dir());
|
||||||
@@ -95,7 +98,8 @@
|
|||||||
//! # #[cfg(all(feature = "async-std1", feature = "file-transport", feature = "builder"))]
|
//! # #[cfg(all(feature = "async-std1", feature = "file-transport", feature = "builder"))]
|
||||||
//! # async fn run() -> Result<(), Box<dyn Error>> {
|
//! # async fn run() -> Result<(), Box<dyn Error>> {
|
||||||
//! use std::env::temp_dir;
|
//! use std::env::temp_dir;
|
||||||
//! use lettre::{AsyncTransport, AsyncStd1Executor, Message, AsyncFileTransport};
|
//!
|
||||||
|
//! use lettre::{AsyncFileTransport, AsyncStd1Executor, AsyncTransport, Message};
|
||||||
//!
|
//!
|
||||||
//! // Write to the local temp directory
|
//! // Write to the local temp directory
|
||||||
//! let sender = AsyncFileTransport::<AsyncStd1Executor>::new(temp_dir());
|
//! let sender = AsyncFileTransport::<AsyncStd1Executor>::new(temp_dir());
|
||||||
@@ -132,20 +136,22 @@
|
|||||||
//! {"forward_path":["hei@domain.tld"],"reverse_path":"nobody@domain.tld"}
|
//! {"forward_path":["hei@domain.tld"],"reverse_path":"nobody@domain.tld"}
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
pub use self::error::Error;
|
|
||||||
use crate::{address::Envelope, Transport};
|
|
||||||
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
|
||||||
use crate::{AsyncTransport, Executor};
|
|
||||||
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
|
||||||
use async_trait::async_trait;
|
|
||||||
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::{
|
use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
||||||
|
use async_trait::async_trait;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub use self::error::Error;
|
||||||
|
use crate::{address::Envelope, Transport};
|
||||||
|
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
||||||
|
use crate::{AsyncTransport, Executor};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
type Id = String;
|
type Id = String;
|
||||||
|
|||||||
@@ -56,8 +56,7 @@
|
|||||||
//! #
|
//! #
|
||||||
//! # #[cfg(all(feature = "builder", feature = "smtp-transport"))]
|
//! # #[cfg(all(feature = "builder", feature = "smtp-transport"))]
|
||||||
//! # fn main() -> Result<(), Box<dyn Error>> {
|
//! # fn main() -> Result<(), Box<dyn Error>> {
|
||||||
//! use lettre::transport::smtp::authentication::Credentials;
|
//! use lettre::{transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport};
|
||||||
//! use lettre::{Message, SmtpTransport, Transport};
|
|
||||||
//!
|
//!
|
||||||
//! let email = Message::builder()
|
//! let email = Message::builder()
|
||||||
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
//! Error and result type for sendmail transport
|
//! Error and result type for sendmail transport
|
||||||
|
|
||||||
use crate::BoxError;
|
|
||||||
use std::{error::Error as StdError, fmt};
|
use std::{error::Error as StdError, fmt};
|
||||||
|
|
||||||
|
use crate::BoxError;
|
||||||
|
|
||||||
/// The Errors that may occur when sending an email over sendmail
|
/// The Errors that may occur when sending an email over sendmail
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
inner: Box<Inner>,
|
inner: Box<Inner>,
|
||||||
|
|||||||
@@ -33,7 +33,9 @@
|
|||||||
//! #
|
//! #
|
||||||
//! # #[cfg(all(feature = "tokio1", feature = "sendmail-transport", feature = "builder"))]
|
//! # #[cfg(all(feature = "tokio1", feature = "sendmail-transport", feature = "builder"))]
|
||||||
//! # async fn run() -> Result<(), Box<dyn Error>> {
|
//! # async fn run() -> Result<(), Box<dyn Error>> {
|
||||||
//! use lettre::{Message, AsyncTransport, Tokio1Executor, AsyncSendmailTransport, SendmailTransport};
|
//! use lettre::{
|
||||||
|
//! AsyncSendmailTransport, AsyncTransport, Message, SendmailTransport, Tokio1Executor,
|
||||||
|
//! };
|
||||||
//!
|
//!
|
||||||
//! let email = Message::builder()
|
//! let email = Message::builder()
|
||||||
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
||||||
@@ -72,6 +74,17 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::{
|
||||||
|
ffi::OsString,
|
||||||
|
io::Write,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
#[cfg(feature = "async-std1")]
|
#[cfg(feature = "async-std1")]
|
||||||
use crate::AsyncStd1Executor;
|
use crate::AsyncStd1Executor;
|
||||||
@@ -80,15 +93,6 @@ use crate::Tokio1Executor;
|
|||||||
use crate::{address::Envelope, Transport};
|
use crate::{address::Envelope, Transport};
|
||||||
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
||||||
use crate::{AsyncTransport, Executor};
|
use crate::{AsyncTransport, Executor};
|
||||||
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
|
||||||
use async_trait::async_trait;
|
|
||||||
#[cfg(any(feature = "async-std1", feature = "tokio1"))]
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::{
|
|
||||||
ffi::OsString,
|
|
||||||
io::Write,
|
|
||||||
process::{Command, Stdio},
|
|
||||||
};
|
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
//! Provides limited SASL authentication mechanisms
|
//! Provides limited SASL authentication mechanisms
|
||||||
|
|
||||||
use crate::transport::smtp::error::{self, Error};
|
|
||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
|
|
||||||
|
use crate::transport::smtp::error::{self, Error};
|
||||||
|
|
||||||
/// Accepted authentication mechanisms
|
/// Accepted authentication mechanisms
|
||||||
///
|
///
|
||||||
/// Trying LOGIN last as it is deprecated.
|
/// Trying LOGIN last as it is deprecated.
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
use std::{fmt::Display, time::Duration};
|
||||||
|
|
||||||
|
use futures_util::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||||
|
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
use super::escape_crlf;
|
||||||
use super::{AsyncNetworkStream, ClientCodec, TlsParameters};
|
use super::{AsyncNetworkStream, ClientCodec, TlsParameters};
|
||||||
use crate::{
|
use crate::{
|
||||||
transport::smtp::{
|
transport::smtp::{
|
||||||
@@ -10,11 +16,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
Envelope,
|
Envelope,
|
||||||
};
|
};
|
||||||
use futures_util::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
|
||||||
use std::{fmt::Display, time::Duration};
|
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
|
||||||
use super::escape_crlf;
|
|
||||||
|
|
||||||
macro_rules! try_smtp (
|
macro_rules! try_smtp (
|
||||||
($err: expr, $client: ident) => ({
|
($err: expr, $client: ident) => ({
|
||||||
|
|||||||
@@ -6,25 +6,22 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "async-std1-native-tls")]
|
||||||
|
use async_native_tls::TlsStream as AsyncStd1TlsStream;
|
||||||
|
#[cfg(feature = "async-std1")]
|
||||||
|
use async_std::net::{TcpStream as AsyncStd1TcpStream, ToSocketAddrs as AsyncStd1ToSocketAddrs};
|
||||||
use futures_io::{
|
use futures_io::{
|
||||||
AsyncRead as FuturesAsyncRead, AsyncWrite as FuturesAsyncWrite, Error as IoError, ErrorKind,
|
AsyncRead as FuturesAsyncRead, AsyncWrite as FuturesAsyncWrite, Error as IoError, ErrorKind,
|
||||||
Result as IoResult,
|
Result as IoResult,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "tokio1")]
|
|
||||||
use tokio1_crate::io::{AsyncRead as _, AsyncWrite as _, ReadBuf as Tokio1ReadBuf};
|
|
||||||
|
|
||||||
#[cfg(feature = "async-std1")]
|
|
||||||
use async_std::net::{TcpStream as AsyncStd1TcpStream, ToSocketAddrs as AsyncStd1ToSocketAddrs};
|
|
||||||
#[cfg(feature = "tokio1")]
|
|
||||||
use tokio1_crate::net::{TcpStream as Tokio1TcpStream, ToSocketAddrs as Tokio1ToSocketAddrs};
|
|
||||||
|
|
||||||
#[cfg(feature = "async-std1-native-tls")]
|
|
||||||
use async_native_tls::TlsStream as AsyncStd1TlsStream;
|
|
||||||
#[cfg(feature = "tokio1-native-tls")]
|
|
||||||
use tokio1_native_tls_crate::TlsStream as Tokio1TlsStream;
|
|
||||||
|
|
||||||
#[cfg(feature = "async-std1-rustls-tls")]
|
#[cfg(feature = "async-std1-rustls-tls")]
|
||||||
use futures_rustls::client::TlsStream as AsyncStd1RustlsTlsStream;
|
use futures_rustls::client::TlsStream as AsyncStd1RustlsTlsStream;
|
||||||
|
#[cfg(feature = "tokio1")]
|
||||||
|
use tokio1_crate::io::{AsyncRead as _, AsyncWrite as _, ReadBuf as Tokio1ReadBuf};
|
||||||
|
#[cfg(feature = "tokio1")]
|
||||||
|
use tokio1_crate::net::{TcpStream as Tokio1TcpStream, ToSocketAddrs as Tokio1ToSocketAddrs};
|
||||||
|
#[cfg(feature = "tokio1-native-tls")]
|
||||||
|
use tokio1_native_tls_crate::TlsStream as Tokio1TlsStream;
|
||||||
#[cfg(feature = "tokio1-rustls-tls")]
|
#[cfg(feature = "tokio1-rustls-tls")]
|
||||||
use tokio1_rustls::client::TlsStream as Tokio1RustlsTlsStream;
|
use tokio1_rustls::client::TlsStream as Tokio1RustlsTlsStream;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
use super::escape_crlf;
|
||||||
use super::{ClientCodec, NetworkStream, TlsParameters};
|
use super::{ClientCodec, NetworkStream, TlsParameters};
|
||||||
use crate::{
|
use crate::{
|
||||||
address::Envelope,
|
address::Envelope,
|
||||||
@@ -18,9 +20,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
|
||||||
use super::escape_crlf;
|
|
||||||
|
|
||||||
macro_rules! try_smtp (
|
macro_rules! try_smtp (
|
||||||
($err: expr, $client: ident) => ({
|
($err: expr, $client: ident) => ({
|
||||||
match $err {
|
match $err {
|
||||||
|
|||||||
@@ -7,16 +7,14 @@
|
|||||||
//!
|
//!
|
||||||
//! # #[cfg(feature = "smtp-transport")]
|
//! # #[cfg(feature = "smtp-transport")]
|
||||||
//! # fn main() -> Result<(), Box<dyn Error>> {
|
//! # fn main() -> Result<(), Box<dyn Error>> {
|
||||||
//! use lettre::transport::smtp::{SMTP_PORT, extension::ClientId, commands::*, client::SmtpConnection};
|
//! use lettre::transport::smtp::{
|
||||||
|
//! client::SmtpConnection, commands::*, extension::ClientId, SMTP_PORT,
|
||||||
|
//! };
|
||||||
//!
|
//!
|
||||||
//! let hello = ClientId::Domain("my_hostname".to_string());
|
//! let hello = ClientId::Domain("my_hostname".to_string());
|
||||||
//! let mut client = SmtpConnection::connect(&("localhost", SMTP_PORT), None, &hello, None)?;
|
//! let mut client = SmtpConnection::connect(&("localhost", SMTP_PORT), None, &hello, None)?;
|
||||||
//! client.command(
|
//! client.command(Mail::new(Some("user@example.com".parse()?), vec![]))?;
|
||||||
//! Mail::new(Some("user@example.com".parse()?), vec![])
|
//! client.command(Rcpt::new("user@example.org".parse()?, vec![]))?;
|
||||||
//! )?;
|
|
||||||
//! client.command(
|
|
||||||
//! Rcpt::new("user@example.org".parse()?, vec![])
|
|
||||||
//! )?;
|
|
||||||
//! client.command(Data)?;
|
//! client.command(Data)?;
|
||||||
//! client.message("Test email".as_bytes())?;
|
//! client.message("Test email".as_bytes())?;
|
||||||
//! client.command(Quit)?;
|
//! client.command(Quit)?;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use std::{
|
|||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
use native_tls::TlsStream;
|
use native_tls::TlsStream;
|
||||||
|
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(feature = "rustls-tls")]
|
||||||
use rustls::{ClientConnection, ServerName, StreamOwned};
|
use rustls::{ClientConnection, ServerName, StreamOwned};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#[cfg(any(feature = "native-tls", feature = "rustls-tls"))]
|
use std::fmt::{self, Debug};
|
||||||
use crate::transport::smtp::{error, Error};
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
use std::{sync::Arc, time::SystemTime};
|
||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
use native_tls::{Protocol, TlsConnector};
|
use native_tls::{Protocol, TlsConnector};
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(feature = "rustls-tls")]
|
||||||
@@ -7,9 +9,9 @@ use rustls::{
|
|||||||
client::{ServerCertVerified, ServerCertVerifier, WebPkiVerifier},
|
client::{ServerCertVerified, ServerCertVerifier, WebPkiVerifier},
|
||||||
ClientConfig, Error as TlsError, OwnedTrustAnchor, RootCertStore, ServerName,
|
ClientConfig, Error as TlsError, OwnedTrustAnchor, RootCertStore, ServerName,
|
||||||
};
|
};
|
||||||
use std::fmt::{self, Debug};
|
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(any(feature = "native-tls", feature = "rustls-tls"))]
|
||||||
use std::{sync::Arc, time::SystemTime};
|
use crate::transport::smtp::{error, Error};
|
||||||
|
|
||||||
/// Accepted protocols by default.
|
/// Accepted protocols by default.
|
||||||
/// This removes TLS 1.0 and 1.1 compared to tls-native defaults.
|
/// This removes TLS 1.0 and 1.1 compared to tls-native defaults.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
//! SMTP commands
|
//! SMTP commands
|
||||||
|
|
||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
address::Address,
|
address::Address,
|
||||||
transport::smtp::{
|
transport::smtp::{
|
||||||
@@ -9,7 +11,6 @@ use crate::{
|
|||||||
response::Response,
|
response::Response,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
/// EHLO command
|
/// EHLO command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
@@ -288,9 +289,10 @@ impl Auth {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::transport::smtp::extension::MailBodyParameter;
|
use crate::transport::smtp::extension::MailBodyParameter;
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_display() {
|
fn test_display() {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
//! Error and result type for SMTP clients
|
//! Error and result type for SMTP clients
|
||||||
|
|
||||||
|
use std::{error::Error as StdError, fmt};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
transport::smtp::response::{Code, Severity},
|
transport::smtp::response::{Code, Severity},
|
||||||
BoxError,
|
BoxError,
|
||||||
};
|
};
|
||||||
use std::{error::Error as StdError, fmt};
|
|
||||||
|
|
||||||
// Inspired by https://github.com/seanmonstar/reqwest/blob/a8566383168c0ef06c21f38cbc9213af6ff6db31/src/error.rs
|
// Inspired by https://github.com/seanmonstar/reqwest/blob/a8566383168c0ef06c21f38cbc9213af6ff6db31/src/error.rs
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
//! ESMTP features
|
//! ESMTP features
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
|
fmt::{self, Display, Formatter},
|
||||||
|
net::{Ipv4Addr, Ipv6Addr},
|
||||||
|
result::Result,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::transport::smtp::{
|
use crate::transport::smtp::{
|
||||||
authentication::Mechanism,
|
authentication::Mechanism,
|
||||||
error::{self, Error},
|
error::{self, Error},
|
||||||
response::Response,
|
response::Response,
|
||||||
util::XText,
|
util::XText,
|
||||||
};
|
};
|
||||||
use std::{
|
|
||||||
collections::HashSet,
|
|
||||||
fmt::{self, Display, Formatter},
|
|
||||||
net::{Ipv4Addr, Ipv6Addr},
|
|
||||||
result::Result,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Client identifier, the parameter to `EHLO`
|
/// Client identifier, the parameter to `EHLO`
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
@@ -292,12 +293,13 @@ impl Display for RcptParameter {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::transport::smtp::{
|
use crate::transport::smtp::{
|
||||||
authentication::Mechanism,
|
authentication::Mechanism,
|
||||||
response::{Category, Code, Detail, Response, Severity},
|
response::{Category, Code, Detail, Response, Severity},
|
||||||
};
|
};
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clientid_fmt() {
|
fn test_clientid_fmt() {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))]
|
//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))]
|
||||||
//! # fn test() -> Result<(), Box<dyn std::error::Error>> {
|
//! # fn test() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
//! use lettre::{Message, Transport, SmtpTransport};
|
//! use lettre::{Message, SmtpTransport, Transport};
|
||||||
//!
|
//!
|
||||||
//! let email = Message::builder()
|
//! let email = Message::builder()
|
||||||
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
||||||
@@ -43,8 +43,7 @@
|
|||||||
//! .body(String::from("Be happy!"))?;
|
//! .body(String::from("Be happy!"))?;
|
||||||
//!
|
//!
|
||||||
//! // Create TLS transport on port 465
|
//! // Create TLS transport on port 465
|
||||||
//! let sender = SmtpTransport::relay("smtp.example.com")?
|
//! let sender = SmtpTransport::relay("smtp.example.com")?.build();
|
||||||
//! .build();
|
|
||||||
//! // Send the email via remote relay
|
//! // Send the email via remote relay
|
||||||
//! let result = sender.send(&email);
|
//! let result = sender.send(&email);
|
||||||
//! assert!(result.is_ok());
|
//! assert!(result.is_ok());
|
||||||
@@ -59,7 +58,13 @@
|
|||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))]
|
//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))]
|
||||||
//! # fn test() -> Result<(), Box<dyn std::error::Error>> {
|
//! # fn test() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
//! use lettre::{Message, Transport, SmtpTransport, transport::smtp::{PoolConfig, authentication::{Credentials, Mechanism}}};
|
//! use lettre::{
|
||||||
|
//! transport::smtp::{
|
||||||
|
//! authentication::{Credentials, Mechanism},
|
||||||
|
//! PoolConfig,
|
||||||
|
//! },
|
||||||
|
//! Message, SmtpTransport, Transport,
|
||||||
|
//! };
|
||||||
//!
|
//!
|
||||||
//! let email = Message::builder()
|
//! let email = Message::builder()
|
||||||
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
||||||
@@ -71,11 +76,14 @@
|
|||||||
//! // Create TLS transport on port 587 with STARTTLS
|
//! // Create TLS transport on port 587 with STARTTLS
|
||||||
//! let sender = SmtpTransport::starttls_relay("smtp.example.com")?
|
//! let sender = SmtpTransport::starttls_relay("smtp.example.com")?
|
||||||
//! // Add credentials for authentication
|
//! // Add credentials for authentication
|
||||||
//! .credentials(Credentials::new("username".to_string(), "password".to_string()))
|
//! .credentials(Credentials::new(
|
||||||
|
//! "username".to_string(),
|
||||||
|
//! "password".to_string(),
|
||||||
|
//! ))
|
||||||
//! // Configure expected authentication mechanism
|
//! // Configure expected authentication mechanism
|
||||||
//! .authentication(vec![Mechanism::Plain])
|
//! .authentication(vec![Mechanism::Plain])
|
||||||
//! // Connection pool settings
|
//! // Connection pool settings
|
||||||
//! .pool_config( PoolConfig::new().max_size(20))
|
//! .pool_config(PoolConfig::new().max_size(20))
|
||||||
//! .build();
|
//! .build();
|
||||||
//!
|
//!
|
||||||
//! // Send the email via remote relay
|
//! // Send the email via remote relay
|
||||||
@@ -90,7 +98,10 @@
|
|||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))]
|
//! # #[cfg(all(feature = "builder", any(feature = "native-tls", feature = "rustls-tls")))]
|
||||||
//! # fn test() -> Result<(), Box<dyn std::error::Error>> {
|
//! # fn test() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
//! use lettre::{Message, Transport, SmtpTransport, transport::smtp::client::{TlsParameters, Tls}};
|
//! use lettre::{
|
||||||
|
//! transport::smtp::client::{Tls, TlsParameters},
|
||||||
|
//! Message, SmtpTransport, Transport,
|
||||||
|
//! };
|
||||||
//!
|
//!
|
||||||
//! let email = Message::builder()
|
//! let email = Message::builder()
|
||||||
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
//! .from("NoBody <nobody@domain.tld>".parse()?)
|
||||||
@@ -101,7 +112,8 @@
|
|||||||
//!
|
//!
|
||||||
//! // Custom TLS configuration
|
//! // Custom TLS configuration
|
||||||
//! let tls = TlsParameters::builder("smtp.example.com".to_string())
|
//! let tls = TlsParameters::builder("smtp.example.com".to_string())
|
||||||
//! .dangerous_accept_invalid_certs(true).build()?;
|
//! .dangerous_accept_invalid_certs(true)
|
||||||
|
//! .build()?;
|
||||||
//!
|
//!
|
||||||
//! // Create TLS transport on port 465
|
//! // Create TLS transport on port 465
|
||||||
//! let sender = SmtpTransport::relay("smtp.example.com")?
|
//! let sender = SmtpTransport::relay("smtp.example.com")?
|
||||||
@@ -116,6 +128,10 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use client::Tls;
|
||||||
|
|
||||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||||
pub use self::async_transport::{AsyncSmtpTransport, AsyncSmtpTransportBuilder};
|
pub use self::async_transport::{AsyncSmtpTransport, AsyncSmtpTransportBuilder};
|
||||||
#[cfg(feature = "pool")]
|
#[cfg(feature = "pool")]
|
||||||
@@ -132,8 +148,6 @@ use crate::transport::smtp::{
|
|||||||
extension::ClientId,
|
extension::ClientId,
|
||||||
response::Response,
|
response::Response,
|
||||||
};
|
};
|
||||||
use client::Tls;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||||
mod async_transport;
|
mod async_transport;
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
use std::fmt::{self, Debug};
|
use std::{
|
||||||
use std::mem;
|
fmt::{self, Debug},
|
||||||
use std::ops::{Deref, DerefMut};
|
mem,
|
||||||
use std::sync::Arc;
|
ops::{Deref, DerefMut},
|
||||||
use std::time::{Duration, Instant};
|
sync::Arc,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
use futures_util::lock::Mutex;
|
use futures_util::{
|
||||||
use futures_util::stream::{self, StreamExt};
|
lock::Mutex,
|
||||||
|
stream::{self, StreamExt},
|
||||||
|
};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
use crate::executor::SpawnHandle;
|
use super::{
|
||||||
use crate::transport::smtp::async_transport::AsyncSmtpClient;
|
super::{client::AsyncSmtpConnection, Error},
|
||||||
use crate::Executor;
|
PoolConfig,
|
||||||
|
};
|
||||||
use super::super::client::AsyncSmtpConnection;
|
use crate::{executor::SpawnHandle, transport::smtp::async_transport::AsyncSmtpClient, Executor};
|
||||||
use super::super::Error;
|
|
||||||
use super::PoolConfig;
|
|
||||||
|
|
||||||
pub struct Pool<E: Executor> {
|
pub struct Pool<E: Executor> {
|
||||||
config: PoolConfig,
|
config: PoolConfig,
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
use std::fmt::{self, Debug};
|
use std::{
|
||||||
use std::ops::{Deref, DerefMut};
|
fmt::{self, Debug},
|
||||||
use std::sync::{Arc, Mutex, TryLockError};
|
mem,
|
||||||
use std::time::{Duration, Instant};
|
ops::{Deref, DerefMut},
|
||||||
use std::{mem, thread};
|
sync::{Arc, Mutex, TryLockError},
|
||||||
|
thread,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
super::{client::SmtpConnection, Error},
|
||||||
|
PoolConfig,
|
||||||
|
};
|
||||||
use crate::transport::smtp::transport::SmtpClient;
|
use crate::transport::smtp::transport::SmtpClient;
|
||||||
|
|
||||||
use super::super::client::SmtpConnection;
|
|
||||||
use super::super::Error;
|
|
||||||
use super::PoolConfig;
|
|
||||||
|
|
||||||
pub struct Pool {
|
pub struct Pool {
|
||||||
config: PoolConfig,
|
config: PoolConfig,
|
||||||
connections: Mutex<Vec<ParkedConnection>>,
|
connections: Mutex<Vec<ParkedConnection>>,
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
//! SMTP response, containing a mandatory return code and an optional text
|
//! SMTP response, containing a mandatory return code and an optional text
|
||||||
//! message
|
//! message
|
||||||
|
|
||||||
use crate::transport::smtp::{error, Error};
|
use std::{
|
||||||
|
fmt::{Display, Formatter, Result},
|
||||||
|
result,
|
||||||
|
str::FromStr,
|
||||||
|
string::ToString,
|
||||||
|
};
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::streaming::{tag, take_until},
|
bytes::streaming::{tag, take_until},
|
||||||
@@ -10,12 +16,8 @@ use nom::{
|
|||||||
sequence::{preceded, tuple},
|
sequence::{preceded, tuple},
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
use std::{
|
|
||||||
fmt::{Display, Formatter, Result},
|
use crate::transport::smtp::{error, Error};
|
||||||
result,
|
|
||||||
str::FromStr,
|
|
||||||
string::ToString,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// First digit indicates severity
|
/// First digit indicates severity
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
|
|||||||
@@ -28,12 +28,14 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use std::{error::Error as StdError, fmt};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||||
use crate::AsyncTransport;
|
use crate::AsyncTransport;
|
||||||
use crate::{address::Envelope, Transport};
|
use crate::{address::Envelope, Transport};
|
||||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use std::{error::Error as StdError, fmt};
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Error;
|
pub struct Error;
|
||||||
|
|||||||
@@ -9,13 +9,15 @@ fn default_date() -> std::time::SystemTime {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(all(feature = "file-transport", feature = "builder"))]
|
#[cfg(all(feature = "file-transport", feature = "builder"))]
|
||||||
mod sync {
|
mod sync {
|
||||||
use crate::default_date;
|
|
||||||
use lettre::{FileTransport, Message, Transport};
|
|
||||||
use std::{
|
use std::{
|
||||||
env::temp_dir,
|
env::temp_dir,
|
||||||
fs::{read_to_string, remove_file},
|
fs::{read_to_string, remove_file},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use lettre::{FileTransport, Message, Transport};
|
||||||
|
|
||||||
|
use crate::default_date;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn file_transport() {
|
fn file_transport() {
|
||||||
let sender = FileTransport::new(temp_dir());
|
let sender = FileTransport::new(temp_dir());
|
||||||
@@ -104,15 +106,16 @@ mod sync {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(all(feature = "file-transport", feature = "builder", feature = "tokio1"))]
|
#[cfg(all(feature = "file-transport", feature = "builder", feature = "tokio1"))]
|
||||||
mod tokio_1 {
|
mod tokio_1 {
|
||||||
use crate::default_date;
|
|
||||||
use lettre::{AsyncFileTransport, AsyncTransport, Message, Tokio1Executor};
|
|
||||||
use std::{
|
use std::{
|
||||||
env::temp_dir,
|
env::temp_dir,
|
||||||
fs::{read_to_string, remove_file},
|
fs::{read_to_string, remove_file},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use lettre::{AsyncFileTransport, AsyncTransport, Message, Tokio1Executor};
|
||||||
use tokio1_crate as tokio;
|
use tokio1_crate as tokio;
|
||||||
|
|
||||||
|
use crate::default_date;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn file_transport_tokio1() {
|
async fn file_transport_tokio1() {
|
||||||
let sender = AsyncFileTransport::<Tokio1Executor>::new(temp_dir());
|
let sender = AsyncFileTransport::<Tokio1Executor>::new(temp_dir());
|
||||||
@@ -155,13 +158,15 @@ mod tokio_1 {
|
|||||||
feature = "async-std1"
|
feature = "async-std1"
|
||||||
))]
|
))]
|
||||||
mod asyncstd_1 {
|
mod asyncstd_1 {
|
||||||
use crate::default_date;
|
|
||||||
use lettre::{AsyncFileTransport, AsyncStd1Executor, AsyncTransport, Message};
|
|
||||||
use std::{
|
use std::{
|
||||||
env::temp_dir,
|
env::temp_dir,
|
||||||
fs::{read_to_string, remove_file},
|
fs::{read_to_string, remove_file},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use lettre::{AsyncFileTransport, AsyncStd1Executor, AsyncTransport, Message};
|
||||||
|
|
||||||
|
use crate::default_date;
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn file_transport_asyncstd1() {
|
async fn file_transport_asyncstd1() {
|
||||||
let sender = AsyncFileTransport::<AsyncStd1Executor>::new(temp_dir());
|
let sender = AsyncFileTransport::<AsyncStd1Executor>::new(temp_dir());
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ mod sync {
|
|||||||
#[cfg(all(feature = "smtp-transport", feature = "builder", feature = "tokio1"))]
|
#[cfg(all(feature = "smtp-transport", feature = "builder", feature = "tokio1"))]
|
||||||
mod tokio_1 {
|
mod tokio_1 {
|
||||||
use lettre::{AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor};
|
use lettre::{AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor};
|
||||||
|
|
||||||
use tokio1_crate as tokio;
|
use tokio1_crate as tokio;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#[cfg(all(test, feature = "smtp-transport", feature = "pool"))]
|
#[cfg(all(test, feature = "smtp-transport", feature = "pool"))]
|
||||||
mod sync {
|
mod sync {
|
||||||
use lettre::{address::Envelope, SmtpTransport, Transport};
|
|
||||||
use std::{sync::mpsc, thread};
|
use std::{sync::mpsc, thread};
|
||||||
|
|
||||||
|
use lettre::{address::Envelope, SmtpTransport, Transport};
|
||||||
|
|
||||||
fn envelope() -> Envelope {
|
fn envelope() -> Envelope {
|
||||||
Envelope::new(
|
Envelope::new(
|
||||||
Some("user@localhost".parse().unwrap()),
|
Some("user@localhost".parse().unwrap()),
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ mod sync {
|
|||||||
#[cfg(all(feature = "builder", feature = "tokio1"))]
|
#[cfg(all(feature = "builder", feature = "tokio1"))]
|
||||||
mod tokio_1 {
|
mod tokio_1 {
|
||||||
use lettre::{transport::stub::StubTransport, AsyncTransport, Message};
|
use lettre::{transport::stub::StubTransport, AsyncTransport, Message};
|
||||||
|
|
||||||
use tokio1_crate as tokio;
|
use tokio1_crate as tokio;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|||||||
Reference in New Issue
Block a user