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