1pub mod common;
5pub mod dkim;
6
7pub use common::crypto::{RsaKey, Sha256};
9pub use common::headers::HeaderWriter;
10pub use dkim::{DkimSigner, Signature};
11
12pub fn sign_email(email: &str, domain: &str, selector: &str, private_key: &str) -> String {
25 let pk_rsa = RsaKey::<Sha256>::from_pkcs1_pem(private_key).unwrap();
27 let signature_rsa = DkimSigner::from_key(pk_rsa)
28 .domain(domain)
29 .selector(selector)
30 .headers(["From", "To", "Subject"])
31 .sign(email.as_bytes())
32 .unwrap();
33
34 format!("{}{}", signature_rsa.to_header(), email)
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum Error {
40 NoHeadersFound,
41 CryptoError(String),
42 Base64,
43}
44
45pub type Result<T> = std::result::Result<T, Error>;
46
47impl std::error::Error for Error {}
48
49impl std::fmt::Display for Error {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 match self {
52 Error::NoHeadersFound => write!(f, "No headers found to sign"),
53 Error::CryptoError(err) => write!(f, "Cryptography error: {err}"),
54 Error::Base64 => write!(f, "Base64 encoding error."),
55 }
56 }
57}
58
59impl From<rsa::errors::Error> for Error {
61 fn from(err: rsa::errors::Error) -> Self {
62 Error::CryptoError(err.to_string())
63 }
64}
65
66impl From<rsa::pkcs1::Error> for Error {
68 fn from(err: rsa::pkcs1::Error) -> Self {
69 Error::CryptoError(err.to_string())
70 }
71}