mail_auth/dkim/
headers.rs1use super::{Canonicalization, HashAlgorithm, Signature};
10use crate::{
11 headers::{HEADER_CAPACITY, HeaderWriter, IntegerBuffer, Writer},
12 utf8::to_str_lossy,
13};
14use encodify::{Fold, base64, qp};
15use std::fmt::{Display, Formatter};
16
17impl Signature {
18 pub fn write(&self, writer: &mut impl Writer, as_header: bool) {
28 let (header, new_line) = match self.ch {
29 Canonicalization::Relaxed if !as_header => (&b"dkim-signature:"[..], &b" "[..]),
30 _ => (&b"DKIM-Signature: "[..], &b"\r\n\t"[..]),
31 };
32 let fold = Fold {
33 separator: new_line,
34 ..Fold::DKIM
35 };
36 writer.write(header);
37 writer.write(b"v=1; a=");
38 writer.write(self.a.name().as_bytes());
39 for (tag, value) in [(&b"; s="[..], &self.s), (&b"; d="[..], &self.d)] {
40 writer.write(tag);
41 writer.write(value.as_bytes());
42 }
43 writer.write(b"; c=");
44 self.ch.serialize_name(writer);
45 writer.write(b"/");
46 self.cb.serialize_name(writer);
47
48 if let Some(atps) = &self.atps {
49 writer.write(b"; atps=");
50 writer.write(atps.as_bytes());
51 writer.write(b"; atpsh=");
52 writer.write(match self.atpsh {
53 Some(HashAlgorithm::Sha256) => b"sha256",
54 Some(HashAlgorithm::Sha1) => b"sha1",
55 Some(HashAlgorithm::Sha512) | None => b"none",
56 });
57 }
58 if self.r {
59 writer.write(b"; r=y");
60 }
61
62 writer.write(b";");
63 writer.write(new_line);
64
65 let mut bw = 1;
66 for (num, h) in self.h.iter().enumerate() {
67 if bw + h.len() + 1 >= 76 {
68 writer.write(new_line);
69 bw = 1;
70 }
71 if num > 0 {
72 writer.write_len(b":", &mut bw);
73 } else {
74 writer.write_len(b"h=", &mut bw);
75 }
76 writer.write_len(h.as_bytes(), &mut bw);
77 }
78
79 if !self.i.is_empty() {
80 if bw + self.i.len() + 3 >= 76 {
81 writer.write(b";");
82 writer.write(new_line);
83 bw = 1;
84 } else {
85 writer.write_len(b"; ", &mut bw);
86 }
87 writer.write_len(b"i=", &mut bw);
88 qp::DKIM.encode_folded(&self.i, &mut bw, fold, |piece| writer.write(piece));
89 }
90
91 let mut integer = IntegerBuffer::new();
92 for (tag, value) in [
93 (&b"t="[..], self.t),
94 (&b"x="[..], self.x),
95 (&b"l="[..], self.l),
96 ] {
97 if value > 0 {
98 let value = integer.digits(value);
99 writer.write_len(b";", &mut bw);
100 if bw + tag.len() + value.len() >= 76 {
101 writer.write(new_line);
102 bw = 1;
103 } else {
104 writer.write_len(b" ", &mut bw);
105 }
106
107 writer.write_len(tag, &mut bw);
108 writer.write_len(value, &mut bw);
109 }
110 }
111
112 for (tag, value) in [(&b"; bh="[..], &self.bh), (&b"; b="[..], &self.b)] {
113 writer.write_len(tag, &mut bw);
114 base64::STANDARD.encode_folded(value, &mut bw, fold, |piece| writer.write(piece));
115 }
116
117 writer.write(b";");
118 if as_header {
119 writer.write(b"\r\n");
120 }
121 }
122}
123
124impl HeaderWriter for Signature {
125 fn write_header(&self, writer: &mut impl Writer) {
126 self.write(writer, true);
127 }
128}
129
130impl Display for Signature {
131 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
132 let mut buf = Vec::with_capacity(HEADER_CAPACITY);
133 self.write(&mut buf, false);
134 f.write_str(&to_str_lossy(&buf))
135 }
136}