From 6e33cfb59d22fff20dbf1ee429308e1587c62ab3 Mon Sep 17 00:00:00 2001 From: David Dreschner Date: Tue, 13 Jan 2026 17:21:57 +0100 Subject: [PATCH] fix: Make c= flag optional, remove requirement of two canonical rules and fix broken raw message for c=simple --- src/DKIM.php | 8 ++++---- src/Validator.php | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/DKIM.php b/src/DKIM.php index 616dc38..7481b14 100644 --- a/src/DKIM.php +++ b/src/DKIM.php @@ -82,7 +82,7 @@ abstract class DKIM * * @throws DKIMException */ - protected function canonicalizeHeaders(array $headers, string $style = 'relaxed'): string + protected function canonicalizeHeaders(array $headers, string $style): string { if (count($headers) === 0) { throw new DKIMException('Attempted to canonicalize empty header array'); @@ -124,7 +124,7 @@ abstract class DKIM * * @return string */ - protected function canonicalizeBody(string $body, string $style = 'relaxed', int $length = -1): string + protected function canonicalizeBody(string $body, string $style, int $length = -1): string { if ($body === '') { return self::CRLF; @@ -245,7 +245,7 @@ abstract class DKIM 'unfolded' => $currentHeaderValue, 'decoded' => self::rfc2047Decode($currentHeaderValue), 'rawarray' => $currentRawHeaderLines, - 'raw' => implode(self::CRLF . ' ', $currentRawHeaderLines), //Refold lines + 'raw' => implode(self::CRLF, $currentRawHeaderLines), //Refold lines ]; } $currentHeaderLabel = $matches[1]; @@ -257,7 +257,7 @@ abstract class DKIM } //This is a folded continuation of the current header $currentHeaderValue .= $matches[1]; - $currentRawHeaderLines[] = $matches[1]; + $currentRawHeaderLines[] = $matches[0]; } ++$headerLineIndex; if ($headerLineIndex >= $headerLineCount) { diff --git a/src/Validator.php b/src/Validator.php index fc558c0..62b7340 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -83,8 +83,24 @@ class Validator extends DKIM ]; } - //Validate canonicalization algorithms for header and body - [$headerCA, $bodyCA] = explode('/', $dkimTags['c']); + //Validate optional canonicalization algorithms for header and body + //Use simple/simple as default unless defined differently + $headerCA = 'simple'; + $bodyCA = 'simple'; + + if (array_key_exists('c', $dkimTags)) { + $containsBodyAndHeaderAlgorithm = strpos($dkimTags['c'], '/') !== false; + + if ($containsBodyAndHeaderAlgorithm) { + $rules = explode('/', $dkimTags['c']); + + $headerCA = $rules[0]; + $bodyCA = $rules[1]; + } else { + $headerCA = $dkimTags['c']; + } + } + if ($headerCA !== 'relaxed' && $headerCA !== 'simple') { $output[$signatureIndex][] = [ 'status' => 'PERMFAIL', @@ -298,6 +314,7 @@ class Validator extends DKIM $host = sprintf('%s._domainkey.%s', $selector, $domain); $textRecords = dns_get_record($host, DNS_TXT); + if ($textRecords === false) { return false; } -- 2.43.0