Releases: maksimtech/mailradar
Release list
MailRadar 2026.41
Fixed
-
The report no longer ends with a traceback. Rich wraps
sys.stdoutin a
FileProxywhile a spinner runs and restores the stream without flushing it, so
a partial line sat in that buffer until the proxy was garbage-collected — often
during interpreter shutdown, where the message is
ImportError: sys.meta_path is None. It appeared after a completed analysis, on
a terminal only, and looked like the software failing at the worst possible
moment. All eight spinners now flush both streams before they stop. -
One pull request per CodeQL upgrade, not four. The four
codeql-action
steps are pinned to a commit here, and Dependabot treats each path as its own
dependency: on 2026-09-29 it opened #18, #19, #21 and #22 for the same
4.38.1 → 4.38.2 bump, and every one failed with "Loaded a configuration file for
version '4.38.1', but running version '4.38.2'" — each moved one step and left
three behind, while CodeQL requires them to match. All four are on 4.38.2 now,
and agroupsentry keeps them moving together. mailradar was the only Radar
exposed: the other four track the moving@v4tag, which hides the skew.
Added
- A CI gate that refuses. Every other security workflow reports:
snyk.yml
carriescontinue-on-error, CodeQL and Docker Scout upload SARIF, and
SonarCloud decides its quality gate after the job has already succeeded. On
2026-09-29 all of them were green while ten high-severity alerts were open.
security-posture.ymlreads what they published and fails when a blocking
finding has nobody's name against it;SECURITY-EXCEPTIONS.tomlrecords the
accepted ones, each with a reason and a review date.sonarcloud.ymlnow waits
for its own quality gate, without which a red gate is a green job.
Changed
- The prose is in English throughout. The quoted law stays in Italian, because
that is the language it is read in.
MailRadar 2026.40
Changed
-
Nothing in the shipped package.
mailradar/is byte-identical to
2026.09.12: no behaviour changes, no fixes, nothing to upgrade for. This
version exists because the five Radar restarted from a common baseline, and a
baseline that skips whoever had nothing to say would not be one. It is said
here rather than left to be guessed from an empty diff. -
Baseline: the five Radar restart from a common number. They had drifted to
.32, .12, .11, .6 and .3 of the same generation, which left the shared part of
the version meaning nothing at all. The highest count in the suite was taken,
rounded up for headroom, and every Radar starts again from 2026.40. From here
the count belongs to each Radar again, and something urgent gets a third
segment on top: 2026.40.1 before 2026.41. -
The workflow named Tests now runs the tests. It contained no pytest
invocation: it installed the package and ran three CLI commands, two of them
against a live domain, so the check required on every pull request depended on
DNS and on somebody else's mail server. The suite was running inside
sonarcloud.yml, on 3.12 only, which meant the four-version matrix here was
proving thatmailradar --helpexits zero on four versions. -
PyYAML is declared. The tests read the workflow files and had been borrowing
it frommutmut->libcst, which on Python 3.13 requirespyyaml-ft
instead — a fork that installs no module calledyaml.
MailRadar 2026.09.12
Fixed
mailradar batchreads its list of domains as UTF-8. It used a bare
open(file), so the locale chose the encoding. An internationalised domain is
the ordinary case here, not an exotic one —società.itandmüller.deare
both registrable — and read through cp1252 the query went to a domain that
does not resolve, reported as though it had been the one asked for. Three more
defects in the same four lines: a byte order mark, which Notepad writes by
default, became part of the first domain; anOSErrorthat is not
FileNotFoundErrorescaped as a traceback; and#was tested against the
unstripped line, so an indented comment was queried as a domain.- One
GPGResult, not two. The class was declared in bothchecker.pyand
gpg.py, and the two were not the same:gpg.py's carries afingerprint
field the other lacked. Sincelookup_gpgreturnsgpg.py's, a scanned
DomainReportand a default-built one held different shapes in the same
field. The duplicate is removed. - An unverifiable law now says what it costs. The report warned that an act
could not be fetched and separately printedSHA256: non disponibileagainst
each citation, with nothing joining the two, so a missing hash read as a
defect in the hashing. It is not: with no verified text there is nothing to
hash. MAILRADAR_HOMEis no longer taken literally.~/cachemade a directory
named~, a relative value followed the working directory so the cache
stopped being one cache, and" "became a directory name._discover_via_websitedeclaredextra_subdomains: list[str]and defaulted
it toNone. The GPG lookup now pairs addresses with results under
strict=True:executor.mapyields one result per input, so the lengths are
equal by construction, and this checks it rather than assuming it.
Changed
- ruff, mypy, hypothesis and mutmut are development dependencies, with a
Qualityworkflow running ruff and mypy on every push and pull request, and a
weekly, non-blocking mutation run. - Fifteen new properties checked against generated input: the DMARC and BIMI tag
parsers read a string a domain owner writes by hand, and the email extractor is
checked against its near-misses —example.communityand
example.com.evil.orgmust not matchexample.com. - A contract test refuses any code in this repository that lets the locale
choose a text encoding. - Every string the tool writes itself is now in English, which the
CHANGELOGs already were. The report's section isProvisions appliedrather
thanNorme applicate, and finding titles, scope notes, evidence lines and
the release script's messages follow. What the tool quotes is unchanged: a
provision's text is fetched from the official Italian version of each act and
hashed, so translating it would change every SHA-256 in every cache and report
"the law changed" for every citation on the next run, for nothing.
MailRadar 2026.09.9
Added
--versionoption:mailradar --versionprintsMailRadar <version>and exits.
The version is read frommailradar.__version__, the single source of truth
also used bypyproject.toml.
Fixed
- Docker: the
latestimage is now rebuilt every week from the most recent tag,
without cache and pulling a fresh base image, so Debian security patches are
picked up without waiting for a release. Versioned images are left unchanged.
Security
- Docker: pip is upgraded before installing MailRadar and then removed from the
final image. It is not needed at runtime and its vendored dependencies had
known CVEs. SECURITY.md: the known open CVEs are now attributed to the correct base
image (Debian Trixie) and the list was updated (OpenSSL is no longer
affected).
MailRadar 2026.09.8
Fixed
send: encryption with a key fetched from a keyserver failed because the key
was never in the local keyring. The key is now imported into a throwaway
temporary keyring, so the user's own keyring is left untouched.send: if a GPG key is found but encryption fails, the report is no longer
silently sent in plaintext. It is not sent, the report is printed for manual
delivery and the command exits with code 1.- Total score could exceed 100 because the raw per-check maximums add up to
more than 100. The raw score is now normalized to a 0-100 scale. - DMARC and BIMI tag values containing
=were truncated. - An invalid DMARC
pctvalue (non-numeric or outside 0-100) no longer crashes
the analysis: it is reported as an issue and treated as 100 (RFC 7489 §6.3). - A non-UTF-8 TXT record no longer crashes the analysis.
batch: a domain that fails analysis no longer stops the whole run. It is
reported and listed in a final "Failed" summary.discover: the email regex matched look-alike domains (e.g. addresses at
example.communityorexample.com.evil.orgwhen discoveringexample.com).discover: guessed role addresses (RFC 2142) are now shown separately as
unverified candidates instead of being mixed with addresses found in public
sources. They are skipped for domains that publish a null MX (RFC 7505).discover: GPG lookups for discovered addresses now run in parallel and
also cover the guessed candidates.
Security
- DNS records, domain names, keyserver data and report text shown in the
terminal are escaped, so Rich markup injected via DNS records or other
external data is no longer interpreted.
MailRadar 2026.09.7
Changed
- Bumped
anyiofrom 4.15.0 to 4.15.1. - CI: bumped GitHub Actions (
actions/checkout,actions/setup-python,
docker/setup-qemu-action,github/codeql-action) and aligned all CodeQL
steps to v4.38.0.
MailRadar 2026.09.6
Changed
- Test coverage raised to 84%, with new tests for the CLI,
discoverand GPG
modules.
MailRadar 2026.09.5
Changed
- Version bump only. No code changes since 2026.09.4.
MailRadar 2026.09.4
Added
release.shrelease automation script.
Changed
- The Docker image and PyPI publish workflows now run on version tags (
v*).
The Docker workflow strips thevprefix and leading zeros from the tag to
match the version published on PyPI.
Security
- Docker base image moved from Debian Bookworm to Debian Trixie
(python:3.12-slim-trixie) to address OpenSSL CVEs.
MailRadar 2026.09.3
Added
send --sign: sign the outgoing report with the sender's GPG private key
(clear-signed, using the--fromaddress). The passphrase is asked
interactively.SECURITY.mdsecurity policy with a vulnerability reporting contact and the
status of known CVEs.- Built distributions are GPG-signed in the PyPI publish workflow.
- Tests for GPG signing and SMTP sending.
Changed
- CI: manual
workflow_dispatchtrigger for the publish and Docker workflows,
SonarCloud analysis for Dependabot PRs, coverage reporting to SonarCloud,
and CodSpeed benchmarks skipped on PRs that do not touch code.
Fixed
- The publish workflow imports the signing key from a temporary file.
- Corrected the
codeql-actioncommit hash in the Docker workflow.