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).
95 lines
3.2 KiB
C++
95 lines
3.2 KiB
C++
#ifndef __SMTPServer_h__
|
|
# define __SMTPServer_h__
|
|
|
|
# include <string>
|
|
# include <vector>
|
|
# include <filesystem>
|
|
# include "EPoll.h"
|
|
# include "TCPServer.h"
|
|
# include "TLSInfo.h"
|
|
# include "SMTPSession.h"
|
|
# include "MailFileSystem.h"
|
|
# include "__SMTP_AUTH.h"
|
|
# include "__SMTP_DATA.h"
|
|
# include "__SMTP_EHLO.h"
|
|
# include "__SMTP_EXPN.h"
|
|
# include "__SMTP_HELO.h"
|
|
# include "__SMTP_HELP.h"
|
|
# include "__SMTP_MAIL.h"
|
|
# include "__SMTP_NOOP.h"
|
|
# include "__SMTP_QUIT.h"
|
|
# include "__SMTP_RCPT.h"
|
|
# include "__SMTP_RSET.h"
|
|
# include "__SMTP_VRFY.h"
|
|
# include "INotify.h"
|
|
# include "SendMail.h"
|
|
# include "DKIMSigner.h"
|
|
# include "SpamAssassinFilter.h"
|
|
namespace mail {
|
|
|
|
class SMTPServer : public core::TCPServer, public core::INotify {
|
|
|
|
public:
|
|
// watchQueue controls whether this instance watches the mail
|
|
// queue directory and relays/delivers what lands in it - true by
|
|
// default for the ordinary single-listener case. Running a
|
|
// second SMTPServer for a submission/TLS port alongside the
|
|
// plaintext one needs watchQueue=false on exactly one of the two:
|
|
// each SMTPServer's own INotify watch is independent, so two
|
|
// watchers on the same directory would each fire inCreate() for
|
|
// every queued message, delivering it twice.
|
|
// dkimSigner is optional (nullptr = outbound mail goes out
|
|
// unsigned) and not owned - passed straight through to every
|
|
// SendMail this instance's inCreate() constructs for outbound
|
|
// relay.
|
|
SMTPServer(core::EPoll &ePoll, std::string hostName, MailFileSystem &mailFileSystem,
|
|
core::IPAddress ipAddress, core::TLSInfo *tlsInfo, bool watchQueue = true,
|
|
DKIMSigner *dkimSigner = nullptr);
|
|
|
|
MailFileSystem &mailFileSystem;
|
|
std::string hostName;
|
|
core::EPoll &ePoll;
|
|
DKIMSigner *dkimSigner;
|
|
|
|
// Advertised via EHLO's "250-SIZE <n>" and enforced by __SMTP_DATA
|
|
// while accumulating a message body - RFC 1870. 25MB, matching
|
|
// the limit most real providers (e.g. Gmail) use.
|
|
static const size_t maxMessageSize = 25 * 1024 * 1024;
|
|
|
|
SMTPSession * getSocketAccept(core::EPoll &ePoll) override;
|
|
void sessionErrorHandler(std::string errorString, std::stringstream &out);
|
|
|
|
protected:
|
|
void inCreate(coreutils::ZString &name);
|
|
|
|
private:
|
|
__SMTP_AUTH _smtp_auth;
|
|
__SMTP_DATA _smtp_data;
|
|
__SMTP_EHLO _smtp_ehlo;
|
|
__SMTP_EXPN _smtp_expn;
|
|
__SMTP_HELO _smtp_helo;
|
|
__SMTP_HELP _smtp_help;
|
|
__SMTP_MAIL _smtp_mail;
|
|
__SMTP_NOOP _smtp_noop;
|
|
__SMTP_QUIT _smtp_quit;
|
|
__SMTP_RCPT _smtp_rcpt;
|
|
__SMTP_RSET _smtp_rset;
|
|
__SMTP_VRFY _smtp_vrfy;
|
|
int wd;
|
|
|
|
void processExisting();
|
|
|
|
// Writes one already-scanned message into one mailbox's Inbox
|
|
// or Spam folder - factored out of inCreate() so an alias
|
|
// (MailFileSystem::ifAliasExists()/getAliasMailboxes()) can
|
|
// deliver the same scanned copy to each of its target mailboxes,
|
|
// not just the single recipient a plain local delivery has.
|
|
void deliverToMailbox(coreutils::ZString &mailbox, coreutils::ZString &messageId,
|
|
SpamAssassinFilter::Result &scan);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|