pub struct DkimSigner<T: SigningKey, State = NeedDomain> { /* private fields */ }Expand description
A DKIM1 message signer (RFC 6376, Section 5).
Built from a signing key with DkimSigner::from_key, then configured
in a fixed order that the type state enforces:
DkimSigner::from_key(key).domain(..).selector(..).headers(..) yields a
DkimSigner<_, signer::Ready>. Only a Ready signer can sign, and only a
Ready signer accepts the optional settings (atps, atps_hash,
identity, expiration, body_length, reporting,
header_canonicalization, body_canonicalization).
Defaults: relaxed/relaxed canonicalization, no expiration (x=
omitted), no body length (l= omitted), no failure reports requested
(r= omitted), no ATPS and no i= tag. The algorithm is taken from the
key.
Signing returns a Signature; write it in front of the message as a
DKIM-Signature header with
HeaderWriter.
§Example
use mail_auth::{crypto::Ed25519Key, dkim::DkimSigner, headers::HeaderWriter};
let message = b"From: bill@example.com\r\nTo: jdoe@example.com\r\n\
Subject: TPS Report\r\n\r\nHello.\r\n";
let key = Ed25519Key::from_pkcs8_der(&pkcs8_der)?;
let signature = DkimSigner::from_key(key)
.domain("example.com")
.selector("ed")
.headers(["From", "To", "Subject"])
.sign(message)?;
let signed = format!(
"{}{}",
signature.to_header(),
std::str::from_utf8(message).unwrap_or_default()
);Implementations§
Source§impl<T: SigningKey> DkimSigner<T>
impl<T: SigningKey> DkimSigner<T>
Sourcepub fn from_key(key: T) -> DkimSigner<T, NeedDomain>
pub fn from_key(key: T) -> DkimSigner<T, NeedDomain>
Source§impl<T: SigningKey> DkimSigner<T, NeedDomain>
impl<T: SigningKey> DkimSigner<T, NeedDomain>
Sourcepub fn domain(self, domain: impl Into<String>) -> DkimSigner<T, NeedSelector>
pub fn domain(self, domain: impl Into<String>) -> DkimSigner<T, NeedSelector>
Sets the signing domain (d= tag).
The public key must be published under this domain, at
<selector>._domainkey.<domain>.
Source§impl<T: SigningKey> DkimSigner<T, NeedSelector>
impl<T: SigningKey> DkimSigner<T, NeedSelector>
Sourcepub fn selector(self, selector: impl Into<String>) -> DkimSigner<T, NeedHeaders>
pub fn selector(self, selector: impl Into<String>) -> DkimSigner<T, NeedHeaders>
Sets the selector (s= tag) naming the key record under the signing
domain.
Source§impl<T: SigningKey> DkimSigner<T, NeedHeaders>
impl<T: SigningKey> DkimSigner<T, NeedHeaders>
Sourcepub fn headers(
self,
headers: impl IntoIterator<Item = impl Into<String>>,
) -> DkimSigner<T, Ready>
pub fn headers( self, headers: impl IntoIterator<Item = impl Into<String>>, ) -> DkimSigner<T, Ready>
Sets the names of the header fields to sign (h= tag) and returns a
signer ready to sign.
Names are matched case insensitively. Every occurrence of a listed
header present in the message is signed, and h= lists them bottom
up. Listed names absent from the message are still appended to h=,
so adding such a header later breaks the signature (RFC 6376,
Section 5.4). Include at least From (RFC 6376, Section 5.4.1).
Source§impl<T: SigningKey> DkimSigner<T, Ready>
impl<T: SigningKey> DkimSigner<T, Ready>
Sourcepub fn atps(self, atps: impl Into<String>) -> Self
pub fn atps(self, atps: impl Into<String>) -> Self
Sets the RFC 6541 atps= tag: the author domain on whose behalf this
third-party signature is made.
Without atps_hash, atpsh=none is written.
Sourcepub fn atps_hash(self, atps_hash: HashAlgorithm) -> Self
pub fn atps_hash(self, atps_hash: HashAlgorithm) -> Self
Sets the RFC 6541 atpsh= tag: the hash applied to d= when the
verifier builds the ATPS query name. Only written together with
atps.
Sourcepub fn identity(self, identity: impl Into<String>) -> Self
pub fn identity(self, identity: impl Into<String>) -> Self
Sets the agent or user identifier (i= tag).
Its domain must be the signing domain or a subdomain of it, otherwise
verification fails with DkimError::AuidMismatch.
Sourcepub fn expiration(self, expiration: Duration) -> Self
pub fn expiration(self, expiration: Duration) -> Self
Sets the signature validity period, counted from the signing time.
The produced signature carries x= equal to t= plus expiration,
rounded up to whole seconds and capped at u64::MAX, so
Duration::MAX means no practical expiry. A zero duration, the
default, omits the x= tag.
Sourcepub fn body_length(self, body_length: bool) -> Self
pub fn body_length(self, body_length: bool) -> Self
Includes the body length (l= tag) in the signature when true.
Off by default. Signing the length lets anyone append content after the signed body without breaking the signature (RFC 6376, Section 8.2), and strict verifiers ignore such signatures.
Sourcepub fn reporting(self, reporting: bool) -> Self
pub fn reporting(self, reporting: bool) -> Self
Requests RFC 6651 failure reports (r=y tag) when true.
Off by default. Verifiers send reports to the address published in
the _report._domainkey.<domain> record.
Sourcepub fn header_canonicalization(self, ch: Canonicalization) -> Self
pub fn header_canonicalization(self, ch: Canonicalization) -> Self
Sets the header canonicalization (first half of the c= tag).
Defaults to Canonicalization::Relaxed.
Sourcepub fn body_canonicalization(self, cb: Canonicalization) -> Self
pub fn body_canonicalization(self, cb: Canonicalization) -> Self
Sets the body canonicalization (second half of the c= tag).
Defaults to Canonicalization::Relaxed.
Source§impl<T: SigningKey> DkimSigner<T, Ready>
impl<T: SigningKey> DkimSigner<T, Ready>
Sourcepub fn sign(&self, message: &[u8]) -> Result<Signature>
pub fn sign(&self, message: &[u8]) -> Result<Signature>
Signs a complete RFC 5322 message (headers and body).
Headers listed with headers are signed, the
body is hashed with the configured canonicalization, t= is set to
the current time and x= and l= are filled in when enabled. The
returned Signature is written in front of the message as a
DKIM-Signature header with
HeaderWriter.
§Errors
Returns Error::NoHeadersFound when the list of headers to sign is
empty, or Error::Crypto when the signing operation fails. Listed
headers that are absent from the message are still signed (as empty),
which prevents them from being added later.
§Example
use mail_auth::{crypto::Ed25519Key, dkim::DkimSigner, headers::HeaderWriter};
let message = "From: bill@example.com\r\nSubject: Hi\r\n\r\nHello.\r\n";
let signature = DkimSigner::from_key(Ed25519Key::from_pkcs8_der(&pkcs8_der)?)
.domain("example.com")
.selector("ed")
.headers(["From", "Subject"])
.sign(message.as_bytes())?;
println!("{}{}", signature.to_header(), message);Sourcepub fn sign_chained<'x>(
&self,
chunks: impl IntoIterator<Item = &'x [u8]>,
) -> Result<Signature>
pub fn sign_chained<'x>( &self, chunks: impl IntoIterator<Item = &'x [u8]>, ) -> Result<Signature>
Signs a message supplied as consecutive chunks, for example extra headers prepended to a stored message.
The chunks are read as if concatenated; otherwise identical to
sign.
§Errors
Returns Error::NoHeadersFound when the list of headers to sign is
empty, or Error::Crypto when the signing operation fails. Listed
headers that are absent from the message are still signed (as empty),
which prevents them from being added later.
Source§impl<T: SigningKey> DkimSigner<T, Ready>
impl<T: SigningKey> DkimSigner<T, Ready>
Sourcepub fn sign_streaming(&self) -> DkimSigningStream<'_, T>
pub fn sign_streaming(&self) -> DkimSigningStream<'_, T>
Creates a streaming signer that borrows this signer’s key and copies its settings.
Feed raw message data with DkimSigningStream::write, then call
DkimSigningStream::finish to obtain the signature.
Headers are buffered until the header/body boundary (\r\n\r\n) is
detected. After that, body content is streamed through the hasher
without additional buffering.
§Example
use mail_auth::{crypto::Ed25519Key, dkim::DkimSigner};
let signer = DkimSigner::from_key(Ed25519Key::from_pkcs8_der(&pkcs8_der)?)
.domain("example.com")
.selector("default")
.headers(["From", "To", "Subject"]);
let mut stream = signer.sign_streaming();
for chunk in message_chunks {
stream.write(chunk);
}
let signature = stream.finish()?;Source§impl<T: SigningKey, State> DkimSigner<T, State>
impl<T: SigningKey, State> DkimSigner<T, State>
Sourcepub fn template(&self) -> &Signature
pub fn template(&self) -> &Signature
Returns the signature template configured so far.
The template holds the tags that will be copied into every produced
signature. Before signing, x holds the validity period in seconds
(not an absolute time) and l is 1 when body length signing is
enabled; both are resolved when a message is signed.
Source§impl<T: SigningKey, State> DkimSigner<T, State>
impl<T: SigningKey, State> DkimSigner<T, State>
Trait Implementations§
Source§impl<T: Clone + SigningKey, State: Clone> Clone for DkimSigner<T, State>
impl<T: Clone + SigningKey, State: Clone> Clone for DkimSigner<T, State>
Source§impl<T: Debug + SigningKey, State: Debug> Debug for DkimSigner<T, State>
impl<T: Debug + SigningKey, State: Debug> Debug for DkimSigner<T, State>
impl<T: Eq + SigningKey, State: Eq> Eq for DkimSigner<T, State>
Source§impl<T: PartialEq + SigningKey, State: PartialEq> PartialEq for DkimSigner<T, State>
impl<T: PartialEq + SigningKey, State: PartialEq> PartialEq for DkimSigner<T, State>
impl<T: PartialEq + SigningKey, State: PartialEq> StructuralPartialEq for DkimSigner<T, State>
Auto Trait Implementations§
impl<T, State> Freeze for DkimSigner<T, State>
impl<T, State> RefUnwindSafe for DkimSigner<T, State>
impl<T, State> Send for DkimSigner<T, State>
impl<T, State> Sync for DkimSigner<T, State>
impl<T, State> Unpin for DkimSigner<T, State>
impl<T, State> UnsafeUnpin for DkimSigner<T, State>
impl<T, State> UnwindSafe for DkimSigner<T, State>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more