27 May 2026
A large release. The headline is RFC 8301 enforcement: RSA-SHA1 is now completely disabled for both signing and verification, with a new On-WeakAlgorithm option to control what happens to messages that carry such a signature (check the man-page).
Alongside that are new features; better systemd integration; and a substantial number of bug fixes that surfaced through an audit of OpenDKIM changes (PhoenixDKIM was forked from OpenDKIM); a completed pass of -Wconversion / -Wsign-conversion remediation; and systematic testing under Clang, its sanitisers, and the extended CMake hardening flag set.
RSA-SHA1 verification is now refused unconditionally, in line with RFC 8301 (Cryptographic Algorithm and Key Usage Update to DomainKeys Identified Mail (DKIM)). The daemon sets DKIM_LIBFLAGS_NOSHA1VERIFY on every startup; any rsa-sha1 signature is permanently marked as a weak-algorithm failure before any DNS lookup or cryptographic work takes place. RSA-SHA1 signing is also disabled.
A new On-WeakAlgorithm configuration option controls the milter disposition for messages carrying an rsa-sha1 signature: neutral (default — deliver with a neutral result), reject, quarantine, tempfail, or discard. The value accept is rejected at configuration load time.
New CheckSigningTable configuration option and -g / -G command-line flags. When enabled, the daemon verifies that the sender address appears in the signing table before applying a signature, so a misconfigured table produces a logged diagnostic rather than a silently unsigned message.
opendkim-genzone gains a -s flag that extends DNS zone output to cover subdomains when used with -d. Zone output is now reproducible: records are sorted and contain no timestamp-dependent content.
The KeyTable now accepts an optional fourth field specifying the signing algorithm (e.g. ed25519). Different keys in the same table may use different algorithms.
systemd integration:
Type=notify readiness signalling — the daemon calls sd_notify(3) after binding its socket, so service dependencies activate only once PhoenixDKIM is ready to accept connections.
Watchdog keep-alive — a background thread sends WATCHDOG=1 pings on the configured WatchdogSec interval.
Service hardening directives added to the systemd unit (PrivateTmp, ProtectSystem, CapabilityBoundingSet, and others).
opendkim -V now prints the full build configuration: enabled optional features, library versions, and compile-time flags. Development builds embed the git commit hash in the version string.
A DKIM_FEATURE_ED25519 capability flag has been added so callers can test for Ed25519 support at run time. New unit tests t-test204 and t-test205 provide multi-key signing coverage.
Removed K&R __P() portability wrappers throughout the codebase. A C89 prototype-aware compiler is now assumed.
Removed the smfi_insheader() compatibility shim for sendmail < 8.13.0.
Removed the dead conf_singleauthres configuration field.
dkim_sign() now correctly emits the l= body-length tag when a length is supplied. A missing final CRLF is no longer rejected when the l= tag is in use.
The header field-body character validation always returned “valid” due to a tautology in the comparison; it now correctly rejects out-of-range characters.
Fixed an assert crash in dkim_canon_selecthdrs when all header fields are skipped.
Fixed operator precedence in the DKIM_SIG_CHECK macro.
odkim.del_header() now deletes the correct indexed instance rather than always the first occurrence.
The milter capabilities mask is now declared correctly for FinalPolicyScript Lua hooks.
NoHeaderB now correctly suppresses header.b extraction from the Authentication-Results output.
authserv-id and job-id values are now quoted in Authentication-Results output as required by RFC 8601.
Authentication-Results key tag fields now use comma as the separator, not semicolon.
Authentication-Results headers with a no-result entry are now accepted as valid syntax.
DNAME resource records are now skipped when parsing DNS answers for both DKIM key lookups and DKIM failure reports.
The libunbound resolver context now loads /etc/resolv.conf by default, matching the behaviour of the standard system resolver.
Fixed several memory leaks and an orphaned-list bug in key lookup code (issue #272).
endpwent() is now called on all early return paths from key safety checks (issue #198).
Fixed a stack overflow in miltertest when REPLBODY data exceeded the response buffer.
dkimf_lua_writer is now guarded against the end-of-dump convention introduced in Lua 5.5.
Many further fixes to key handling, DNS resolution, Authentication-Results formatting, miltertest, and the Lua hook interface. See the full release notes for the complete list.
PhoenixDKIM shares its lineage with OpenDKIM, which has recently started to receive maintenance again! We periodically review fixes made there and assess each one against our codebase. A number of those fixes were applicable here — some landed as-is, others were adapted to account for code paths that have since diverged — and are reflected in the bug fixes above.
As the two code bases continue to diverge, not every OpenDKIM fix translates directly; in those cases the underlying issue was assessed independently and addressed in a manner suited to our code. The audit nonetheless remains a valuable source of known issues and we intend to keep conducting it on a regular basis.
A substantial portion of the fixes in this release were surfaced by building and testing under a wider set of compilers and analysis tools:
Clang build. Compiling with Clang in addition to GCC exposes a distinct set of diagnostics. Several correctness issues — including sign-compare warnings, implicit-conversion warnings unique to Clang, and const-qualification problems — were found and fixed this way.
Clang sanitisers. Builds with AddressSanitizer (ASan) and UndefinedBehaviorSanitizer (UBSan) caught errors, undefined behaviour, and reads from uninitialised memory that are invisible to a normal build. Several of the bug fixes above were discovered through sanitiser runs.
CMake hardening and warning flags. The build system carries an extended set of optional warning and hardening flags (-Wconversion, -Wsign-conversion, -Wcast-align, stack protectors, _FORTIFY_SOURCE, and others) that are off by default in most projects. Enabling these systematically revealed the conversion and sign-compare issues addressed in earlier betas, as well as several of the correctness fixes in this one.
-Wconversion and -Wsign-conversion warnings have been addressed systematically across libopendkim, the daemon, miltertest, and the test suite. The work covered signed/unsigned arithmetic, implicit narrowing conversions, integer type mismatches at function call boundaries, and byte-extraction casts. No -Wconversion or -Wsign-conversion diagnostics remain in the default build configuration.