#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys, os, random, MySQLdb, subprocess, time, string, argparse
import smtplib, email.mime.text, email.utils
from settings import *
from templates import *

# setup
random.seed = os.urandom(32)

# DB stuff
db = MySQLdb.connect(user=DB_USER, passwd=DB_PW, db=DB_NAME, charset='utf8')

def db_execute(query, args):
   cursor = db.cursor(MySQLdb.cursors.DictCursor)
   if len(args) == 1 and isinstance(args[0], dict): args = args[0] # einzelnes dict weiterreichen
   cursor.execute(query, args)
   return cursor

def db_fetch_one_row(query, *args):
   cursor = db_execute(query, args)
   result = cursor.fetchone()
   if cursor.fetchone() is not None:
      raise Exception("Found more than one result, only one was expected")
   cursor.close()
   return result

def db_run(query, *args):
   cursor = db_execute(query, args)
   cursor.close()

def new_user(name, hash, ):
   db_run('INSERT INTO users (username, password, active) VALUES (%s, %s, -1)', name, hash)

def new_alias(name, alias):
   db_run('INSERT INTO aliases (mail, user) VALUES (%s, %s)', name, alias)

# interaction with dbadm pw
def gen_hash(plain):
   return subprocess.check_output(["doveadm", "pw", "-s", "SHA512-CRYPT", "-r", str(64*1024), "-p", plain]).decode('utf-8').strip()

# more tools
def gen_pw(length = 12):
   chars = string.ascii_letters + string.digits
   return ''.join(random.choice(chars) for i in range(length))

def send_mail(user, mail, password, forward):
   assert password is not None, "Sending mail for non-password accounts not yet supported."
   incoming = (INCOMING_FORWARD if forward else INCOMING_IMAP).format(password=password, user=user, host=HOST, forward=forward)
   text = TEMPLATE.format(password=password, user=user, host=HOST, forward=forward, incoming=incoming)
   subject = SUBJECT.format(user=user, host=HOST)
   # construct mail content
   msg = email.mime.text.MIMEText(text, 'plain', 'utf-8')
   msg['Subject'] = subject
   msg['Date'] = email.utils.formatdate(localtime=True)
   msg['From'] = MAIL_ADDR
   msg['To'] = mail
   msg['Bcc'] = MAIL_ADDR
   # put into envelope and send
   s = smtplib.SMTP('localhost')
   s.sendmail(MAIL_ADDR, [mail, MAIL_ADDR], msg.as_string())
   s.quit()

# read command-line arguments
parser = argparse.ArgumentParser(description='Create a new e-mail user')
parser.add_argument("-u", "--username",
                    dest="username", required=True,
                    help="The name of the user (that's also its address).")
parser.add_argument("-f", "--forward",
                    dest="forward",
                    help="Where to forward emails to.")
#parser.add_argument("-p", "--password",
#                    action="store_true", dest="password",
#                    help="Whether to create an account and password for this user.")
parser.add_argument("-m", "--mail", nargs='?',
                    action="store", dest="mail", const=True,
                    help="Whether to notify the user about their new account.")
args = parser.parse_args()

# sanity check
if args.mail == True:
   if args.forward:
      args.mail = args.forward
   else:
      print("Whom should I send the mail to? Please use `-m <address>`.")
      sys.exit(1)
domain = args.username.split('@')[-1]
if domain not in DOMAINS:
   print("{} is not a domain we can handle mail for.".format(domain))
   sys.exit(1)

# do stuff
password = gen_pw()
new_user(args.username, gen_hash(password))
print("Created {} with password {}".format(args.username, password))
if args.forward:
   new_alias(args.username, args.forward)
   print("Forwarded {} to {}".format(args.username, args.forward))
if args.mail:         
   send_mail(args.username, args.mail, password, args.forward)
   print("Sent mail about the new account to {}".format(args.mail))
