Add per-domain DKIM signing, admin console TLS, log rotation, and resolver timeout scoping

- DKIM signing was hardcoded to one domain; now keyed per-domain off
  the sending address, fixing mail for every domain but the original.
- Admin console (port 1027) is now TLS-wrapped instead of plaintext.
- barantmail.log now rotates by size (config-driven) instead of
  growing unbounded (previously hit 23GB).
- ResolverThreadScope.h: a <setenv> scoping fix for name resolution
  inside a <try> block that previously did not survive its own
  container.
- IMAPArgs.cpp: fixed "UID STORE 1:*" wrongly requiring UID 1 to
  exist, which silently made empty-folder operations delete nothing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Brad ArantandClaude Sonnet 5 committed 2026-10-06 17:39:06 +00:00
1 parent 5f3e6ed2e6
commit 407cc2e915
11 files changed
+284 -81

No files matched your search

+32 -11
View File
@@ -3,6 +3,7 @@
#include "TLSInfo.h"
#include <string>
#include <vector>
namespace coreutils { class JFile; }
@@ -26,11 +27,13 @@ namespace mail {
/// "key": "/path/to/privkey.pem",
/// "caCertificate": "/path/to/ca.pem"
/// },
/// "dkim": {
/// "domain": "mail.example.com",
/// "selector": "default",
/// "privateKey": "/path/to/dkim_private.pem"
/// }
/// "dkim": [
/// { "domain": "example.com", "selector": "default",
/// "privateKey": "/path/to/example.com.private.pem" },
/// { "domain": "second-domain.com", "selector": "default",
/// "privateKey": "/path/to/second-domain.com.private.pem" }
/// ],
/// "log": { "maxSizeBytes": 104857600, "maxBackups": 5 }
/// }
///
/// "hostName", "mailPath", and "smtp.port" are required - plain port
@@ -43,8 +46,18 @@ namespace mail {
/// "tls.certificate" and "tls.key" become required - there is no
/// path through this class that hands back a submission/IMAPS/POP3S
/// listener request without a real certificate configured for it.
/// "dkim" is entirely optional - outbound mail goes out unsigned
/// unless all three of its fields are present.
/// "dkim" is entirely optional (an empty/missing array - outbound
/// mail goes out unsigned for any domain with no matching entry).
/// Each entry's three fields are all required. A message is signed
/// using whichever entry's "domain" matches the sender address's
/// own domain (case-sensitive exact match) - a domain with no entry
/// here just goes out unsigned, same as if "dkim" were absent
/// entirely.
/// "log" is entirely optional - "maxSizeBytes"/"maxBackups" each
/// independently default (100MB / 5 backups) if omitted, and the
/// whole section can be left out for the same defaults. Applied to
/// coreutils::Log's static rotation fields once this config loads -
/// see Log.h's own doc comment for what rotation actually does.
///
class BARANTMailConfig {
@@ -78,10 +91,18 @@ namespace mail {
core::TLSInfo *getTlsInfo();
bool hasDkim();
std::string getDkimDomain();
std::string getDkimSelector();
std::string getDkimPrivateKeyPath();
struct DkimEntry {
std::string domain;
std::string selector;
std::string privateKeyPath;
};
/// Empty if "dkim" is absent from the config file.
std::vector<DkimEntry> getDkimEntries();
bool hasLog();
size_t getLogMaxSizeBytes();
int getLogMaxBackups();
///
/// The admin console (see ConsoleServer/ConsoleSession) - "port"