3 Commits

Author SHA1 Message Date
95423ebf63 Remove pyc files
pyc files are not compatible across multiple python versions
Harden systemd service files
2023-06-24 20:12:20 -04:00
2bcc807b91 Allow multiple servers of same type 2023-06-23 22:03:58 -04:00
bcd250d2b0 change STDOUT to CONSOLE 2023-06-23 21:42:00 -04:00
5 changed files with 62 additions and 51 deletions

View File

@ -14,10 +14,10 @@ requirements.txt: Pipfile.lock
pipenv requirements > requirements.txt
build: clean requirements.txt
python3 -m pip install -r requirements.txt --target build
python3 -m pip install -r requirements.txt --no-compile --target build
cp -r mail4one/ build/
sed -i "s/DEVELOMENT/$(shell scripts/get_version.sh)/" build/mail4one/version.py
python3 -m compileall build/mail4one -f
rm -rf build/mail4one/__pycache__
rm -rf build/*.dist-info
python3 -m zipapp \
--output mail4one.pyz \

View File

@ -9,14 +9,19 @@ Requires=network-online.target
[Service]
User=mail4one
ExecStart=/usr/local/bin/mail4one --config /etc/mail4one/config.json
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
StateDirectory=mail4one
StateDirectory=mail4one/certs mail4one/mails
StateDirectoryMode=0750
UMask=
LogsDirectory=mail4one
WorkingDirectory=/var/lib/mail4one
ProtectSystem=strict
PrivateTmp=true
PrivateUsers=true
ProtectHome=yes
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.target

View File

@ -10,7 +10,7 @@ set -x
if [ "$RENEWED_DOMAINS" = "mail.mydomain.com" ]
then
mkdir -p /var/lib/mail4one/certs
chmod 500 /var/lib/mail4one/certs
chmod 750 /var/lib/mail4one/certs
chown mail4one:mail4one /var/lib/mail4one/certs
cp "$RENEWED_LINEAGE/fullchain.pem" /var/lib/mail4one/certs/
cp "$RENEWED_LINEAGE/privkey.pem" /var/lib/mail4one/certs/

View File

@ -41,6 +41,7 @@ class TLSCfg(Jata):
class ServerCfg(Jata):
server_type: str
host: str = "default"
port: int
# disabled: bool = False
@ -48,22 +49,25 @@ class ServerCfg(Jata):
class PopCfg(ServerCfg):
server_type = "pop"
port = 995
timeout_seconds = 60
class SmtpStartTLSCfg(ServerCfg):
smtputf8 = True
server_type = "smtp_starttls"
smtputf8 = True # Not used yet
port = 25
class SmtpCfg(ServerCfg):
smtputf8 = True
server_type = "smtp_starttls"
smtputf8 = True # Not used yet
port = 465
class LogCfg(Jata):
logfile = "STDOUT"
logfile = "CONSOLE"
level = "INFO"
@ -77,10 +81,7 @@ class Config(Jata):
boxes: list[Mbox]
users: list[User]
pop: PopCfg | None = None
smtp_starttls: SmtpStartTLSCfg | None = None
smtp: SmtpCfg | None = None
# smtp_port_submission = 587
servers: list[ServerCfg]
CheckerFn = Callable[[str], bool]

View File

@ -23,7 +23,7 @@ def create_tls_context(certfile, keyfile) -> ssl.SSLContext:
def setup_logging(cfg: config.LogCfg):
logging_format = "%(asctime)s %(name)s %(levelname)s %(message)s @ %(filename)s:%(lineno)d"
if cfg.logfile == "STDOUT":
if cfg.logfile == "CONSOLE":
logging.basicConfig(level=cfg.level, format=logging_format)
else:
logging.basicConfig(filename=cfg.logfile,
@ -45,7 +45,7 @@ async def a_main(cfg: config.Config) -> None:
elif tls == "disable":
return None
else:
tls_cfg = config.TLSCfg(pop.tls)
tls_cfg = config.TLSCfg(tls)
return create_tls_context(tls_cfg.certfile, tls_cfg.keyfile)
def get_host(host):
@ -57,47 +57,52 @@ async def a_main(cfg: config.Config) -> None:
mbox_finder = config.gen_addr_to_mboxes(cfg)
servers: list[asyncio.Server] = []
if cfg.pop:
pop = config.PopCfg(cfg.pop)
pop_server = await create_pop_server(
host=get_host(pop.host),
port=pop.port,
mails_path=Path(cfg.mails_path),
users=cfg.users,
ssl_context=get_tls_context(pop.tls),
timeout_seconds=pop.timeout_seconds,
)
servers.append(pop_server)
if not cfg.servers:
logging.warning("Nothing to do!")
return
if cfg.smtp_starttls:
stls = config.SmtpStartTLSCfg(cfg.smtp_starttls)
stls_context = get_tls_context(stls.tls)
if not stls_context:
raise Exception("starttls requires ssl_context")
smtp_server_starttls = await create_smtp_server_starttls(
host=get_host(stls.host),
port=stls.port,
mails_path=Path(cfg.mails_path),
mbox_finder=mbox_finder,
ssl_context=stls_context,
)
servers.append(smtp_server_starttls)
if cfg.smtp:
smtp = config.SmtpCfg(cfg.smtp)
smtp_server = await create_smtp_server(
host=get_host(smtp.host),
port=smtp.port,
mails_path=Path(cfg.mails_path),
mbox_finder=mbox_finder,
ssl_context=get_tls_context(smtp.tls),
)
servers.append(smtp_server)
for scfg in cfg.servers:
if scfg.server_type == "pop":
pop = config.PopCfg(scfg)
pop_server = await create_pop_server(
host=get_host(pop.host),
port=pop.port,
mails_path=Path(cfg.mails_path),
users=cfg.users,
ssl_context=get_tls_context(pop.tls),
timeout_seconds=pop.timeout_seconds,
)
servers.append(pop_server)
elif scfg.server_type == "smtp_starttls":
stls = config.SmtpStartTLSCfg(scfg)
stls_context = get_tls_context(stls.tls)
if not stls_context:
raise Exception("starttls requires ssl_context")
smtp_server_starttls = await create_smtp_server_starttls(
host=get_host(stls.host),
port=stls.port,
mails_path=Path(cfg.mails_path),
mbox_finder=mbox_finder,
ssl_context=stls_context,
)
servers.append(smtp_server_starttls)
elif scfg.server_type == "smtp":
smtp = config.SmtpCfg(scfg)
smtp_server = await create_smtp_server(
host=get_host(smtp.host),
port=smtp.port,
mails_path=Path(cfg.mails_path),
mbox_finder=mbox_finder,
ssl_context=get_tls_context(smtp.tls),
)
servers.append(smtp_server)
else:
logging.error(f"Unknown server {scfg.server_type=}")
if servers:
await asyncio.gather(*[server.serve_forever() for server in servers])
else:
logging.warn("Nothing to do!")
logging.warning("Nothing to do!")
def main() -> None: