------------------------------------------------------------------------
r1938066 | fkento | 2026-09-10 04:35:20 +0000 (Thu, 10 Sep 2026) | 50
lines
Redirectors: parse URIs with Mail::SpamAssassin::URI
Replaces the hand-rolled parsing in _parse_uri and _extract_embedded_uri
with the URI class. Extraction becomes a loop over parsed query
parameters rather than regexes run against the raw querystring, which
removes a class of bug rather than patching instances of it:
- An encoded separator inside a parameter value no longer ends it. The
query is split while still encoded and each value decoded afterwards,
so ?url=evil.com%2Fp%3Fx%3D1%26tid%3Dgood.com keeps its whole target.
- Whether url_redirector_params captures greedily stops mattering, since
splitting the query replaces capturing it. The setting is now matched
against one \"name=value\" at a time, so a greedy capture can no
longer
run past the end of the value it belongs to. Its capture group is
still honoured where it has one, which lets a regex pull the target
out of a value that wraps it, as in \"u=12345|https://example.com/\";
with no capture group the whole value is the candidate.
- An embedded target that is itself percent-encoded is found without a
second pattern to match the encoded form.
Extraction runs in three stages: a parameter whose name matches
url_redirector_params, then any parameter whose value looks like a URI,
then a target embedded in the path. The first stage keeps a configured
name winning over a decoy such as a logo or a return URL appearing
earlier in the querystring; the second finds targets under names no list
anticipates.
Two fixes fall out of the rewrite:
- A fragment is stripped before fetching, on both sides of the
self-redirect comparison. RFC 7231 lets a Location carry one, so a
redirector that echoed a fragment defeated the comparison and the
destination was walked as though it were a new hop.
- A URI is now searched for an embedded one on its own merits: the
scheme, and whether there is a path or query to search. The wrapper's
host is not consulted, since an embedded URI is never taken from it --
requiring a dot there meant https://localhost/?url=https://evil.com/x
and any other dotless intranet host had their target ignored.
_walk_redirects parses each URI once and passes the object down, so a
chain of three hops parses four URIs rather than seven.
Redirectors: use reserved example domains in the match tests
Submitted by: Kent Oyer <kent.oyer@gmail.com>
Github: closes #41
------------------------------------------------------------------------
r1938048 | fkento | 2026-09-09 16:12:48 +0000 (Wed, 09 Sep 2026) | 1 line
Change redirector track.senderbulk.com from GET to HEAD
------------------------------------------------------------------------
r1938039 | gbechis | 2026-09-09 14:47:37 +0000 (Wed, 09 Sep 2026) | 2
lines
add Mailjet redirector
------------------------------------------------------------------------
r1938033 | fkento | 2026-09-09 05:49:28 +0000 (Wed, 09 Sep 2026) | 1 line
Add redirector: geno.link
------------------------------------------------------------------------
r1938025 | fkento | 2026-09-08 23:01:23 +0000 (Tue, 08 Sep 2026) | 6 lines
Add redirector: track.senderbulk.com
Submitted by: Kent Oyer <kent.oyer@gmail.com>
Github: closes #42
------------------------------------------------------------------------
r1938016 | billcole | 2026-09-08 18:40:38 +0000 (Tue, 08 Sep 2026) | 1
line
remove broad Apple WL due to reported TestFlight spam on SA-Users
------------------------------------------------------------------------
r1937838 | fkento | 2026-09-03 22:14:43 +0000 (Thu, 03 Sep 2026) | 34
lines
Add Mail::SpamAssassin::URI, a URI parser class
Splits a URI into its RFC 3986 components and percent-decodes each one
separately, reusing the reference regex already in HTML.pm.
The order is the point. Percent-encoding exists so a reserved character
can appear as data inside a component, so the boundaries have to be found
in the raw string and only then may each component be decoded. Decoding
the whole URI first invents boundaries nothing else sees: in
https://host/a%3Fx=1 the %3F belongs to the path rather than starting a
query string, and in ?url=a%26b=c the %26 belongs to the value of url
rather than separating two parameters.
Accessors come in two flavours to match: authority, raw_path, query and
fragment are returned as they appeared, while host, path and the
parameter accessors are decoded. host() also lowercases and folds an
internationalised name to its ASCII form, so one host has one identity
however a message spells it. Verified against the CPAN URI module, which
agrees on every http case tested.
Query parameters are exposed both as an ordered list, which keeps every
occurrence of a repeated name, and as a hashref, which is lossy and keeps
the first. A parameter with no "=" is distinguished from one with an
empty value.
Nothing here validates a URI; every string parses, including the empty
one, so callers ask a question they care about (is_http, or whether host
is defined) rather than testing for undef. A URI arrives from a hostile
message rather than from a config file, so refusing to parse it is not
useful.
No behaviour changes anywhere yet; nothing calls this.
------------------------------------------------------------------------
r1937768 | gbechis | 2026-09-02 12:45:38 +0000 (Wed, 02 Sep 2026) | 2
lines
mention that DecodeShortURLs plugin is now deprecated
------------------------------------------------------------------------
r1937762 | gbechis | 2026-09-02 09:44:47 +0000 (Wed, 02 Sep 2026) | 3
lines
make `ifplugin Mail::SpamAssassin::Plugin::DecodeShortURLs` work
even if only Redirectors plugin is loaded
------------------------------------------------------------------------
r1937759 | gbechis | 2026-09-02 08:08:12 +0000 (Wed, 02 Sep 2026) | 6
lines
runs GitHub Actions workflows locally in Docker using
https://github.com/nektos/act
Submitted by: Giovanni <g.bechis@snb.it>
Github: closes #38
------------------------------------------------------------------------
r1937758 | gbechis | 2026-09-02 07:44:45 +0000 (Wed, 02 Sep 2026) | 2
lines
Silence warnings after recent Mail::DMARC update
------------------------------------------------------------------------
r1937746 | gbechis | 2026-09-01 22:30:45 +0000 (Tue, 01 Sep 2026) | 2
lines
make Handler::Image and Perlcritic happy
------------------------------------------------------------------------
r1937745 | gbechis | 2026-09-01 22:29:00 +0000 (Tue, 01 Sep 2026) | 2
lines
skip NeuralNetwork tests if AI:Fann module is not installed
------------------------------------------------------------------------
r1937744 | gbechis | 2026-09-01 22:24:11 +0000 (Tue, 01 Sep 2026) | 2
lines
unbreak CNAME dns tests with Perl < 5.26
------------------------------------------------------------------------
r1937741 | fkento | 2026-09-01 20:09:59 +0000 (Tue, 01 Sep 2026) | 1 line
Add 2nd form of Microsoft OAuth redirector URL
------------------------------------------------------------------------
r1937692 | gbechis | 2026-08-31 13:00:11 +0000 (Mon, 31 Aug 2026) | 2
lines
automatically cleanup old database records
------------------------------------------------------------------------
r1937627 | jhardin | 2026-08-29 18:42:53 +0000 (Sat, 29 Aug 2026) | 1 line
Reduce URI_PHISH score due to real-world FP report, pending evidence
------------------------------------------------------------------------
r1937585 | fkento | 2026-08-28 18:29:27 +0000 (Fri, 28 Aug 2026) | 14
lines
Run apply_handlers() before the extract_metadata plugin hook
Only a MIME-part handler renders a non-text/plain part --
Node::rendered()
handles text/plain and nothing else, so a text/html part gets its text
solely
from Handler::HTML calling set_rendered(). That means any reader which
asks
for rendered body text before apply_handlers() has run caches an EMPTY
array,
and every later reader for the rest of the scan sees nothing.
A plugin hooking extract_metadata is exactly such an early reader, and
that
hook fired before apply_handlers(). Move the call to the top of
PerMsgStatus::extract_message_metadata so handlers have rendered every
part
before any plugin can observe the body.
------------------------------------------------------------------------
r1937584 | fkento | 2026-08-28 18:28:37 +0000 (Fri, 28 Aug 2026) | 3 lines
Replace DecodeShortURLs with Redirectors in t/all_modules.t
------------------------------------------------------------------------
r1937532 | fkento | 2026-08-27 18:17:55 +0000 (Thu, 27 Aug 2026) | 20
lines
Bayes: sort tokens in MySQL store to prevent InnoDB deadlocks
bayes_token is InnoDB with PRIMARY KEY (id, token), so every token
write takes a row lock on the clustered index. _put_tokens and
tok_touch_all iterated tokens in Perl hash / caller order, which is
randomized per process, so two concurrent scans that share tokens
could lock the same rows in opposite orders and deadlock.
Sorting the tokens gives every writer a single global lock order, so
the circular wait cannot form. The token column is binary(5), so
Perl's default string sort matches InnoDB's byte ordering on the
clustered index.
Also, replace `dbg` with `warn` so future MySQL errors are visible in
the logs.
Submitted by: Kent Oyer <kent.oyer@gmail.com>
Github: closes #40
------------------------------------------------------------------------
r1937482 | gbechis | 2026-08-26 08:41:14 +0000 (Wed, 26 Aug 2026) | 3
lines
Correctly parse Exim 4.99 received lines
bz #8365
------------------------------------------------------------------------
r1937480 | gbechis | 2026-08-26 08:17:13 +0000 (Wed, 26 Aug 2026) | 2
lines
add migration scripts
------------------------------------------------------------------------
r1937476 | gbechis | 2026-08-26 07:54:38 +0000 (Wed, 26 Aug 2026) | 10
lines
merge DecodeShortURLs and Redirectors plugins
alias all short_url_* subs to equivalent redirector subs
if Mail::SpamAssassin::Plugin::DecodeShortURLs is used and cache is
enabled, continue to use old SQL tables.
Submitted by: Giovanni <g.bechis@snb.it>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Github: closes #36
------------------------------------------------------------------------
r1937475 | gbechis | 2026-08-26 07:50:53 +0000 (Wed, 26 Aug 2026) | 2
lines
Check that Selenium is actually running before trying the test
------------------------------------------------------------------------
r1937456 | fkento | 2026-08-25 21:16:50 +0000 (Tue, 25 Aug 2026) | 79
lines
Move HTML rendering from Message::Node::rendered() into Handler::HTML
Rendering an HTML part is the HTML handler's job, but handle_html() only
called $node->rendered() to warm a cache and then read the results back.
The parse now happens in the handler; rendered() renders text/plain and
otherwise returns whatever the part's handler published with
set_rendered().
Mail::SpamAssassin::HTML is untouched.
Note this makes the HTML handler load-bearing: with it not loaded, no
HTML
is parsed at all -- no rendered body text, no html_results for the html_*
eval rules, and no URIs from href/src/action. Previously only the URI
harvest was lost. v403.pre loads it by default (under the
feature_handlers guard), so an install whose lib/ and rules/ come from
the
same version is unaffected; a site running this code against an older
v403.pre, or one that has commented the loadhandler out, is not. The
existing warn in Message::apply_handlers() for a text/html part with no
registered handler covers this; it now says what is actually lost, and
has
moved inside the part-walking loop, which reuses the per-node handler
lookup already done there instead of a separate find_parts() scan. Two
cases it used to miss now warn: a message whose only text/html part is a
synthetic child produced by another handler (ICS, Archive), and a config
with no handlers registered at all -- the latter returned early, before
the check.
Node.pm:
- new decode_and_normalize(): decode() plus the charset decision,
factored
out of the two branches of rendered() that each had their own copy.
Returns ($text, $character_semantics) so a caller feeding a parser
that
must be told whether it is getting bytes or characters can do so.
- set_rendered() takes optional $invisible and $visible arguments, for a
renderer that can tell hidden text from shown text. Both default to
the
old behaviour, so existing callers are unaffected.
- rendered() no longer parses HTML; its type gate is text/plain only.
Handler/SVG.pm now publishes the text it extracts with set_rendered(),
under the part's own image/svg+xml type. Previously an SVG part was
rendered only as a side effect of rendered()'s HTML branch, which stamped
it text/html -- so an SVG arriving as an attachment (the common case) was
then dropped from the body by the text/* attachment skip in
get_body_text_array_common().
This is a behaviour change, not just code motion: SVG text now reaches
body
rules where it did not before, the same way OCR'd image and PDF text
already do. On t/data/nice/handler_svg the body gains \"SVGSENTINEL
Please
view documents on docusign secure link\".
Bayes asks for the MIME-part handlers explicitly on the learn path
(get_body_from_msg). It already got them, but only incidentally: it
calls
Message::extract_message_metadata, which does not run handlers, and then
_get_msgdata_from_permsgstatus -> get_uri_list -> get_uri_detail_list,
which does. The handler-extracted text Bayes learns therefore hung on a
call made for its URIs. apply_handlers() is idempotent, so this is a
no-op at runtime; it just stops the token stream depending on that.
One smaller behaviour change: text/plain parts now emit the
\"normalize_charset is off\" debug line, which only the HTML branch used
to
log. Debug output only.
Also:
- Pyzor::Digest::Pieces read {rendered} directly, which only worked if
something else had already rendered the part; call rendered().
- Message::get_body_text_array_common no longer pushes an undef into
{metadata}{html_all} when a handler publishes text/html without
html_results.
- t/scan_text_attach.t builds a PerMsgStatus and calls apply_handlers(),
as a real scan does; it previously relied on rendered() lazily parsing
HTML with no handler having run.
Verified behaviour-neutral for HTML: rendered/visible/invisible text,
utf8 flags and the html_results stats are byte-identical across 70
rendered parts from 23 fixtures, with normalize_charset both on and off.
Add note to UPGRADE file
Submitted by: Kent Oyer <kent.oyer@gmail.com>
Github: closes #39
------------------------------------------------------------------------
r1937446 | fkento | 2026-08-25 19:23:48 +0000 (Tue, 25 Aug 2026) | 1 line
Add redirector doubleclick.net
------------------------------------------------------------------------
r1937439 | gbechis | 2026-08-25 15:48:55 +0000 (Tue, 25 Aug 2026) | 2
lines
typo
------------------------------------------------------------------------
r1937371 | gbechis | 2026-08-24 14:08:45 +0000 (Mon, 24 Aug 2026) | 3
lines
skip DMARC tests if a buggy Mail::DMARC package is installed
see https://github.com/msimerson/mail-dmarc/pull/310 for details
------------------------------------------------------------------------
r1937273 | fkento | 2026-08-20 16:26:35 +0000 (Thu, 20 Aug 2026) | 11
lines
HTML: honor style attribute on body and font, apply CSS after HTML
attributes
text_style() iterated tag attributes with keys %$attr, so on a tag
carrying
both a presentational attribute and a style attribute, hash order decided
which won. <body bgcolor="black" style="background-color: white">
rendered
as invisible or visible depending on the hash seed. Sort so 'style' is
processed last, matching CSS precedence over presentational attributes.
Also add 'style' to %ok_attributes for body and font.
------------------------------------------------------------------------
r1937215 | sidney | 2026-08-19 00:42:00 +0000 (Wed, 19 Aug 2026) | 4 lines
Bug 8409 - Fix ReturnUndef Perlcritic warnings where safe
Suppress the warning where it cannot be proven safe to change the return
See bug 8409 comments and attachments for details
Github: closes #37
------------------------------------------------------------------------
r1937180 | fkento | 2026-08-17 15:31:19 +0000 (Mon, 17 Aug 2026) | 1 line
Add missing file
------------------------------------------------------------------------
r1937178 | gbechis | 2026-08-17 13:51:27 +0000 (Mon, 17 Aug 2026) | 2
lines
add metadata to Redirectors subs, silence a warning on
t/cross_user_config_leak.t test.
------------------------------------------------------------------------
r1937177 | gbechis | 2026-08-17 13:21:25 +0000 (Mon, 17 Aug 2026) | 2
lines
silence compilation warnings
------------------------------------------------------------------------
r1937176 | gbechis | 2026-08-17 13:13:05 +0000 (Mon, 17 Aug 2026) | 2
lines
do not try to install a file that has not been committed yet
------------------------------------------------------------------------
r1937171 | fkento | 2026-08-17 05:00:51 +0000 (Mon, 17 Aug 2026) | 26
lines
PDF: extract CCITT fax images by wrapping them in a TIFF header
Faxed PDFs encode their page images with CCITTFaxDecode (Group 3/4 fax),
as do monochrome scans, and _get_image_data had no branch for it: it fell
through to 'unsupported', extract_images dropped the image, and no
sub-part ever reached the image handler. A PDF whose pages are all fax
images was therefore invisible to OCR.
Rather than implementing T.4/T.6, leave the data encoded and wrap it in a
TIFF header, which image readers decode natively (libtiff, via leptonica,
in tesseract). The codec parameters live in /DecodeParms rather than the
stream, so the wrapping happens in the parser while they are in hand; the
descriptor then carries a complete image file, as 'jpeg' already did, and
the handler passes it through as image/tiff.
/K maps onto the TIFF compression tag (Group 4, Group 3 1-D, Group 3 2-D)
and BlackIs1 onto PhotometricInterpretation. Group 4 combined with
EncodedByteAlign has no TIFF equivalent and is declined rather than
wrapped into data that would decode to garbage.
Also add a TIFF branch to Handler::Image::_image_info. Without it a TIFF
sub-part is an unrecognised type, and the type gate skips OCR entirely.
This also means genuine image/tiff mail attachments now OCR, where before
they were silently dropped.
------------------------------------------------------------------------
r1937168 | sidney | 2026-08-16 23:15:25 +0000 (Sun, 16 Aug 2026) | 1 line
Bug 8408 - Fix bad test plan count in t/handler_archive.t
------------------------------------------------------------------------
r1937151 | gbechis | 2026-08-16 10:05:10 +0000 (Sun, 16 Aug 2026) | 3
lines
document how `check()` and `got_hit()` should be called by external
software.
bz #8116
------------------------------------------------------------------------
r1937150 | gbechis | 2026-08-16 09:49:10 +0000 (Sun, 16 Aug 2026) | 3
lines
randomize ip addresses returned by `getaddrinfo`
bz #7046
------------------------------------------------------------------------
r1937149 | gbechis | 2026-08-16 09:09:17 +0000 (Sun, 16 Aug 2026) | 4
lines
commit only every 1000 records during `sa-learn --restore`
to improve speed.
bz #6710
------------------------------------------------------------------------
r1937148 | gbechis | 2026-08-16 08:52:56 +0000 (Sun, 16 Aug 2026) | 4
lines
check Subject length after stripping UTF-8 chars
bz #5859
------------------------------------------------------------------------
r1937060 | gbechis | 2026-08-11 22:21:01 +0000 (Tue, 11 Aug 2026) | 2
lines
add Intuit redirector
------------------------------------------------------------------------
r1937046 | jhardin | 2026-08-10 15:39:30 +0000 (Mon, 10 Aug 2026) | 1 line
Fix FP in __URI_DOTCN_SPOOF, bug#8407
------------------------------------------------------------------------
r1936954 | gbechis | 2026-08-07 10:07:57 +0000 (Fri, 07 Aug 2026) | 3
lines
skip data:image/png uris, they're not domains.
bz #8405
------------------------------------------------------------------------
r1936945 | fkento | 2026-08-06 23:26:54 +0000 (Thu, 06 Aug 2026) | 13
lines
Redirectors: report the real LWP error instead of assuming a timeout
A client-warning of 'Internal response' only means LWP synthesized the
500 itself, it covers connection timeouts, DNS failures, oversized
response headers, and protocol errors alike. Logging 'Connection
timeout' for all of them misreports the cause, e.g. a 500 Header line
too long (limit is 8192) was being shown as a timeout.
Log the response status line, which already carries the actual reason.
Also use the header() accessor rather than reaching into the
HTTP::Headers hash, and guard against an undefined value, the old eq
comparison warned on any synthesized 500 lacking the header.
------------------------------------------------------------------------
r1936924 | gbechis | 2026-08-06 14:00:28 +0000 (Thu, 06 Aug 2026) | 1 line
add Beehiiv redirector
------------------------------------------------------------------------
r1936901 | fkento | 2026-08-05 19:49:06 +0000 (Wed, 05 Aug 2026) | 7 lines
Update MailChimp redirect URL format
Redirect URLs from MailChimp have no path now
https://us.list-manage.com/XXXXXXX
------------------------------------------------------------------------
r1936882 | fkento | 2026-08-04 20:36:17 +0000 (Tue, 04 Aug 2026) | 18
lines
PDF: parse link annotations on every page, not just page 1
Annotations are now parsed for every page. This is cheap (a dict lookup
per
annotation); walking the page content streams stays page-1-only, so the
existing optimization is preserved. That walk exists to feed
ImageCount,
ImageArea/ImageRatio and the image extraction used for OCR.
ClickArea is still accumulated only for page 1, to stay consistent with
PageArea, both of which are used to calculate ClickRatio. LinkCount and
the
URI list still cover every page.
Since links are now read from the whole document, add a pdf_max_uris
setting
(default 30, 0 disables) capping the number of distinct URIs retained per
PDF, so a PDF stuffed with link annotations cannot flood the URI list
and the
URIBL lookups that follow. Duplicate links to an already-seen URI do not
consume the cap, and LinkCount still counts every link.
------------------------------------------------------------------------
r1936878 | fkento | 2026-08-04 16:44:48 +0000 (Tue, 04 Aug 2026) | 1 line
Add redirector newoldstamp.com
------------------------------------------------------------------------
r1936861 | gbechis | 2026-08-04 09:43:19 +0000 (Tue, 04 Aug 2026) | 2
lines
fix typos spotted by fossies.org
------------------------------------------------------------------------
r1936844 | fkento | 2026-08-03 17:46:42 +0000 (Mon, 03 Aug 2026) | 7 lines
Improve phone number obfuscation rule
* use bounded repetition counts
* require valid area code (must not start with 0 or 1, must not end with
11)
------------------------------------------------------------------------
r1936771 | jhardin | 2026-08-01 00:49:13 +0000 (Sat, 01 Aug 2026) | 1 line
tuning bitcoin extortion rules
------------------------------------------------------------------------
r1936737 | gbechis | 2026-07-30 14:48:23 +0000 (Thu, 30 Jul 2026) | 2
lines
install missing dependencies
------------------------------------------------------------------------
r1936736 | gbechis | 2026-07-30 14:43:43 +0000 (Thu, 30 Jul 2026) | 2
lines
fix regression tests
------------------------------------------------------------------------
r1936735 | gbechis | 2026-07-30 14:39:13 +0000 (Thu, 30 Jul 2026) | 2
lines
when we rewrite the envelope, use headers with the same case as the
original email
------------------------------------------------------------------------
r1936721 | gbechis | 2026-07-30 08:49:29 +0000 (Thu, 30 Jul 2026) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1936659 | gbechis | 2026-07-28 06:43:52 +0000 (Tue, 28 Jul 2026) | 2
lines
use a queue to speedup CNAME processing
------------------------------------------------------------------------
r1936637 | gbechis | 2026-07-27 13:49:48 +0000 (Mon, 27 Jul 2026) | 3
lines
Track the PID that owns each cached dbh/sth set and reconnect whenever
the current process differs
------------------------------------------------------------------------
r1936636 | gbechis | 2026-07-27 13:30:04 +0000 (Mon, 27 Jul 2026) | 2
lines
remove scores for rules removed a while ago
------------------------------------------------------------------------
r1936623 | gbechis | 2026-07-27 09:51:55 +0000 (Mon, 27 Jul 2026) | 2
lines
add wix[.]com redirector
------------------------------------------------------------------------
r1936613 | gbechis | 2026-07-27 07:20:20 +0000 (Mon, 27 Jul 2026) | 18
lines
Replace meta-rule full-rescan retry with a dependency-driven work queue
do_meta_tests() restarted its entire foreach over meta_check_ready (or
meta_pending when finishing) via \"goto RULE\" every time any meta
resolved, re-checking the dependency list of every still-pending meta
each time, even ones unaffected by what just resolved. Replace it with
an explicit work queue seeded the same way, where resolving a meta
pushes only the specific metas listed in its meta_deprules reverse-map
(the same map PerMsgStatus::rule_ready() already uses) instead of
rescanning everything.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
initialize queue
Submitted by: Giovanni <g.bechis@snb.it>
Github: closes #32
------------------------------------------------------------------------
r1936591 | fkento | 2026-07-26 01:38:14 +0000 (Sun, 26 Jul 2026) | 23
lines
Bug 8404: fix NBSP false positives in HTML obfuscation detection
Add t/html_obfuscation_ratio.t to guard the obfuscation-ratio
calculation
against regressions. Writing it uncovered a new false positive:
html_text()
counts a text node's trailing character and the next node's leading
character as "obfuscation" when both are word characters (a word split
across a tag), but its character class treated NBSP as a word character.
A non-breaking space renders as whitespace and, via the
<br>-before-closing-block rewrite in html_tag(), is inserted by the
parser
itself, so NBSP-separated runs were wrongly counted as split words.
Exclude
\xa0 from the class, taking care not to confuse it with legitimate text:
- a leading UTF-8 NBSP is skipped with (?!\xc2\xa0), without excluding
the shared \xc2 lead byte (© ® ° ...);
- a trailing \xa0 still counts when it is the tail byte of a multibyte
letter (à, Š, CJK, ...) rather than an NBSP.
The word-character class is factored into $wordchar with the leading and
trailing variants built from it. The test exercises these cases directly
against Mail::SpamAssassin::HTML in both character-semantics modes.
------------------------------------------------------------------------
r1936588 | jhardin | 2026-07-25 17:20:23 +0000 (Sat, 25 Jul 2026) | 1 line
Add subrule for rb.gy redirector to evaluate its (ab)use and for scored
rules.
------------------------------------------------------------------------
r1936559 | fkento | 2026-07-24 20:53:40 +0000 (Fri, 24 Jul 2026) | 1 line
Bug 8404: Fix HTML_OBFUSCATE_* false positives
------------------------------------------------------------------------
r1936530 | fkento | 2026-07-23 23:04:51 +0000 (Thu, 23 Jul 2026) | 23
lines
Message::Node: fix BOM'd UTF-16 decoding in _normalize
detect_utf16() returned undef when the data began with a UTF-16 BOM
("let perl figure it out from the BOM"), but its only caller --
_normalize()'s UTF-16 branch -- used solely the decoder it returned.
So BOM'd UTF-16 fell through to the Windows-1252 last resort and was
mangled (the BOM bytes ff fe / fe ff decoded to c3 bf c3 be, with the
interleaved NUL bytes preserved).
Return the BOM-aware UTF-16 decoder from detect_utf16() on a BOM instead
of undef; it consumes the BOM and picks endianness from it.
detect_utf16()
now returns undef only when the data does not look like UTF-16 at all.
While here, bound the endianness heuristic to a 1024-byte prefix instead
of scanning the whole part: the check is statistical, so a prefix gives
the same verdict while avoiding the unpack() of a multi-MB body into
per-nibble arrays. The BOM pre-check now tests $_[0] directly (only the
first two bytes matter) rather than copying the body first.
Add t/node_utf16.t: direct unit tests covering detect_utf16() and
_normalize('UTF-16') for BOM'd and BOM-less UTF-16 of either endianness,
------------------------------------------------------------------------
r1936522 | gbechis | 2026-07-23 13:56:10 +0000 (Thu, 23 Jul 2026) | 3
lines
update optional dependencies
fix #8402
------------------------------------------------------------------------
r1936520 | gbechis | 2026-07-23 11:04:23 +0000 (Thu, 23 Jul 2026) | 2
lines
detect Microsoft Oauth2 service abuse
------------------------------------------------------------------------
r1936519 | gbechis | 2026-07-23 10:46:30 +0000 (Thu, 23 Jul 2026) | 3
lines
add a warning if Mail::SpamAssassin::Handler::HTML handler is not loaded.
might save some debug headache to someone else.
------------------------------------------------------------------------
r1936490 | fkento | 2026-07-22 15:22:20 +0000 (Wed, 22 Jul 2026) | 1 line
PDF: Skip tests when required modules are missing
------------------------------------------------------------------------
r1936486 | gbechis | 2026-07-22 13:34:40 +0000 (Wed, 22 Jul 2026) | 25
lines
Cache eval-plugin glue methods for the process lifetime, not per message
PerMsgStatus::finish() undefined every register_plugin_eval_glue()
generated wrapper sub (and any register_generated_rule_method() plugin
subs) and cleared their tracking hash after every single message, even
though this glue is 100% static per-config -- forcing a fresh eval()
compile of every distinct eval-plugin function on every message instead
of once per process, the same \"compile once, reuse\" pattern Check.pm
already uses for its rule subs.
It also contradicted register_generated_rule_method()'s
documented contract, which says these methods are destroyed at
Mail::SpamAssassin::finish() (session end), not per-message.
Move the cleanup to Mail::SpamAssassin::finish(), alongside the
existing finish_tests plugin-hook cleanup. Since that code runs
outside the PerMsgStatus package, bare (non-fully-qualified) method
names now need explicit qualification to avoid undefining the wrong
symbol.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Submitted by: Giovanni <g.bechis@snb.it>
Github: closes #34
------------------------------------------------------------------------
r1936449 | gbechis | 2026-07-22 07:12:42 +0000 (Wed, 22 Jul 2026) | 2
lines
remove start-of-string anchors and set the rule as lossy, it's a speed
gain in any case
------------------------------------------------------------------------
r1936448 | gbechis | 2026-07-22 07:10:58 +0000 (Wed, 22 Jul 2026) | 2
lines
document dead code
------------------------------------------------------------------------
r1936447 | gbechis | 2026-07-22 06:40:00 +0000 (Wed, 22 Jul 2026) | 3
lines
precompute the per-hit metadata that run_body_fast_scan() would
otherwise have to re-derive with regexps on every single hit
------------------------------------------------------------------------
r1936424 | fkento | 2026-07-21 16:08:47 +0000 (Tue, 21 Jul 2026) | 1 line
Make rule compatible with older versions
------------------------------------------------------------------------
r1936423 | gbechis | 2026-07-21 15:27:05 +0000 (Tue, 21 Jul 2026) | 3
lines
limit base64 decoding based on scan size, we do not need to decode a big
message
just to discard it later
------------------------------------------------------------------------
r1936399 | fkento | 2026-07-20 17:45:00 +0000 (Mon, 20 Jul 2026) | 1 line
Sync MANIFEST
------------------------------------------------------------------------
r1936398 | fkento | 2026-07-20 17:42:08 +0000 (Mon, 20 Jul 2026) | 1 line
ICS: route HTML calendar properties to the HTML handler as sub-parts
------------------------------------------------------------------------
r1936344 | fkento | 2026-07-20 06:03:43 +0000 (Mon, 20 Jul 2026) | 23
lines
Extract HTML URIs in the HTML handler instead of _process_html_uri_list
Move HTML URI harvesting out of PerMsgStatus::_process_html_uri_list
and
into Handler::HTML::handle_html, so that:
* URIs are extracted from synthetic HTML parts too. Handlers can emit
child parts that never appear in the original MIME tree. The old
walk
iterated metadata->{html_all}, which only holds parts from the
parsed
message tree, so it never saw these. Harvesting as each part is
rendered by its handler covers synthetic parts as well.
* HTML-specific code lives in the HTML handler, alongside the
rendering
it depends on, rather than in PerMsgStatus.
handle_html now walks html_results->{uri_detail} and calls
add_uri_detail_list (type 'html', copying anchor_text), mirroring what
_process_html_uri_list did.
get_uri_detail_list now ensures apply_handlers has run before
assembling
the list, so a caller fetching URIs without a full scan still gets HTML
URIs.
------------------------------------------------------------------------
r1936340 | fkento | 2026-07-20 02:47:04 +0000 (Mon, 20 Jul 2026) | 1 line
Add redirectors (Omnisend)
------------------------------------------------------------------------
r1936301 | jhardin | 2026-07-19 02:42:05 +0000 (Sun, 19 Jul 2026) | 1 line
Bitcoin rules tuning
------------------------------------------------------------------------
r1936300 | jhardin | 2026-07-19 02:28:01 +0000 (Sun, 19 Jul 2026) | 1 line
Fix backwards FP avoidance
------------------------------------------------------------------------
r1936298 | billcole | 2026-07-18 21:43:27 +0000 (Sat, 18 Jul 2026) | 1
line
prepare msphish rule for future FP mitigation
------------------------------------------------------------------------
r1936281 | billcole | 2026-07-17 18:51:33 +0000 (Fri, 17 Jul 2026) | 1
line
simplify bad-referer exclusion
------------------------------------------------------------------------
r1936253 | gbechis | 2026-07-17 10:44:30 +0000 (Fri, 17 Jul 2026) | 2
lines
silence a warning when saving the DMARC report and no DKIM record is
present
------------------------------------------------------------------------
r1936252 | gbechis | 2026-07-17 10:36:54 +0000 (Fri, 17 Jul 2026) | 3
lines
make NeuralNetwork plugin work even without Bayes plugin enabled
add a `--plugin` option to sa-learn in order to dump NeuralNetwork stats
------------------------------------------------------------------------
r1936211 | gbechis | 2026-07-16 15:47:09 +0000 (Thu, 16 Jul 2026) | 2
lines
Add a redirector
------------------------------------------------------------------------
r1936172 | fkento | 2026-07-15 19:34:41 +0000 (Wed, 15 Jul 2026) | 1 line
Add a calendar rule to sandbox for testing
------------------------------------------------------------------------
r1936171 | fkento | 2026-07-15 19:32:04 +0000 (Wed, 15 Jul 2026) | 10
lines
mkrules: recognize ifhandler as a conditional and load handlers for lint
Only 'if'/'ifplugin' were treated as conditional-openers, so an
'ifhandler'
line in a sandbox rule was dropped and its 'endif' orphaned -- desyncing
if/endif in the generated 72_active.cf and stripping the handler guard
so the
handler's evals linted as 'unknown eval'.
- add 'ifhandler' to the conditional-opener regex
- handle 'ifhandler' in invert_conditional (inverts to if !plugin(...))
- load rules/v403.pre's handlers in the lint pretext, guarded by
feature_handlers
------------------------------------------------------------------------
r1936170 | fkento | 2026-07-15 19:02:28 +0000 (Wed, 15 Jul 2026) | 13
lines
Add ICS handler for text/calendar parts
Handler::ICS parses text/calendar parts and renders each event's
SUMMARY and DESCRIPTION into the body so ordinary body rules can match
it (SpamAssassin otherwise skips text/calendar); the same text is also
exposed to the new "icstext" rule type, kept separate from the body.
Links in the URL, ATTACH and LOCATION properties are added to the URI
detail list (type "ics"). Provides the check_ics_attendee_count,
check_ics_random_start_time and check_ics_event_prop evals, the last of
which matches a regex against any event property (parameters included)
for hunting arbitrary or extension properties.
------------------------------------------------------------------------
r1936167 | fkento | 2026-07-15 17:51:21 +0000 (Wed, 15 Jul 2026) | 1 line
Bug 6439: Scan text attachments
------------------------------------------------------------------------
r1936164 | jhardin | 2026-07-15 15:06:49 +0000 (Wed, 15 Jul 2026) | 1 line
Add wasmer.app free hosting, observed in phishing. Add comments about
replit.dev
------------------------------------------------------------------------
r1936140 | billcole | 2026-07-14 17:31:50 +0000 (Tue, 14 Jul 2026) | 1
line
sync online changes
------------------------------------------------------------------------
r1936135 | gbechis | 2026-07-14 15:16:40 +0000 (Tue, 14 Jul 2026) | 2
lines
make AI::Fann optional
------------------------------------------------------------------------
r1936126 | gbechis | 2026-07-14 07:17:56 +0000 (Tue, 14 Jul 2026) | 3
lines
avoid FPs on KAM_LOTTO2, make it clear that any committer can manage
kmcgrail@ sandbox
commit on behalf of kmcgrail@
------------------------------------------------------------------------
r1936095 | fkento | 2026-07-13 04:22:11 +0000 (Mon, 13 Jul 2026) | 8 lines
Skip calendar parts by effective_type
Match the text/calendar rawbody skip on effective_type()
so alias MIME types (application/ics, text/x-vcalendar)
and .ics-named parts are skipped too, consistent with
the non-text skip on the line above.
------------------------------------------------------------------------
r1936091 | fkento | 2026-07-12 15:57:08 +0000 (Sun, 12 Jul 2026) | 1 line
put a null between parts so they don't collapse together
------------------------------------------------------------------------
r1936071 | fkento | 2026-07-12 04:07:57 +0000 (Sun, 12 Jul 2026) | 1 line
Add URL shortener spoo.me
------------------------------------------------------------------------
r1936045 | billcole | 2026-07-10 15:28:03 +0000 (Fri, 10 Jul 2026) | 1
line
add subrule for MS phishing
------------------------------------------------------------------------
r1936044 | jhardin | 2026-07-10 14:59:39 +0000 (Fri, 10 Jul 2026) | 1 line
Fix UPPERCASE_URI insufficient format matching causing FP
------------------------------------------------------------------------
r1935791 | fkento | 2026-07-02 04:24:25 +0000 (Thu, 02 Jul 2026) | 46
lines
Add the first six MIME-part handlers to the handler framework
The handler framework itself shipped in an earlier release; this adds the
first set of handlers that make it useful. The point of the paradigm is
to process nested content by chaining handlers together: each handler can
return synthetic child parts that the framework re-dispatches by type, so
JavaScript embedded in an HTML file inside a rar archive, or text in an
image embedded in a PDF, is unwrapped one layer at a time and reaches the
handler that can inspect it -- all bounded by handler_max_depth,
handler_max_parts, handler_max_bytes, and handler_time_limit.
Handlers (lib/Mail/SpamAssassin/Handler/):
HTML (text/html) - render HTML parts and surface content with no MIME
part of its own (inline data: images, embedded JavaScript) as child
parts for the image and JavaScript handlers.
JavaScript (text/javascript) - collect script text for the new
"script" rule type and add navigation/redirect URLs to the URI
detail list (type "script").
SVG (image/svg+xml) - expose SVG text to the new "svgtext" rule type,
add links to the URI detail list (type "svg"), and surface embedded
script for the JavaScript handler.
Image (image/*) - OCR image parts with tesseract and inject the text
into the body. New "imagetext" rule type.
PDF (application/pdf) - parse PDFs with the new pure-Perl
Mail::SpamAssassin::PDF parser, expose metadata via pdf2_* eval rules
and _PDF2*_ tags, add URLs to the URI detail list (type "pdf"), and
extract embedded images for the image handler.
Archive (application/zip, application/vnd.rar) - unpack zip and rar
attachments and return the files inside as child parts for
re-dispatch.
HTML, JavaScript, and SVG are loaded by default from v403.pre; Image,
PDF, and Archive ship commented-out because they depend on external tools
(tesseract, unrar) or non-core Perl modules (Crypt::RC4,
Crypt::Mode::CBC).
Also adds the pure-Perl PDF parser (lib/Mail/SpamAssassin/PDF/), handler
and PDF unit tests plus fixtures under t/, and updates HTML.pm and
Message/Node.pm to support the handlers. UPGRADE, MANIFEST, and
rules/v403.pre updated accordingly.
------------------------------------------------------------------------
r1935766 | gbechis | 2026-07-01 12:53:30 +0000 (Wed, 01 Jul 2026) | 1 line
sync
------------------------------------------------------------------------
r1935723 | billcole | 2026-06-29 17:45:23 +0000 (Mon, 29 Jun 2026) | 1
line
more work on targeted load shedding
------------------------------------------------------------------------
r1935722 | billcole | 2026-06-29 17:42:05 +0000 (Mon, 29 Jun 2026) | 1
line
more work on targeted load shedding
------------------------------------------------------------------------
r1935721 | billcole | 2026-06-29 17:40:32 +0000 (Mon, 29 Jun 2026) | 1
line
more work on targeted load shedding
------------------------------------------------------------------------
r1935720 | billcole | 2026-06-29 16:52:38 +0000 (Mon, 29 Jun 2026) | 1
line
tuning load shedding
------------------------------------------------------------------------
r1935691 | fkento | 2026-06-28 06:15:20 +0000 (Sun, 28 Jun 2026) | 1 line
Add t/handler_aliases.t that should have been in r1935656
------------------------------------------------------------------------
r1935690 | fkento | 2026-06-28 04:55:15 +0000 (Sun, 28 Jun 2026) | 1 line
Add Handler base class that should have been in r1935656
------------------------------------------------------------------------
r1935689 | fkento | 2026-06-28 04:51:44 +0000 (Sun, 28 Jun 2026) | 1 line
Conf: add feature_handlers flag for gating loadhandler/ifhandler in cf
files
------------------------------------------------------------------------
r1935687 | fkento | 2026-06-28 04:03:54 +0000 (Sun, 28 Jun 2026) | 1 line
Remove surveymonkeyuser.com from default welcomelist - actively being
abused
------------------------------------------------------------------------
r1935685 | jhardin | 2026-06-27 17:48:39 +0000 (Sat, 27 Jun 2026) | 1 line
Add PHP-based redirector observed in phishing
------------------------------------------------------------------------
r1935671 | fkento | 2026-06-27 01:14:05 +0000 (Sat, 27 Jun 2026) | 15
lines
Redirectors: only extract embedded URIs that actually look like URLs
_extract_embedded_uri turned any url_redirector_params value into an
embedded URI, prepending http:// to bare tokens. Referral codes and
labels such as r=to8ex or redirect=app-store-no-desktop became bogus
http://to8ex / http://app-store-no-desktop URIs that were added to the
URI detail list and subjected to URIBL/HASHBL lookups, causing false
positives.
Require the captured value to look like a URL (explicit/encoded scheme,
scheme-relative //host, or bare host.tld/path) before accepting it. Also
guard against a user-supplied param regex with no capture group, which
left $1 undefined and fabricated a bare "http://".
Add regression tests covering both.
------------------------------------------------------------------------
r1935668 | billcole | 2026-06-26 19:05:34 +0000 (Fri, 26 Jun 2026) | 1
line
tweaking load levels for DDoS defense
------------------------------------------------------------------------
r1935666 | billcole | 2026-06-26 17:11:37 +0000 (Fri, 26 Jun 2026) | 2
lines
fixed explcit 'return undef' in 3 places to quiet PerlCritic test.
------------------------------------------------------------------------
r1935656 | fkento | 2026-06-26 04:24:07 +0000 (Fri, 26 Jun 2026) | 1 line
Add Mail::SpamAssassin::Handler base class and
loadhandler/tryhandler/ifhandler directives
------------------------------------------------------------------------
r1935653 | billcole | 2026-06-25 21:49:58 +0000 (Thu, 25 Jun 2026) | 2
lines
NO COMMENT!
------------------------------------------------------------------------
r1935652 | billcole | 2026-06-25 21:48:12 +0000 (Thu, 25 Jun 2026) | 2
lines
Cargo-culting my own coade...
------------------------------------------------------------------------
r1935651 | billcole | 2026-06-25 21:44:24 +0000 (Thu, 25 Jun 2026) | 2
lines
I hope this suffices...
------------------------------------------------------------------------
r1935650 | billcole | 2026-06-25 21:41:36 +0000 (Thu, 25 Jun 2026) | 2
lines
BLANK LINES
------------------------------------------------------------------------
r1935649 | billcole | 2026-06-25 21:39:50 +0000 (Thu, 25 Jun 2026) | 2
lines
This should really be it???
------------------------------------------------------------------------
r1935648 | billcole | 2026-06-25 21:29:55 +0000 (Thu, 25 Jun 2026) | 2
lines
Last fix?
------------------------------------------------------------------------
r1935647 | billcole | 2026-06-25 21:28:25 +0000 (Thu, 25 Jun 2026) | 2
lines
More fiddly http details
------------------------------------------------------------------------
r1935646 | billcole | 2026-06-25 21:22:23 +0000 (Thu, 25 Jun 2026) | 2
lines
Add http header to bailout
------------------------------------------------------------------------
r1935645 | billcole | 2026-06-25 21:09:55 +0000 (Thu, 25 Jun 2026) | 3
lines
Initial protective stanza added to bail out on excess load
------------------------------------------------------------------------
r1935636 | fkento | 2026-06-25 15:40:23 +0000 (Thu, 25 Jun 2026) | 1 line
Add Mailchimp redirector URL
------------------------------------------------------------------------
r1935621 | fkento | 2026-06-24 18:17:22 +0000 (Wed, 24 Jun 2026) | 1 line
Add pdf mime-type aliases
------------------------------------------------------------------------
r1935614 | fkento | 2026-06-24 07:24:06 +0000 (Wed, 24 Jun 2026) | 1 line
Add redirector for crono.one
------------------------------------------------------------------------
r1935606 | fkento | 2026-06-23 23:25:46 +0000 (Tue, 23 Jun 2026) | 1 line
plugin_file.t: match any stock plugin in loaded list, not ARC by
position.
------------------------------------------------------------------------
r1935605 | fkento | 2026-06-23 23:12:26 +0000 (Tue, 23 Jun 2026) | 1 line
Add 'handler' to debug facility list
------------------------------------------------------------------------
r1935596 | fkento | 2026-06-23 17:30:05 +0000 (Tue, 23 Jun 2026) | 1 line
Add heic/heif to mime-type map
------------------------------------------------------------------------
r1935564 | fkento | 2026-06-23 04:10:27 +0000 (Tue, 23 Jun 2026) | 8 lines
Add MIME-part handler framework for plugins
Plugins can register a method as the handler for a content-type pattern
via register_handler(). Each matching MIME part is dispatched to its
handler, which can inject extracted text and return synthetic child
parts that are dispatched recursively. Dispatch is bounded by new
handler_max_depth, handler_max_parts, handler_max_bytes, and
handler_time_limit options.
------------------------------------------------------------------------
r1935536 | fkento | 2026-06-21 05:01:52 +0000 (Sun, 21 Jun 2026) | 1 line
Util: keep user token as :name for malformed XS entries (revises
r1934692)
------------------------------------------------------------------------
r1935526 | gbechis | 2026-06-19 15:26:50 +0000 (Fri, 19 Jun 2026) | 2
lines
speedup SQL queries
------------------------------------------------------------------------
r1935477 | fkento | 2026-06-18 16:10:18 +0000 (Thu, 18 Jun 2026) | 1 line
Add redirector for Moosend
------------------------------------------------------------------------
r1935400 | gbechis | 2026-06-16 09:14:06 +0000 (Tue, 16 Jun 2026) | 2
lines
prevent "500 Header line too long (limit is 8192)" error
------------------------------------------------------------------------
r1935397 | fkento | 2026-06-16 06:42:39 +0000 (Tue, 16 Jun 2026) | 1 line
Add more redirector URLs for HighLevel CRM
------------------------------------------------------------------------
r1935396 | fkento | 2026-06-16 06:31:34 +0000 (Tue, 16 Jun 2026) | 1 line
Add redirector URLs for HighLevel CRM
------------------------------------------------------------------------
r1935363 | gbechis | 2026-06-15 15:43:05 +0000 (Mon, 15 Jun 2026) | 2
lines
fix check when MBOX files are checked
------------------------------------------------------------------------
r1935216 | jhardin | 2026-06-13 00:49:49 +0000 (Sat, 13 Jun 2026) | 1 line
replit.dev URL strong abuse sign in public email
------------------------------------------------------------------------
r1935148 | gbechis | 2026-06-08 15:09:30 +0000 (Mon, 08 Jun 2026) | 2
lines
move `check_examined` sub to a common file
------------------------------------------------------------------------
r1935147 | gbechis | 2026-06-08 15:03:46 +0000 (Mon, 08 Jun 2026) | 2
lines
add training buffer and periodic RPROP batch retrain
------------------------------------------------------------------------
r1934996 | gbechis | 2026-06-05 08:08:11 +0000 (Fri, 05 Jun 2026) | 2
lines
bare CR or LF are illegal; only \r\n followed by a space is valid folding
------------------------------------------------------------------------
r1934990 | gbechis | 2026-06-05 06:42:03 +0000 (Fri, 05 Jun 2026) | 2
lines
add more redirectors
------------------------------------------------------------------------
r1934987 | billcole | 2026-06-04 20:56:45 +0000 (Thu, 04 Jun 2026) | 1
line
tweak to drop php scans faster, canonicalize quoting
------------------------------------------------------------------------
r1934939 | billcole | 2026-06-03 17:34:05 +0000 (Wed, 03 Jun 2026) | 1
line
remove bogus VERSION args on package declarations
------------------------------------------------------------------------
r1934912 | gbechis | 2026-06-03 08:54:54 +0000 (Wed, 03 Jun 2026) | 2
lines
unbreak redirectors with uppercase path
------------------------------------------------------------------------
r1934889 | jhardin | 2026-06-02 14:51:47 +0000 (Tue, 02 Jun 2026) | 2
lines
Reduce TONLINE_FAKE_DKIM score limit, T-Online _may_ be signing mails
now.
bug#8397
------------------------------------------------------------------------
r1934880 | gbechis | 2026-06-02 13:09:09 +0000 (Tue, 02 Jun 2026) | 2
lines
cache only needed values, not the whole freqs hash
------------------------------------------------------------------------
r1934851 | billcole | 2026-06-01 17:11:37 +0000 (Mon, 01 Jun 2026) | 1
line
adding more bad referers
------------------------------------------------------------------------
r1934802 | fkento | 2026-05-31 04:42:36 +0000 (Sun, 31 May 2026) | 1 line
Add a couple URL "lengtheners"
------------------------------------------------------------------------
r1934694 | fkento | 2026-05-27 18:23:35 +0000 (Wed, 27 May 2026) | 1 line
Add links.iterable.com to redirectors
------------------------------------------------------------------------
r1934692 | fkento | 2026-05-27 16:50:58 +0000 (Wed, 27 May 2026) | 13
lines
Drop XS pseudo-entries with neither phrase nor address
When Email::Address::XS encounters unparseable input (e.g. a truncated
address header), it emits an entry with both address and phrase undef.
_parse_header_addresses_xs was copying the entire input string into
phrase for those entries, which caused header:first:name lookups to
return the whole header — for example, a long multi-recipient To header
truncated at MAX_HEADER_VALUE_LENGTH would yield a single 8KB 'name'
that matched any non-trivial length-based rule.
Drop these entries instead. The internal parser already does so
implicitly, and an entry with no address and no real phrase carries no
information for downstream :addr or :name consumers.
------------------------------------------------------------------------
r1934655 | fkento | 2026-05-26 19:00:13 +0000 (Tue, 26 May 2026) | 1 line
HTML: Collect cids during parsing. Useful to other plugins
------------------------------------------------------------------------
r1934654 | fkento | 2026-05-26 18:58:31 +0000 (Tue, 26 May 2026) | 1 line
disposition type is case-insensitive per RFC 2183
------------------------------------------------------------------------
r1934649 | fkento | 2026-05-26 17:51:41 +0000 (Tue, 26 May 2026) | 1 line
Add rule for testing
------------------------------------------------------------------------
r1934648 | fkento | 2026-05-26 17:48:44 +0000 (Tue, 26 May 2026) | 1 line
Change to scoring rule
------------------------------------------------------------------------
r1934642 | jhardin | 2026-05-26 14:57:29 +0000 (Tue, 26 May 2026) | 1 line
Add some rules for evaluation
------------------------------------------------------------------------
r1934573 | fkento | 2026-05-25 02:07:36 +0000 (Mon, 25 May 2026) | 1 line
Add .mimecastprotect.com to redirectors
------------------------------------------------------------------------
r1934572 | fkento | 2026-05-25 02:04:19 +0000 (Mon, 25 May 2026) | 8 lines
HTML: strip internal whitespace from http/https/ftp URIs in canon_uri
Some mailers soft-wrap long href values by inserting CRLF+space mid-URL.
MUAs strip that whitespace at click time, but SpamAssassin previously
kept it, leaving the URI mangled. The Redirectors plugin needs the
unmangled URL to follow shorteners/redirectors to their destination,
so canonicalize the URI by collapsing internal whitespace for
http/https/ftp schemes.
------------------------------------------------------------------------
r1934571 | fkento | 2026-05-25 00:25:28 +0000 (Mon, 25 May 2026) | 1 line
Remove bare domain app.getresponse.com
------------------------------------------------------------------------
r1934567 | fkento | 2026-05-24 18:45:08 +0000 (Sun, 24 May 2026) | 1 line
Redirectors: skip img-only URIs (likely tracking pixels, not redirectors)
------------------------------------------------------------------------
r1934565 | fkento | 2026-05-24 18:29:19 +0000 (Sun, 24 May 2026) | 1 line
Add more redirectors
------------------------------------------------------------------------
r1934560 | fkento | 2026-05-24 16:45:07 +0000 (Sun, 24 May 2026) | 1 line
Add path for certain redirectors
------------------------------------------------------------------------
r1934524 | fkento | 2026-05-22 22:38:16 +0000 (Fri, 22 May 2026) | 1 line
Add Active Campaign redirectors
------------------------------------------------------------------------
r1934511 | fkento | 2026-05-22 19:23:25 +0000 (Fri, 22 May 2026) | 1 line
remove bit.ly from url_shortener_get; HEAD method works fine
------------------------------------------------------------------------
r1934510 | fkento | 2026-05-22 17:35:24 +0000 (Fri, 22 May 2026) | 1 line
Move .blob.core.windows.net to url_redirector_selenium block
------------------------------------------------------------------------
r1934485 | fkento | 2026-05-21 18:49:34 +0000 (Thu, 21 May 2026) | 29
lines
Redirectors: add url_redirector_selenium directive for per-host Selenium
use
New directive registers hosts with method='selenium', mirroring
url_redirector / url_redirector_get syntax (bare domain, leading-dot
suffix, optional /path prefix). Lets operators opt specific hosts into
Selenium-driven redirect unwrapping without flipping the global flag
to "every redirector goes through Chrome".
url_redirector_use_selenium is redefined as a runtime kill switch for
the Selenium subsystem. When 0, hosts in url_redirector_selenium are
skipped entirely -- there is no LWP fallback, because hosts only
belong in that list if their redirects aren't discoverable via LWP
(e.g. JS-driven). redir_url() still fires for those hosts so detection
rules continue to work while the subsystem is off.
UAs are now built lazily and cached on $pms: messages with no
HTTP-eligible URIs no longer construct a UA at all, and Selenium init
failures cache undef so we don't retry per URL within a message.
Removed _make_ua in favor of _get_lwp_ua / _get_selenium_ua. Dropped
$ua from the _walk_redirects parameter chain.
_add_redirector_entry now warns when a domspec is re-registered with a
different method, so directive conflicts (e.g. same host in
url_redirector and url_redirector_selenium) don't silently flip
behavior based on parse order.
t/redirectors_match.t: added selenium-method round-trip cases.
t/redirectors.t: Selenium subblock now uses url_redirector_selenium
alongside url_redirector_use_selenium 1.
------------------------------------------------------------------------
r1934484 | fkento | 2026-05-21 17:29:06 +0000 (Thu, 21 May 2026) | 1 line
Add rule to detect Microsoft OAuth authorize endpoint redirector abuse
------------------------------------------------------------------------
r1934472 | fkento | 2026-05-21 06:32:02 +0000 (Thu, 21 May 2026) | 3 lines
Add rules to detect search engine redirector abuse
------------------------------------------------------------------------
r1934442 | fkento | 2026-05-20 17:04:24 +0000 (Wed, 20 May 2026) | 1 line
Add Google AMP redirectors and sort list
------------------------------------------------------------------------
r1934409 | fkento | 2026-05-19 18:09:32 +0000 (Tue, 19 May 2026) | 9 lines
Redirectors: register eval rule `redir_url_valid`
* Renamed sub and $pms flag from `redir_url_redir` to `redir_url_valid`.
Nothing
downstream could have been consuming the old name, since it was never
registered
as an eval rule.
* Added new eval rule `redir_url_valid` and POD documentation
------------------------------------------------------------------------
r1934403 | gbechis | 2026-05-19 15:18:22 +0000 (Tue, 19 May 2026) | 2
lines
add an url shortener
------------------------------------------------------------------------
r1934387 | fkento | 2026-05-19 06:24:54 +0000 (Tue, 19 May 2026) | 1 line
Add more Google domains
------------------------------------------------------------------------
r1934386 | fkento | 2026-05-19 06:16:49 +0000 (Tue, 19 May 2026) | 12
lines
Prevent wasted HTTP traffic to non-redirect URLs
* awstrack.me
* exactag.com
* cc.rs6.net
* mandrillapp.com
* list-manage.com
* bing.com
* msn.com
* msn.com.br
------------------------------------------------------------------------
r1934382 | fkento | 2026-05-19 05:56:49 +0000 (Tue, 19 May 2026) | 1 line
Limit HTTP lookups on non-redirector Google URLs
------------------------------------------------------------------------
r1934381 | fkento | 2026-05-19 05:18:03 +0000 (Tue, 19 May 2026) | 32
lines
Redirectors: gate HTTP requests on configured-redirector allowlist
Refactored the plugin so HTTP requests are only made to hosts listed
in
url_redirector / url_redirector_get.
Previously, when an embedded URL was found in a querystring parameter,
the plugin would HTTP-fetch that embedded URL, even when its host was
not on the allowlist. The allowlist is meant to limit which hosts the
plugin probes, in order to prevent accidentally triggering an action
such as unsubscribing from a list, confirming an email, or approving
a request.
Extracted URLs are still added to uri_detail_list so URI rules see
them. Only the unwarranted HTTP fetch is suppressed.
Embedded-URI extraction now also runs when network tests are
disabled,
since it requires no HTTP.
Existing flag semantics (redir_url, redir_url_redir,
redir_url_chained,
redir_url_chained_domain, redir_url_loop, redir_url_maxchain,
redir_url_<rcode>) and the documented max_redir_urls /
max_redir_url_redirections limits are preserved.
Isolated HTTP work in a helper method _do_http
t/redirectors.t and its fixtures switched from third-party hosts
(google.com, disq.us) to apache.org-only endpoints
(spamassassin.apache.org/full/4.0.x for a real 301 chain,
community.apache.org/404 for a real 404), so SpamAssassin's test suite
no longer sends traffic to outside services.
------------------------------------------------------------------------
r1934363 | fkento | 2026-05-18 21:59:47 +0000 (Mon, 18 May 2026) | 1 line
Preserve anchor_text and types from redirected URL
------------------------------------------------------------------------
r1934355 | jhardin | 2026-05-18 14:34:35 +0000 (Mon, 18 May 2026) | 1 line
Add MSFT free content hosting to aux_tlds, observed in phishing
------------------------------------------------------------------------
r1934333 | fkento | 2026-05-18 05:33:59 +0000 (Mon, 18 May 2026) | 1 line
Add more url redirectors
------------------------------------------------------------------------
r1934332 | fkento | 2026-05-18 04:31:22 +0000 (Mon, 18 May 2026) | 22
lines
Redirectors: support per-path matching and simplify domain matching
- url_redirector and url_redirector_get accept an optional /path suffix;
a URL only matches when its path begins with that string and ends at
a path-segment boundary. Useful to follow click-tracking endpoints
(e.g. .r.af.d.sendibt2.com/tr/cl/) without chasing tracking-pixel
endpoints (/tr/op/) on the same host.
- Rewrote _check_redirector_uri: linear lookup (exact host, auto-www,
suffix walk) replaces the previous dot-counting branches. Leading-dot
entries match subdomains only, not the bare domain (matches prior
behavior). Bare entries still auto-match the www subdomain.
- clear_url_redirector understands the same domain/path syntax and
drops the host entry when its path list becomes empty.
- has_url_redirector_path version feature so rule files can gate the
new syntax with can().
- 25_url_redirectors.cf: restrict .awstrack.me to /L0/ (click) so the
open-tracking /O0/ endpoint is no longer fetched.
- t/redirectors_match.t: new unit tests (network-independent) cover
domain matching, path-prefix gating, segment-boundary handling, and
clear_url_redirector.
- t/debug.t: register the existing "Redirectors" debug facility, which
the new code paths surface more frequently.
------------------------------------------------------------------------
r1934280 | fkento | 2026-05-17 01:12:15 +0000 (Sun, 17 May 2026) | 1 line
Remove TxRep dependency on ->all_from_addrs()[0] -- check From:addr
directly
------------------------------------------------------------------------
r1934279 | fkento | 2026-05-17 01:08:19 +0000 (Sun, 17 May 2026) | 2 lines
all_from_addrs / all_to_addrs: append Resent-* headers instead of
replacing the normal From/To set, so welcomelist/blocklist/RBL/freemail
rules still see the original author and recipients on resent mail
bz #8394
------------------------------------------------------------------------
r1934252 | jhardin | 2026-05-16 02:56:14 +0000 (Sat, 16 May 2026) | 1 line
FP Avoidance tuning
------------------------------------------------------------------------
r1934251 | jhardin | 2026-05-16 02:44:30 +0000 (Sat, 16 May 2026) | 1 line
Set score limit on a rule
------------------------------------------------------------------------
r1934193 | gbechis | 2026-05-14 16:26:10 +0000 (Thu, 14 May 2026) | 2
lines
add welcomelist_spf tests
------------------------------------------------------------------------
r1934167 | gbechis | 2026-05-13 14:45:24 +0000 (Wed, 13 May 2026) | 4
lines
add url_skip_redirect_to option to prevent loops
with urls that go to intermediate consent/gateway pages
and then go back to previous url
------------------------------------------------------------------------
r1934166 | gbechis | 2026-05-13 13:15:32 +0000 (Wed, 13 May 2026) | 2
lines
more improvements to replay algorithm
------------------------------------------------------------------------
r1934147 | billcole | 2026-05-12 17:09:16 +0000 (Tue, 12 May 2026) | 1
line
Fix HTML_FONT_SIZE_HUGE to work with px (4.x) and web-sized (1-7) fonts.
As suggested by Matija Nalis on the Users list.
------------------------------------------------------------------------
r1934130 | gbechis | 2026-05-12 06:28:14 +0000 (Tue, 12 May 2026) | 2
lines
improve replay algorithm
------------------------------------------------------------------------
r1934105 | fkento | 2026-05-11 16:28:26 +0000 (Mon, 11 May 2026) | 1 line
Add freemail domain myyahoo.com
------------------------------------------------------------------------
r1934077 | gbechis | 2026-05-11 07:56:07 +0000 (Mon, 11 May 2026) | 2
lines
fix locking
------------------------------------------------------------------------
r1934076 | gbechis | 2026-05-11 07:25:15 +0000 (Mon, 11 May 2026) | 2
lines
improve replay algorithm, improve locking
------------------------------------------------------------------------
r1934061 | fkento | 2026-05-10 19:57:23 +0000 (Sun, 10 May 2026) | 12
lines
Add more freemail domains
bell.net
cox.net
earthlink.net
hawaiiantel.net
optonline.net
verizon.net
windstream.net
zoominternet.net
------------------------------------------------------------------------
r1934007 | jhardin | 2026-05-09 20:38:05 +0000 (Sat, 09 May 2026) | 1 line
Add another observed scam phone number
------------------------------------------------------------------------
r1933970 | jhardin | 2026-05-09 02:04:56 +0000 (Sat, 09 May 2026) | 1 line
FP avoidance tuning
------------------------------------------------------------------------
r1933927 | jhardin | 2026-05-08 01:47:09 +0000 (Fri, 08 May 2026) | 1 line
Add another observed scam phone number, broaden obfuscation detection
------------------------------------------------------------------------
r1933911 | gbechis | 2026-05-07 16:37:59 +0000 (Thu, 07 May 2026) | 2
lines
held the lock for less time to speedup concurrent training
------------------------------------------------------------------------
r1933887 | gbechis | 2026-05-06 13:54:16 +0000 (Wed, 06 May 2026) | 3
lines
Wrap the retry loop in eval so an alarm/die during the wait does
not leak the temp lock file
------------------------------------------------------------------------
r1933883 | fkento | 2026-05-06 10:54:51 +0000 (Wed, 06 May 2026) | 1 line
Remove bad sandbox rules
------------------------------------------------------------------------
r1933882 | fkento | 2026-05-06 10:53:42 +0000 (Wed, 06 May 2026) | 1 line
Remove bad sandbox rules
------------------------------------------------------------------------
r1933837 | fkento | 2026-05-05 01:52:11 +0000 (Tue, 05 May 2026) | 5 lines
MIMEEval: anchor mime_attachment match to disposition type
Avoid false positives where the Content-Disposition is 'inline' but the
filename parameter contains the substring 'attachment' (e.g.
'inline; filename=...Attachment.png').
------------------------------------------------------------------------
r1933817 | gbechis | 2026-05-04 16:27:31 +0000 (Mon, 04 May 2026) | 2
lines
avoid a warning
------------------------------------------------------------------------
r1933809 | jhardin | 2026-05-04 14:13:27 +0000 (Mon, 04 May 2026) | 1 line
add another observed scam phone number
------------------------------------------------------------------------
r1933800 | gbechis | 2026-05-04 06:33:17 +0000 (Mon, 04 May 2026) | 2
lines
fix check_neuralnetwork sub
------------------------------------------------------------------------
r1933794 | fkento | 2026-05-03 22:35:33 +0000 (Sun, 03 May 2026) | 1 line
Add t/html_whitespace.t (missing from r1933760)
------------------------------------------------------------------------
r1933793 | jhardin | 2026-05-03 21:45:51 +0000 (Sun, 03 May 2026) | 1 line
FP tuning
------------------------------------------------------------------------
r1933775 | fkento | 2026-05-03 17:25:41 +0000 (Sun, 03 May 2026) | 1 line
Add rules to check for vertical whitespace
------------------------------------------------------------------------
r1933774 | fkento | 2026-05-03 17:02:25 +0000 (Sun, 03 May 2026) | 1 line
fix POD: add missing =over 4 before extracttext_cache_autoclean =item
------------------------------------------------------------------------
r1933760 | fkento | 2026-05-03 07:44:36 +0000 (Sun, 03 May 2026) | 26
lines
Add eval:vertical_whitespace(<threshold>)
Triggers when the number of consecutive blanks lines exceeds <threshold>
This offers several improvements over eval:check_blank_line_ratio():
check_blank_line_ratio
- Calls get_decoded_body_text_array()
- Includes all parts
- Includes raw html markup
- Includes invisible text
- Counts all blank lines
vertical_whitespace
- Calls visible_rendered()
- Includes message body only (no attachments)
- Renders HTML
- Excludes invisible text
- Counts consecutive blank lines
The changes to HTML.pm are to
- Render whitespace closer to how an MUA would render it
- Prevent false positives because **too much** whitespace was in the
rendered output
------------------------------------------------------------------------
r1933717 | jhardin | 2026-05-02 19:41:15 +0000 (Sat, 02 May 2026) | 1 line
Publish a good-performing rule
------------------------------------------------------------------------
r1933706 | gbechis | 2026-05-02 12:58:03 +0000 (Sat, 02 May 2026) | 4
lines
improve caching
improve html handling, from fkento@
add more fine grained rules, from fkento@
------------------------------------------------------------------------
r1933702 | jhardin | 2026-05-02 04:12:41 +0000 (Sat, 02 May 2026) | 1 line
Add obfu rule for evaluation
------------------------------------------------------------------------
r1933701 | jhardin | 2026-05-02 03:48:42 +0000 (Sat, 02 May 2026) | 1 line
Add some missed glyphs observed in spam to 25_replace.cf
------------------------------------------------------------------------
r1933698 | jhardin | 2026-05-02 01:24:40 +0000 (Sat, 02 May 2026) | 1 line
Add more observed scam phone numbers
------------------------------------------------------------------------
r1933570 | gbechis | 2026-04-30 06:50:38 +0000 (Thu, 30 Apr 2026) | 4
lines
retrain model after pruning
add more info to the vocabulary like bayes already does
change default values to be a bit more aggressive
------------------------------------------------------------------------
r1933479 | gbechis | 2026-04-29 09:40:30 +0000 (Wed, 29 Apr 2026) | 2
lines
mention ExtractText cache
------------------------------------------------------------------------
r1933478 | gbechis | 2026-04-29 09:38:16 +0000 (Wed, 29 Apr 2026) | 2
lines
sync MANIFEST
------------------------------------------------------------------------
r1933477 | gbechis | 2026-04-29 09:34:28 +0000 (Wed, 29 Apr 2026) | 2
lines
add cache support to ExtractText plugin
------------------------------------------------------------------------
r1933471 | jhardin | 2026-04-29 03:46:39 +0000 (Wed, 29 Apr 2026) | 1 line
Obfuscated HTML attachment tweaks
------------------------------------------------------------------------
r1933469 | jhardin | 2026-04-29 01:47:05 +0000 (Wed, 29 Apr 2026) | 1 line
Add another observed scammer phone number
------------------------------------------------------------------------
r1933468 | gbechis | 2026-04-28 22:17:16 +0000 (Tue, 28 Apr 2026) | 3
lines
do not trigger RDNS_DYNAMIC on mta-ru-XXX hostnames
bz #8391
------------------------------------------------------------------------
r1933414 | gbechis | 2026-04-28 08:51:42 +0000 (Tue, 28 Apr 2026) | 1 line
sync
------------------------------------------------------------------------
r1933413 | gbechis | 2026-04-28 08:49:41 +0000 (Tue, 28 Apr 2026) | 1 line
add a redirector
------------------------------------------------------------------------
r1933396 | gbechis | 2026-04-27 16:43:36 +0000 (Mon, 27 Apr 2026) | 2
lines
mention check_hashbl_bodyfuzzy() new sub added to HashBL plugin
------------------------------------------------------------------------
r1933395 | gbechis | 2026-04-27 16:31:51 +0000 (Mon, 27 Apr 2026) | 8
lines
Add FuzzyHash::ZOrder MinHash/LSH near-duplicate body detection
Integrate into HashBL plugin via check_hashbl_bodyfuzzy(), which
queries a DNS blocklist for indexed body digests and fires when
similarity (0-100 Hamming-based score) meets the configured
sim_threshold.
This new rbl type matches on emails similar to known spam messages.
------------------------------------------------------------------------
r1933375 | gbechis | 2026-04-27 06:45:50 +0000 (Mon, 27 Apr 2026) | 1 line
add url shortener
------------------------------------------------------------------------
r1933373 | gbechis | 2026-04-27 06:38:36 +0000 (Mon, 27 Apr 2026) | 2
lines
prevent corrupted models from being written to filesystem
------------------------------------------------------------------------
r1933372 | fkento | 2026-04-27 05:16:00 +0000 (Mon, 27 Apr 2026) | 1 line
Add branded bitly domain (rem.ax)
------------------------------------------------------------------------
r1933316 | jhardin | 2026-04-24 21:54:04 +0000 (Fri, 24 Apr 2026) | 1 line
Add PMP training rule for eval
------------------------------------------------------------------------
r1933315 | jhardin | 2026-04-24 20:53:34 +0000 (Fri, 24 Apr 2026) | 1 line
Another scammer phone number
------------------------------------------------------------------------
r1933279 | jhardin | 2026-04-24 01:35:51 +0000 (Fri, 24 Apr 2026) | 1 line
Update scam phone numbers
------------------------------------------------------------------------
r1933272 | gbechis | 2026-04-23 16:23:39 +0000 (Thu, 23 Apr 2026) | 3
lines
log all occurrences of captured tags
bz #8392
------------------------------------------------------------------------
r1933250 | jhardin | 2026-04-22 14:42:24 +0000 (Wed, 22 Apr 2026) | 1 line
phone number obfu FP tuning
------------------------------------------------------------------------
r1933226 | gbechis | 2026-04-21 21:02:57 +0000 (Tue, 21 Apr 2026) | 3
lines
Substitute %{TAGNAME} at each message check, fixes capture tags in
spamd(8)
bz #8388
------------------------------------------------------------------------
r1933186 | gbechis | 2026-04-20 15:14:51 +0000 (Mon, 20 Apr 2026) | 2
lines
prune vocabulary in the correct code path
------------------------------------------------------------------------
r1933166 | jhardin | 2026-04-20 01:06:54 +0000 (Mon, 20 Apr 2026) | 7
lines
Bug #8389
RuleQA: Implement fallback to previously-published scores on masscheck
corpus starvation that would previously have completely blocked rule
publication. This allows rule bug fixes to be published even in the face
of masscheck corpus problems.
Kill switch: Suppress all publication after checking corpus state by
creating /usr/local/spamassassin/automc/DISABLE_PUBLISH on sa-vm - hard
gate for disaster response.
Code generated with assistance of Claude Sonnet 4.6, adversarial review
by Claude Opus 4.7
------------------------------------------------------------------------
r1933165 | jhardin | 2026-04-19 18:12:03 +0000 (Sun, 19 Apr 2026) | 1 line
Phone number obfuscation FP tuning
------------------------------------------------------------------------
r1933162 | gbechis | 2026-04-19 13:57:03 +0000 (Sun, 19 Apr 2026) | 4
lines
use 2 hidden neurons in the neural network
consistently use correct SIGMOID algorithm
use chi-squared algorithm to prune unused terms
------------------------------------------------------------------------
r1933152 | jhardin | 2026-04-18 18:26:38 +0000 (Sat, 18 Apr 2026) | 1 line
Remove some dubious letter obfuscations of digits, might be used but
increases FP risk
------------------------------------------------------------------------
r1933151 | jhardin | 2026-04-18 18:17:32 +0000 (Sat, 18 Apr 2026) | 1 line
More observed phone scam numbers
------------------------------------------------------------------------
r1933150 | jhardin | 2026-04-18 18:03:31 +0000 (Sat, 18 Apr 2026) | 1 line
Migrate X-Mailer rules to their own file and normalize.
------------------------------------------------------------------------
r1933141 | fkento | 2026-04-17 20:15:46 +0000 (Fri, 17 Apr 2026) | 1 line
Large negative absolute positioning is invisible text
------------------------------------------------------------------------
r1933139 | fkento | 2026-04-17 18:38:39 +0000 (Fri, 17 Apr 2026) | 1 line
Text with 'transform: scale(0)' should be treated as invisible
------------------------------------------------------------------------
r1933135 | billcole | 2026-04-17 12:57:50 +0000 (Fri, 17 Apr 2026) | 1
line
fix FP BZ#8387
------------------------------------------------------------------------
r1933134 | billcole | 2026-04-17 12:54:34 +0000 (Fri, 17 Apr 2026) | 1
line
fix FP BZ#8387
------------------------------------------------------------------------
r1933124 | jhardin | 2026-04-17 01:17:24 +0000 (Fri, 17 Apr 2026) | 1 line
digidip (phishing-abused public redirector) has multiple redirector
subdomains
------------------------------------------------------------------------
r1933098 | gbechis | 2026-04-16 07:31:11 +0000 (Thu, 16 Apr 2026) | 2
lines
speedup learning phase
------------------------------------------------------------------------
r1933012 | gbechis | 2026-04-13 07:19:37 +0000 (Mon, 13 Apr 2026) | 8
lines
Fix spamc hang on TLS 1.3 connections due to post-handshake
NewSessionTicket records
Add a --debug parameter to spamc(1)
Submitted by: Dan Mahoney <github@gushi.org>
with tweaks by me
Github: closes #26
------------------------------------------------------------------------
r1933011 | gbechis | 2026-04-13 06:56:39 +0000 (Mon, 13 Apr 2026) | 7
lines
Fix SSL socket binding bugs and update SSL documentation
Submitted by: Dan Mahoney <github@gushi.org>
with tweaks by me
Github: closes #25
------------------------------------------------------------------------
r1933002 | jhardin | 2026-04-12 19:34:29 +0000 (Sun, 12 Apr 2026) | 1 line
Add a generic formatted phone number obfuscation detector for evaluation
------------------------------------------------------------------------
r1932973 | jhardin | 2026-04-11 01:04:36 +0000 (Sat, 11 Apr 2026) | 1 line
Retire VALIDITY subrules to avoid problems
------------------------------------------------------------------------
r1932968 | billcole | 2026-04-10 15:02:25 +0000 (Fri, 10 Apr 2026) | 1
line
Beating Validity to death, decapitating, and staking the heart
------------------------------------------------------------------------
r1932938 | jhardin | 2026-04-10 03:36:37 +0000 (Fri, 10 Apr 2026) | 1 line
Add another phone scam number, work around replacetags "falsy" bug
------------------------------------------------------------------------
r1932937 | jhardin | 2026-04-10 03:34:56 +0000 (Fri, 10 Apr 2026) | 1 line
Work around ReplaceTags subjecting tag names to perl "falsy" logic
------------------------------------------------------------------------
r1932918 | jhardin | 2026-04-09 01:17:08 +0000 (Thu, 09 Apr 2026) | 1 line
Add new phone scam number
------------------------------------------------------------------------
r1932887 | gbechis | 2026-04-08 06:42:02 +0000 (Wed, 08 Apr 2026) | 3
lines
improve locking and retrain algorithm
improve forget method
------------------------------------------------------------------------
r1932882 | gbechis | 2026-04-07 16:54:23 +0000 (Tue, 07 Apr 2026) | 2
lines
add Inky's redirector
------------------------------------------------------------------------
r1932878 | fkento | 2026-04-07 07:21:37 +0000 (Tue, 07 Apr 2026) | 9 lines
ARC: only trust contiguous run of trusted sealers at top of chain
When collecting trusted ARC instances, walk the chain from newest to
oldest and stop at the first untrusted sealer. An untrusted hop means
anything older than it cannot be trusted either, since that untrusted
intermediary could have forged the older AAR headers. Previously any
seal signed by a trusted domain was accepted regardless of position,
which could allow a trusted sealer downstream of an untrusted hop to
vouch for results that were never actually verified by a trusted party.
------------------------------------------------------------------------
r1932860 | jhardin | 2026-04-05 18:22:54 +0000 (Sun, 05 Apr 2026) | 1 line
Allow for 3TLD only-one-domain bug
------------------------------------------------------------------------
r1932846 | fkento | 2026-04-04 14:26:16 +0000 (Sat, 04 Apr 2026) | 1 line
Honor skip_uribl_checks in AskDNS plugin
------------------------------------------------------------------------
r1932777 | gbechis | 2026-04-03 07:07:17 +0000 (Fri, 03 Apr 2026) | 1 line
add url shortener
------------------------------------------------------------------------
r1932725 | jhardin | 2026-04-02 02:40:05 +0000 (Thu, 02 Apr 2026) | 1 line
Add misleading MailChimp account name rule
------------------------------------------------------------------------
r1932724 | jhardin | 2026-04-02 02:36:19 +0000 (Thu, 02 Apr 2026) | 1 line
Add list-manage.com regional subdomains as 3TLDs, the subdomain below
that is user-controlled.
------------------------------------------------------------------------
r1932694 | gbechis | 2026-04-01 06:37:43 +0000 (Wed, 01 Apr 2026) | 2
lines
add url shorteners
------------------------------------------------------------------------
r1932669 | billcole | 2026-03-30 19:09:51 +0000 (Mon, 30 Mar 2026) | 1
line
testing .world with its own rule...
------------------------------------------------------------------------
r1932597 | jhardin | 2026-03-27 17:16:58 +0000 (Fri, 27 Mar 2026) | 1 line
FP Avoidance tuning, promote a rule to scored
------------------------------------------------------------------------
r1932596 | jhardin | 2026-03-27 16:42:56 +0000 (Fri, 27 Mar 2026) | 1 line
Added another scam phone number
------------------------------------------------------------------------
r1932595 | jhardin | 2026-03-27 16:25:10 +0000 (Fri, 27 Mar 2026) | 1 line
Fix incomplete emoji byte range
------------------------------------------------------------------------
r1932590 | gbechis | 2026-03-27 08:17:35 +0000 (Fri, 27 Mar 2026) | 2
lines
avoid warnings SpamAssassin versions older then trunk
------------------------------------------------------------------------
r1932584 | jhardin | 2026-03-27 01:37:10 +0000 (Fri, 27 Mar 2026) | 1 line
Add rule to check legitimacy of suspicious Google infra URL
------------------------------------------------------------------------
r1932583 | jhardin | 2026-03-27 01:18:03 +0000 (Fri, 27 Mar 2026) | 1 line
Add subrules for emoji(s) in subject and from name
------------------------------------------------------------------------
r1932582 | jhardin | 2026-03-27 00:46:09 +0000 (Fri, 27 Mar 2026) | 1 line
Add new numbers, FP avoidance tuning
------------------------------------------------------------------------
r1932581 | jhardin | 2026-03-27 00:44:33 +0000 (Fri, 27 Mar 2026) | 1 line
Add EMOJI and EMOJI_BROAD replace tokens
------------------------------------------------------------------------
r1932516 | fkento | 2026-03-24 20:24:04 +0000 (Tue, 24 Mar 2026) | 13
lines
Handle DMARC permerror/temperror without falling back to
Mail::DMARC::PurePerl
When an Authentication-Results header contains dmarc=permerror or
dmarc=temperror, these are terminal results that should not trigger a
fallback to Mail::DMARC::PurePerl for a redundant DNS lookup.
Also fixes the Mail::DMARC::PurePerl path where "too many policies"
was incorrectly setting dmarc_policy to "no policy available", which
caused check_dmarc_missing to fire instead of the more accurate
permerror result.
Adds new check_dmarc_permerror and check_dmarc_temperror eval rules
with corresponding DMARC_PERMERROR and DMARC_TEMPERROR rules.
------------------------------------------------------------------------
r1932487 | fkento | 2026-03-23 18:24:20 +0000 (Mon, 23 Mar 2026) | 5 lines
Fix uninitialized value warnings from queue-based MIME traversal
The queue-based tree walk bypassed find_parts(), which was responsible
for triggering lazy body parsing via parse_body(). Add explicit
parse_body() call before traversal to ensure the MIME tree is built.
------------------------------------------------------------------------
r1932464 | jhardin | 2026-03-22 17:17:43 +0000 (Sun, 22 Mar 2026) | 1 line
Phone number FP reduction
------------------------------------------------------------------------
r1932429 | gbechis | 2026-03-21 08:06:50 +0000 (Sat, 21 Mar 2026) | 2
lines
rewrite locking logic using `Mail::SpamAssassin::Locker`
------------------------------------------------------------------------
r1932428 | fkento | 2026-03-21 04:35:43 +0000 (Sat, 21 Mar 2026) | 6 lines
Add multipart_alternative_preferred_part config option
New setting allows choosing which part of a multipart/alternative
section to use for rendered body text (text/html or text/plain),
skipping the other alternative. Defaults to empty (all parts included,
preserving existing behavior).
------------------------------------------------------------------------
r1932427 | fkento | 2026-03-21 04:31:44 +0000 (Sat, 21 Mar 2026) | 12
lines
DMARC plugin: fix undef warnings when ARC overrides DMARC result
When ARC overrides a DMARC fail to pass, the code then tried to look up
the published policy via $result->published->p, which dies because the
original validation was a failure with no pass-path policy. This left
dmarc_policy unset, causing 'uninitialized value' warnings in the eval
closures and a logged exception.
Fix by setting dmarc_policy from the original disposition when ARC
overrides, and wrapping $result->published->p in eval for the normal
pass path. Added defined checks on dmarc_policy in all eval closures
as a safety net.
------------------------------------------------------------------------
r1932424 | jhardin | 2026-03-21 02:24:04 +0000 (Sat, 21 Mar 2026) | 1 line
use replacetags digit patterns
------------------------------------------------------------------------
r1932423 | jhardin | 2026-03-21 02:01:36 +0000 (Sat, 21 Mar 2026) | 1 line
Add replace tag for all digits (like \d only obfuscation-aware)
------------------------------------------------------------------------
r1932422 | jhardin | 2026-03-21 01:16:05 +0000 (Sat, 21 Mar 2026) | 1 line
Add another scam phone number
------------------------------------------------------------------------
r1932421 | jhardin | 2026-03-21 01:14:13 +0000 (Sat, 21 Mar 2026) | 1 line
add replace tags for obfuscated digits
------------------------------------------------------------------------
r1932411 | gbechis | 2026-03-20 13:42:56 +0000 (Fri, 20 Mar 2026) | 1 line
fix destroy method
------------------------------------------------------------------------
r1932400 | gbechis | 2026-03-20 07:43:57 +0000 (Fri, 20 Mar 2026) | 2
lines
close open handles on exit
------------------------------------------------------------------------
r1932382 | gbechis | 2026-03-19 08:14:29 +0000 (Thu, 19 Mar 2026) | 2
lines
use a shared or exclusive lock on the model files
------------------------------------------------------------------------
r1932380 | fkento | 2026-03-19 06:28:44 +0000 (Thu, 19 Mar 2026) | 1 line
Fix "uninitialized value in die" warning when using AuthRes+DKIM
------------------------------------------------------------------------
r1932372 | gbechis | 2026-03-18 17:58:13 +0000 (Wed, 18 Mar 2026) | 3
lines
add `txrep_skip_domain` option in order to completely
skip TxRep processing for some domains
------------------------------------------------------------------------
r1932371 | gbechis | 2026-03-18 17:45:19 +0000 (Wed, 18 Mar 2026) | 3
lines
Fix NS queries, A dns queries were always triggered
bz #8374
------------------------------------------------------------------------
r1932360 | fkento | 2026-03-17 19:01:30 +0000 (Tue, 17 Mar 2026) | 12
lines
ARC plugin: re-use arc= results from AuthRes plugin when available
The ARC plugin now checks for parsed arc= results from the AuthRes
plugin before performing its own Mail::DKIM::ARC::Verifier-based
cryptographic verification. Plugin priorities swapped so AuthRes (-20)
runs before ARC (-10).
Trusted AAR parsing refactored into a shared helper so it works both
with the native verifier path and the AuthRes path (which parses
ARC-Seal headers directly for trusted domain detection).
If AuthRes is not loaded, behavior is unchanged.
------------------------------------------------------------------------
r1932359 | fkento | 2026-03-17 18:19:19 +0000 (Tue, 17 Mar 2026) | 10
lines
DMARC plugin: use results from AuthRes plugin when available
When the AuthRes plugin has parsed a DMARC result and policy from an
Authentication-Results header, use those instead of performing local
validation with Mail::DMARC::PurePerl. Both result and published domain
policy (via policy.published-domain-policy property) must be present;
otherwise the plugin falls back to its own validation.
ARC override logic extracted into shared _check_arc_override method
used by both the AuthRes and Mail::DMARC::PurePerl code paths.
------------------------------------------------------------------------
r1932356 | jhardin | 2026-03-17 09:52:41 +0000 (Tue, 17 Mar 2026) | 1 line
Add new rules for specific phone numbers observed in scams.
------------------------------------------------------------------------
r1932347 | fkento | 2026-03-16 20:13:53 +0000 (Mon, 16 Mar 2026) | 12
lines
DKIM plugin: re-use results from AuthRes plugin when available
The DKIM plugin now checks for parsed DKIM results from the AuthRes
plugin before performing its own Mail::DKIM-based verification. This
avoids redundant signature verification when Authentication-Results
headers have already been parsed by a trusted MTA.
Constructs real Mail::DKIM::Signature objects from AuthRes data so all
existing code paths (valid signature checks, author domain signature
detection, welcomelist matching) work unchanged.
Priority order: caller-supplied signatures > AuthRes > own verification.
------------------------------------------------------------------------
r1932342 | fkento | 2026-03-16 17:47:42 +0000 (Mon, 16 Mar 2026) | 1 line
Clean up ARC debug output
------------------------------------------------------------------------
r1932341 | fkento | 2026-03-16 17:30:31 +0000 (Mon, 16 Mar 2026) | 5 lines
Fix ARC debug logging: use domain() directly instead of DKIM-style
identity extraction
ARC signatures use i= for the instance index, not an email identity
like DKIM. The identity-based domain extraction was returning undef
because there is no @ in the ARC i= value.
------------------------------------------------------------------------
r1932333 | fkento | 2026-03-16 11:54:00 +0000 (Mon, 16 Mar 2026) | 1 line
Fix typo
------------------------------------------------------------------------
r1932331 | fkento | 2026-03-16 11:06:43 +0000 (Mon, 16 Mar 2026) | 21
lines
Separate ARC into dedicated plugin from DKIM
ARC (Authenticated Received Chain, RFC 8617) verification was
previously
embedded in the DKIM plugin. This moves it to a standalone
Mail::SpamAssassin::Plugin::ARC with its own configuration and rules.
New plugin features:
- arc_trusted_sealers config to specify trusted ARC sealer domains
- Parses ARC-Authentication-Results headers from trusted sealers
- check_arc_trusted eval rule for messages with trusted ARC results
- Runs in parsed_metadata phase so results are available to other
plugins
New Mail::SpamAssassin::Header::ArcAuthenticationResults class extends
AuthenticationResults to handle the i= instance index prefix in AAR
headers.
DMARC plugin updated to use parsed AAR results: when DMARC fails and a
trusted AAR contains dmarc=pass, the result is overridden directly
instead of reconstructing validation from SPF+DKIM components.
------------------------------------------------------------------------
r1932302 | fkento | 2026-03-15 05:33:23 +0000 (Sun, 15 Mar 2026) | 16
lines
SPF plugin: prefer AuthRes plugin results over direct header parsing
Restructure _check_spf() to use a three-tier priority for obtaining
SPF results:
1. AuthRes plugin ($pms->{authres_parsed}{spf}) - preferred source
since AuthRes already handles trusted header filtering and proper
RFC 8601 parsing
2. Received-SPF headers from internal hosts - unchanged fallback
3. DNS lookups via Mail::SPF - last resort
Remove the old manual Authentication-Results header regex parsing from
the SPF plugin, as this is now handled by the AuthRes plugin. Extract
repeated result-setting code into _set_spf_result() helper.
Update UPGRADE to note that users relying on A-R header parsing need
to enable the AuthRes plugin (v401.pre).
------------------------------------------------------------------------
r1932298 | fkento | 2026-03-14 08:14:50 +0000 (Sat, 14 Mar 2026) | 25
lines
Rewrite AuthRes plugin to use new Header::AuthenticationResults parser
The AuthRes plugin previously hand-rolled a fragile A-R header parser
that
died (discarding the entire header) on unknown methods or properties.
Real-world headers from servers like Mail::Milter::Authentication
include
extended properties (policy.published-domain-policy) and non-standard
methods (x-tls) that caused valid results to be skipped.
Create Mail::SpamAssassin::Header::AuthenticationResults, inheriting
from
ParameterHeader, which handles the structural parsing (comment
stripping,
semicolon tokenization, quoted strings, line unfolding). The subclass
adds
A-R-specific secondary parsing of method results and
ptype.property=value
pairs.
Simplify the AuthRes plugin to use the new class. Remove the
hand-rolled
parser (regex constants, skip_cfws, the old parse_authres), the method/
property whitelists, and ARC handling (handled in other plugins). All
parsed methods and properties now flow through to
$pms->{authres_parsed}
regardless of whether they appear in a whitelist, so
check_authres_result
works for any method present in the header.
The $pms->{authres_parsed} and $pms->{authres_result} structures are
preserved for compatibility with other plugins.
------------------------------------------------------------------------
r1932294 | axb | 2026-03-13 09:52:55 +0000 (Fri, 13 Mar 2026) | 1 line
added tr.ee
------------------------------------------------------------------------
r1932277 | gbechis | 2026-03-12 10:18:55 +0000 (Thu, 12 Mar 2026) | 2
lines
avoid a warning if http connection breaks
------------------------------------------------------------------------
r1932276 | gbechis | 2026-03-12 09:01:39 +0000 (Thu, 12 Mar 2026) | 3
lines
reset PerMsgStatus at the correct time, otherwise memory is not always
deallocated.
correctly assign username
------------------------------------------------------------------------
r1932267 | gbechis | 2026-03-11 18:00:39 +0000 (Wed, 11 Mar 2026) | 2
lines
install v403.pre file
------------------------------------------------------------------------
r1932264 | gbechis | 2026-03-11 16:05:06 +0000 (Wed, 11 Mar 2026) | 2
lines
sync with latest changes
------------------------------------------------------------------------
r1932263 | gbechis | 2026-03-11 15:59:01 +0000 (Wed, 11 Mar 2026) | 1 line
add a url shortener
------------------------------------------------------------------------
r1932250 | gbechis | 2026-03-10 08:46:06 +0000 (Tue, 10 Mar 2026) | 2
lines
improve locking
------------------------------------------------------------------------
r1932248 | gbechis | 2026-03-10 07:51:45 +0000 (Tue, 10 Mar 2026) | 3
lines
do not downgrade requests to plain http
bz #8373
------------------------------------------------------------------------
r1932246 | fkento | 2026-03-10 04:33:57 +0000 (Tue, 10 Mar 2026) | 1 line
Add documentation to UPGRADE file
------------------------------------------------------------------------
r1932239 | gbechis | 2026-03-09 18:15:59 +0000 (Mon, 09 Mar 2026) | 1 line
improve locking
------------------------------------------------------------------------
r1932225 | gbechis | 2026-03-09 07:49:38 +0000 (Mon, 09 Mar 2026) | 1 line
improve locking
------------------------------------------------------------------------
r1932217 | gbechis | 2026-03-08 08:39:06 +0000 (Sun, 08 Mar 2026) | 7
lines
update to latest version
- Run TF-IDF transform only when needed
- change sql schema to fix retraining
- Improve locking and SQL queries
------------------------------------------------------------------------
r1932206 | fkento | 2026-03-07 07:37:13 +0000 (Sat, 07 Mar 2026) | 1 line
Add noskip tflag
------------------------------------------------------------------------
r1932182 | jhardin | 2026-03-05 16:04:51 +0000 (Thu, 05 Mar 2026) | 1 line
Add 2TLD "mocha.app", free app hosting, observed in phishing
------------------------------------------------------------------------
r1932175 | gbechis | 2026-03-05 09:40:44 +0000 (Thu, 05 Mar 2026) | 2
lines
display the correct domain on debug lines, better ARC check
------------------------------------------------------------------------
r1932162 | gbechis | 2026-03-04 17:23:04 +0000 (Wed, 04 Mar 2026) | 3
lines
If the named capture regexp doesn't match, substitute the part of the
regexp with a token that will never match and continue processing the
regexp
bz #8360
------------------------------------------------------------------------
r1932157 | gbechis | 2026-03-04 15:07:04 +0000 (Wed, 04 Mar 2026) | 2
lines
mark NeuralNetwork plugin as experimental while development continues
------------------------------------------------------------------------
r1932149 | gbechis | 2026-03-04 10:07:51 +0000 (Wed, 04 Mar 2026) | 1 line
consider only non zero hits and use the correct vector size
------------------------------------------------------------------------
r1932146 | gbechis | 2026-03-04 08:00:18 +0000 (Wed, 04 Mar 2026) | 1 line
add a "neuralnetwork_min_vocab_hits" configuration option in order to
run the prediction only if the message hits on enough words on the
vocabulary
------------------------------------------------------------------------
r1932139 | gbechis | 2026-03-03 16:44:46 +0000 (Tue, 03 Mar 2026) | 2
lines
add Digital Ocean S3 endpoints
------------------------------------------------------------------------
r1932127 | gbechis | 2026-03-03 11:11:09 +0000 (Tue, 03 Mar 2026) | 2
lines
add a 2tld and reorder
------------------------------------------------------------------------
r1932126 | gbechis | 2026-03-03 09:56:49 +0000 (Tue, 03 Mar 2026) | 1 line
correctly retrain if vocabulary size changes
------------------------------------------------------------------------
r1932098 | gbechis | 2026-03-02 08:28:23 +0000 (Mon, 02 Mar 2026) | 1 line
add 2tlds
------------------------------------------------------------------------
r1932097 | gbechis | 2026-03-02 07:29:27 +0000 (Mon, 02 Mar 2026) | 1 line
improve algorithm if training set is unbalanced
------------------------------------------------------------------------
r1932067 | gbechis | 2026-02-27 10:08:34 +0000 (Fri, 27 Feb 2026) | 1 line
avoid warnings when connection breaks
------------------------------------------------------------------------
r1932056 | gbechis | 2026-02-26 15:40:51 +0000 (Thu, 26 Feb 2026) | 2
lines
add a CAVEATS section
------------------------------------------------------------------------
r1932055 | gbechis | 2026-02-26 15:22:07 +0000 (Thu, 26 Feb 2026) | 1 line
make sure the model is correctly trained
------------------------------------------------------------------------
r1932053 | gbechis | 2026-02-26 09:00:40 +0000 (Thu, 26 Feb 2026) | 1 line
correctly retrain the model
------------------------------------------------------------------------
r1932051 | gbechis | 2026-02-26 07:31:48 +0000 (Thu, 26 Feb 2026) | 1 line
expire in-memory cache when needed
------------------------------------------------------------------------
r1932048 | jhardin | 2026-02-26 02:55:11 +0000 (Thu, 26 Feb 2026) | 1 line
Add 4TLDs for fastly.net zoned CDN, observed in phishing.
------------------------------------------------------------------------
r1932042 | gbechis | 2026-02-25 08:38:02 +0000 (Wed, 25 Feb 2026) | 1 line
retrain from vocabulary if available
------------------------------------------------------------------------
r1932039 | gbechis | 2026-02-25 07:28:27 +0000 (Wed, 25 Feb 2026) | 1 line
remove unused terms from disk as well
------------------------------------------------------------------------
r1932034 | gbechis | 2026-02-24 23:59:31 +0000 (Tue, 24 Feb 2026) | 1 line
Retrain the model from vocabulary statistics when vocab size has changed
------------------------------------------------------------------------
r1932033 | gbechis | 2026-02-24 23:12:18 +0000 (Tue, 24 Feb 2026) | 2
lines
install dependencies to make Github tests work on Linux
------------------------------------------------------------------------
r1932032 | gbechis | 2026-02-24 23:08:05 +0000 (Tue, 24 Feb 2026) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1932031 | gbechis | 2026-02-24 23:07:35 +0000 (Tue, 24 Feb 2026) | 2
lines
add a redirector
------------------------------------------------------------------------
r1932030 | gbechis | 2026-02-24 23:05:52 +0000 (Tue, 24 Feb 2026) | 2
lines
add Mail::SpamAssassin::Plugin::NeuralNetwork to check messages using
Fast Artificial Neural Network library
------------------------------------------------------------------------
r1932003 | gbechis | 2026-02-23 11:18:19 +0000 (Mon, 23 Feb 2026) | 2
lines
fix with Perl 5.40 and strict pragma
------------------------------------------------------------------------
r1931989 | jhardin | 2026-02-22 19:41:12 +0000 (Sun, 22 Feb 2026) | 1 line
Add 2tld `twil.io` observed hosting phishing content.
------------------------------------------------------------------------
r1931946 | gbechis | 2026-02-20 07:15:05 +0000 (Fri, 20 Feb 2026) | 2
lines
document more metadata related subs
------------------------------------------------------------------------
r1931890 | gbechis | 2026-02-16 14:53:00 +0000 (Mon, 16 Feb 2026) | 2
lines
add exceptions for mail.qq.com FPs
------------------------------------------------------------------------
r1931880 | fkento | 2026-02-16 03:34:41 +0000 (Mon, 16 Feb 2026) | 1 line
Remove rules causing problems
------------------------------------------------------------------------
r1931856 | gbechis | 2026-02-13 16:59:34 +0000 (Fri, 13 Feb 2026) | 3
lines
revert r1931682 and add a working test for the case
fix #8366
------------------------------------------------------------------------
r1931848 | gbechis | 2026-02-13 10:23:01 +0000 (Fri, 13 Feb 2026) | 2
lines
improve HELO_STATIC_HOST rule for Mailgun
------------------------------------------------------------------------
r1931834 | gbechis | 2026-02-12 18:04:27 +0000 (Thu, 12 Feb 2026) | 2
lines
add a generic url extractor
------------------------------------------------------------------------
r1931833 | gbechis | 2026-02-12 18:03:44 +0000 (Thu, 12 Feb 2026) | 1 line
define empty_tags as an empty string by default
------------------------------------------------------------------------
r1931832 | gbechis | 2026-02-12 17:29:14 +0000 (Thu, 12 Feb 2026) | 5
lines
add "empty_tags" configuration.
This is a list of tags that might be undefined because they are set by
3rd party plugins.
Setting this configuration will prevent those tags from being set with
an invalid value
if they are not defined.
------------------------------------------------------------------------
r1931804 | gbechis | 2026-02-11 09:09:10 +0000 (Wed, 11 Feb 2026) | 2
lines
add Backblaze 4tlds
------------------------------------------------------------------------
r1931798 | gbechis | 2026-02-10 23:18:16 +0000 (Tue, 10 Feb 2026) | 3
lines
don't run a test as root if it has a problem resulting from setuid nobody
bz #8364
------------------------------------------------------------------------
r1931738 | gbechis | 2026-02-06 15:10:21 +0000 (Fri, 06 Feb 2026) | 2
lines
new Mailgun HELO names are seen as dynamic ip
------------------------------------------------------------------------
r1931726 | gbechis | 2026-02-05 18:20:27 +0000 (Thu, 05 Feb 2026) | 2
lines
return early if the host is not valid
------------------------------------------------------------------------
r1931724 | gbechis | 2026-02-05 17:36:36 +0000 (Thu, 05 Feb 2026) | 2
lines
if the host is an octal number try to convert it into an ip address
------------------------------------------------------------------------
r1931713 | gbechis | 2026-02-04 17:56:09 +0000 (Wed, 04 Feb 2026) | 1 line
add redirectors
------------------------------------------------------------------------
r1931710 | billcole | 2026-02-04 13:36:31 +0000 (Wed, 04 Feb 2026) | 1
line
remove Validity 'blocked' rules from force-active list
------------------------------------------------------------------------
r1931682 | gbechis | 2026-02-03 08:26:12 +0000 (Tue, 03 Feb 2026) | 2
lines
extract ip addresses from new Gmail received headers
------------------------------------------------------------------------
r1931630 | axb | 2026-01-31 14:15:32 +0000 (Sat, 31 Jan 2026) | 2 lines
added spectrum.net
------------------------------------------------------------------------
r1931584 | gbechis | 2026-01-28 17:50:41 +0000 (Wed, 28 Jan 2026) | 3
lines
improve redirection checks in the http-equiv tag case,
silence a warning when using Selenium and fix regression tests
------------------------------------------------------------------------
r1931582 | gbechis | 2026-01-28 09:45:01 +0000 (Wed, 28 Jan 2026) | 2
lines
add a 4tld
------------------------------------------------------------------------
r1931575 | gbechis | 2026-01-27 22:50:00 +0000 (Tue, 27 Jan 2026) | 2
lines
Google is using more ipv6 ip addresses for Gmail relay, fix check
accordingly
------------------------------------------------------------------------
r1931550 | gbechis | 2026-01-26 17:46:41 +0000 (Mon, 26 Jan 2026) | 2
lines
add another redirector
------------------------------------------------------------------------
r1931548 | gbechis | 2026-01-26 17:24:08 +0000 (Mon, 26 Jan 2026) | 2
lines
add a Google redirector domain
------------------------------------------------------------------------
r1931547 | gbechis | 2026-01-26 17:22:14 +0000 (Mon, 26 Jan 2026) | 2
lines
try to extract more urls from URIs
------------------------------------------------------------------------
r1931467 | gbechis | 2026-01-22 11:25:07 +0000 (Thu, 22 Jan 2026) | 2
lines
add more tlds
------------------------------------------------------------------------
r1931340 | gbechis | 2026-01-16 09:01:43 +0000 (Fri, 16 Jan 2026) | 2
lines
add a Google 3tld domain
------------------------------------------------------------------------
r1931338 | gbechis | 2026-01-16 07:52:44 +0000 (Fri, 16 Jan 2026) | 2
lines
another abused Google redirector
------------------------------------------------------------------------
r1931330 | gbechis | 2026-01-15 08:22:07 +0000 (Thu, 15 Jan 2026) | 3
lines
fix password protected Redis access with legacy configuration
bz #8362
------------------------------------------------------------------------
r1931315 | gbechis | 2026-01-14 14:22:35 +0000 (Wed, 14 Jan 2026) | 2
lines
add support for 4tld domains in order to be able to query S3 endpoints
in RBLs
------------------------------------------------------------------------
r1931310 | gbechis | 2026-01-14 10:30:56 +0000 (Wed, 14 Jan 2026) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1931304 | gbechis | 2026-01-14 07:25:13 +0000 (Wed, 14 Jan 2026) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1931286 | gbechis | 2026-01-13 10:04:11 +0000 (Tue, 13 Jan 2026) | 2
lines
better handling of malformed uris
------------------------------------------------------------------------
r1931282 | gbechis | 2026-01-13 07:37:26 +0000 (Tue, 13 Jan 2026) | 2
lines
add another freemail provider
------------------------------------------------------------------------
r1931268 | gbechis | 2026-01-12 16:32:44 +0000 (Mon, 12 Jan 2026) | 2
lines
check all values of Reply-to header
------------------------------------------------------------------------
r1931252 | gbechis | 2026-01-12 10:40:25 +0000 (Mon, 12 Jan 2026) | 2
lines
check more email addresses in check_rbl_headers
------------------------------------------------------------------------
r1931241 | jhardin | 2026-01-11 20:41:26 +0000 (Sun, 11 Jan 2026) | 1 line
Add focused rule for Amazon Prime phishing via Google Draw
------------------------------------------------------------------------
r1931240 | jhardin | 2026-01-11 20:24:39 +0000 (Sun, 11 Jan 2026) | 1 line
Add 2tld created.app observed in phishing - generated website hosting
site
------------------------------------------------------------------------
r1931221 | jhardin | 2026-01-10 22:27:01 +0000 (Sat, 10 Jan 2026) | 1 line
Shopify recommands Klaviyo email provider to their merchants, make the
Shopify-image-not-from-Shopify rule aware of that
------------------------------------------------------------------------
r1931185 | gbechis | 2026-01-08 13:49:06 +0000 (Thu, 08 Jan 2026) | 7
lines
add an url shortener
Submitted by: Mickael Maillot <mmaillot@secuserve.com>
Github: closes #23
------------------------------------------------------------------------
r1931173 | gbechis | 2026-01-07 17:38:17 +0000 (Wed, 07 Jan 2026) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1931142 | jhardin | 2026-01-06 03:52:03 +0000 (Tue, 06 Jan 2026) | 1 line
Avoid FP on French name. Closes #21 in github.
------------------------------------------------------------------------
r1931126 | gbechis | 2026-01-05 14:28:29 +0000 (Mon, 05 Jan 2026) | 6
lines
fix GMAIL_NOREPLY rule
Submitted by: Giovanni <g.bechis@snb.it>
Github: closes #22
------------------------------------------------------------------------
r1931123 | gbechis | 2026-01-05 14:18:03 +0000 (Mon, 05 Jan 2026) | 2
lines
disable hardcoded score for LONGWORDS rule
------------------------------------------------------------------------
r1931121 | gbechis | 2026-01-05 10:45:04 +0000 (Mon, 05 Jan 2026) | 2
lines
missed in previous
------------------------------------------------------------------------
r1931120 | gbechis | 2026-01-05 10:42:54 +0000 (Mon, 05 Jan 2026) | 2
lines
Let nightly score MONEY_BACK rule
------------------------------------------------------------------------
r1931119 | gbechis | 2026-01-05 10:05:07 +0000 (Mon, 05 Jan 2026) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1931118 | gbechis | 2026-01-05 09:36:19 +0000 (Mon, 05 Jan 2026) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1931114 | jhardin | 2026-01-05 01:28:31 +0000 (Mon, 05 Jan 2026) | 1 line
Add website hosting domain observed in phishing
------------------------------------------------------------------------
r1931015 | billcole | 2025-12-31 17:48:40 +0000 (Wed, 31 Dec 2025) | 1
line
typo correction
------------------------------------------------------------------------
r1930952 | billcole | 2025-12-28 23:22:38 +0000 (Sun, 28 Dec 2025) | 1
line
update svn URLs to use https. Also committing added warnings in
masses/rule-qa/reports-from-logs, as it already existed on sa-vm
------------------------------------------------------------------------
r1930951 | billcole | 2025-12-28 23:03:19 +0000 (Sun, 28 Dec 2025) | 1
line
fixed missing escape
------------------------------------------------------------------------
r1930804 | gbechis | 2025-12-22 16:58:36 +0000 (Mon, 22 Dec 2025) | 2
lines
disable non working rule
------------------------------------------------------------------------
r1930702 | gbechis | 2025-12-18 08:46:39 +0000 (Thu, 18 Dec 2025) | 2
lines
Add a freemail domain
------------------------------------------------------------------------
r1930591 | billcole | 2025-12-15 14:53:23 +0000 (Mon, 15 Dec 2025) | 1
line
Rule inspired by Mark London's spam
------------------------------------------------------------------------
r1930436 | gbechis | 2025-12-10 18:34:38 +0000 (Wed, 10 Dec 2025) | 2
lines
make it possible to use \. as a replacement in
Mail::SpamAssassin::Plugin::HashBL::check_hashbl_bodyre
------------------------------------------------------------------------
r1930243 | gbechis | 2025-12-04 07:47:19 +0000 (Thu, 04 Dec 2025) | 2
lines
match obfuscated URI
------------------------------------------------------------------------
r1930201 | gbechis | 2025-12-02 17:59:27 +0000 (Tue, 02 Dec 2025) | 2
lines
log Selenium warnings
------------------------------------------------------------------------
r1930086 | jhardin | 2025-11-28 22:59:13 +0000 (Fri, 28 Nov 2025) | 1 line
Add a subrule to try to assess occurrence of "about:https://" URL
obfuscation (Bug 8358)
------------------------------------------------------------------------
r1929970 | gbechis | 2025-11-25 10:23:32 +0000 (Tue, 25 Nov 2025) | 2
lines
list another Google domain
------------------------------------------------------------------------
r1929868 | gbechis | 2025-11-19 14:49:53 +0000 (Wed, 19 Nov 2025) | 2
lines
add a redirector
------------------------------------------------------------------------
r1929867 | gbechis | 2025-11-19 14:49:09 +0000 (Wed, 19 Nov 2025) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1929866 | jhardin | 2025-11-19 13:24:37 +0000 (Wed, 19 Nov 2025) | 1 line
Add another IPFS provider observed in phishing
------------------------------------------------------------------------
r1929865 | jhardin | 2025-11-19 13:13:37 +0000 (Wed, 19 Nov 2025) | 1 line
Add 3TLD ipfs.w3s.link
------------------------------------------------------------------------
r1929730 | gbechis | 2025-11-14 09:41:02 +0000 (Fri, 14 Nov 2025) | 2
lines
add redirectors
------------------------------------------------------------------------
r1929661 | gbechis | 2025-11-11 14:23:38 +0000 (Tue, 11 Nov 2025) | 2
lines
add a url shortener
------------------------------------------------------------------------
r1929643 | gbechis | 2025-11-11 08:23:02 +0000 (Tue, 11 Nov 2025) | 2
lines
do not export a sub that has been removed some time ago
------------------------------------------------------------------------
r1929642 | gbechis | 2025-11-11 07:32:59 +0000 (Tue, 11 Nov 2025) | 2
lines
add 2tlds and 3tld
------------------------------------------------------------------------
r1929589 | jhardin | 2025-11-08 03:00:15 +0000 (Sat, 08 Nov 2025) | 1 line
Reduce score limit due to FP report, FP Avoidance tuning.
------------------------------------------------------------------------
r1929576 | axb | 2025-11-07 08:37:34 +0000 (Fri, 07 Nov 2025) | 1 line
added regex for rebrand.ly
------------------------------------------------------------------------
r1929575 | axb | 2025-11-07 08:33:37 +0000 (Fri, 07 Nov 2025) | 1 line
added url_shortener rebrand.ly
------------------------------------------------------------------------
r1929554 | gbechis | 2025-11-06 07:58:24 +0000 (Thu, 06 Nov 2025) | 2
lines
another abused Google redirector
------------------------------------------------------------------------
r1929502 | gbechis | 2025-11-04 08:14:15 +0000 (Tue, 04 Nov 2025) | 2
lines
match fake List-Unsubscribe headers
------------------------------------------------------------------------
r1929482 | gbechis | 2025-11-03 07:48:13 +0000 (Mon, 03 Nov 2025) | 2
lines
add a url shortener
------------------------------------------------------------------------
r1929481 | gbechis | 2025-11-03 07:48:01 +0000 (Mon, 03 Nov 2025) | 2
lines
add a redirector
------------------------------------------------------------------------
r1929438 | gbechis | 2025-10-31 16:12:03 +0000 (Fri, 31 Oct 2025) | 2
lines
add 2tlds
------------------------------------------------------------------------
r1929341 | jhardin | 2025-10-25 17:45:18 +0000 (Sat, 25 Oct 2025) | 1 line
Pin score for strong phishing indicator
------------------------------------------------------------------------
r1929316 | jhardin | 2025-10-24 04:55:33 +0000 (Fri, 24 Oct 2025) | 1 line
Add another CN -> JP phishing rule
------------------------------------------------------------------------
r1929315 | jhardin | 2025-10-24 04:38:58 +0000 (Fri, 24 Oct 2025) | 1 line
Add CN -> JP Mastercard phishing
------------------------------------------------------------------------
r1929290 | gbechis | 2025-10-22 16:09:32 +0000 (Wed, 22 Oct 2025) | 2
lines
fix timeout handling in Selenium code
------------------------------------------------------------------------
r1929266 | gbechis | 2025-10-22 07:27:11 +0000 (Wed, 22 Oct 2025) | 2
lines
mention Selenium support to Redirectors plugin
------------------------------------------------------------------------
r1929265 | gbechis | 2025-10-22 07:22:26 +0000 (Wed, 22 Oct 2025) | 3
lines
add the possibility to check for redirectors using Selenium
this catches redirects that uses Javascript and other tricks
------------------------------------------------------------------------
r1929232 | gbechis | 2025-10-20 10:34:59 +0000 (Mon, 20 Oct 2025) | 2
lines
add 2tlds
------------------------------------------------------------------------
r1929216 | jhardin | 2025-10-18 20:30:21 +0000 (Sat, 18 Oct 2025) | 1 line
improve cn->jp phishing rule
------------------------------------------------------------------------
r1929175 | gbechis | 2025-10-16 13:39:33 +0000 (Thu, 16 Oct 2025) | 2
lines
avoid a warning
------------------------------------------------------------------------
r1929174 | gbechis | 2025-10-16 13:00:36 +0000 (Thu, 16 Oct 2025) | 1 line
update redirector after Sophos change
------------------------------------------------------------------------
r1929170 | gbechis | 2025-10-16 09:54:39 +0000 (Thu, 16 Oct 2025) | 2
lines
remove duplicated parameters in order to better catch loops
------------------------------------------------------------------------
r1929159 | fkento | 2025-10-15 19:19:13 +0000 (Wed, 15 Oct 2025) | 1 line
Add support for nested anchor tags
------------------------------------------------------------------------
r1929158 | gbechis | 2025-10-15 14:28:12 +0000 (Wed, 15 Oct 2025) | 2
lines
add a 3tld
------------------------------------------------------------------------
r1929157 | gbechis | 2025-10-15 14:27:31 +0000 (Wed, 15 Oct 2025) | 2
lines
add a url redirector
------------------------------------------------------------------------
r1929156 | gbechis | 2025-10-15 14:26:53 +0000 (Wed, 15 Oct 2025) | 2
lines
add a url shortener
------------------------------------------------------------------------
r1929117 | gbechis | 2025-10-13 16:33:35 +0000 (Mon, 13 Oct 2025) | 3
lines
check that is possible to verify if the DNS answer is a CNAME
bz #8353
------------------------------------------------------------------------
r1929081 | jhardin | 2025-10-11 21:04:23 +0000 (Sat, 11 Oct 2025) | 1 line
Add uppercase accented E in FUZZY_SECURITY fr exclusion. github PR, fix
#18
------------------------------------------------------------------------
r1929038 | gbechis | 2025-10-10 06:40:54 +0000 (Fri, 10 Oct 2025) | 2
lines
add 2tlds
------------------------------------------------------------------------
r1929009 | gbechis | 2025-10-07 22:01:15 +0000 (Tue, 07 Oct 2025) | 2
lines
add a freemail provider
------------------------------------------------------------------------
r1929008 | gbechis | 2025-10-07 22:00:29 +0000 (Tue, 07 Oct 2025) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1929007 | gbechis | 2025-10-07 21:59:44 +0000 (Tue, 07 Oct 2025) | 2
lines
add Cisco redirector
------------------------------------------------------------------------
r1928925 | billcole | 2025-10-03 14:09:02 +0000 (Fri, 03 Oct 2025) | 1
line
Add .htaccess for RuleQA site
------------------------------------------------------------------------
r1928894 | jhardin | 2025-10-02 05:46:41 +0000 (Thu, 02 Oct 2025) | 1 line
Add rule for snip.ly URLs: site allows third-party web page
modifications without owner consent and has been observed in phishing.
------------------------------------------------------------------------
r1928877 | gbechis | 2025-10-01 09:58:19 +0000 (Wed, 01 Oct 2025) | 2
lines
return early if the new url has an unsupported protocol
------------------------------------------------------------------------
r1928774 | gbechis | 2025-09-26 14:50:25 +0000 (Fri, 26 Sep 2025) | 3
lines
in order to hit ARC_VALID, make sure that all ARC-Seals pass, and the
most recent ARC-Message-Signature passes
bz #8352
------------------------------------------------------------------------
r1928772 | gbechis | 2025-09-26 07:42:17 +0000 (Fri, 26 Sep 2025) | 2
lines
improve rcvd parser for some Qmail headers
------------------------------------------------------------------------
r1928715 | jhardin | 2025-09-24 01:28:14 +0000 (Wed, 24 Sep 2025) | 1 line
Add subrule for eval for emails trying to look like they are from NPMJS
------------------------------------------------------------------------
r1928632 | jhardin | 2025-09-20 01:16:28 +0000 (Sat, 20 Sep 2025) | 1 line
Argh! case-insensitive pls!
------------------------------------------------------------------------
r1928631 | jhardin | 2025-09-20 01:13:44 +0000 (Sat, 20 Sep 2025) | 1 line
Add a couple of redirectors observed in phishing
------------------------------------------------------------------------
r1928630 | jhardin | 2025-09-20 01:13:09 +0000 (Sat, 20 Sep 2025) | 1 line
Add some hosting services observed in phishing collectors
------------------------------------------------------------------------
r1928614 | gbechis | 2025-09-19 09:25:56 +0000 (Fri, 19 Sep 2025) | 2
lines
add more abused redirectors
------------------------------------------------------------------------
r1928613 | gbechis | 2025-09-19 09:25:40 +0000 (Fri, 19 Sep 2025) | 2
lines
add more 2tlds
------------------------------------------------------------------------
r1928511 | gbechis | 2025-09-16 14:49:54 +0000 (Tue, 16 Sep 2025) | 2
lines
improve received headers parser
------------------------------------------------------------------------
r1928495 | fkento | 2025-09-15 15:47:19 +0000 (Mon, 15 Sep 2025) | 5 lines
Include SVG files in rawbody rules
SVG files can contain text, html, and JavaScript so treat them just like
html files.
------------------------------------------------------------------------
r1928475 | fkento | 2025-09-15 04:14:08 +0000 (Mon, 15 Sep 2025) | 1 line
Bug 8351: Remove invalid import
------------------------------------------------------------------------
r1928244 | gbechis | 2025-09-05 09:30:05 +0000 (Fri, 05 Sep 2025) | 2
lines
find more redirected domains
------------------------------------------------------------------------
r1928242 | gbechis | 2025-09-05 07:55:30 +0000 (Fri, 05 Sep 2025) | 2
lines
uri_list test requires network access
------------------------------------------------------------------------
r1928240 | gbechis | 2025-09-05 06:36:52 +0000 (Fri, 05 Sep 2025) | 2
lines
skip CNAME checks if dns_max_cname_cache == 0
------------------------------------------------------------------------
r1928224 | gbechis | 2025-09-04 06:49:25 +0000 (Thu, 04 Sep 2025) | 2
lines
prevent sa-learn(1) from accessing network when is not needed
------------------------------------------------------------------------
r1928219 | jhardin | 2025-09-04 00:31:55 +0000 (Thu, 04 Sep 2025) | 1 line
FP avoidance tuning
------------------------------------------------------------------------
r1928208 | gbechis | 2025-09-03 16:44:04 +0000 (Wed, 03 Sep 2025) | 2
lines
add has_dns_max_cname_cache feature
------------------------------------------------------------------------
r1928199 | gbechis | 2025-09-03 09:30:17 +0000 (Wed, 03 Sep 2025) | 3
lines
limit CNAME cache to 10 entries by default and make it configurable
increase speed processing when there are a huge number of uris
------------------------------------------------------------------------
r1928197 | gbechis | 2025-09-03 08:16:10 +0000 (Wed, 03 Sep 2025) | 2
lines
improve CNAME caching
------------------------------------------------------------------------
r1928193 | jhardin | 2025-09-03 00:53:49 +0000 (Wed, 03 Sep 2025) | 1 line
Bug#8347: Remove high fixed score for URI_GOOG_STO_SPAMMY, masscheck
corpora now have a lot of this so it's scoring well.
------------------------------------------------------------------------
r1928192 | gbechis | 2025-09-02 21:51:43 +0000 (Tue, 02 Sep 2025) | 2
lines
remove additional slashes after http://
------------------------------------------------------------------------
r1928191 | gbechis | 2025-09-02 21:49:35 +0000 (Tue, 02 Sep 2025) | 2
lines
add Docsend to redirectors
------------------------------------------------------------------------
r1928190 | gbechis | 2025-09-02 21:48:42 +0000 (Tue, 02 Sep 2025) | 2
lines
add a 2tld
------------------------------------------------------------------------
r1928154 | jhardin | 2025-08-31 17:48:11 +0000 (Sun, 31 Aug 2025) | 1 line
FP Avoidance tuning and score adjustment
------------------------------------------------------------------------
r1928101 | gbechis | 2025-08-30 14:09:31 +0000 (Sat, 30 Aug 2025) | 2
lines
Apache SpamAssassin 4.0.2 has been released
------------------------------------------------------------------------
r1928046 | gbechis | 2025-08-27 13:15:53 +0000 (Wed, 27 Aug 2025) | 2
lines
preparing to release 4.0.2
------------------------------------------------------------------------