From: Ralf Jung Date: Mon, 27 Nov 2017 21:34:37 +0000 (+0100) Subject: add newmail X-Git-Url: https://git.ralfj.de/lets-encrypt-tiny.git/commitdiff_plain/21e858b9cb9accbb14ee1a7faebf0d7c360830ef?ds=inline add newmail --- diff --git a/.gitignore b/.gitignore index bee8a64..8025bc0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +*~ diff --git a/newmail/.gitignore b/newmail/.gitignore new file mode 100644 index 0000000..26e3eaf --- /dev/null +++ b/newmail/.gitignore @@ -0,0 +1,2 @@ +*.pyc +settings.py diff --git a/newmail/newmail b/newmail/newmail new file mode 100755 index 0000000..86a1d99 --- /dev/null +++ b/newmail/newmail @@ -0,0 +1,102 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +from __future__ import print_function +import sys, os, random, MySQLdb, subprocess, time, string, argparse +import urllib, 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
`.") + 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)) diff --git a/newmail/templates.py b/newmail/templates.py new file mode 100644 index 0000000..7be7108 --- /dev/null +++ b/newmail/templates.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +SUBJECT = "Deine E-Mail-Adresse {user}" +TEMPLATE = """Hallo, + +du hast jetzt einen E-Mail-Account "{user}" mit Passwort "{password}". +Bevor du dich einloggen kannst, musst du das Passwort unter ändern. + +{incoming} + +Versenden kannst du Mails via SMTP: + Server: {host} + Port: 587 + Verschlüsselung: STARTTLS + Benutzername: {user} + +Bitte prüfe, ob das alles funktioniert. Bei Problemen kannst du dich gerne an mich wenden. + +Viele Grüße, +Ralf""" +INCOMING_FORWARD = "Eingehende Mails werden an deine Adresse {forward} weitergeleitet." +INCOMING_IMAP = '''Der Zugriff auf das Postfach erfolgt via IMAP: + Server: {host} + Port: 143 + Verschlüsselung: STARTTLS + Benutzername: {user}''' +