Skip to content

Releases

v1.0.106

Choose a tag to compare

@github-actions github-actions released this 05 Nov 20:48

Wiring switches the cPanel hook on when the Exim options turn it off

cPanel leaves a custom ACL hook out of /etc/exim.conf when /etc/exim.conf.localopts carries acl_<hook name>=0, and WHM's Exim Configuration Manager writes that line for every custom hook that was still empty the last time the Exim configuration was saved. On such a server MSFE-NG's include sat in custom_begin_mail_pre, buildeximconf reported success, and the include never reached Exim: mail was delivered unscanned, and 1.0.105's new doctor check failed without --fix being able to clear it (issue #17).

  • Wire Exim → MailScanner and msfe-ng doctor --fix now set acl_custom_begin_mail_pre=1 in the options file when it is switched off there, before rebuilding and restarting Exim. The shadow options file is handled the same way.
  • Doctor: named-queue include built into exim.conf names the options file and the line when that is the cause.
  • SMTP-time rejects: the same switch is applied to its hook when the include line is added.

By hand, on a server that cannot upgrade yet:

sed -i 's/^acl_custom_begin_mail_pre=.*/acl_custom_begin_mail_pre=1/' /etc/exim.conf.localopts
/scripts/buildeximconf && /scripts/restartsrv_exim

Wiki: Troubleshooting → Wired, no errors — but mail is delivered unscanned and the Dashboard stays at 0. Upgrade: msfe-ng upgrade, or the Service tab.

v1.0.105

Choose a tag to compare

@github-actions github-actions released this 04 Nov 23:30

The doctor checks that Exim really carries the scanning wiring

The named-queue wiring is two files MSFE-NG writes — the ACL fragment and its include line in the cPanel hook — plus one step cPanel does: /scripts/buildeximconf copies the hook into /etc/exim.conf, and Exim is restarted to read it. The doctor only looked at the two files. When the build had not picked the hook up, or Exim had not been restarted, every check passed while Exim delivered mail unscanned, MailScanner idled and the Dashboard stayed at 0 (issue #17).

  • Doctor: named-queue include built into exim.conf (Fail) — /etc/exim.conf does not include the fragment. msfe-ng doctor --fix (the banner's Fix what can be fixed) runs /scripts/buildeximconf && /scripts/restartsrv_exim and says so if the include is still missing afterwards.
  • Doctor: Exim running its current configuration (Warn) — exim.conf changed after the Exim daemon started, so the running Exim still uses the previous one. This covers every Exim-side change: the wiring, local-submission privacy, SMTP-time rejects. doctor --fix restarts Exim.
  • Wire Exim → MailScanner verifies after its own rebuild that the include landed and prints a WARNING: line in the activity console when it did not.

Wiki: Troubleshooting → Wired, no errors — but mail is delivered unscanned and the Dashboard stays at 0. Upgrade: msfe-ng upgrade, or the Service tab.

v1.0.104

Choose a tag to compare

@github-actions github-actions released this 04 Nov 13:27

The message tester looks inside zip attachments

MailScanner does not only test an attachment's own name: for an archive it unpacks the members and tests each member's stored path (folders included) against the separate Archives: Filename Rules file, whose stock very long filename limit is 150 characters, not the 255 of the top-level file. A photo in a folder with a descriptive name can be blocked that way while the message tester said every attachment was allowed.

  • Test message / msfe-ng conf test-message now read a zip's table of contents and report every member — path/in/zip (in archive.zip) → deny by archives.filename.rules.conf (.{150,}: …) — exactly as the engine would judge it, and the prediction counts those members as blocked.
  • An encrypted member is reported as refused unless Allow Password-Protected Archives is on.
  • Members are not unpacked: the Archives: Filetype Rules (which need the bytes) and nested archives stay with the engine, and the transcript says so. Zip64 archives are reported as unread rather than guessed.

Wiki: Config. Upgrade: msfe-ng upgrade, or the Service tab.

v1.0.103

Choose a tag to compare

@github-actions github-actions released this 02 Nov 22:34

OSINT can be switched on from its own view

Delivery → OSINT used to say OSINT is switched off. Tick "OSINT lookups" in the OSINT providers card of the Config tab and leave you to find that card yourself.

  • The notice now carries a Switch OSINT on button: one click writes osint_enabled = true and the view reloads ready to run. The daemon reads its config per request, so nothing restarts.
  • The same notice links to the OSINT providers card of the Config tab (opens the tab and scrolls to the card) for the optional HIBP, Brave Search and Hunter keys.

Wiki: OSINT, Config. Upgrade: msfe-ng upgrade, or the Service tab.

1.0.102: drag-and-drop rule ordering, ⚠ on rules that can never fire

Choose a tag to compare

@github-actions github-actions released this 29 Oct 20:05

Rules in the right order, and a ⚠ on the ones that can never fire

MailScanner reads filename.rules.conf (and filetype.rules.conf, the archives.* twins and every ruleset) top to bottom and the first match wins. An allow \.doc\.docx$ added below the stock possible filename hiding deny never allows anything, and until now nothing said so.

  • Drag to reorder — every table editor in the Config tab (rulesets, file rules, RBL lists, scanners, host lists) has a ⋮⋮ handle; drag a row where it belongs, or use ↑ / ↓ from the keyboard. The file is written in the order you see: a rule's comment block and spacing move with it, a deleted rule takes its comment along, and an unchanged order reproduces the file byte for byte.
  • ⚠ a rule an earlier one always beats — for file rules, each pattern yields example names generated from the pattern itself, and one run of the engine's perl tells which rule catches them first. A rule whose examples are all taken by an earlier rule with a different action gets ⚠; the tooltip names the winning row and the example (never reached for names like file.doc.docx — row 7 (deny …) matches first), a click jumps to it. Same-action duplicates are not flagged. The check re-runs after every drag or edit, before you save.
  • The tester says it too — msfe-ng conf test, the Config tab's tester and the doctor warn line N is never reached for names like 'file.doc.docx': line M (deny) matches first, with a link to the line.
  • API: GET /api/conf/file carries shadows; POST /api/conf/check-rows checks a set of rows without saving.

Reminder from the field: the rule files are read when a MailScanner child starts, so a hand edit needs Reload MailScanner; a save from the Config tab does that for you.

Wiki: Config, Troubleshooting. Upgrade: msfe-ng upgrade, or the Service tab.

1.0.101: Check for updates always asks afresh

Choose a tag to compare

@github-actions github-actions released this 20 Oct 13:11

Check for updates always asks afresh

The sidebar badge asks the daemon a few seconds after every page load, and the daemon keeps that answer for an hour. A release published after that moment was invisible to Service → Check for updates until the hour passed, since the button read the same kept answer.

  • Check for updates now skips the kept answer and asks GitHub at once; the fresh result replaces the kept one, so the sidebar badge follows.
  • The badge and its six-hour timer are unchanged, and the daemon still asks GitHub at most once an hour for them.

Wiki: Service (Updates). Upgrade: msfe-ng upgrade, or the Service tab.

1.0.100: a re-sent message keeps its original envelope sender

Choose a tag to compare

@github-actions github-actions released this 20 Oct 12:53

A re-sent message keeps its original envelope sender

Release (resend) handed the stored copy to Exim with no sender, so the copy was injected as the daemon's own user: Exim logged <= root@⟨host⟩ U=root P=local, the Messages log showed the re-sent copy as From root@⟨host⟩ from 127.0.0.1, and the receiving server saw the host's root address as the envelope sender, so the real sender's SPF and DMARC were never evaluated.

  • Original sender kept: the resend, the bulk Release selected and the user-portal release now pass Exim -f ⟨original sender⟩, taken from the message log's sender (MailScanner records the envelope sender there) or, when the row is gone, from the stored copy's Return-Path:. The receiving server now sees the message as coming from the sender, not from this host.
  • Bounces stay bounces: a message that arrived with an empty sender is re-sent as -f <>.
  • Nothing unsafe reaches the command line: a logged sender that fails the address check is skipped; with nothing usable the message is injected as before.
  • Release (forward) and Report to SpamCop are unchanged: the forwarded copy is From the release address and still goes out as the daemon's user.

Wiki: Messages (Release section). Upgrade: msfe-ng upgrade, or the Service tab.

1.0.99: one Messages panel with Log and Quarantine views

Choose a tag to compare

@github-actions github-actions released this 20 Oct 10:52

One Messages panel: Log and Quarantine views

Clicking a status filter in Messages could show an empty list for every filter. The search set by the Dashboard's Show messages from ⟨domain⟩ link (or typed by hand) stayed active while the status buttons were clicked, so each filter was evaluated inside that hidden search, and nothing on screen said so. The filters were right; the state was invisible. The panel now shows what it filters on and what each filter holds.

  • Status chips with counts: All, Clean, Low spam, High spam, Infected, Attachments, Whitelist, Blacklist, Quarantined — each with its count for the current search and window, so an empty filter is visible before the click; a chip at 0 is dimmed. Blocked (releasable) is gone: it was the same filter as Quarantined. GET /api/messages/counts?field&text&days answers in one query.
  • Visible search: the active search and time window are pills under the chips (Sender domain: example.com ✕, last 7 days ✕), each removable, with Clear all. An empty result names what is filtered and offers Clear search.
  • Quarantine is a view of Messages: the Quarantine tab is gone from the rail; at the top of the Messages card, Log | Quarantine switches between the message log and what is actually on disk. Same search bar (in Quarantine the text searches sender, recipient, subject and id at once, the window becomes the first quarantine date), same columns, same message screen, chips All / Spam / Held with counts. The selection bar carries Copy to INBOX, Release selected and Purge selected there; Purge older sits under the table. Old #qmsg= deep links still work.
  • Auto-refresh belongs to the Log view and waits while rows are selected.

Wiki: Messages, Quarantine, Admin UI basics. Upgrade: msfe-ng upgrade, or the Service tab.

1.0.98: match rules can also reject at SMTP time

Choose a tag to compare

@github-actions github-actions released this 16 Oct 16:53

Match rules can also reject at SMTP time

A match rule used to act only inside MailScanner: the message was accepted, queued, scanned, scored 100 and dropped, and the source banned a minute later from the log — a bot sending the same subject a thousand times still cost a thousand scans. A rule can now carry Also reject at SMTP time (subject, from, to and header rules; not body): Exim refuses the message at DATA with 550 Rejected by local policy (MSFE-NG rule #n), nothing is queued, MailScanner never sees it, and the minute cron bans the source from /var/log/exim_rejectlog (reason smtp, the usual exclusions). The SpamAssassin rule stays in place as the second line of defence.

  • Never refused: authenticated submissions, loopback, and every sender on the global or a domain's whitelist (written to /etc/msfe-ng/exim/smtp-deny-whitelist).
  • Wiring: one deny stanza per flagged rule in /etc/msfe-ng/exim/smtp-deny.conf, included from cPanel's message-check ACL hook (ACL_CHECK_MESSAGE_PRE_BLOCK/custom_begin_check_message_pre), regenerated on every save and sync, validated by exim -be and exim -bV, rolled back when Exim refuses it, and followed by an Exim restart whenever it changed. Every pattern is escaped so nothing in it can reach Exim's string expansion.
  • Visibility: an SMTP column with the day's count in the Rules-tab and Config tables, and a Refused at SMTP time block in the Rules tab listing the last 50 refused messages (these never reach the Messages tab). GET /api/autoban/rejects.
  • Doctor SMTP-time rejects wired: a stale or missing fragment is fixed by sync (--fix); a hook the built exim.conf does not include gets the host checklist.
  • CLI: msfe-ng autoban rejects [--limit n] [--json], msfe-ng autoban smtp-off (the kill switch). uninstall.sh removes the fragment and the hook line.

Verify on your host before relying on it. The cPanel block directory above is cPanel's documented hook point for acl_smtp_data, but MSFE-NG could not check its name from the build machine. After flagging the first rule, run msfe-ng doctor: the check must say ok (the built /etc/exim.conf includes the fragment); otherwise ls /usr/local/cpanel/etc/exim/acls/ must list the block — if cPanel names it differently, set MSFE_NG_SMTP_DENY_BLOCK=<name> for the daemon and the cron, re-save a rule and rebuild. Then send a test message with the banned subject from outside: it must bounce with the 550. The wiki's Rules → Reject at SMTP time has the checklist.

Wiki: Rules, Config, Troubleshooting, CLI. Upgrade: msfe-ng upgrade, or the Service tab.

v1.0.97

Choose a tag to compare

@github-actions github-actions released this 16 Oct 15:36

Auto-ban match rules in the Rules tab

The match rules created with Ban rule… on a message (subject, sender, recipient, header or body patterns that block delivery and ban the source in csf) were listed only inside the Config tab's auto-ban card. The Rules tab now opens with an Auto-ban match rules card — the same table, with edit, delete and add — and both ban modals link to it with All match rules →. Thresholds, dry run and the recent bans stay in the Config tab.

Wiki: Rules, Messages. Upgrade: msfe-ng upgrade, or the Service tab.