WIP: building out ARC processing

This is not fully baked yet, but I want to checkpoint.

refs: https://github.com/KumoCorp/kumomta/issues/16
This commit is contained in:
Wez Furlong
2025-10-30 11:51:54 +00:00
parent 93210b8346
commit ee4266cd19
10 changed files with 708 additions and 129 deletions
+157
View File
@@ -0,0 +1,157 @@
use crate::header::{ARCMessageSignatureHeader, ARCSealHeader};
use crate::{verify_email_header, DKIMError, ParsedEmail};
use dns_resolver::Resolver;
use mailparsing::ARCAuthenticationResults;
use std::collections::BTreeMap;
pub const MAX_ARC_INSTANCE: u8 = 50;
pub const ARC_MESSAGE_SIGNATURE_HEADER_NAME: &str = "ARC-Message-Signature";
pub const ARC_SEAL_HEADER_NAME: &str = "ARC-Seal";
pub const ARC_AUTHENTICATION_RESULTS_HEADER_NAME: &str = "ARC-Authentication-Results";
#[derive(Debug)]
pub struct ARCSet {
pub aar: ARCAuthenticationResults,
pub seal: ARCSealHeader,
pub sig: ARCMessageSignatureHeader,
}
impl ARCSet {
pub fn instance(&self) -> u8 {
self.aar.instance
}
}
pub async fn analyze_arc(email: &ParsedEmail<'_>, resolver: &dyn Resolver) {
let mut seals = BTreeMap::new();
let mut sigs = BTreeMap::new();
let mut aars = BTreeMap::new();
let headers = email.get_headers();
let mut issues = vec![];
for hdr in headers.iter_named(ARC_SEAL_HEADER_NAME) {
match ARCSealHeader::parse(hdr.get_raw_value()) {
Ok(seal) => {
let instance = seal.arc_instance().expect("validated by parse");
seals.entry(instance).or_insert_with(Vec::new).push(seal);
}
Err(err) => {
issues.push(err);
}
}
}
for hdr in headers.iter_named(ARC_MESSAGE_SIGNATURE_HEADER_NAME) {
match ARCMessageSignatureHeader::parse(hdr.get_raw_value()) {
Ok(sig) => {
let instance = sig.arc_instance().expect("validated by parse");
sigs.entry(instance).or_insert_with(Vec::new).push(sig);
}
Err(err) => {
issues.push(err);
}
}
}
for hdr in headers.iter_named(ARC_AUTHENTICATION_RESULTS_HEADER_NAME) {
match hdr.as_arc_authentication_results() {
Ok(aar) => {
if aar.instance == 0 || aar.instance > MAX_ARC_INSTANCE {
issues.push(DKIMError::InvalidARCInstance);
continue;
}
aars.entry(aar.instance).or_insert_with(Vec::new).push(aar);
}
Err(err) => {
issues.push(err.into());
}
}
}
let mut arc_sets = BTreeMap::new();
for instance in 1..=MAX_ARC_INSTANCE {
match (
seals.get(&instance),
sigs.get(&instance),
aars.get(&instance),
) {
(Some(seal), Some(sig), Some(aar)) => {
if seal.len() > 1 || sig.len() > 1 || aar.len() > 1 {
issues.push(DKIMError::DuplicateARCInstance(instance));
continue;
}
arc_sets.insert(
instance,
ARCSet {
seal: seal[0].clone(),
sig: sig[0].clone(),
aar: aar[0].clone(),
},
);
}
(None, None, None) => {
// Not an error unless there are gaps; we'll check
// for that below
}
_ => {
// One or more are missing
issues.push(DKIMError::MissingARCInstance(instance));
}
}
}
// Ensure that the keys are contiguous
for instance in 2..=MAX_ARC_INSTANCE {
if arc_sets.contains_key(&instance) {
let prior = instance - 1;
if !arc_sets.contains_key(&prior) {
issues.push(DKIMError::MissingARCInstance(prior));
}
}
}
for arc_set in arc_sets.values() {
eprintln!("{arc_set:#?}");
eprintln!("Processing instance {}", arc_set.instance());
if let Err(err) = verify_email_header(
resolver,
ARC_MESSAGE_SIGNATURE_HEADER_NAME,
&arc_set.sig,
email,
)
.await
{
issues.push(err);
}
// Verify the Seal
if let Err(err) =
verify_email_header(resolver, ARC_SEAL_HEADER_NAME, &arc_set.seal, email).await
{
issues.push(err);
}
}
eprintln!("Issues: {issues:#?}");
}
#[cfg(test)]
mod test {
use super::*;
use dns_resolver::TestResolver;
const EXAMPLE_MESSAGE: &str = include_str!("../test/arc-example.eml");
#[tokio::test]
async fn test_parse_example_from_rfc8617() {
let email = ParsedEmail::parse(EXAMPLE_MESSAGE.replace('\n', "\r\n")).unwrap();
let resolver = TestResolver::default().with_txt(
"fm3._domainkey.messagingengine.com",
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3TntGwdEtmIx+H8Etk1IgA2gLzy9v22TO+BcTUmUFaURWSG413g+VItm86ntW1bfbgFk/ArrTVAzQxgynoCQky3VXMXl2qEKgGSrLv+QaNvbebVDZI6VZX8D5+aJIN3sCSVY1eXA4x6LbPZ8pAqIAuAhtfXc7rVKbELqlEaUMrQ+ovyjF4R6gfL621BKdLeTF89/kbqJhLwmgtzok6UBUzexDDBhZ0gfGw331J+7aqdJLWUCQv6iE3zkI4myyEcMrgWxRjdZ861x374pNzady/B688A5i4BHoVnBJBuLEYfS1gTCC/7SB6U5AdEin3P0/+DqSH36cu8+MvAZ1C7E2wIDAQAB"
);
analyze_arc(&email, &resolver).await;
}
}
+9
View File
@@ -63,6 +63,12 @@ pub enum DKIMError {
CanonicalLineEndingsRequired,
#[error(transparent)]
Dns(#[from] DnsError),
#[error("ARC instance tag is invalid")]
InvalidARCInstance,
#[error("ARC Set Instance {0} has duplicate headers")]
DuplicateARCInstance(u8),
#[error("ARC Set Instance {0} has missing headers")]
MissingARCInstance(u8),
}
impl DKIMError {
@@ -85,6 +91,9 @@ impl DKIMError {
| BodyHashDidNotVerify
| MalformedBody
| CanonicalLineEndingsRequired
| InvalidARCInstance
| DuplicateARCInstance(_)
| MissingARCInstance(_)
| MailParsingError(_)
| UnsupportedCanonicalizationType(_)
| UnsupportedHashAlgorithm(_) => Status::Permfail,
+46 -92
View File
@@ -1,6 +1,6 @@
use crate::header::DKIM_SIGNATURE_HEADER_NAME;
use crate::{canonicalization, DKIMError, DKIMHeader, ParsedEmail};
use crate::{canonicalization, DKIMError, ParsedEmail, TaggedHeader};
use data_encoding::BASE64;
use mailparsing::Header;
use sha1::{Digest as _, Sha1};
use sha2::Sha256;
use std::collections::HashMap;
@@ -118,33 +118,23 @@ pub(crate) fn compute_body_hash<'a>(
/// Holds a list of header names, normalized to lower case
#[derive(Debug)]
pub(crate) enum HeaderList {
/// A list of possibly duplicated header names
MaybeMultiple(Vec<String>),
/// A list of of unique header names
Unique(Vec<String>),
}
pub(crate) struct HeaderList(Vec<String>);
impl HeaderList {
pub fn as_h_list(&self) -> String {
match self {
Self::MaybeMultiple(list) | Self::Unique(list) => list.join(":"),
}
self.0.join(":")
}
/// Computes the header list that should be used to over-sign
/// the provided email message, and returns it
pub fn compute_over_signed(&self, email: &ParsedEmail) -> Self {
let unique_header_names = match self {
Self::Unique(names) => names.clone(),
Self::MaybeMultiple(names) => {
// Note that Self::new() normalized the names, so we can
// simply dedup without further concern for normalization
let mut n = names.clone();
n.sort();
n.dedup();
n
}
let unique_header_names = {
// Note that Self::new() normalized the names, so we can
// simply dedup without further concern for normalization
let mut n = self.0.clone();
n.sort();
n.dedup();
n
};
let email_headers = email.get_headers();
@@ -157,63 +147,17 @@ impl HeaderList {
result.push(name);
}
Self::MaybeMultiple(result)
Self(result)
}
/// Build a header list.
/// Analyzes the list to determine whether it is a unique list or not
pub fn new(list: Vec<String>) -> Self {
let normalized: Vec<String> = list.into_iter().map(|s| s.to_ascii_lowercase()).collect();
let mut all_single = true;
for name in &normalized {
let n: usize = normalized
.iter()
.map(|candidate| if candidate == name { 1 } else { 0 })
.sum();
if n > 1 {
all_single = false;
break;
}
}
if all_single {
Self::Unique(normalized)
} else {
Self::MaybeMultiple(normalized)
}
Self(normalized)
}
/// Apply `apply` to each header in the provided email that
/// matches the headers, follow the order set out in Section 5.4.2
fn apply<'a, F: FnMut(&'a str, &'a [u8])>(&self, email: &'a ParsedEmail, apply: F) {
match self {
Self::MaybeMultiple(list) => Self::apply_multiple(list, email, apply),
Self::Unique(list) => Self::apply_unique(list, email, apply),
}
}
/// Perform the apply when we know that the list of header names
/// are unique.
/// We can avoid allocating any additional state for this case.
fn apply_unique<'a, F: FnMut(&'a str, &'a [u8])>(
header_list: &[String],
email: &'a ParsedEmail,
mut apply: F,
) {
let email_headers = email.get_headers();
'outer: for name in header_list {
for header in email_headers.iter().rev() {
if header.get_name().eq_ignore_ascii_case(name) {
apply(header.get_name(), header.get_raw_value().as_bytes());
continue 'outer;
}
}
}
}
/// Section 5.4.2:
/// matches the headers, returning them in the order set out in Section 5.4.2
/// Signers wishing to sign multiple instances of such a header field MUST
/// include the header field name multiple times in the "h=" tag of the
/// DKIM-Signature header field and MUST sign such header fields in order
@@ -222,11 +166,8 @@ impl HeaderList {
/// To facilitate this, we need to maintain state for each header name
/// in the list to ensure that we select the appropriate header in the
/// appropriate order.
fn apply_multiple<'a, F: FnMut(&'a str, &'a [u8])>(
header_list: &[String],
email: &'a ParsedEmail,
mut apply: F,
) {
fn compute_concrete_header_list<'a>(&self, email: &'a ParsedEmail) -> Vec<&'a Header<'a>> {
let mut headers = vec![];
let email_headers = email.get_headers();
let num_headers = email_headers.len();
@@ -234,7 +175,7 @@ impl HeaderList {
// to lower case. That happens in our constructor.
let mut last_index: HashMap<&String, usize> = HashMap::new();
'outer: for name in header_list {
'outer: for name in &self.0 {
let index = last_index.get(name).unwrap_or(&num_headers);
for (header_index, header) in email_headers
.iter()
@@ -243,7 +184,7 @@ impl HeaderList {
.skip(num_headers - index)
{
if header.get_name().eq_ignore_ascii_case(name) {
apply(header.get_name(), header.get_raw_value().as_bytes());
headers.push(header);
last_index.insert(name, header_index);
continue 'outer;
}
@@ -253,9 +194,11 @@ impl HeaderList {
// treated as the null string (including the header field name, header
// field value, all punctuation, and the trailing CRLF).
// -> don't include it in the returned signed_headers.
// FIXME: something is fishy here.
last_index.insert(name, 0);
}
headers
}
}
@@ -263,15 +206,21 @@ pub(crate) fn compute_headers_hash<'a>(
canonicalization_type: canonicalization::Type,
headers: &HeaderList,
hash_algo: HashAlgo,
dkim_header: &DKIMHeader,
dkim_header: &TaggedHeader,
email: &'a ParsedEmail<'a>,
signature_header_name: &str,
) -> Result<Vec<u8>, DKIMError> {
let mut input = Vec::new();
let mut hasher = HashImpl::from_algo(hash_algo);
headers.apply(email, |key, value| {
canonicalization_type.canon_header_into(key, value, &mut input);
});
let concrete = headers.compute_concrete_header_list(email);
for header in concrete {
canonicalization_type.canon_header_into(
header.get_name(),
header.get_raw_value().as_bytes(),
&mut input,
);
}
// Add the DKIM-Signature header in the hash. Remove the value of the
// signature (b) first.
@@ -280,7 +229,7 @@ pub(crate) fn compute_headers_hash<'a>(
let value = dkim_header.raw().replace(sign, "");
let mut canonicalized_value = vec![];
canonicalization_type.canon_header_into(
DKIM_SIGNATURE_HEADER_NAME,
signature_header_name,
value.as_bytes(),
&mut canonicalized_value,
);
@@ -300,9 +249,10 @@ pub(crate) fn compute_headers_hash<'a>(
#[cfg(test)]
mod tests {
use super::*;
use crate::{DKIMHeader, DKIM_SIGNATURE_HEADER_NAME};
fn dkim_header() -> DKIMHeader {
crate::DKIMHeader::parse("v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=smtp; d=test.com; t=1641506955; h=content-type:to: subject:date:from:mime-version:sender; bh=PU2XIErWsXvhvt1W96ntPWZ2VImjVZ3vBY2T/A+wA3A=; b=PIO0A014nyntOGKdTdtvCJor9ZxvP1M3hoLeEh8HqZ+RvAyEKdAc7VOg+/g/OTaZgsmw6U sZCoN0YNVp+2o9nkaeUslsVz3M4I55HcZnarxl+fhplIMcJ/3s0nIhXL51MfGPRqPbB7/M Gjg9/07/2vFoid6Kitg6Z+CfoD2wlSRa8xDfmeyA2cHpeVuGQhGxu7BXuU8kGbeM4+weit Ql3t9zalhikEPI5Pr7dzYFrgWNOEO6w6rQfG7niKON1BimjdbJlGanC7cO4UL361hhXT4X iXLnC9TG39xKFPT/+4nkHy8pp6YvWkD3wKlBjwkYNm0JvKGwTskCMDeTwxXhAg==").unwrap()
DKIMHeader::parse("v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=smtp; d=test.com; t=1641506955; h=content-type:to: subject:date:from:mime-version:sender; bh=PU2XIErWsXvhvt1W96ntPWZ2VImjVZ3vBY2T/A+wA3A=; b=PIO0A014nyntOGKdTdtvCJor9ZxvP1M3hoLeEh8HqZ+RvAyEKdAc7VOg+/g/OTaZgsmw6U sZCoN0YNVp+2o9nkaeUslsVz3M4I55HcZnarxl+fhplIMcJ/3s0nIhXL51MfGPRqPbB7/M Gjg9/07/2vFoid6Kitg6Z+CfoD2wlSRa8xDfmeyA2cHpeVuGQhGxu7BXuU8kGbeM4+weit Ql3t9zalhikEPI5Pr7dzYFrgWNOEO6w6rQfG7niKON1BimjdbJlGanC7cO4UL361hhXT4X iXLnC9TG39xKFPT/+4nkHy8pp6YvWkD3wKlBjwkYNm0JvKGwTskCMDeTwxXhAg==").unwrap()
}
#[test]
@@ -436,7 +386,8 @@ Hello Alice
&headers,
hash_algo,
&dkim_header(),
&email
&email,
DKIM_SIGNATURE_HEADER_NAME
)
.unwrap(),
&[
@@ -451,7 +402,8 @@ Hello Alice
&headers,
hash_algo,
&dkim_header(),
&email
&email,
DKIM_SIGNATURE_HEADER_NAME
)
.unwrap(),
&[
@@ -481,7 +433,8 @@ Hello Alice
&headers,
hash_algo,
&dkim_header(),
&email
&email,
DKIM_SIGNATURE_HEADER_NAME
)
.unwrap(),
&[
@@ -496,7 +449,8 @@ Hello Alice
&headers,
hash_algo,
&dkim_header(),
&email
&email,
DKIM_SIGNATURE_HEADER_NAME
)
.unwrap(),
&[
@@ -516,11 +470,11 @@ Hello Alice
header_list: &HeaderList,
email: &'a ParsedEmail,
) -> Vec<(&'a str, &'a [u8])> {
let mut result = vec![];
header_list.apply(email, |key, value| {
result.push((key, value));
});
result
header_list
.compute_concrete_header_list(email)
.into_iter()
.map(|header| (header.get_name(), header.get_raw_value().as_bytes()))
.collect()
}
#[test]
+44 -5
View File
@@ -1,3 +1,4 @@
use crate::arc::MAX_ARC_INSTANCE;
use crate::{parser, DKIMError, HeaderList};
use dns_resolver::Name;
use indexmap::map::IndexMap;
@@ -78,6 +79,19 @@ impl TaggedHeader {
&self.raw_bytes
}
pub fn arc_instance(&self) -> Result<u8, DKIMError> {
let instance = self
.get_required_tag("i")
.parse::<u8>()
.map_err(|_| DKIMError::InvalidARCInstance)?;
if instance == 0 || instance > MAX_ARC_INSTANCE {
return Err(DKIMError::InvalidARCInstance);
}
Ok(instance)
}
/// Generate the DKIM-Signature header from the tags
fn serialize(&self) -> String {
let mut out = String::new();
@@ -311,7 +325,7 @@ impl DKIMHeaderBuilder {
/// DKIM; instead, this tag is replaced by the instance tag as defined
/// in Section 4.2.1.
#[derive(Debug, Clone, Default)]
pub(crate) struct ARCMessageSignatureHeader {
pub struct ARCMessageSignatureHeader {
tagged: TaggedHeader,
}
@@ -334,12 +348,13 @@ impl ARCMessageSignatureHeader {
header.validate_required_tags()?;
header.check_common_tags()?;
header.arc_instance()?;
Ok(header)
}
fn validate_required_tags(&self) -> Result<(), DKIMError> {
const REQUIRED_TAGS: &[&str] = &["a", "b", "bh", "d", "h", "s"];
const REQUIRED_TAGS: &[&str] = &["a", "b", "bh", "d", "h", "s", "i"];
for required in REQUIRED_TAGS {
if self.get_tag(required).is_none() {
return Err(DKIMError::SignatureMissingRequiredTag(required));
@@ -350,7 +365,7 @@ impl ARCMessageSignatureHeader {
}
#[derive(Debug, Clone, Default)]
pub(crate) struct ARCSealHeader {
pub struct ARCSealHeader {
tagged: TaggedHeader,
}
@@ -369,15 +384,39 @@ impl std::ops::DerefMut for ARCSealHeader {
impl ARCSealHeader {
pub fn parse(value: &str) -> Result<Self, DKIMError> {
let tagged = TaggedHeader::parse(value)?;
let header = Self { tagged };
let mut header = Self { tagged };
header.validate_required_tags()?;
header.arc_instance()?;
if header.get_tag("h").is_some() {
// TODO: MUST result in cv status of fail, see Section 5.1.1
}
// Force in some values so that we can re-use the rest of
// the dkim infra on this header type
header.set_tag(
"h",
"ARC-Authentication-Results:ARC-Message-Signature:ARC-Seal",
);
header.set_tag("c", "relaxed");
Ok(header)
}
fn set_tag(&mut self, name: &str, value: &str) {
self.tagged.tags.insert(
name.to_string(),
parser::Tag {
name: name.to_string(),
value: value.to_string(),
raw_value: value.to_string(),
},
);
}
fn validate_required_tags(&self) -> Result<(), DKIMError> {
const REQUIRED_TAGS: &[&str] = &["a", "b", "d", "s"];
const REQUIRED_TAGS: &[&str] = &["a", "b", "d", "s", "i"];
for required in REQUIRED_TAGS {
if self.get_tag(required).is_none() {
return Err(DKIMError::SignatureMissingRequiredTag(required));
+38 -28
View File
@@ -2,6 +2,7 @@
use crate::errors::Status;
use crate::hash::HeaderList;
use crate::header::TaggedHeader;
use dns_resolver::{HickoryResolver, Resolver};
use ed25519_dalek::pkcs8::DecodePrivateKey;
use ed25519_dalek::SigningKey;
@@ -12,6 +13,7 @@ use openssl::pkey_ctx::PkeyCtx;
use openssl::rsa::{Padding, Rsa};
use std::collections::BTreeMap;
pub mod arc;
pub mod canonicalization;
mod errors;
mod hash;
@@ -175,7 +177,8 @@ fn verify_signature(
async fn verify_email_header<'a>(
resolver: &dyn Resolver,
dkim_header: &'a DKIMHeader,
signature_header_name: &str,
dkim_header: &'a TaggedHeader,
email: &'a ParsedEmail<'a>,
) -> Result<(), DKIMError> {
let public_keys = public_key::retrieve_public_keys(
@@ -188,12 +191,6 @@ async fn verify_email_header<'a>(
let (header_canonicalization_type, body_canonicalization_type) =
parser::parse_canonicalization(dkim_header.get_tag("c"))?;
let hash_algo = parser::parse_hash_algo(dkim_header.get_required_tag("a"))?;
let computed_body_hash = hash::compute_body_hash(
body_canonicalization_type,
dkim_header.parse_tag("l")?,
hash_algo,
email,
)?;
let header_list: Vec<String> = dkim_header
.get_required_tag("h")
@@ -207,12 +204,20 @@ async fn verify_email_header<'a>(
hash_algo,
dkim_header,
email,
signature_header_name,
)?;
tracing::debug!("body_hash {:?}", computed_body_hash);
let header_body_hash = dkim_header.get_required_tag("bh");
if header_body_hash != computed_body_hash {
return Err(DKIMError::BodyHashDidNotVerify);
if let Some(header_body_hash) = dkim_header.get_tag("bh") {
let computed_body_hash = hash::compute_body_hash(
body_canonicalization_type,
dkim_header.parse_tag("l")?,
hash_algo,
email,
)?;
tracing::debug!("body_hash {:?}", computed_body_hash);
if header_body_hash != computed_body_hash {
return Err(DKIMError::BodyHashDidNotVerify);
}
}
let signature = data_encoding::BASE64
@@ -320,25 +325,28 @@ pub async fn verify_email_with_resolver<'a>(
props.insert("header.b".to_string(), b_tag);
let mut reason = None;
let result = match verify_email_header(resolver, dkim_header, email).await {
Ok(()) => {
if signing_domain.eq_ignore_ascii_case(from_domain) {
"pass"
} else {
let why = "mail-from-mismatch-signing-domain".to_string();
reason.replace(why.clone());
props.insert("policy.dkim-rules".to_string(), why);
"policy"
let result =
match verify_email_header(resolver, DKIM_SIGNATURE_HEADER_NAME, dkim_header, email)
.await
{
Ok(()) => {
if signing_domain.eq_ignore_ascii_case(from_domain) {
"pass"
} else {
let why = "mail-from-mismatch-signing-domain".to_string();
reason.replace(why.clone());
props.insert("policy.dkim-rules".to_string(), why);
"policy"
}
}
}
Err(err) => {
reason.replace(format!("{err}"));
match err.status() {
Status::Tempfail => "temperror",
Status::Permfail => "permerror",
Err(err) => {
reason.replace(format!("{err}"));
match err.status() {
Status::Tempfail => "temperror",
Status::Permfail => "permerror",
}
}
}
};
};
results.push(AuthenticationResult {
method: "dkim".to_string(),
@@ -506,6 +514,7 @@ $ORIGIN brisbane._domainkey.football.example.com
verify_email_header(
&resolver,
DKIM_SIGNATURE_HEADER_NAME,
&DKIMHeader::parse(raw_header_dkim).unwrap(),
&email,
)
@@ -555,6 +564,7 @@ Joe.
verify_email_header(
&resolver,
DKIM_SIGNATURE_HEADER_NAME,
&DKIMHeader::parse(raw_header_rsa).unwrap(),
&email,
)
+1
View File
@@ -295,6 +295,7 @@ impl Signer {
self.hash_algo,
&dkim_header,
email,
DKIM_SIGNATURE_HEADER_NAME,
)
}
}
+185
View File
@@ -0,0 +1,185 @@
Return-Path: <wez@wezfurlong.org>
Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42])
by slotpi15m71 (Cyrus 3.13.0-alpha0-1341-g6c10bd1c5-fm-20251013.001-g6c10bd1c) with LMTPA;
Thu, 30 Oct 2025 05:58:08 -0400
X-Cyrus-Session-Id: slotpi15m71-1761818288-1181264-2-10905896220539992579
X-Sieve: CMU Sieve 3.0
X-Spam-known-sender: yes ("Self sent message"); in-addressbook, self-send;
2A9FBB1A-0A50-11F0-953D-C6A695ACF6E2 ("Imported 20250326")
X-Spam-sender-reputation: 999 (email; noauth)
X-Spam-score: 0.0
X-Spam-hits: ALL_TRUSTED -1, BAYES_00 -1.9, ME_FROM_EQ_TO 0.01, ME_SC_SENDERREP -100,
ME_SENDERREP_ALLOW -4, SHORTCIRCUIT -0.0001, SPF_PASS -0.001,
LANGUAGES unknown, BAYES_USED user, SA_VERSION 4.0.1
X-Spam-source: IP='Unknown', Host='unk', Country='unk', FromHeader='org', MailFrom='org'
X-Spam-charsets:
X-Resolved-to: wez@wezfurlong.org
X-Delivered-to: wez@wezfurlong.org
X-Mail-from: wez@wezfurlong.org
Received: from phl-mx-07 ([10.202.2.206])
by phl-compute-02.internal (LMTPProxy); Thu, 30 Oct 2025 05:58:08 -0400
Received: from phl-mx-07.messagingengine.com (localhost [127.0.0.1])
by mailmx.phl.internal (Postfix) with ESMTP id F38B720E00E0
for <wez@wezfurlong.org>; Thu, 30 Oct 2025 05:58:07 -0400 (EDT)
Received: from mailmx.phl.internal (localhost [127.0.0.1])
by phl-mx-07.messagingengine.com (Authentication Milter) with ESMTP
id FA4D1679830.F2D1A20E00B4;
Thu, 30 Oct 2025 05:58:07 -0400
ARC-Seal: i=1; a=rsa-sha256; cv=none; d=messagingengine.com; s=fm3; t=
1761818287; b=ycwa8bnZ1tzWb6H7JnfvMbAcXQarSXzeH4FF70n897IuqJjpK5
m0OEH28pRIMClrC7MyimD9LcccWGTipSLMnEpv0KmI9vR2U6XhP4H4GRjTPllIkA
iUmAlS3sBmZTgfYSA/G1EbNaT4Nze7gnls5nRJkzxr1fj8uISFwMxkbNLam4KX/7
+LzoKHUjI73wSb163y3j6iPb4haU7pxtuBoStGBlh0iZmnM+uj1akTbJnKr7VHKS
Ei84Pwc6wiRDjGwR7L8WUNJ1jOUaxHs+9fBDf03DL/yRmLIuVo14l/vjN/GV/9Ho
ZYblFYalGQ/0vYo06nbN1AprpO02h75DX8TA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=
messagingengine.com; h=mime-version:date:from:to:message-id
:subject:content-type:content-transfer-encoding; s=fm3; t=
1761818287; bh=CuO/UH3bRHVPCZuIP5Cvk96qUDS4wL+5Fe9pIlYTsgg=; b=W
a3kfSabLIPfuoIoSAfny5UlDGvvoBePo0x/2cZgy/GMN8FVtYZVJZtZDvzuvk25B
O5zNW4x3ygfJ+jH0Y5F4GGkHXV0G2qBL+Qmr+CRZHL3dbEQOD+y55W+E0gdXxrhw
anst7erKfRpLu+aJNn6T10YTKKBwRmipOAM4IuyQQI2E8W3cp15jfInM/v+EkiGm
NV03GyAWGX+UPhs0BVqvLEN7a+PobwQQiDVLEY7NF4y5E+c810RphyVXHvPqlIF2
oTv7SCdoBEIA5Mw0F+HuY3jsK43xXbdolaoXb/u5Qdr8F/rwu3jEOlDP0awfg94e
COR4JQJdVrWjpQFxrG4Rw==
ARC-Authentication-Results: i=1; phl-mx-07.messagingengine.com;
x-csa=none;
x-me-sender=pass
policy.xms=
rzYDaZmgN376x5oNMHG94qT3s0y89wRpz7PaOSKeSVnszK_f19i0FzFocbt-07jXzmTQDndlWgz5yZX37AqB44eZE_Zhsr3TWTzd5ssnPy6whnBK6AvQPK-XDevRVZ_bz8E6Fk3RSukcnrmnOPMVHcqttFAAw27cCKjC3tNcZ2w;
x-ptr=pass smtp.helo=fout-a1-smtp.messagingengine.com
policy.ptr=fout-a1-smtp.messagingengine.com;
bimi=skipped (DMARC did not pass);
arc=none (no signatures found);
dkim=pass (2048-bit rsa key sha256) header.d=messagingengine.com
header.i=@messagingengine.com header.b=LeEj0x/z header.a=rsa-sha256
header.s=fm3;
dkim=pass (2048-bit rsa key sha256) header.d=wezfurlong.org
header.i=@wezfurlong.org header.b=ij2uTb0J header.a=rsa-sha256
header.s=fm1;
dmarc=none policy.published-domain-policy=none
policy.applied-disposition=none policy.evaluated-disposition=none
(p=none,d=none,d.eval=none) policy.policy-from=p
header.from=wezfurlong.org;
iprev=pass smtp.remote-ip=103.168.172.144
(fout-a1-smtp.messagingengine.com);
spf=pass smtp.mailfrom=wez@wezfurlong.org
smtp.helo=fout-a1-smtp.messagingengine.com
X-ME-Authentication-Results: phl-mx-07.messagingengine.com;
x-tls=pass smtp.version=TLSv1.3 smtp.cipher=TLS_AES_256_GCM_SHA384
smtp.bits=256/256;
x-vs=clean score=15 state=0
Authentication-Results: phl-mx-07.messagingengine.com;
x-csa=none;
x-me-sender=pass
policy.xms=
rzYDaZmgN376x5oNMHG94qT3s0y89wRpz7PaOSKeSVnszK_f19i0FzFocbt-07jXzmTQDndlWgz5yZX37AqB44eZE_Zhsr3TWTzd5ssnPy6whnBK6AvQPK-XDevRVZ_bz8E6Fk3RSukcnrmnOPMVHcqttFAAw27cCKjC3tNcZ2w;
x-ptr=pass smtp.helo=fout-a1-smtp.messagingengine.com
policy.ptr=fout-a1-smtp.messagingengine.com
Authentication-Results: phl-mx-07.messagingengine.com;
bimi=skipped (DMARC did not pass)
Authentication-Results: phl-mx-07.messagingengine.com;
arc=none (no signatures found)
Authentication-Results: phl-mx-07.messagingengine.com;
dkim=pass (2048-bit rsa key sha256) header.d=messagingengine.com
header.i=@messagingengine.com header.b=LeEj0x/z header.a=rsa-sha256
header.s=fm3;
dkim=pass (2048-bit rsa key sha256) header.d=wezfurlong.org
header.i=@wezfurlong.org header.b=ij2uTb0J header.a=rsa-sha256
header.s=fm1;
dmarc=none policy.published-domain-policy=none
policy.applied-disposition=none policy.evaluated-disposition=none
(p=none,d=none,d.eval=none) policy.policy-from=p
header.from=wezfurlong.org;
iprev=pass smtp.remote-ip=103.168.172.144
(fout-a1-smtp.messagingengine.com);
spf=pass smtp.mailfrom=wez@wezfurlong.org
smtp.helo=fout-a1-smtp.messagingengine.com
X-ME-VSCause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduieeifeduucetufdoteggodetrf
dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu
rghilhhouhhtmecufedttdenucgoteeftdduqddtudculdduhedmnecujfgurhepofggff
fhvffkufgtgfesthejredtredttdenucfhrhhomhepfdghvgiiucfhuhhrlhhonhhgfdcu
oeifvgiiseifvgiifhhurhhlohhnghdrohhrgheqnecuggftrfgrthhtvghrnhepgfdttd
efjedvffdthedtgeeufedtgeevkeevvedufeeivedttefhvdeludeltdeinecukfhppedu
tdefrdduieekrddujedvrddugeegnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrg
hmpehinhgvthepuddtfedrudeikedrudejvddrudeggedphhgvlhhopehfohhuthdqrgdu
qdhsmhhtphdrmhgvshhsrghgihhnghgvnhhgihhnvgdrtghomhdpmhgrihhlfhhrohhmpe
eofigviiesfigviihfuhhrlhhonhhgrdhorhhgqedpnhgspghrtghpthhtohepuddprhgt
phhtthhopeeofigviiesfigviihfuhhrlhhonhhgrdhorhhgqe
X-ME-VSScore: 15
X-ME-VSCategory: clean
X-ME-CSA: none
X-ME-Received: <xmx:rzYDaXNm-rDxQDwrK3xagr0LHNGf9mp9zpGrc_Q4TXemuEwSFq9-DA>
X-ME-Received: <xmx:rzYDaTb-H9y55mXe4CcTXVj9rIGVU5XbQGU29dNqpuv4GHO-xohwOA>
Received-SPF: pass
(wezfurlong.org: Sender is authorized to use 'wez@wezfurlong.org' in 'mfrom' identity (mechanism 'include:spf.messagingengine.com' matched))
receiver=phl-mx-07.messagingengine.com;
identity=mailfrom;
envelope-from="wez@wezfurlong.org";
helo=fout-a1-smtp.messagingengine.com;
client-ip=103.168.172.144
Received: from mailfout.phl.internal (phl-outbound-01.internal [10.202.2.181])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits))
(No client certificate requested)
by mailmx.phl.internal (Postfix) with ESMTPS id F2D1A20E00B4
for <wez@wezfurlong.org>; Thu, 30 Oct 2025 05:58:06 -0400 (EDT)
Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41])
by mailfout.phl.internal (Postfix) with ESMTP id E5C3FEC01A3
for <wez@wezfurlong.org>; Thu, 30 Oct 2025 05:58:06 -0400 (EDT)
Received: from phl-imap-15 ([10.202.2.104])
by phl-compute-01.internal (MEProxy); Thu, 30 Oct 2025 05:58:06 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=wezfurlong.org;
h=cc:content-transfer-encoding:content-type:content-type:date
:date:from:from:in-reply-to:message-id:mime-version:reply-to
:subject:subject:to:to; s=fm1; t=1761818286; x=1761904686; bh=Cu
O/UH3bRHVPCZuIP5Cvk96qUDS4wL+5Fe9pIlYTsgg=; b=ij2uTb0JGMxJvGQoT0
9FxAxNWQ113YYjX1IlhJd8oXCQVLthnji9nzjg8PQ1T39xMqp0qh0J7NTfOFl0si
yPWrrFDU3LBtMWll5XwmoC6ghavGy4rxx8uVK/MZT6zqwYzMqmhXWER0JlVDFzf9
7SkYJSwJR/sINOP776xZWTPxICxHISPd+pq5mqdKXY/4KemSXwbdF6ugIjI6rHwM
vYBF/wwiMjTTjP7uuvQTJIX+UgOUBEukKuQhOcxNo0wmWKP0xm78G8C1sq+gX6nf
6y7ildrW2AY1QUgNv5zQXho2RLT1SlkoPfThbfDw/ujuDDQaafn7kxgVID/P6trt
1+BQ==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
messagingengine.com; h=cc:content-transfer-encoding:content-type
:content-type:date:date:feedback-id:feedback-id:from:from
:in-reply-to:message-id:mime-version:reply-to:subject:subject:to
:to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=
1761818286; x=1761904686; bh=CuO/UH3bRHVPCZuIP5Cvk96qUDS4wL+5Fe9
pIlYTsgg=; b=LeEj0x/z/0dOVL2vxLMe45R5kq47+dt/yOGqeZvdMaritIeKOcG
DMNHzjiEEWGKvb19AdGuJ/ybq1DgF85W6bivYlr95/BJAz7+BBHrpfC6HYR3b/hs
Xu1YT0ksPJ0V+EGUcHrNTIMXXyHTpe2rw4FcKLxF2NX06+T3l7BDVMwitHiluQke
vc5ipeFoAL0fQrncLFMeX2eDLQ0L6W9gaxy5TKrcg4JHSGQyZm/5Y545CXKktdrg
kE1ky1c+Fat9xwJX3NgEZEmAMG7+tUPxVBWg9nVA95lyvQILDs31r6Q+vZyXopXb
2JOF5y5FGkYshq3N+nbSifQwbMMBwRb9uXw==
X-ME-Sender: <xms:rjYDafszAuHg-2bLeCrbuebWY1Pp0ubOomcYQel2e13sSrmWUJtQIQ>
<xme:rjYDabR3ljlnE-cekoa0aG9An5ar_4wwMzy6WAF1Yc0QCHCWcAANLYxpC0AFCOQE6
ITSzipJm1-Aswr873zDE9AoNwBcTTMeP0Sh6k1pT6QQ_Fpv1Q>
X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduieeifeduucetufdoteggodetrf
dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu
rghilhhouhhtmecufedttdenucgoteeftdduqddtudculdduhedmnecujfgurhepofggff
fhvffkufgtgfesthejredtredttdenucfhrhhomhepfdghvgiiucfhuhhrlhhonhhgfdcu
oeifvgiiseifvgiifhhurhhlohhnghdrohhrgheqnecuggftrfgrthhtvghrnhepgfdttd
efjedvffdthedtgeeufedtgeevkeevvedufeeivedttefhvdeludeltdeinecuvehluhhs
thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepfigviiesfigviihfuh
hrlhhonhhgrdhorhhgpdhnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhuthdp
rhgtphhtthhopeifvgiiseifvgiifhhurhhlohhnghdrohhrgh
X-ME-Proxy: <xmx:rjYDaXRjNrRbZFF-zGWqlpNMv-fx-ymZDLzQk8xzJq0L3GtIWQfgNQ>
<xmx:rjYDafukEobSKGzdrNeZRaQc0dKnSwmYlzyw35j2tsW2l3FbeC2BFw>
<xmx:rjYDaScssBPX1Pz3w-xNjSGk7V7TLwPxJoXFOE4g8HosqZ0Ww3SJIA>
<xmx:rjYDacJXF5igyBZRR3aDjaL26YlB1YNRtq0NuVdR736vo6hqZIr0EQ>
<xmx:rjYDaRbo0rq7zZ8c61Mri_2W4bAMvmQhFJCzp7W0s59p5JDi1h6IX28->
Feedback-ID: i26884094:Fastmail
Received: by mailuser.phl.internal (Postfix, from userid 501)
id 8D1B3780076; Thu, 30 Oct 2025 05:58:06 -0400 (EDT)
X-Mailer: MessagingEngine.com Webmail Interface
MIME-Version: 1.0
Date: Thu, 30 Oct 2025 09:57:45 +0000
From: "Wez Furlong" <wez@wezfurlong.org>
To: "Wez Furlong" <wez@wezfurlong.org>
Message-Id: <296b6703-4af3-4d92-b5ad-dde20b9ff61d@app.fastmail.com>
Subject: testing arc
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
another test for arc
+227
View File
@@ -0,0 +1,227 @@
Return-Path: <wez@kumomta.com>
Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42])
by slotpi15m71 (Cyrus 3.13.0-alpha0-1341-g6c10bd1c5-fm-20251013.001-g6c10bd1c) with LMTPA;
Thu, 30 Oct 2025 05:42:59 -0400
X-Cyrus-Session-Id: slotpi15m71-1761817379-4093319-2-8826037471221011994
X-Sieve: CMU Sieve 3.0
X-Spam-known-sender: yes ("Address wez@kumomta.com in From header is in addressbook");
in-addressbook; 42641a0a-c8ba-4e19-870f-1584b9a291f5 ("Autosaved")
X-Spam-sender-reputation: 1000 (email)
X-Spam-score: 0.0
X-Spam-hits: BAYES_00 -1.9, ME_SC_SENDERREP -100, ME_SENDERREP_ALLOW -4,
RCVD_IN_DNSWL_NONE -0.0001, RCVD_IN_MSPIKE_H2 0.001,
SHORTCIRCUIT -0.0001, SPF_HELO_NONE 0.001, SPF_PASS -0.001,
LANGUAGES unknown, BAYES_USED user, SA_VERSION 4.0.1
X-Spam-source: IP='209.85.222.174', Host='mail-qk1-f174.google.com', Country='US',
FromHeader='com', MailFrom='com'
X-Spam-charsets:
X-Resolved-to: wez@wezfurlong.org
X-Delivered-to: wez@wezfurlong.org
X-Mail-from: wez@kumomta.com
Received: from phl-mx-04 ([10.202.2.203])
by phl-compute-02.internal (LMTPProxy); Thu, 30 Oct 2025 05:42:59 -0400
Received: from phl-mx-04.messagingengine.com (localhost [127.0.0.1])
by mailmx.phl.internal (Postfix) with ESMTP id 740A61380093
for <wez@wezfurlong.org>; Thu, 30 Oct 2025 05:42:58 -0400 (EDT)
Received: from mailmx.phl.internal (localhost [127.0.0.1])
by phl-mx-04.messagingengine.com (Authentication Milter) with ESMTP
id 45C04F27DE4.191D31380068;
Thu, 30 Oct 2025 05:42:58 -0400
ARC-Seal: i=1; a=rsa-sha256; cv=none; d=messagingengine.com; s=fm3; t=
1761817378; b=xiPk/Etps3qMOwoWhXiJyxGxMtV3XC0U6OtYQX1ORnaq8Bj7jH
/OgegZSo4PH1FXl4kuWfqYvVszPrSXLAtxybz2usLE37d2NO531QeoWEHGQK39bI
acPCAJV3NzD5GbbtaHI7eCzO0H1GKhEn07yfGbo/VTWalVNXHlXov2mySzEJl/lE
Q6do2hF7DbBif5ChICfGmWu/xS90t13D9EYg+eMPmg7QL719nJ66u7txtMCzXQ01
ReDn9Xk+/kqwXPFh/6MWvJztPs3j8goi3qHo5gIh7Tj/S7yhGNpDz1lJwlJFrJXW
lv+TEnKLfEZ5r+bo9V+DO1RIrHNvrLSs6YFA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=
messagingengine.com; h=mime-version:date:from:to:message-id
:subject:content-type:content-transfer-encoding; s=fm3; t=
1761817378; bh=B4Sdwm/LsvO9X1e98hS643RXXxvU5oFkgjJHmUF8s3k=; b=X
7ABn3lCWF9ZaYd1xPhmzqJFHGCKOP2OJUbmH7osxevxAdHiSkSyeU3NS+mYbYNXZ
t8UlZfhdWlX+EBQcbr85qAnYwACjqaCBaX2kIJa/6SRWVS17f1ZLuUX5gWH4lv9l
nfoigfvAJWG50gQ51BFKiIthzLg/vWRpgGHh/RyMmmVnQIrPLkar/0rj4f1HQaaO
pTUhrAY9uVzXmQT4m/oGt/m05k+GPTGmQq6AHs3QHxmNRDGcGfdgmP3laHwIN4Y7
XJ19+f8ZGmfKRCr0scORyXO9iDYbFjnfu7AUnNrBXXZRO1vOKXgV/jL0cdP4Ux2l
wabpV6OSsLihL9RSJjVdw==
ARC-Authentication-Results: i=1; phl-mx-04.messagingengine.com;
x-csa=none;
x-me-sender=fail;
x-ptr=pass smtp.helo=mail-qk1-f174.google.com
policy.ptr=mail-qk1-f174.google.com;
bimi=pass header.d=kumomta.com header.selector=default;
arc=none (no signatures found);
dkim=pass (1024-bit rsa key sha256) header.d=kumomta.com
header.i=@kumomta.com header.b=ZUrWtUUp header.a=rsa-sha256
header.s=gw1024;
dmarc=pass policy.published-domain-policy=reject
policy.applied-disposition=none policy.evaluated-disposition=none
(p=reject,d=none,d.eval=none) policy.policy-from=p
header.from=kumomta.com;
iprev=pass smtp.remote-ip=209.85.222.174 (mail-qk1-f174.google.com);
spf=pass smtp.mailfrom=wez@kumomta.com
smtp.helo=mail-qk1-f174.google.com
X-ME-Authentication-Results: phl-mx-04.messagingengine.com;
x-tls=pass smtp.version=TLSv1.3 smtp.cipher=TLS_AES_256_GCM_SHA384
smtp.bits=256/256;
x-vs=clean score=0 state=0
Authentication-Results: phl-mx-04.messagingengine.com;
x-csa=none;
x-me-sender=fail;
x-ptr=pass smtp.helo=mail-qk1-f174.google.com
policy.ptr=mail-qk1-f174.google.com
Authentication-Results: phl-mx-04.messagingengine.com;
bimi=pass header.d=kumomta.com header.selector=default
Authentication-Results: phl-mx-04.messagingengine.com;
arc=none (no signatures found)
Authentication-Results: phl-mx-04.messagingengine.com;
dkim=pass (1024-bit rsa key sha256) header.d=kumomta.com
header.i=@kumomta.com header.b=ZUrWtUUp header.a=rsa-sha256
header.s=gw1024;
dmarc=pass policy.published-domain-policy=reject
policy.applied-disposition=none policy.evaluated-disposition=none
(p=reject,d=none,d.eval=none) policy.policy-from=p
header.from=kumomta.com;
iprev=pass smtp.remote-ip=209.85.222.174 (mail-qk1-f174.google.com);
spf=pass smtp.mailfrom=wez@kumomta.com
smtp.helo=mail-qk1-f174.google.com
BIMI-Indicator: PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Inllcy
I/Pgo8c3ZnIGJhc2VQcm9maWxlPSJ0aW55LXBzIiB2ZXJzaW9uPSIxLjIiIHZpZXdCb3g9
IjAgMCAxMDgwIDEwODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+Ci
AgPHRpdGxlPmJpbWktc3ZnLXRpbnktMTItcHM8L3RpdGxlPgogIDxwYXRoIGlkPSJPcmFu
Z2VfQnViYmxlIiBkPSJNMjA0LjM5LDMyOS4yMWMtLjA1LTgxLjAyLDY1LjU5LTE0Ni43My
wxNDYuNjEtMTQ2Ljc3bDU1NC4wNy0uMzFjODEuMDItLjA1LDE0Ni43Myw2NS41OSwxNDYu
NzcsMTQ2LjYxbC4xNiwyOTMuMzhjLjA0LDgwLjk2LTY1LjY1LDE0Ni43My0xNDYuNjEsMT
Q2Ljc3bDUwLjk2LDE0OS43MWMyLjIzLDYuNTUtNS4xNCwxMi4xOS0xMC44OCw4LjMybC0y
MzQuMzQtMTU3LjkyLTM1OS44LjJjLTgxLjAxLjA1LTE0Ni43Mi02NS41OS0xNDYuNzctMT
Q2LjYxbC0uMTYtMjkzLjM4WiIgZmlsbD0iI2Y4YTYyOCIgZmlsbC1ydWxlPSJldmVub2Rk
IiBzdHJva2U9IiNmOGE2MjgiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZH
RoPSIxNiIvPgogIDxwYXRoIGlkPSJFbnZlbG9wZSIgZD0iTTg4OS44OSw0MzRjMC04MS4y
OS02NS45LTE0Ny4xOS0xNDcuMTktMTQ3LjE5SDE4OS42M2MtODEuMywwLTE0Ny4yLDY1Lj
ktMTQ3LjIsMTQ3LjJ2MjkyLjg3YzAsODAuNzMsNjUuMzUsMTQ2LjMxLDE0NS45OSwxNDYu
NjkuMzQsMCwuNTkuMzQuNDguNjZsLTU3LjA3LDE2Ny45NmMtLjE2LjQ2LjM2Ljg2Ljc2Lj
U4bDI1MC42Ny0xNjkuMTJjLjA4LS4wNi4xOC0uMDkuMjgtLjA5aDM1OS4xNGM4MS4zLDAs
MTQ3LjItNjUuOSwxNDcuMi0xNDcuMnYtMjkyLjM3WiIgZmlsbD0iI2ZmZiIgZmlsbC1ydW
xlPSJldmVub2RkIiBzdHJva2U9IiNmMTg5MTUiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIg
c3Ryb2tlLXdpZHRoPSI0MCIvPgogIDxwYXRoIGlkPSJUb3BfQXJyb3ciIGQ9Ik0xMDguMD
IsMjQxLjA3czYzLjcxLTEyMy41OSwxNDYtMTQ5Ljc1YzcyLjg4LTIzLjE2LDI4OS42OC0x
My4wOSwyODkuNjgtMTMuMDlsLTM5LjE1LTQ0LjIzLDM5LjE1LDQ0LjIzLTM0LjMsMzguMz
QiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2Y2Yzk2MiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5k
IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjQwIi8+CiAgPHBhdG
ggaWQ9IkJvdHRvbV9BcnJvdyIgZD0iTTgyNi4xMiw5NjQuOTljLTcyLjg4LDIzLjE2LTM1
Mi4xNCwxNS43Mi0zNTIuMTQsMTUuNzJsMzkuMTUsNDQuMjQtMzkuMTUtNDQuMjQsMzQuMy
0zOC4zNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZjZjOTYyIiBzdHJva2UtbGluZWNhcD0i
cm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iNDAiLz4KIC
A8cG9seWxpbmUgaWQ9IkVudmVsb3BlX0xpZCIgcG9pbnRzPSI4Ny45OSAzMzEuNzUgNDYx
LjMzIDY3NC40MSA4NDcuNzcgMzMxLjA4IiBmaWxsPSJub25lIiBzdHJva2U9IiNmMTg5MT
UiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ry
b2tlLXdpZHRoPSI0MCIvPgo8L3N2Zz4=
BIMI-Location: v=BIMI1;
l=https://kumomta.com/hubfs/bimi-svg-tiny-12-ps.svg
X-ME-VSCause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduieeivdejucetufdoteggodetrf
dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu
rghilhhouhhtmecufedttdenucenucfjughrpefoggffhffvkffutgfgsehtjeertdertd
dtnecuhfhrohhmpedfhggviicuhfhurhhlohhnghdfuceofigviieskhhumhhomhhtrgdr
tghomheqnecuggftrfgrthhtvghrnhepfffgtdfhgfeiheefteeghfeklefggfetheehle
duieeltdekueeivdduheeukeefnecukfhppedvtdelrdekhedrvddvvddrudejgedpuddt
fedrudeikedrudejvddrvddtudenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmh
epihhnvghtpedvtdelrdekhedrvddvvddrudejgedphhgvlhhopehmrghilhdqqhhkuddq
fhdujeegrdhgohhoghhlvgdrtghomhdpmhgrihhlfhhrohhmpeeofigviieskhhumhhomh
htrgdrtghomheqpdhnsggprhgtphhtthhopedupdhrtghpthhtohepoeifvgiiseifvgii
fhhurhhlohhnghdrohhrgheq
X-ME-VSScore: 0
X-ME-VSCategory: clean
X-ME-CSA: none
X-ME-Received: <xmx:ITMDadu5rhJICsd39G_PeKMkvMx6Zc9xDjCxlnNotmOYonE5L15pxA>
X-ME-Received: <xmx:ITMDaQU_vE_LQ-8tp2jclyuZ8b112gZ6SAKSMyw9qooGi03lT90kxA>
Received-SPF: pass
(kumomta.com: Sender is authorized to use 'wez@kumomta.com' in 'mfrom' identity (mechanism 'include:_spf.google.com' matched))
receiver=phl-mx-04.messagingengine.com;
identity=mailfrom;
envelope-from="wez@kumomta.com";
helo=mail-qk1-f174.google.com;
client-ip=209.85.222.174
Received: from mail-qk1-f174.google.com (mail-qk1-f174.google.com [209.85.222.174])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
(No client certificate requested)
by phl-mx-04.messagingengine.com (Postfix) with ESMTPS id 191D31380068
for <wez@wezfurlong.org>; Thu, 30 Oct 2025 05:42:57 -0400 (EDT)
Received: by mail-qk1-f174.google.com with SMTP id af79cd13be357-8a9b1cb735bso80565385a.1
for <wez@wezfurlong.org>; Thu, 30 Oct 2025 02:42:57 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=kumomta.com; s=gw1024; t=1761817375; x=1762422175; darn=wezfurlong.org;
h=content-transfer-encoding:subject:message-id:to:from:date
:mime-version:feedback-id:from:to:cc:subject:date:message-id
:reply-to;
bh=B4Sdwm/LsvO9X1e98hS643RXXxvU5oFkgjJHmUF8s3k=;
b=ZUrWtUUpDLtUvfj2pBptKB+fhkGJyYOup7W3u9f1AQCZMplp+gZF29+d8Mpej01bgt
YwBrL3tVYThSNr9lbCGfgxU0yFMAZJqsGmPqibtbOOAwHYLariRqVvwCAbfIBsOqdFbp
SflMWfIv04xyfmc9J+NIxjglWuFq8avQMWDQc=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1761817375; x=1762422175;
h=content-transfer-encoding:subject:message-id:to:from:date
:mime-version:feedback-id:x-gm-message-state:from:to:cc:subject:date
:message-id:reply-to;
bh=B4Sdwm/LsvO9X1e98hS643RXXxvU5oFkgjJHmUF8s3k=;
b=fY9bkPqG3Lp877M8ge2aaX5GvdOnE8FxQCrJ++8gf9Rg7i3d9QvhaGoS4K23sGgcji
dCGlwZH1XRzb+8uIe3vXSjBafz+YAo1QvP83ATA1IZ9Bx277Ir6x3rOGbkmt8G03ZDpq
MJeQ0I/swrKGAcum2nUDBxQVdAEoRrXGWumIJyfZHDhfBu40qHzPOYkoOuxB3C9RMQeE
r6FKEqcYJJ367HBnlt+DtQCPw4hwxjHmiC1AS6NcYUR379VhPMLpnZvnDVo0hvYoxzgw
/0JF6Ms6/28Vwq4MwPeTyj90qbYwsHUoN5jTc11twGEPoVf5tCm7p9NbYrTSjGL2BYGx
DZ9Q==
X-Gm-Message-State: AOJu0YwxTPh5798JYSLr03+uMmd2skNm2eU20oA1hYLShW4imaKmP9zt
h34sHKaKcQmA6gKu5RJ3WbXrWptFGl46n6CbKkWLuiH1ynfbpeVUKcnvTCfvrAeadJ8LPtxv7t8
OIiWV
X-Gm-Gg: ASbGncs4LvTcjUTYbJxeMzeDS2YKSVJrBMHsqoKLsfrMjOXAnOKPK43tSxuocGm/Y7N
qp4R9JImOxho5wATSsOFrjj/Sk5EVxiAZrKtcB4I9NCP0g/vuwKHNGkFJFGDeR+F0k4YKe4RIL8
Akr+ylkKbwy9JV2r2ghlpBVbJMygyFqLJqEvCNIaXdGKd+AgW1hEriN7h9G9UQ3c1hDVqVQsISF
PDlYuxyxscyb1jbZd9Ydg96D3RhJLY/KGb8zj4R0Xmt6IyEeF5xqnTWZcuEFZmgUZAZh8FdT2sh
QyK2uHaI+I+ubPaB5AN8FFjWHVeXIkYOpyXO6iKtAl3oUrePJaT34kOYvfX9fGUlQqywLZduRjN
GJ0+hgGOqijVM2ImUhBmbpgpFWox99Oqvb0qkyjoGRJ7EknwcM5w6u3nmjtxL4aPaOm75WL5aMB
si1kc7bQGVD+xCC/9Jcng/ClWnZxs1aUPSjUcu8+DL6ymwgUvlpzSrFwPsO4A=
X-Google-Smtp-Source: AGHT+IHc20q+08CNfpTLtnwhY38hLyGsYAxu380LFBLlj0ZePkf/hBLRiNhju9rAxFY0JhEY+H8tWw==
X-Received: by 2002:a05:620a:394f:b0:8a2:a5b2:e3bc with SMTP id af79cd13be357-8aa2ea0cac4mr326831385a.89.1761817375491;
Thu, 30 Oct 2025 02:42:55 -0700 (PDT)
Received: from fauth-a2-smtp.messagingengine.com (fauth-a2-smtp.messagingengine.com. [103.168.172.201])
by smtp.gmail.com with ESMTPSA id af79cd13be357-89f26073cedsm1231115385a.52.2025.10.30.02.42.55
for <wez@wezfurlong.org>
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Thu, 30 Oct 2025 02:42:55 -0700 (PDT)
Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41])
by mailfauth.phl.internal (Postfix) with ESMTP id E6F78F40074
for <wez@wezfurlong.org>; Thu, 30 Oct 2025 05:42:54 -0400 (EDT)
Received: from phl-imap-15 ([10.202.2.104])
by phl-compute-01.internal (MEProxy); Thu, 30 Oct 2025 05:42:54 -0400
X-ME-Sender: <xms:HjMDacOgAAJ7Mvc3xEulnDQhP5tiKG0Y_R56cAnSzrB1YymmFQUr6A>
<xme:HjMDadx4BpQ8oOoMzz3vEOQxCxXYYfWF_oiCfpolzhTUOdVtS9Ma5Lg_7fLy8Mca4
E-ryIIhuNlduKgDjEo1Ai61idNp9hIzg2646OZOdES3w6LkRA>
X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduieeivdekucetufdoteggodetrf
dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu
rghilhhouhhtmecufedttdenucenucfjughrpefoggffhffvkffutgfgsehtjeertdertd
dtnecuhfhrohhmpedfhggviicuhfhurhhlohhnghdfuceofigviieskhhumhhomhhtrgdr
tghomheqnecuggftrfgrthhtvghrnhepfffgtdfhgfeiheefteeghfeklefggfetheehle
duieeltdekueeivdduheeukeefnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghm
pehmrghilhhfrhhomhepfigviidomhgvshhmthhprghuthhhphgvrhhsohhnrghlihhthi
dqudehheekvddvvdeifedquddvtdehfeejvdehqdifvgiipeepkhhumhhomhhtrgdrtgho
mhesfigviihfuhhrlhhonhhgrdhorhhgpdhnsggprhgtphhtthhopedupdhmohguvgepsh
hmthhpohhuthdprhgtphhtthhopeifvgiiseifvgiifhhurhhlohhnghdrohhrgh
X-ME-Proxy: <xmx:HjMDaTyheut7TUdvYTLSIGCcjiibdZpGp7cjBgM28OQS3YwBaj0QJw>
<xmx:HjMDaSOjAsIHAYsXou74rBZTTakYVL3OpNwiqUM5VvMnWyC0ebH70Q>
<xmx:HjMDaS9TFzRDPkpt8JfoocmmfzvMHvAzE99vsgUXSY4xr03JewsqMg>
<xmx:HjMDaSomdPzedkZHR1k8SQMw9XFtAGqCCPBB9FaVgiL3I5QmyJxM5Q>
<xmx:HjMDaU7xmhOUd54mxjV9ciS0e2Wuxr2kEX4jkgZ2KESxMXv84ic2SRIk>
Feedback-ID: i9d6e48e7:Fastmail
Received: by mailuser.phl.internal (Postfix, from userid 501)
id B9A12780076; Thu, 30 Oct 2025 05:42:54 -0400 (EDT)
X-Mailer: MessagingEngine.com Webmail Interface
MIME-Version: 1.0
Date: Thu, 30 Oct 2025 09:42:34 +0000
From: "Wez Furlong" <wez@kumomta.com>
To: "Wez Furlong" <wez@wezfurlong.org>
Message-Id: <1a30158a-fd9e-4a2c-a052-362856fec025@app.fastmail.com>
Subject: testing to see how arc turns out
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
This is a test
-3
View File
@@ -1,3 +0,0 @@
2022._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; t=y:s; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyrnZAH3hf+hp53o5gz7CfRNHme6iCW8koRNgV3bDiZcPxoC9nhjyMPWD/rizalhykziEaz0WBodeSalGjTXqH6yrlUobekxJO9UmzKrIpWCfsdbHLfTHCO6kk4JLeKs+hRs+/v2tPvcVnGD/A76cBXI5ksfrtUzeTlsPDYDSbafgBXvi9CTMAEUd3iB+HtjQbNuQJbNnZrLotB"
"PGjuFTcUKCafCmFu31K6ZMDnOJadfoZO8cClti53V2DLz7NDO3kZIGiAHsNcptcZN3MnHRhMl2Buy5vdi4lfDXhjl5ozhb8MeY0LAJikJm9RUQ3GcHBdvqchnz53gcNXIApMuK2QIDAQAB" ) ; ----- DKIM key 2022 for example.com
+1 -1
View File
@@ -1058,7 +1058,7 @@ fn keyword(input: Span) -> IResult<Span, String> {
context(
"keyword",
map(
take_while1(|c: char| c.is_ascii_alphanumeric() || c == '+'),
take_while1(|c: char| c.is_ascii_alphanumeric() || c == '+' || c == '-'),
|s: Span| s.to_string(),
),
)(input)