# requiring aliases for email addresses typically used in DCV to forward
# requiring aliases for email addresses typically used in DCV to forward
# only to accounts that are administrators on this system.
# only to accounts that are administrators on this system.
return("This alias can only have administrators of this system as destinations because the address is frequently used for domain control validation.",400)
return("This alias can only have administrators of this system as destinations because the address is frequently used for domain control validation.",400)
validated_receivers.append(email)
validated_forwards_to.append(email)
receivers=",".join(validated_receivers)
# validate permitted_senders
valid_logins=get_mail_users(env)
valid_logins=get_mail_users(env)
validated_permitted_senders=[]
permitted_senders=permitted_senders.strip()
# validate senders
# Parse comma and \n-separated sender logins & validate. The permitted_senders must be
validated_senders=[]
senders=senders.strip()
# Parse comma and \n-separated sender logins & validate. The senders must be
# valid usernames.
# valid usernames.
forlineinsenders.split("\n"):
forlineinpermitted_senders.split("\n"):
forlogininline.split(","):
forlogininline.split(","):
login=login.strip()
login=login.strip()
iflogin=="":continue
iflogin=="":continue
ifloginnotinvalid_logins:
ifloginnotinvalid_logins:
return("Invalid sender login (%s)."%login,400)
return("Invalid permitted sender: %s is not a user on this system."%login,400)
validated_senders.append(login)
validated_permitted_senders.append(login)
senders=",".join(validated_senders)
# Make sure the alias has either a forwards_to or a permitted_sender.
echo"CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, extra, privileges TEXT NOT NULL DEFAULT '');" | sqlite3 $db_path;
echo"CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, extra, privileges TEXT NOT NULL DEFAULT '');" | sqlite3 $db_path;
echo"CREATE TABLE aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, address TEXT NOT NULL UNIQUE, receivers TEXT NOT NULL, senders TEXT NOT NULL);" | sqlite3 $db_path;
echo"CREATE TABLE aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL UNIQUE, destination TEXT NOT NULL, permitted_senders TEXT);" | sqlite3 $db_path;
# SQL statement that returns a list of addresses/domains the logged in username
# Postfix will query the exact address first, where the priority will be alias
# is allowed to send as. This is similar to virtual-alias-maps.cf (see below).
# records first, then user records. If there are no matches for the exact
# Matches from the users table take priority over (direct) aliases.
# address, then Postfix will query just the domain part, which we call
# catch-alls and domain aliases. A NULL permitted_senders column means to
# take the value from the destination column.
cat> /etc/postfix/sender-login-maps.cf <<EOF;
cat> /etc/postfix/sender-login-maps.cf <<EOF;
dbpath=$db_path
dbpath=$db_path
query = SELECT senders from (SELECT senders, 0 as priority FROM aliases WHERE address='%s' UNION SELECT email as senders, 1 as priority FROM users WHERE email='%s') ORDER BY priority LIMIT 1;
query = SELECT permitted_senders FROM (SELECT permitted_senders, 0 AS priority FROM aliases WHERE source='%s' AND permitted_senders IS NOT NULL UNION SELECT destination AS permitted_senders, 1 AS priority FROM aliases WHERE source='%s' AND permitted_senders IS NULL UNION SELECT email as permitted_senders, 2 AS priority FROM users WHERE email='%s') ORDER BY priority LIMIT 1;
query = SELECT 1 FROM users WHERE email LIKE '%%@%s' UNION SELECT 1 FROM aliases WHERE address LIKE '%%@%s'
query = SELECT 1 FROM users WHERE email LIKE '%%@%s' UNION SELECT 1 FROM aliases WHERE source LIKE '%%@%s'
EOF
EOF
# SQL statement to check if we handle mail for a user.
# SQL statement to check if we handle incoming mail for a user.
cat> /etc/postfix/virtual-mailbox-maps.cf <<EOF;
cat> /etc/postfix/virtual-mailbox-maps.cf <<EOF;
dbpath=$db_path
dbpath=$db_path
query = SELECT 1 FROM users WHERE email='%s'
query = SELECT 1 FROM users WHERE email='%s'
...
@@ -127,9 +132,13 @@ EOF
...
@@ -127,9 +132,13 @@ EOF
# might be returned by the UNION, so the whole query is wrapped in
# might be returned by the UNION, so the whole query is wrapped in
# another select that prioritizes the alias definition to preserve
# another select that prioritizes the alias definition to preserve
# postfix's preference for aliases for whole email addresses.
# postfix's preference for aliases for whole email addresses.
#
# Since we might have alias records with an empty destination because
# it might have just permitted_senders, skip any records with an
# empty destination here so that other lower priority rules might match.
cat> /etc/postfix/virtual-alias-maps.cf <<EOF;
cat> /etc/postfix/virtual-alias-maps.cf <<EOF;
dbpath=$db_path
dbpath=$db_path
query = SELECT receivers from (SELECT receivers, 0 as priority FROM aliases WHERE address='%s' UNION SELECT email as receivers, 1 as priority FROM users WHERE email='%s') ORDER BY priority LIMIT 1;
query = SELECT destination from (SELECT destination, 0 as priority FROM aliases WHERE source='%s' AND destination<>'' UNION SELECT email as destination, 1 as priority FROM users WHERE email='%s') ORDER BY priority LIMIT 1;
shell("check_call",["sqlite3",db,"ALTER TABLE aliases RENAME TO aliases_8"])
# Create the new aliases table, initially empty.
shell("check_call",["sqlite3",db,"CREATE TABLE aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, address TEXT NOT NULL UNIQUE, receivers TEXT NOT NULL, senders TEXT NOT NULL)"])