Make this all internal only for now

This commit is contained in:
Paolo Barbolini
2025-05-02 07:20:20 +02:00
parent b7482f0232
commit d31490a2a9
8 changed files with 72 additions and 111 deletions

View File

@@ -4,10 +4,7 @@ use lettre::{
message::header::ContentType, message::header::ContentType,
transport::smtp::{ transport::smtp::{
authentication::Credentials, authentication::Credentials,
client::{ client::{Certificate, Tls, TlsParameters},
tls::{native_tls::Certificate, NativeTls, TlsParametersBuilder},
Tls,
},
}, },
Message, SmtpTransport, Transport, Message, SmtpTransport, Transport,
}; };
@@ -27,9 +24,9 @@ fn main() {
// Use a custom certificate stored on disk to securely verify the server's certificate // Use a custom certificate stored on disk to securely verify the server's certificate
let pem_cert = fs::read("certificate.pem").unwrap(); let pem_cert = fs::read("certificate.pem").unwrap();
let cert = Certificate::from_pem(&pem_cert).unwrap(); let cert = Certificate::from_pem(&pem_cert).unwrap();
let tls = TlsParametersBuilder::<NativeTls>::new("smtp.server.com".to_owned()) let tls = TlsParameters::builder("smtp.server.com".to_owned())
.add_root_certificate(cert) .add_root_certificate(cert)
.build_legacy() .build()
.unwrap(); .unwrap();
let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned()); let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());

View File

@@ -34,14 +34,12 @@ pub use self::async_net::AsyncNetworkStream;
pub use self::async_net::AsyncTokioStream; pub use self::async_net::AsyncTokioStream;
use self::net::NetworkStream; use self::net::NetworkStream;
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))] #[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
pub(super) use self::tls::deprecated::InnerTlsParameters; pub(super) use self::tls::current::InnerTlsParameters;
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))] #[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
#[allow(deprecated)] pub use self::tls::current::TlsVersion;
pub use self::tls::deprecated::TlsVersion;
#[allow(deprecated)]
pub use self::{ pub use self::{
connection::SmtpConnection, connection::SmtpConnection,
tls::deprecated::{Certificate, Identity, Tls, TlsParameters, TlsParametersBuilder}, tls::current::{Certificate, Identity, Tls, TlsParameters, TlsParametersBuilder},
}; };
#[cfg(any(feature = "tokio1", feature = "async-std1"))] #[cfg(any(feature = "tokio1", feature = "async-std1"))]
@@ -50,7 +48,7 @@ mod async_connection;
mod async_net; mod async_net;
mod connection; mod connection;
mod net; mod net;
pub mod tls; mod tls;
/// The codec used for transparency /// The codec used for transparency
#[derive(Debug)] #[derive(Debug)]

View File

@@ -55,21 +55,21 @@ pub(super) fn build_connector(
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[non_exhaustive] #[non_exhaustive]
pub enum CertificateStore { pub(super) enum CertificateStore {
#[default] #[default]
System, System,
None, None,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Certificate(pub(super) boring::x509::X509); pub(super) struct Certificate(pub(super) boring::x509::X509);
impl Certificate { impl Certificate {
pub fn from_pem(pem: &[u8]) -> Result<Self, Error> { pub(super) fn from_pem(pem: &[u8]) -> Result<Self, Error> {
Ok(Self(boring::x509::X509::from_pem(pem).map_err(error::tls)?)) Ok(Self(boring::x509::X509::from_pem(pem).map_err(error::tls)?))
} }
pub fn from_der(der: &[u8]) -> Result<Self, Error> { pub(super) fn from_der(der: &[u8]) -> Result<Self, Error> {
Ok(Self(boring::x509::X509::from_der(der).map_err(error::tls)?)) Ok(Self(boring::x509::X509::from_der(der).map_err(error::tls)?))
} }
} }
@@ -81,13 +81,13 @@ impl Debug for Certificate {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Identity { pub(super) struct Identity {
pub(super) chain: boring::x509::X509, pub(super) chain: boring::x509::X509,
pub(super) key: boring::pkey::PKey<boring::pkey::Private>, pub(super) key: boring::pkey::PKey<boring::pkey::Private>,
} }
impl Identity { impl Identity {
pub fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> { pub(super) fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> {
let chain = boring::x509::X509::from_pem(pem).map_err(error::tls)?; let chain = boring::x509::X509::from_pem(pem).map_err(error::tls)?;
let key = boring::pkey::PKey::private_key_from_pem(key).map_err(error::tls)?; let key = boring::pkey::PKey::private_key_from_pem(key).map_err(error::tls)?;
Ok(Self { chain, key }) Ok(Self { chain, key })
@@ -102,7 +102,7 @@ impl Debug for Identity {
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
#[non_exhaustive] #[non_exhaustive]
pub enum MinTlsVersion { pub(super) enum MinTlsVersion {
Tlsv10, Tlsv10,
Tlsv11, Tlsv11,
#[default] #[default]

View File

@@ -7,7 +7,6 @@ use crate::transport::smtp::{error, Error};
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[non_exhaustive] #[non_exhaustive]
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))] #[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
#[deprecated]
pub enum TlsVersion { pub enum TlsVersion {
/// TLS 1.0 /// TLS 1.0
/// ///
@@ -120,8 +119,6 @@ impl Debug for Tls {
/// Source for the base set of root certificates to trust. /// Source for the base set of root certificates to trust.
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
#[deprecated]
#[allow(deprecated)]
pub enum CertificateStore { pub enum CertificateStore {
/// Use the default for the TLS backend. /// Use the default for the TLS backend.
/// ///
@@ -153,29 +150,22 @@ pub struct TlsParameters {
/// Builder for `TlsParameters` /// Builder for `TlsParameters`
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[deprecated]
pub struct TlsParametersBuilder { pub struct TlsParametersBuilder {
domain: String, domain: String,
#[allow(deprecated)]
cert_store: CertificateStore, cert_store: CertificateStore,
#[allow(deprecated)]
root_certs: Vec<Certificate>, root_certs: Vec<Certificate>,
#[allow(deprecated)]
identity: Option<Identity>, identity: Option<Identity>,
accept_invalid_hostnames: bool, accept_invalid_hostnames: bool,
accept_invalid_certs: bool, accept_invalid_certs: bool,
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))] #[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
#[allow(deprecated)]
min_tls_version: TlsVersion, min_tls_version: TlsVersion,
} }
#[allow(deprecated)]
impl TlsParametersBuilder { impl TlsParametersBuilder {
/// Creates a new builder for `TlsParameters` /// Creates a new builder for `TlsParameters`
pub fn new(domain: String) -> Self { pub fn new(domain: String) -> Self {
Self { Self {
domain, domain,
#[allow(deprecated)]
cert_store: CertificateStore::Default, cert_store: CertificateStore::Default,
root_certs: Vec::new(), root_certs: Vec::new(),
identity: None, identity: None,
@@ -187,8 +177,6 @@ impl TlsParametersBuilder {
} }
/// Set the source for the base set of root certificates to trust. /// Set the source for the base set of root certificates to trust.
#[deprecated]
#[allow(deprecated)]
pub fn certificate_store(mut self, cert_store: CertificateStore) -> Self { pub fn certificate_store(mut self, cert_store: CertificateStore) -> Self {
self.cert_store = cert_store; self.cert_store = cert_store;
self self
@@ -272,7 +260,6 @@ impl TlsParametersBuilder {
docsrs, docsrs,
doc(cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))) doc(cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls")))
)] )]
#[deprecated]
pub fn build(self) -> Result<TlsParameters, Error> { pub fn build(self) -> Result<TlsParameters, Error> {
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
return self.build_rustls(); return self.build_rustls();
@@ -286,7 +273,6 @@ impl TlsParametersBuilder {
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
pub fn build_native(self) -> Result<TlsParameters, Error> { pub fn build_native(self) -> Result<TlsParameters, Error> {
#[allow(deprecated)]
let cert_store = match self.cert_store { let cert_store = match self.cert_store {
CertificateStore::Default => super::native_tls::CertificateStore::System, CertificateStore::Default => super::native_tls::CertificateStore::System,
CertificateStore::None => super::native_tls::CertificateStore::None, CertificateStore::None => super::native_tls::CertificateStore::None,
@@ -330,7 +316,6 @@ impl TlsParametersBuilder {
#[cfg(feature = "boring-tls")] #[cfg(feature = "boring-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
pub fn build_boring(self) -> Result<TlsParameters, Error> { pub fn build_boring(self) -> Result<TlsParameters, Error> {
#[allow(deprecated)]
let cert_store = match self.cert_store { let cert_store = match self.cert_store {
CertificateStore::Default => super::boring_tls::CertificateStore::System, CertificateStore::Default => super::boring_tls::CertificateStore::System,
CertificateStore::None => super::boring_tls::CertificateStore::None, CertificateStore::None => super::boring_tls::CertificateStore::None,
@@ -367,7 +352,6 @@ impl TlsParametersBuilder {
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
pub fn build_rustls(self) -> Result<TlsParameters, Error> { pub fn build_rustls(self) -> Result<TlsParameters, Error> {
#[allow(deprecated)]
let cert_store = match self.cert_store { let cert_store = match self.cert_store {
#[cfg(feature = "rustls-native-certs")] #[cfg(feature = "rustls-native-certs")]
CertificateStore::Default => super::rustls::CertificateStore::NativeCerts, CertificateStore::Default => super::rustls::CertificateStore::NativeCerts,
@@ -430,14 +414,11 @@ impl TlsParameters {
docsrs, docsrs,
doc(cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))) doc(cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls")))
)] )]
#[allow(deprecated)]
pub fn new(domain: String) -> Result<Self, Error> { pub fn new(domain: String) -> Result<Self, Error> {
TlsParametersBuilder::new(domain).build() TlsParametersBuilder::new(domain).build()
} }
/// Creates a new `TlsParameters` builder /// Creates a new `TlsParameters` builder
#[deprecated]
#[allow(deprecated)]
pub fn builder(domain: String) -> TlsParametersBuilder { pub fn builder(domain: String) -> TlsParametersBuilder {
TlsParametersBuilder::new(domain) TlsParametersBuilder::new(domain)
} }
@@ -445,8 +426,6 @@ impl TlsParameters {
/// Creates a new `TlsParameters` using native-tls /// Creates a new `TlsParameters` using native-tls
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
#[deprecated]
#[allow(deprecated)]
pub fn new_native(domain: String) -> Result<Self, Error> { pub fn new_native(domain: String) -> Result<Self, Error> {
TlsParametersBuilder::new(domain).build_native() TlsParametersBuilder::new(domain).build_native()
} }
@@ -454,8 +433,6 @@ impl TlsParameters {
/// Creates a new `TlsParameters` using rustls /// Creates a new `TlsParameters` using rustls
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
#[deprecated]
#[allow(deprecated)]
pub fn new_rustls(domain: String) -> Result<Self, Error> { pub fn new_rustls(domain: String) -> Result<Self, Error> {
TlsParametersBuilder::new(domain).build_rustls() TlsParametersBuilder::new(domain).build_rustls()
} }
@@ -463,8 +440,6 @@ impl TlsParameters {
/// Creates a new `TlsParameters` using boring /// Creates a new `TlsParameters` using boring
#[cfg(feature = "boring-tls")] #[cfg(feature = "boring-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
#[deprecated]
#[allow(deprecated)]
pub fn new_boring(domain: String) -> Result<Self, Error> { pub fn new_boring(domain: String) -> Result<Self, Error> {
TlsParametersBuilder::new(domain).build_boring() TlsParametersBuilder::new(domain).build_boring()
} }
@@ -477,7 +452,6 @@ impl TlsParameters {
/// A certificate that can be used with [`TlsParametersBuilder::add_root_certificate`] /// A certificate that can be used with [`TlsParametersBuilder::add_root_certificate`]
#[derive(Clone)] #[derive(Clone)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[deprecated]
pub struct Certificate { pub struct Certificate {
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
native_tls: super::native_tls::Certificate, native_tls: super::native_tls::Certificate,
@@ -488,7 +462,6 @@ pub struct Certificate {
} }
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))] #[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
#[allow(deprecated)]
impl Certificate { impl Certificate {
/// Create a `Certificate` from a DER encoded certificate /// Create a `Certificate` from a DER encoded certificate
pub fn from_der(der: Vec<u8>) -> Result<Self, Error> { pub fn from_der(der: Vec<u8>) -> Result<Self, Error> {
@@ -504,28 +477,17 @@ impl Certificate {
/// Create a `Certificate` from a PEM encoded certificate /// Create a `Certificate` from a PEM encoded certificate
pub fn from_pem(pem: &[u8]) -> Result<Self, Error> { pub fn from_pem(pem: &[u8]) -> Result<Self, Error> {
#[cfg(feature = "rustls")]
let rustls_cert = {
use rustls::pki_types::{self, pem::PemObject as _, CertificateDer};
CertificateDer::pem_slice_iter(pem)
.map(|cert| Ok(super::rustls::Certificate(cert?)))
.collect::<Result<Vec<_>, pki_types::pem::Error>>()
.map_err(|_| error::tls("invalid certificates"))?
};
Ok(Self { Ok(Self {
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
native_tls: super::native_tls::Certificate::from_pem(pem)?, native_tls: super::native_tls::Certificate::from_pem(pem)?,
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
rustls: rustls_cert, rustls: super::rustls::Certificate::from_pem_bundle(pem)?,
#[cfg(feature = "boring-tls")] #[cfg(feature = "boring-tls")]
boring_tls: super::boring_tls::Certificate::from_pem(pem)?, boring_tls: super::boring_tls::Certificate::from_pem(pem)?,
}) })
} }
} }
#[allow(deprecated)]
impl Debug for Certificate { impl Debug for Certificate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Certificate").finish() f.debug_struct("Certificate").finish()
@@ -535,7 +497,6 @@ impl Debug for Certificate {
/// An identity that can be used with [`TlsParametersBuilder::identify_with`] /// An identity that can be used with [`TlsParametersBuilder::identify_with`]
#[derive(Clone)] #[derive(Clone)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[deprecated]
pub struct Identity { pub struct Identity {
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
native_tls: super::native_tls::Identity, native_tls: super::native_tls::Identity,
@@ -545,7 +506,6 @@ pub struct Identity {
boring_tls: super::boring_tls::Identity, boring_tls: super::boring_tls::Identity,
} }
#[allow(deprecated)]
impl Debug for Identity { impl Debug for Identity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Identity").finish() f.debug_struct("Identity").finish()
@@ -553,7 +513,6 @@ impl Debug for Identity {
} }
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))] #[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
#[allow(deprecated)]
impl Identity { impl Identity {
pub fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> { pub fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> {
Ok(Self { Ok(Self {

View File

@@ -2,17 +2,17 @@ use crate::transport::smtp::Error;
#[cfg(feature = "boring-tls")] #[cfg(feature = "boring-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
pub mod boring_tls; pub(super) mod boring_tls;
pub(super) mod deprecated; pub(super) mod current;
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
pub mod native_tls; pub(super) mod native_tls;
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
pub mod rustls; pub(super) mod rustls;
#[derive(Debug)] #[derive(Debug)]
pub struct TlsParametersBuilder<B: TlsBackend> { struct TlsParametersBuilder<B: TlsBackend> {
domain: String, domain: String,
cert_store: B::CertificateStore, cert_store: B::CertificateStore,
root_certs: Vec<B::Certificate>, root_certs: Vec<B::Certificate>,
@@ -23,7 +23,7 @@ pub struct TlsParametersBuilder<B: TlsBackend> {
} }
impl<B: TlsBackend> TlsParametersBuilder<B> { impl<B: TlsBackend> TlsParametersBuilder<B> {
pub fn new(domain: String) -> Self { fn new(domain: String) -> Self {
Self { Self {
domain, domain,
cert_store: Default::default(), cert_store: Default::default(),
@@ -35,44 +35,44 @@ impl<B: TlsBackend> TlsParametersBuilder<B> {
} }
} }
pub fn certificate_store(mut self, cert_store: B::CertificateStore) -> Self { fn certificate_store(mut self, cert_store: B::CertificateStore) -> Self {
self.cert_store = cert_store; self.cert_store = cert_store;
self self
} }
pub fn add_root_certificate(mut self, cert: B::Certificate) -> Self { fn add_root_certificate(mut self, cert: B::Certificate) -> Self {
self.root_certs.push(cert); self.root_certs.push(cert);
self self
} }
pub fn identify_with(mut self, identity: B::Identity) -> Self { fn identify_with(mut self, identity: B::Identity) -> Self {
self.identity = Some(identity); self.identity = Some(identity);
self self
} }
pub fn min_tls_version(mut self, min_tls_version: B::MinTlsVersion) -> Self { fn min_tls_version(mut self, min_tls_version: B::MinTlsVersion) -> Self {
self.min_tls_version = min_tls_version; self.min_tls_version = min_tls_version;
self self
} }
pub fn dangerous_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> Self { fn dangerous_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> Self {
self.accept_invalid_certs = accept_invalid_certs; self.accept_invalid_certs = accept_invalid_certs;
self self
} }
pub fn dangerous_accept_invalid_hostnames(mut self, accept_invalid_hostnames: bool) -> Self { fn dangerous_accept_invalid_hostnames(mut self, accept_invalid_hostnames: bool) -> Self {
self.accept_invalid_hostnames = accept_invalid_hostnames; self.accept_invalid_hostnames = accept_invalid_hostnames;
self self
} }
pub fn build_legacy(self) -> Result<self::deprecated::TlsParameters, Error> { fn build_legacy(self) -> Result<self::current::TlsParameters, Error> {
let domain = self.domain.clone(); let domain = self.domain.clone();
let connector = B::__build_legacy_connector(self)?; let connector = B::__build_legacy_connector(self)?;
Ok(self::deprecated::TlsParameters { connector, domain }) Ok(self::current::TlsParameters { connector, domain })
} }
} }
pub trait TlsBackend: private::SealedTlsBackend { trait TlsBackend: private::SealedTlsBackend {
type CertificateStore: Default; type CertificateStore: Default;
type Certificate; type Certificate;
type Identity; type Identity;
@@ -85,7 +85,7 @@ pub trait TlsBackend: private::SealedTlsBackend {
#[allow(private_interfaces)] #[allow(private_interfaces)]
fn __build_legacy_connector( fn __build_legacy_connector(
builder: TlsParametersBuilder<Self>, builder: TlsParametersBuilder<Self>,
) -> Result<self::deprecated::InnerTlsParameters, Error>; ) -> Result<self::current::InnerTlsParameters, Error>;
} }
#[cfg(feature = "boring-tls")] #[cfg(feature = "boring-tls")]
@@ -93,7 +93,7 @@ pub trait TlsBackend: private::SealedTlsBackend {
#[derive(Debug)] #[derive(Debug)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[non_exhaustive] #[non_exhaustive]
pub struct BoringTls; pub(super) struct BoringTls;
#[cfg(feature = "boring-tls")] #[cfg(feature = "boring-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
@@ -103,6 +103,7 @@ impl TlsBackend for BoringTls {
type Identity = self::boring_tls::Identity; type Identity = self::boring_tls::Identity;
type MinTlsVersion = self::boring_tls::MinTlsVersion; type MinTlsVersion = self::boring_tls::MinTlsVersion;
#[allow(private_interfaces)]
fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> { fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> {
self::boring_tls::build_connector(builder) self::boring_tls::build_connector(builder)
} }
@@ -110,10 +111,10 @@ impl TlsBackend for BoringTls {
#[allow(private_interfaces)] #[allow(private_interfaces)]
fn __build_legacy_connector( fn __build_legacy_connector(
builder: TlsParametersBuilder<Self>, builder: TlsParametersBuilder<Self>,
) -> Result<self::deprecated::InnerTlsParameters, Error> { ) -> Result<self::current::InnerTlsParameters, Error> {
let accept_invalid_hostnames = builder.accept_invalid_hostnames; let accept_invalid_hostnames = builder.accept_invalid_hostnames;
Self::__build_connector(builder).map(|connector| { Self::__build_connector(builder).map(|connector| {
self::deprecated::InnerTlsParameters::BoringTls { self::current::InnerTlsParameters::BoringTls {
connector, connector,
accept_invalid_hostnames, accept_invalid_hostnames,
} }
@@ -126,7 +127,7 @@ impl TlsBackend for BoringTls {
#[derive(Debug)] #[derive(Debug)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[non_exhaustive] #[non_exhaustive]
pub struct NativeTls; pub(super) struct NativeTls;
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))] #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
@@ -136,6 +137,7 @@ impl TlsBackend for NativeTls {
type Identity = self::native_tls::Identity; type Identity = self::native_tls::Identity;
type MinTlsVersion = self::native_tls::MinTlsVersion; type MinTlsVersion = self::native_tls::MinTlsVersion;
#[allow(private_interfaces)]
fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> { fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> {
self::native_tls::build_connector(builder) self::native_tls::build_connector(builder)
} }
@@ -143,9 +145,9 @@ impl TlsBackend for NativeTls {
#[allow(private_interfaces)] #[allow(private_interfaces)]
fn __build_legacy_connector( fn __build_legacy_connector(
builder: TlsParametersBuilder<Self>, builder: TlsParametersBuilder<Self>,
) -> Result<self::deprecated::InnerTlsParameters, Error> { ) -> Result<self::current::InnerTlsParameters, Error> {
Self::__build_connector(builder) Self::__build_connector(builder)
.map(|connector| self::deprecated::InnerTlsParameters::NativeTls { connector }) .map(|connector| self::current::InnerTlsParameters::NativeTls { connector })
} }
} }
@@ -154,7 +156,7 @@ impl TlsBackend for NativeTls {
#[derive(Debug)] #[derive(Debug)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[non_exhaustive] #[non_exhaustive]
pub struct Rustls; pub(super) struct Rustls;
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
@@ -164,6 +166,7 @@ impl TlsBackend for Rustls {
type Identity = self::rustls::Identity; type Identity = self::rustls::Identity;
type MinTlsVersion = self::rustls::MinTlsVersion; type MinTlsVersion = self::rustls::MinTlsVersion;
#[allow(private_interfaces)]
fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> { fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> {
self::rustls::build_connector(builder) self::rustls::build_connector(builder)
} }
@@ -171,15 +174,14 @@ impl TlsBackend for Rustls {
#[allow(private_interfaces)] #[allow(private_interfaces)]
fn __build_legacy_connector( fn __build_legacy_connector(
builder: TlsParametersBuilder<Self>, builder: TlsParametersBuilder<Self>,
) -> Result<self::deprecated::InnerTlsParameters, Error> { ) -> Result<self::current::InnerTlsParameters, Error> {
Self::__build_connector(builder) Self::__build_connector(builder)
.map(|config| self::deprecated::InnerTlsParameters::Rustls { config }) .map(|config| self::current::InnerTlsParameters::Rustls { config })
} }
} }
mod private { mod private {
// FIXME: this should be `pub(super)` but the `private_bounds` lint doesn't like it pub(super) trait SealedTlsBackend: Sized {
pub trait SealedTlsBackend: Sized {
type Connector; type Connector;
} }

View File

@@ -38,23 +38,23 @@ pub(super) fn build_connector(
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[non_exhaustive] #[non_exhaustive]
pub enum CertificateStore { pub(super) enum CertificateStore {
#[default] #[default]
System, System,
None, None,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Certificate(pub(super) native_tls::Certificate); pub(super) struct Certificate(pub(super) native_tls::Certificate);
impl Certificate { impl Certificate {
pub fn from_pem(pem: &[u8]) -> Result<Self, Error> { pub(super) fn from_pem(pem: &[u8]) -> Result<Self, Error> {
Ok(Self( Ok(Self(
native_tls::Certificate::from_pem(pem).map_err(error::tls)?, native_tls::Certificate::from_pem(pem).map_err(error::tls)?,
)) ))
} }
pub fn from_der(der: &[u8]) -> Result<Self, Error> { pub(super) fn from_der(der: &[u8]) -> Result<Self, Error> {
Ok(Self( Ok(Self(
native_tls::Certificate::from_der(der).map_err(error::tls)?, native_tls::Certificate::from_der(der).map_err(error::tls)?,
)) ))
@@ -68,10 +68,10 @@ impl Debug for Certificate {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Identity(pub(super) native_tls::Identity); pub(super) struct Identity(pub(super) native_tls::Identity);
impl Identity { impl Identity {
pub fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> { pub(super) fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> {
Ok(Self( Ok(Self(
native_tls::Identity::from_pkcs8(pem, key).map_err(error::tls)?, native_tls::Identity::from_pkcs8(pem, key).map_err(error::tls)?,
)) ))
@@ -86,7 +86,7 @@ impl Debug for Identity {
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
#[non_exhaustive] #[non_exhaustive]
pub enum MinTlsVersion { pub(super) enum MinTlsVersion {
Tlsv10, Tlsv10,
Tlsv11, Tlsv11,
#[default] #[default]

View File

@@ -80,7 +80,7 @@ pub(super) fn build_connector(
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[non_exhaustive] #[non_exhaustive]
pub enum CertificateStore { pub(super) enum CertificateStore {
#[cfg(feature = "rustls-native-certs")] #[cfg(feature = "rustls-native-certs")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))] #[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))]
#[cfg_attr(feature = "rustls-native-certs", default)] #[cfg_attr(feature = "rustls-native-certs", default)]
@@ -100,10 +100,11 @@ pub enum CertificateStore {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Certificate(pub(super) pki_types::CertificateDer<'static>); pub(super) struct Certificate(pub(super) pki_types::CertificateDer<'static>);
impl Certificate { impl Certificate {
pub fn from_pem(pem: &[u8]) -> Result<Self, Error> { #[allow(dead_code)]
pub(super) fn from_pem(pem: &[u8]) -> Result<Self, Error> {
use rustls::pki_types::pem::PemObject as _; use rustls::pki_types::pem::PemObject as _;
Ok(Self( Ok(Self(
@@ -112,7 +113,16 @@ impl Certificate {
)) ))
} }
pub fn from_der(der: Vec<u8>) -> Result<Self, Error> { pub(super) fn from_pem_bundle(pem: &[u8]) -> Result<Vec<Self>, Error> {
use rustls::pki_types::pem::PemObject as _;
pki_types::CertificateDer::pem_slice_iter(pem)
.map(|cert| Ok(Self(cert?)))
.collect::<Result<Vec<_>, pki_types::pem::Error>>()
.map_err(|_| error::tls("invalid certificate"))
}
pub(super) fn from_der(der: Vec<u8>) -> Result<Self, Error> {
Ok(Self(der.into())) Ok(Self(der.into()))
} }
} }
@@ -123,13 +133,13 @@ impl Debug for Certificate {
} }
} }
pub struct Identity { pub(super) struct Identity {
pub(super) chain: Vec<pki_types::CertificateDer<'static>>, pub(super) chain: Vec<pki_types::CertificateDer<'static>>,
pub(super) key: pki_types::PrivateKeyDer<'static>, pub(super) key: pki_types::PrivateKeyDer<'static>,
} }
impl Identity { impl Identity {
pub fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> { pub(super) fn from_pem(pem: &[u8], key: &[u8]) -> Result<Self, Error> {
use rustls::pki_types::pem::PemObject as _; use rustls::pki_types::pem::PemObject as _;
let key = match pki_types::PrivateKeyDer::from_pem_slice(key) { let key = match pki_types::PrivateKeyDer::from_pem_slice(key) {
@@ -164,7 +174,7 @@ impl Debug for Identity {
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
#[non_exhaustive] #[non_exhaustive]
pub enum MinTlsVersion { pub(super) enum MinTlsVersion {
#[default] #[default]
Tlsv12, Tlsv12,
Tlsv13, Tlsv13,

View File

@@ -107,10 +107,7 @@
//! //!
//! use lettre::{ //! use lettre::{
//! message::header::ContentType, //! message::header::ContentType,
//! transport::smtp::client::{ //! transport::smtp::client::{Certificate, Tls, TlsParameters},
//! tls::{native_tls::Certificate, NativeTls, TlsParametersBuilder},
//! Tls,
//! },
//! Message, SmtpTransport, Transport, //! Message, SmtpTransport, Transport,
//! }; //! };
//! //!
@@ -125,11 +122,9 @@
//! // Custom TLS configuration - Use a self signed certificate //! // Custom TLS configuration - Use a self signed certificate
//! let cert = fs::read("self-signed.crt")?; //! let cert = fs::read("self-signed.crt")?;
//! let cert = Certificate::from_pem(&cert)?; //! let cert = Certificate::from_pem(&cert)?;
//! let tls = TlsParametersBuilder::<NativeTls>::new( //! let tls = TlsParameters::builder(/* TLS SNI value */ "smtp.example.com".to_owned())
//! /* TLS SNI value */ "smtp.example.com".to_owned(), //! .add_root_certificate(cert)
//! ) //! .build()?;
//! .add_root_certificate(cert)
//! .build_legacy()?;
//! //!
//! // Create the SMTPS transport //! // Create the SMTPS transport
//! let sender = SmtpTransport::relay("smtp.example.com")? //! let sender = SmtpTransport::relay("smtp.example.com")?