Files
BARANTMail/__ADMIN_DOMAIN.cpp
Brad Arant e8b2a79907 Add authenticated domain/mailbox/alias/password admin console
Port 1027 used to be an unauthenticated console (see ServerCore's
ConsoleServer/ConsoleSession fix) that also exposed the raw SMTP
command set (AUTH/DATA/EHLO/EXPN/HELO/...) to anyone who could reach
it. It's now started only when barantmail.cfg has a real "admin"
section configured (BARANTMailConfig::hasAdmin/getAdminPort/
getAdminUser/getAdminPassword), matching the same optional-listener
pattern already used for smtpTLS/imap/pop3, and registers four real
commands instead of the SMTP command table:

  domain add|remove|list
  mailbox add|remove|list
  alias add|remove|list
  password reset

MailFileSystem gained the actual domain/mailbox/alias/password CRUD
these commands call (createDomain/removeDomain/listDomains,
createMailbox/removeMailbox/listMailboxes, createAlias/removeAlias/
listAliases, setPassword), matching its existing on-disk layout: a
domain is a directory, a mailbox is a directory with Inbox/Spam/Trash
and a .password file, an alias is a plain file listing target
mailboxes one per line.

getAliasMailboxes() was previously an unconditional stub that always
returned empty (confirmed via grep to have zero callers anywhere),
so an alias could be "created" but could never actually receive mail.
It's now wired for real: SMTPServer::inCreate() checks
ifAliasExists()/getAliasMailboxes() during local delivery and copies
the same spam-scanned message to every target mailbox (extracted into
a new deliverToMailbox() helper so the alias and single-mailbox
delivery paths share it).
2026-09-06 04:08:57 +00:00

38 lines
1.4 KiB
C++

#include "__ADMIN_DOMAIN.h"
namespace mail {
__ADMIN_DOMAIN::__ADMIN_DOMAIN(MailFileSystem &mailFileSystem) : mailFileSystem(mailFileSystem) {}
int __ADMIN_DOMAIN::processCommand(coreutils::ZString &request, core::TCPSession &session) {
// request was already split (by the console's own top-level
// CommandList, delimiter " ") before dispatch reached here, so
// request[0] is "domain" itself, request[1] the verb, request[2]
// the domain name (list has no third argument).
if (request.getList().size() < 2) {
session.out << "Usage: domain add|remove|list [name]" << "\r\n";
return 1;
}
std::string verb = request[1].str();
std::string error;
if (verb == "add" || verb == "remove") {
if (request.getList().size() < 3) {
session.out << "Usage: domain " << verb << " <name>" << "\r\n";
return 1;
}
coreutils::ZString domain(request[2]);
bool ok = (verb == "add") ? mailFileSystem.createDomain(domain, error)
: mailFileSystem.removeDomain(domain, error);
session.out << (ok ? "OK." : ("Failed: " + error)) << "\r\n";
} else if (verb == "list") {
for (auto &domain : mailFileSystem.listDomains())
session.out << domain << "\r\n";
} else {
session.out << "Usage: domain add|remove|list [name]" << "\r\n";
}
return 1;
}
}