butter-portal/install_madmail.py

111 lines
3.9 KiB
Python
Raw Normal View History

2026-03-30 15:15:22 +01:00
import pexpect
import json
import socket
from app import app
from subprocess import run
def resolve_butterbox_ip(hostname):
"""Best-effort lookup of the box's current address, falling back to the
configured default. Mirrors app.routes.resolve_butterbox_ip but avoids a
circular import (routes imports this module) and reuses the hostname that
was already loaded from settings.txt."""
# 1. Resolve the box's own mDNS/.local name.
try:
ip = socket.gethostbyname(f"{hostname}.local")
if ip and not ip.startswith("127."):
return ip
except OSError:
pass
# 2. Fall back to the address of the primary outbound interface. The
# connect() picks a route without sending any packets.
try:
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
if ip and not ip.startswith("127."):
return ip
except OSError:
pass
# 3. Give up and use the configured access-point default.
return app.config['BUTTERBOX_DEFAULT_IP']
2026-03-30 15:15:22 +01:00
def run_madmail_installer():
with open("./settings.txt", "r") as f:
settings = json.load(f)
butterbox_hostname = settings["butterbox_hostname"]
cmd = f"sudo ../madmail/madmail install"
2026-05-07 21:17:51 -04:00
child = pexpect.spawnu(cmd)
2026-03-30 15:15:22 +01:00
child.logfile = open("install_log.txt", "w")
child.expect("Customize every setting")
child.sendline("2")
child.expect("Primary domain")
child.sendline(f"{butterbox_hostname}.local")
2026-03-30 15:15:22 +01:00
child.expect("MX record")
child.sendline(f"{butterbox_hostname}.local")
2026-03-30 15:15:22 +01:00
child.expect("Public IP address")
child.sendline(resolve_butterbox_ip(butterbox_hostname))
2026-03-30 15:15:22 +01:00
child.expect("Additional domains")
child.sendline("")
child.expect("State directory")
child.sendline("")
child.expect("Configuration directory")
child.sendline("")
child.expect("TLS mode")
2026-03-31 14:23:02 +01:00
child.sendline("self_signed")
2026-05-07 21:17:51 -04:00
child.expect("Disable TLS")
child.sendline("y")
2026-03-30 15:15:22 +01:00
child.expect("SMTP port")
2026-03-31 14:23:02 +01:00
child.sendline("25")
2026-03-30 15:15:22 +01:00
child.expect("Submission port")
2026-03-31 14:23:02 +01:00
child.sendline("587")
2026-03-30 15:15:22 +01:00
child.expect("Submission TLS port")
2026-03-31 14:23:02 +01:00
child.sendline("465")
2026-03-30 15:15:22 +01:00
child.expect("IMAP port")
2026-03-31 14:23:02 +01:00
child.sendline("143")
2026-03-30 15:15:22 +01:00
child.expect("IMAP TLS port")
2026-03-31 14:23:02 +01:00
child.sendline("993")
2026-05-07 21:17:51 -04:00
child.expect("Enable chatmail")
2026-03-30 15:15:22 +01:00
child.sendline("y")
child.expect("Chatmail HTTP port")
child.sendline("8081")
child.expect("Chatmail HTTPS port")
child.sendline("8443")
child.expect("Chatmail username length")
2026-03-31 14:23:02 +01:00
child.sendline("8")
2026-03-30 15:15:22 +01:00
child.expect("Chatmail password length")
2026-03-31 14:23:02 +01:00
child.sendline("16")
2026-03-30 15:15:22 +01:00
child.expect("Enable Shadowsocks proxy for faster messaging")
child.sendline("n")
child.expect("Enable TURN server")
child.sendline("n")
child.expect("Allow cleartext SMTP submission")
child.sendline("n")
2026-03-30 15:15:22 +01:00
child.expect("Allow secure join requests without encryption")
child.sendline("y")
2026-03-30 15:15:22 +01:00
child.expect("Passthrough senders")
child.sendline("")
child.expect("Passthrough recipients")
child.sendline("")
child.expect("Maximum message size")
child.sendline("")
child.expect("Add Cloudflare proxy disable tags to DNS records")
child.sendline("n")
child.expect("Enable logging for the server")
child.sendline("y")
child.expect(pexpect.EOF)
daemon_enable = run(["sudo", "systemctl", "enable", "madmail"], capture_output=True, text=True)
if daemon_enable.returncode != 0:
print(f"Issue running systemctl daemon_enable")
daemon_start = run(["sudo", "systemctl", "start", "madmail"], capture_output=True, text=True)
if daemon_start.returncode != 0:
print(f"Issue running systemctl daemon_start")
daemon_reload = run(["sudo", "systemctl", "daemon-reload"], capture_output=True, text=True)
if daemon_reload.returncode != 0:
print(f"Issue running systemctl daemon_reload")