Make this all internal only for now
This commit is contained in:
@@ -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());
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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 {
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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")?
|
||||||
|
|||||||
Reference in New Issue
Block a user