Added support of mail only configuration
- added checkboxes to disable web and/or dns on alias or user creation - added ignore lists for domain not being handled on either web or dns - added API for managing ignore lists Signed-off-by: Bernard `Guyzmo` Pratz <guyzmo+github@m0g.net>
This commit is contained in:
parent
62b6117638
commit
1d9b678d89
|
@ -155,7 +155,12 @@ def mail_users():
|
|||
@authorized_personnel_only
|
||||
def mail_users_add():
|
||||
try:
|
||||
return add_mail_user(request.form.get('email', ''), request.form.get('password', ''), request.form.get('privileges', ''), env)
|
||||
return add_mail_user(request.form.get('email', ''),
|
||||
request.form.get('password', ''),
|
||||
request.form.get('privileges', ''),
|
||||
env,
|
||||
dns_enabled=request.form.get('dns_enabled', False),
|
||||
web_enabled=request.form.get('web_enabled', False))
|
||||
except ValueError as e:
|
||||
return (str(e), 400)
|
||||
|
||||
|
@ -207,7 +212,9 @@ def mail_aliases_add():
|
|||
request.form.get('forwards_to', ''),
|
||||
request.form.get('permitted_senders', ''),
|
||||
env,
|
||||
update_if_exists=(request.form.get('update_if_exists', '') == '1')
|
||||
update_if_exists=(request.form.get('update_if_exists', '') == '1'),
|
||||
dns_enabled=request.form.get('dns_enabled', False),
|
||||
web_enabled=request.form.get('web_enabled', False)
|
||||
)
|
||||
|
||||
@app.route('/mail/aliases/remove', methods=['POST'])
|
||||
|
@ -335,7 +342,7 @@ def ssl_get_status():
|
|||
|
||||
# What domains can we provision certificates for? What unexpected problems do we have?
|
||||
provision, cant_provision = get_certificates_to_provision(env, show_extended_problems=False)
|
||||
|
||||
|
||||
# What's the current status of TLS certificates on all of the domain?
|
||||
domains_status = get_web_domains_info(env)
|
||||
domains_status = [{ "domain": d["domain"], "status": d["ssl_certificate"][0], "text": d["ssl_certificate"][1] } for d in domains_status ]
|
||||
|
|
|
@ -15,8 +15,7 @@ from utils import shell, load_env_vars_from_file, safe_domain_name, sort_domains
|
|||
def get_dns_domains(env):
|
||||
# Add all domain names in use by email users and mail aliases and ensure
|
||||
# PRIMARY_HOSTNAME is in the list.
|
||||
domains = set()
|
||||
domains |= get_mail_domains(env)
|
||||
domains = get_mail_domains(env, filter_list='dns')
|
||||
domains.add(env['PRIMARY_HOSTNAME'])
|
||||
return domains
|
||||
|
||||
|
@ -144,7 +143,7 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en
|
|||
# Define ns2.PRIMARY_HOSTNAME or whatever the user overrides.
|
||||
# User may provide one or more additional nameservers
|
||||
secondary_ns_list = get_secondary_dns(additional_records, mode="NS") \
|
||||
or ["ns2." + env["PRIMARY_HOSTNAME"]]
|
||||
or ["ns2." + env["PRIMARY_HOSTNAME"]]
|
||||
for secondary_ns in secondary_ns_list:
|
||||
records.append((None, "NS", secondary_ns+'.', False))
|
||||
|
||||
|
|
|
@ -3,8 +3,35 @@
|
|||
import subprocess, shutil, os, sqlite3, re
|
||||
import utils
|
||||
from email_validator import validate_email as validate_email_, EmailNotValidError
|
||||
import rtyaml
|
||||
import idna
|
||||
|
||||
def load_domain_blacklist(env, service):
|
||||
try:
|
||||
return set(rtyaml.load(open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)))))
|
||||
except:
|
||||
return set()
|
||||
|
||||
def add_domain_blacklist(env, domain, service):
|
||||
try:
|
||||
ignored = set(rtyaml.load(open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)))))
|
||||
ignored.add(domain)
|
||||
except Exception as err:
|
||||
# if non-existent or baldy formatted, consider it new
|
||||
ignored = {domain}
|
||||
with open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)), "w") as f:
|
||||
f.write(rtyaml.dump(list(ignored)))
|
||||
|
||||
def remove_domain_blacklist(env, domain, service):
|
||||
try:
|
||||
ignored = set(rtyaml.load(open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)))))
|
||||
if domain in ignored:
|
||||
ignored.remove(domain)
|
||||
with open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)), "w") as f:
|
||||
f.write(rtyaml.dump(list(ignored)))
|
||||
except Exception as err:
|
||||
pass
|
||||
|
||||
def validate_email(email, mode=None):
|
||||
# Checks that an email address is syntactically valid. Returns True/False.
|
||||
# Until Postfix supports SMTPUTF8, an email address may contain ASCII
|
||||
|
@ -253,15 +280,20 @@ def get_domain(emailaddr, as_unicode=True):
|
|||
pass
|
||||
return ret
|
||||
|
||||
def get_mail_domains(env, filter_aliases=lambda alias : True):
|
||||
def get_mail_domains(env, filter_aliases=lambda alias : True, filter_list=None):
|
||||
ignored = set()
|
||||
if filter_list == 'dns':
|
||||
ignored |= load_domain_blacklist(env, 'dns')
|
||||
if filter_list in ('web', 'www'):
|
||||
ignored |= load_domain_blacklist(env, 'www')
|
||||
# Returns the domain names (IDNA-encoded) of all of the email addresses
|
||||
# configured on the system.
|
||||
return set(
|
||||
[get_domain(login, as_unicode=False) for login in get_mail_users(env)]
|
||||
+ [get_domain(address, as_unicode=False) for address, *_ in get_mail_aliases(env) if filter_aliases(address) ]
|
||||
)
|
||||
) - ignored
|
||||
|
||||
def add_mail_user(email, pw, privs, env):
|
||||
def add_mail_user(email, pw, privs, env, dns_enabled=True, web_enabled=True):
|
||||
# validate email
|
||||
if email.strip() == "":
|
||||
return ("No email address provided.", 400)
|
||||
|
@ -303,6 +335,14 @@ def add_mail_user(email, pw, privs, env):
|
|||
# write databasebefore next step
|
||||
conn.commit()
|
||||
|
||||
# Add non dns enabled domain to the ignored domain list
|
||||
if dns_enabled == 'false':
|
||||
add_domain_blacklist(env, get_domain(email), 'dns')
|
||||
|
||||
# Add non web enabled domain to the ignored domain list
|
||||
if web_enabled == 'false':
|
||||
add_domain_blacklist(env, get_domain(email), 'www')
|
||||
|
||||
# Update things in case any new domains are added.
|
||||
return kick(env, "mail user added")
|
||||
|
||||
|
@ -347,6 +387,9 @@ def remove_mail_user(email, env):
|
|||
return ("That's not a user (%s)." % email, 400)
|
||||
conn.commit()
|
||||
|
||||
remove_domain_blacklist(env, get_domain(address), 'dns')
|
||||
remove_domain_blacklist(env, get_domain(address), 'www')
|
||||
|
||||
# Update things in case any domains are removed.
|
||||
return kick(env, "mail user removed")
|
||||
|
||||
|
@ -395,7 +438,7 @@ def add_remove_mail_user_privilege(email, priv, action, env):
|
|||
|
||||
return "OK"
|
||||
|
||||
def add_mail_alias(address, forwards_to, permitted_senders, env, update_if_exists=False, do_kick=True):
|
||||
def add_mail_alias(address, forwards_to, permitted_senders, env, update_if_exists=False, dns_enabled=True, web_enabled=True, do_kick=True):
|
||||
# convert Unicode domain to IDNA
|
||||
address = sanitize_idn_email_address(address)
|
||||
|
||||
|
@ -484,6 +527,14 @@ def add_mail_alias(address, forwards_to, permitted_senders, env, update_if_exist
|
|||
|
||||
conn.commit()
|
||||
|
||||
# Add non dns enabled domain to the ignored domain list
|
||||
if dns_enabled == 'false':
|
||||
add_domain_blacklist(env, get_domain(address), 'dns')
|
||||
|
||||
# Add non web enabled domain to the ignored domain list
|
||||
if web_enabled == 'false':
|
||||
add_domain_blacklist(env, get_domain(address), 'www')
|
||||
|
||||
if do_kick:
|
||||
# Update things in case any new domains are added.
|
||||
return kick(env, return_status)
|
||||
|
@ -499,6 +550,9 @@ def remove_mail_alias(address, env, do_kick=True):
|
|||
return ("That's not an alias (%s)." % address, 400)
|
||||
conn.commit()
|
||||
|
||||
remove_domain_blacklist(env, get_domain(address), 'dns')
|
||||
remove_domain_blacklist(env, get_domain(address), 'www')
|
||||
|
||||
if do_kick:
|
||||
# Update things in case any domains are removed.
|
||||
return kick(env, "alias removed")
|
||||
|
|
|
@ -64,6 +64,23 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="addaliasDnsHandling" class="col-sm-1 control-label">New domain</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="addaliasDnsHandling" name="addaliasDnsHandling" type="checkbox" checked>
|
||||
If the email is of a non-managed domain, create DNS configuration for the domain.
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="addaliasWebHandling" name="addaliasWebHandling" type="checkbox" id="addaliasWebHandling" checked>
|
||||
If the email is of a non-managed domain, create Web configuration for the domain.
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-1 col-sm-11">
|
||||
<button id="add-alias-button" type="submit" class="btn btn-primary">Add Alias</button>
|
||||
|
@ -174,6 +191,8 @@ function do_add_alias() {
|
|||
var form_address = $("#addaliasAddress").val();
|
||||
var form_forwardsto = $("#addaliasForwardsTo").val();
|
||||
var form_senders = ($('#addaliasForwardsToAdvanced').prop('checked') ? $("#addaliasSenders").val() : '');
|
||||
var form_dns = $('#addaliasDnsHandling').prop('checked');
|
||||
var form_web = $('#addaliasWebHandling').prop('checked');
|
||||
if ($('#addaliasForwardsToAdvanced').prop('checked') && !/\S/.exec($("#addaliasSenders").val())) {
|
||||
show_modal_error(title, "You did not enter any permitted senders.");
|
||||
return false;
|
||||
|
@ -185,7 +204,9 @@ function do_add_alias() {
|
|||
update_if_exists: is_alias_add_update ? '1' : '0',
|
||||
address: form_address,
|
||||
forwards_to: form_forwardsto,
|
||||
permitted_senders: form_senders
|
||||
permitted_senders: form_senders,
|
||||
dns_enabled: form_dns,
|
||||
web_enabled: form_web
|
||||
},
|
||||
function(r) {
|
||||
// Responses are multiple lines of pre-formatted text.
|
||||
|
@ -204,6 +225,8 @@ function aliases_reset_form() {
|
|||
$("#addaliasAddress").val('')
|
||||
$("#addaliasForwardsTo").val('')
|
||||
$("#addaliasSenders").val('')
|
||||
$('#addaliasDnsHandling').prop('disabled', false);
|
||||
$('#addaliasWebHandling').prop('disabled', false);
|
||||
$('#alias-cancel').addClass('hidden');
|
||||
$('#add-alias-button').text('Add Alias');
|
||||
is_alias_add_update = false;
|
||||
|
@ -232,6 +255,8 @@ function aliases_edit(elem) {
|
|||
$('#addaliasForwardsToAdvanced').prop('checked', senders != "");
|
||||
$('#addaliasForwardsToNotAdvanced').prop('checked', senders == "");
|
||||
$("#addaliasSenders").val(senders);
|
||||
$('#addaliasDnsHandling').prop('disabled', true);
|
||||
$('#addaliasWebHandling').prop('disabled', true);
|
||||
$('#add-alias-button').text('Update');
|
||||
$('body').animate({ scrollTop: 0 })
|
||||
is_alias_add_update = true;
|
||||
|
|
|
@ -28,6 +28,23 @@
|
|||
<option value="admin">Administrator</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="adduserDnsHandling" class="col-sm-1 control-label">New domain</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="adduserDnsHandling" name="adduserDnsHandling" type="checkbox" checked>
|
||||
If the email is of a non-managed domain, create DNS configuration for the domain.
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="adduserWebHandling" name="adduserWebHandling" type="checkbox" id="adduserWebHandling" checked>
|
||||
If the email is of a non-managed domain, create Web configuration for the domain.
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Add User</button>
|
||||
</form>
|
||||
<ul style="margin-top: 1em; padding-left: 1.5em; font-size: 90%;">
|
||||
|
@ -143,13 +160,17 @@ function do_add_user() {
|
|||
var email = $("#adduserEmail").val();
|
||||
var pw = $("#adduserPassword").val();
|
||||
var privs = $("#adduserPrivs").val();
|
||||
var form_dns = $('#adduserDnsHandling').prop('checked');
|
||||
var form_web = $('#adduserWebHandling').prop('checked');
|
||||
api(
|
||||
"/mail/users/add",
|
||||
"POST",
|
||||
{
|
||||
email: email,
|
||||
password: pw,
|
||||
privileges: privs
|
||||
privileges: privs,
|
||||
dns_enabled: form_dns,
|
||||
web_enabled: form_web
|
||||
},
|
||||
function(r) {
|
||||
// Responses are multiple lines of pre-formatted text.
|
||||
|
|
|
@ -16,14 +16,14 @@ def get_web_domains(env, include_www_redirects=True, exclude_dns_elsewhere=True)
|
|||
# Serve web for all mail domains so that we might at least
|
||||
# provide auto-discover of email settings, and also a static website
|
||||
# if the user wants to make one.
|
||||
domains |= get_mail_domains(env)
|
||||
domains |= get_mail_domains(env, filter_list='www')
|
||||
|
||||
if include_www_redirects:
|
||||
# Add 'www.' subdomains that we want to provide default redirects
|
||||
# to the main domain for. We'll add 'www.' to any DNS zones, i.e.
|
||||
# the topmost of each domain we serve.
|
||||
domains |= set('www.' + zone for zone, zonefile in get_dns_zones(env))
|
||||
|
||||
|
||||
if exclude_dns_elsewhere:
|
||||
# ...Unless the domain has an A/AAAA record that maps it to a different
|
||||
# IP address than this box. Remove those domains from our list.
|
||||
|
|
Loading…
Reference in New Issue