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

+21 -8
View File
@@ -1,6 +1,7 @@
#include "SendMail.h"
#include "Log.h"
#include <algorithm>
#include <map>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <cstdlib>
@@ -16,9 +17,9 @@ namespace mail {
SendMail::SendMail(std::string hostName, std::string sendLogPath, std::string messageId,
coreutils::MString from, coreutils::MString recipient, coreutils::MString mailData,
DKIMSigner *dkimSigner)
std::map<std::string, DKIMSigner*> *dkimSigners)
: hostName(hostName), sendLogPath(sendLogPath), messageId(messageId),
from(from), recipient(recipient), mailData(mailData), dkimSigner(dkimSigner) {}
from(from), recipient(recipient), mailData(mailData), dkimSigners(dkimSigners) {}
std::string SendMail::domainOf(coreutils::MString &address) {
std::string addr = address.str();
@@ -216,17 +217,29 @@ namespace mail {
coreutils::File log(logFileName, O_CREAT | O_WRONLY | O_APPEND, 0660);
log.write("=== delivery attempt: message " + messageId + " -> " + recipient.str() + " ===\n");
if (dkimSigner) {
if (dkimSigners) {
// Signed once here, not inside deliverToHost() - deliverToHost()
// can run again against a second MX host if the first fails, and
// the signature (over this exact message content) is the same
// either way, so signing once upfront avoids redundant RSA ops
// and keeps every delivery attempt for this message consistent.
std::string signature = dkimSigner->sign(mailData.str());
coreutils::MString signedData;
signedData << signature.c_str() << mailData;
mailData = signedData;
log.write("DKIM-signed.\n");
// Which signer (if any) is used depends on the sender's own
// domain, not a single server-wide identity - a real multi-
// domain deployment must never sign one domain's mail with a
// different domain's key (DMARC alignment would fail it
// anyway, and it would leak which private key production
// uses for an unrelated domain).
std::string fromDomain = domainOf(from);
auto it = dkimSigners->find(fromDomain);
if (it != dkimSigners->end()) {
std::string signature = it->second->sign(mailData.str());
coreutils::MString signedData;
signedData << signature.c_str() << mailData;
mailData = signedData;
log.write("DKIM-signed (domain: " + fromDomain + ").\n");
} else {
log.write("No DKIM key configured for domain: " + fromDomain + " - sending unsigned.\n");
}
}
std::string domain = domainOf(recipient);