From 443b084a1733ad7f81a8be7faab460d3ceaba885 Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Tue, 7 Oct 2014 19:47:30 +0000 Subject: [PATCH] in the admin, group aliases by domain, fixes #211 --- management/daemon.py | 6 +-- management/mailconfig.py | 65 +++++++++++++++++++++++-------- management/templates/aliases.html | 24 ++++++++---- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/management/daemon.py b/management/daemon.py index 8cf52e1a..695b2a1a 100755 --- a/management/daemon.py +++ b/management/daemon.py @@ -7,9 +7,9 @@ from functools import wraps from flask import Flask, request, render_template, abort, Response import auth, utils -from mailconfig import get_mail_users_ex, get_admins, add_mail_user, set_mail_password, remove_mail_user +from mailconfig import get_mail_users, get_mail_users_ex, get_admins, add_mail_user, set_mail_password, remove_mail_user from mailconfig import get_mail_user_privileges, add_remove_mail_user_privilege -from mailconfig import get_mail_aliases, get_mail_domains, add_mail_alias, remove_mail_alias +from mailconfig import get_mail_aliases, get_mail_aliases_ex, get_mail_domains, add_mail_alias, remove_mail_alias env = utils.load_environment() @@ -146,7 +146,7 @@ def mail_user_privs_remove(): @authorized_personnel_only def mail_aliases(): if request.args.get("format", "") == "json": - return json_response(get_mail_aliases(env, as_json=True)) + return json_response(get_mail_aliases_ex(env)) else: return "".join(x+"\t"+y+"\n" for x, y in get_mail_aliases(env)) diff --git a/management/mailconfig.py b/management/mailconfig.py index ea4a5cc2..74b3c715 100755 --- a/management/mailconfig.py +++ b/management/mailconfig.py @@ -139,29 +139,62 @@ def get_admins(env): users.add(user["email"]) return users -def get_mail_aliases(env, as_json=False): +def get_mail_aliases(env): + # Returns a sorted list of tuples of (alias, forward-to string). c = open_database(env) c.execute('SELECT source, destination FROM aliases') aliases = { row[0]: row[1] for row in c.fetchall() } # make dict # put in a canonical order: sort by domain, then by email address lexicographically - aliases = [ (source, aliases[source]) for source in utils.sort_email_addresses(aliases.keys(), env) ] # sort - - # but put automatic aliases to administrator@ last - aliases.sort(key = lambda x : x[1] == get_system_administrator(env)) - - if as_json: - required_aliases = get_required_aliases(env) - aliases = [ - { - "source": alias[0], - "destination": [d.strip() for d in alias[1].split(",")], - "required": alias[0] in required_aliases or alias[0] == get_system_administrator(env), - } - for alias in aliases - ] + aliases = [ (source, aliases[source]) for source in utils.sort_email_addresses(aliases.keys(), env) ] return aliases +def get_mail_aliases_ex(env): + # Returns a complex data structure of all mail aliases, similar + # to get_mail_users_ex. + # + # [ + # { + # domain: "domain.tld", + # alias: [ + # { + # source: "name@domain.tld", + # destination: ["target1@domain.com", "target2@domain.com", ...], + # required: True|False + # }, + # ... + # ] + # }, + # ... + # ] + + required_aliases = get_required_aliases(env) + domains = {} + for source, destination in get_mail_aliases(env): + # get alias info + domain = get_domain(source) + required = ((source in required_aliases) or (source == get_system_administrator(env))) + + # add to list + if not domain in domains: + domains[domain] = { + "domain": domain, + "aliases": [], + } + domains[domain]["aliases"].append({ + "source": source, + "destination": [d.strip() for d in destination.split(",")], + "required": required, + }) + + # Sort domains. + domains = [domains[domain] for domain in utils.sort_domains(domains.keys(), env)] + + # Sort aliases within each domain first by required-ness then lexicographically by source address. + for domain in domains: + domain["aliases"].sort(key = lambda alias : (alias["required"], alias["source"])) + return domains + def get_mail_alias_map(env): aliases = { } for alias, targets in get_mail_aliases(env): diff --git a/management/templates/aliases.html b/management/templates/aliases.html index 90642de0..2f01dfd9 100644 --- a/management/templates/aliases.html +++ b/management/templates/aliases.html @@ -82,15 +82,23 @@ function show_aliases() { function(r) { $('#alias_table tbody').html(""); for (var i = 0; i < r.length; i++) { - var n = $("#alias-template").clone(); - n.attr('id', ''); + var hdr = $("

"); + hdr.find('h4').text(r[i].domain); + $('#alias_table tbody').append(hdr); - if (r[i].required) n.addClass('alias-required'); - n.attr('data-email', r[i].source); - n.find('td.email').text(r[i].source) - for (var j = 0; j < r[i].destination.length; j++) - n.find('td.target').append($("
").text(r[i].destination[j])) - $('#alias_table tbody').append(n); + for (var k = 0; k < r[i].aliases.length; k++) { + var alias = r[i].aliases[k]; + + var n = $("#alias-template").clone(); + n.attr('id', ''); + + if (alias.required) n.addClass('alias-required'); + n.attr('data-email', alias.source); + n.find('td.email').text(alias.source) + for (var j = 0; j < alias.destination.length; j++) + n.find('td.target').append($("
").text(alias.destination[j])) + $('#alias_table tbody').append(n); + } } })