Skip to main content

DkimSigner

Struct DkimSigner 

Source
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>

Source

pub fn from_key(key: T) -> DkimSigner<T, NeedDomain>

Starts a signer for key.

The a= algorithm is taken from the key. Continue with domain, selector and headers to obtain a signer in the Ready state.

Source§

impl<T: SigningKey> DkimSigner<T, NeedDomain>

Source

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>

Source

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>

Source

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>

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn header_canonicalization(self, ch: Canonicalization) -> Self

Sets the header canonicalization (first half of the c= tag). Defaults to Canonicalization::Relaxed.

Source

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>

Source

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);
Source

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>

Source

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>

Source

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>

Source

pub fn heap_size(&self) -> usize

Approximate heap memory owned by this signer, in bytes: the signature template and the private key material.

Trait Implementations§

Source§

impl<T: Clone + SigningKey, State: Clone> Clone for DkimSigner<T, State>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug + SigningKey, State: Debug> Debug for DkimSigner<T, State>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Eq + SigningKey, State: Eq> Eq for DkimSigner<T, State>

Source§

impl<T: PartialEq + SigningKey, State: PartialEq> PartialEq for DkimSigner<T, State>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<T: PartialEq + SigningKey, State: PartialEq> StructuralPartialEq for DkimSigner<T, State>

Auto Trait Implementations§

§

impl<T, State> Freeze for DkimSigner<T, State>
where PhantomData<State>: Freeze, T: Freeze,

§

impl<T, State> RefUnwindSafe for DkimSigner<T, State>

§

impl<T, State> Send for DkimSigner<T, State>
where PhantomData<State>: Send, T: Send,

§

impl<T, State> Sync for DkimSigner<T, State>
where PhantomData<State>: Sync, T: Sync,

§

impl<T, State> Unpin for DkimSigner<T, State>
where PhantomData<State>: Unpin, T: Unpin,

§

impl<T, State> UnsafeUnpin for DkimSigner<T, State>

§

impl<T, State> UnwindSafe for DkimSigner<T, State>
where PhantomData<State>: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more