#!/usr/bin/env python3
"""
Postfix + Dovecot SMTP/IMAP 서버 설치
도메인: zioinfo.co.kr (IP 기반, DNS MX 없어도 로컬 발송 가능)
계정: info, admin, ythong, choyounbun, guardia / 비밀번호: 1q2w3e!Q
"""
import paramiko, time, sys

HOST='101.79.17.164'; USER='root'; PASS='1q2w3e!Q'
DOMAIN = 'zioinfo.co.kr'
ACCOUNTS = ['info', 'admin', 'ythong', 'choyounbun', 'guardia']
MAIL_PASS = '1q2w3e!Q'

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(HOST, username=USER, password=PASS, timeout=15)
sftp = client.open_sftp()

def run(label, cmd, timeout=120):
    print(f'\n[{label}]')
    chan = client.get_transport().open_session()
    chan.set_combine_stderr(True)
    chan.exec_command(f'export DEBIAN_FRONTEND=noninteractive; {cmd}')
    start = time.time()
    while not chan.exit_status_ready():
        if chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)); sys.stdout.flush()
        if time.time()-start > timeout: print('[TIMEOUT]'); break
        time.sleep(0.3)
    while chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096))
    sys.stdout.flush()
    rc = chan.recv_exit_status()
    print(f'exit={rc}'); return rc

# 1. Postfix + Dovecot 설치
run('Postfix + Dovecot 설치',
    'apt-get install -y -q postfix dovecot-imapd dovecot-pop3d mailutils',
    180)

# 2. Postfix 설정
postfix_main_cf = f"""# Postfix Main Configuration — {DOMAIN}
smtpd_banner = $myhostname ESMTP
biff = no
append_dot_mydomain = no

# 호스트명 설정
myhostname = mail.{DOMAIN}
myorigin = /etc/mailname
mydomain = {DOMAIN}
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

# 네트워크
inet_interfaces = all
inet_protocols = ipv4
mynetworks = 127.0.0.0/8

# 메일박스 (Maildir 형식)
home_mailbox = Maildir/
mailbox_size_limit = 0

# SMTP 인증 (Dovecot SASL)
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous

# TLS (자체서명 인증서 사용)
smtpd_tls_cert_file = /etc/ssl/guardia/server.crt
smtpd_tls_key_file  = /etc/ssl/guardia/server.key
smtpd_use_tls = yes
smtpd_tls_session_cache_database = btree:${{data_directory}}/smtpd_scache
smtp_tls_session_cache_database  = btree:${{data_directory}}/smtp_scache

# 보안
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
recipient_delimiter = +
"""

dovecot_conf = f"""# Dovecot Configuration — {DOMAIN}
protocols = imap pop3 lmtp
listen = *

# 인증 메커니즘
auth_mechanisms = plain login

# 메일 저장소 (Maildir)
mail_location = maildir:~/Maildir

# Postfix SASL 소켓
service auth {{
  unix_listener /var/spool/postfix/private/auth {{
    mode = 0660
    user = postfix
    group = postfix
  }}
}}

# SSL/TLS
ssl = yes
ssl_cert = </etc/ssl/guardia/server.crt
ssl_key  = </etc/ssl/guardia/server.key

# 인증 드라이버
passdb {{
  driver = pam
}}
userdb {{
  driver = passwd
}}

# 로그
log_path = /var/log/dovecot.log
"""

with sftp.open('/etc/postfix/main.cf', 'w') as f: f.write(postfix_main_cf)
with sftp.open('/etc/dovecot/dovecot.conf', 'w') as f: f.write(dovecot_conf)
with sftp.open('/etc/mailname', 'w') as f: f.write(DOMAIN + '\n')
print('설정 파일 생성 완료')

# 3. 메일 계정 생성 (시스템 사용자)
for acc in ACCOUNTS:
    run(f'계정 생성 ({acc}@{DOMAIN})',
        f'id {acc} 2>/dev/null || useradd -m -s /bin/false {acc} && '
        f'echo \"{acc}:{MAIL_PASS}\" | chpasswd && '
        f'mkdir -p /home/{acc}/Maildir/{{cur,new,tmp}} && '
        f'chown -R {acc}:{acc} /home/{acc}/Maildir && '
        f'echo \"{acc}@{DOMAIN} created\"',
        15)

# 4. UFW 포트 오픈
run('UFW SMTP/IMAP 포트',
    'ufw allow 25/tcp && ufw allow 587/tcp && '
    'ufw allow 993/tcp && ufw allow 995/tcp && '
    'ufw allow 143/tcp && ufw allow 110/tcp && echo ok')

# 5. Postfix master.cf에 submission 포트 추가
run('Postfix submission 포트 활성화',
    'grep -q "^submission" /etc/postfix/master.cf || '
    'echo "submission inet n - y - - smtpd" >> /etc/postfix/master.cf')

# 6. 서비스 시작
run('Postfix 시작', 'systemctl enable postfix && systemctl restart postfix && systemctl is-active postfix')
run('Dovecot 시작', 'systemctl enable dovecot && systemctl restart dovecot && systemctl is-active dovecot')

# 7. 로컬 메일 테스트
run('로컬 메일 발송 테스트',
    f'echo "GUARDiA SMTP 테스트 메일" | mail -s "Test" info@{DOMAIN} 2>/dev/null && echo "메일 발송 OK" || echo "mail command 확인 필요"',
    10)

sftp.close(); client.close()
print(f'\nSMTP 서버 구축 완료!')
print(f'도메인: @{DOMAIN}')
print(f'계정: {", ".join(ACCOUNTS)}')
print(f'SMTP: mail.{DOMAIN}:25 (로컬) / 587 (STARTTLS)')
print(f'IMAP: mail.{DOMAIN}:993 (SSL)')
