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).
118 lines
3.6 KiB
C++
118 lines
3.6 KiB
C++
#ifndef __BARANTMailConfig_h__
|
|
#define __BARANTMailConfig_h__
|
|
|
|
#include "TLSInfo.h"
|
|
#include <string>
|
|
|
|
namespace coreutils { class JFile; }
|
|
|
|
namespace mail {
|
|
|
|
///
|
|
/// Server startup configuration, loaded from a JSON file via
|
|
/// CoreUtils' JFile - mirrors APIServer's own ApiServerConfig (see
|
|
/// that class's doc comment for JFile's create-on-missing behavior).
|
|
///
|
|
/// Schema:
|
|
/// {
|
|
/// "hostName": "mail.example.com",
|
|
/// "mailPath": "/var/mail",
|
|
/// "smtp": { "port": 25 },
|
|
/// "smtpTLS": { "port": 465 },
|
|
/// "imap": { "port": 993 },
|
|
/// "pop3": { "port": 995 },
|
|
/// "tls": {
|
|
/// "certificate": "/path/to/fullchain.pem",
|
|
/// "key": "/path/to/privkey.pem",
|
|
/// "caCertificate": "/path/to/ca.pem"
|
|
/// },
|
|
/// "dkim": {
|
|
/// "domain": "mail.example.com",
|
|
/// "selector": "default",
|
|
/// "privateKey": "/path/to/dkim_private.pem"
|
|
/// }
|
|
/// }
|
|
///
|
|
/// "hostName", "mailPath", and "smtp.port" are required - plain port
|
|
/// 25 is the one listener every deployment needs (an inbound peer
|
|
/// MTA relaying mail in has no TLS-first negotiation to fall back
|
|
/// on). "smtpTLS"/"imap"/"pop3" are each independently optional -
|
|
/// leaving one out just means that listener isn't started, so this
|
|
/// same file covers a plaintext-only relay just as well as a full
|
|
/// mail server. The moment any one of those three IS present,
|
|
/// "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.
|
|
///
|
|
|
|
class BARANTMailConfig {
|
|
|
|
public:
|
|
|
|
BARANTMailConfig(const std::string &path);
|
|
~BARANTMailConfig();
|
|
|
|
std::string getHostName();
|
|
std::string getMailPath();
|
|
|
|
int getSmtpPort();
|
|
|
|
bool hasSmtpTLS();
|
|
int getSmtpTLSPort();
|
|
|
|
bool hasImap();
|
|
int getImapPort();
|
|
|
|
bool hasPop3();
|
|
int getPop3Port();
|
|
|
|
///
|
|
/// NULL if none of smtpTLS/imap/pop3 are configured. Owned by
|
|
/// this BARANTMailConfig, valid for as long as it is - pass
|
|
/// straight through to a server's tlsInfo parameter, do not
|
|
/// delete, and don't let this config object go out of scope
|
|
/// while a server built from this pointer is still running.
|
|
///
|
|
|
|
core::TLSInfo *getTlsInfo();
|
|
|
|
bool hasDkim();
|
|
std::string getDkimDomain();
|
|
std::string getDkimSelector();
|
|
std::string getDkimPrivateKeyPath();
|
|
|
|
///
|
|
/// The admin console (see ConsoleServer/ConsoleSession) - "port"
|
|
/// defaults to 1027 if omitted. "user"/"password" are required
|
|
/// once "admin" is present at all; there is no path through this
|
|
/// class that hands back an admin listener with nothing to check
|
|
/// logins against.
|
|
///
|
|
|
|
bool hasAdmin();
|
|
int getAdminPort();
|
|
std::string getAdminUser();
|
|
std::string getAdminPassword();
|
|
|
|
private:
|
|
|
|
coreutils::JFile *file;
|
|
|
|
// Owned, persistent storage for the TLSInfo fields below -
|
|
// TLSInfo's own ZString members are non-owning views, so they
|
|
// have to point at something that outlives them; pointing them at
|
|
// temporary std::strings decoded during construction would leave
|
|
// them dangling the moment this constructor returned.
|
|
std::string certPath, keyPath, caPath;
|
|
|
|
core::TLSInfo tlsInfo;
|
|
bool hasTls = false;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|