Files
BARANTMail/BARANTMailConfig.cpp
Brad ArantandClaude Sonnet 5 407cc2e915 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>
2026-10-06 17:39:06 +00:00

137 lines
4.5 KiB
C++

#include "BARANTMailConfig.h"
#include "Exception.h"
#include "JFile.h"
namespace mail {
BARANTMailConfig::BARANTMailConfig(const std::string &path) {
file = new coreutils::JFile(coreutils::ZString(path.c_str(), path.length()));
if (!file->exists("hostName"))
throw coreutils::Exception("BARANTMailConfig: \"hostName\" is missing from " + path);
if (!file->exists("mailPath"))
throw coreutils::Exception("BARANTMailConfig: \"mailPath\" is missing from " + path);
if (!file->exists("smtp.port"))
throw coreutils::Exception("BARANTMailConfig: \"smtp.port\" is missing from " + path);
if ((file->exists("admin.user") || file->exists("admin.password") || file->exists("admin.port")) &&
(!file->exists("admin.user") || !file->exists("admin.password")))
throw coreutils::Exception(
"BARANTMailConfig: \"admin\" is configured but \"admin.user\"/\"admin.password\" "
"is missing from " + path);
bool needsTls = file->exists("smtpTLS.port") || file->exists("imap.port") || file->exists("pop3.port");
if (needsTls) {
if (!file->exists("tls.certificate") || !file->exists("tls.key"))
throw coreutils::Exception(
"BARANTMailConfig: smtpTLS/imap/pop3 is configured but \"tls.certificate\"/\"tls.key\" "
"is missing from " + path);
certPath = file->getString("tls.certificate");
keyPath = file->getString("tls.key");
tlsInfo.certificate = certPath.c_str();
tlsInfo.key = keyPath.c_str();
if (file->exists("tls.caCertificate")) {
caPath = file->getString("tls.caCertificate");
tlsInfo.cACertificate = caPath.c_str();
}
hasTls = true;
}
}
BARANTMailConfig::~BARANTMailConfig() {
delete file;
}
std::string BARANTMailConfig::getHostName() {
return file->getString("hostName");
}
std::string BARANTMailConfig::getMailPath() {
return file->getString("mailPath");
}
int BARANTMailConfig::getSmtpPort() {
return (int)file->getInt("smtp.port");
}
bool BARANTMailConfig::hasSmtpTLS() {
return file->exists("smtpTLS.port");
}
int BARANTMailConfig::getSmtpTLSPort() {
return (int)file->getInt("smtpTLS.port");
}
bool BARANTMailConfig::hasImap() {
return file->exists("imap.port");
}
int BARANTMailConfig::getImapPort() {
return (int)file->getInt("imap.port");
}
bool BARANTMailConfig::hasPop3() {
return file->exists("pop3.port");
}
int BARANTMailConfig::getPop3Port() {
return (int)file->getInt("pop3.port");
}
core::TLSInfo *BARANTMailConfig::getTlsInfo() {
return hasTls ? &tlsInfo : NULL;
}
std::vector<BARANTMailConfig::DkimEntry> BARANTMailConfig::getDkimEntries() {
std::vector<DkimEntry> entries;
// No length-prefixed array accessor on JFile/JString - probe
// ascending indices via exists() (the same technique the JSON
// path syntax's own "a[2]" bracket form is meant for) until one
// is missing, matching a plain JSON array's natural "no trailing
// comma/count field" shape.
for (int i = 0; ; i++) {
std::string indexPrefix = "dkim[" + std::to_string(i) + "]";
std::string domainPath = indexPrefix + ".domain";
if (!file->exists(domainPath))
break;
std::string selectorPath = indexPrefix + ".selector";
std::string keyPath = indexPrefix + ".privateKey";
DkimEntry entry;
entry.domain = file->getString(domainPath);
entry.selector = file->getString(selectorPath);
entry.privateKeyPath = file->getString(keyPath);
entries.push_back(entry);
}
return entries;
}
bool BARANTMailConfig::hasLog() {
return file->exists("log");
}
size_t BARANTMailConfig::getLogMaxSizeBytes() {
return file->exists("log.maxSizeBytes") ? (size_t)file->getInt("log.maxSizeBytes") : 104857600;
}
int BARANTMailConfig::getLogMaxBackups() {
return file->exists("log.maxBackups") ? (int)file->getInt("log.maxBackups") : 5;
}
bool BARANTMailConfig::hasAdmin() {
return file->exists("admin.user");
}
int BARANTMailConfig::getAdminPort() {
return file->exists("admin.port") ? (int)file->getInt("admin.port") : 1027;
}
std::string BARANTMailConfig::getAdminUser() {
return file->getString("admin.user");
}
std::string BARANTMailConfig::getAdminPassword() {
return file->getString("admin.password");
}
}