# requiring aliases for email addresses typically used in DCV to forward
# 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)
validated_receivers.append(email)
receivers=",".join(validated_receivers)
validated_forwards_to.append(email)
# validate permitted_senders
valid_logins=get_mail_users(env)
validated_permitted_senders=[]
permitted_senders=permitted_senders.strip()
# validate senders
validated_senders=[]
senders=senders.strip()
# Parse comma and \n-separated sender logins & validate. The senders must be
# Parse comma and \n-separated sender logins & validate. The permitted_senders must be
# valid usernames.
forlineinsenders.split("\n"):
forlineinpermitted_senders.split("\n"):
forlogininline.split(","):
login=login.strip()
iflogin=="":continue
ifloginnotinvalid_logins:
return("Invalid sender login (%s)."%login,400)
validated_senders.append(login)
senders=",".join(validated_senders)
return("Invalid permitted sender: %s is not a user on this system."%login,400)
validated_permitted_senders.append(login)
# Make sure the alias has either a forwards_to or a permitted_sender.
<p>An alias can forward email to a <ahref="javascript:show_panel('users')">mail user</a> or to any email address. You can separately grant permission to one or more users to send as an alias.</p>
<p>Aliases are email forwarders. An alias can forward email to a <ahref="javascript:show_panel('users')">mail user</a> or to any email address.</p>
<p>To use an alias or any address besides your own login username in outbound mail, the sending user must be included as a permitted sender for the alias.</p>
<spanclass="catchall hidden">A catch-all alias captures all otherwise unmatched email to a domain. Enter just a part of an email address starting with the @-sign.</span>
<spanclass="domainalias hidden">A domain alias forwards all otherwise unmatched mail from one domain to another domain, preserving the part before the @-sign.</span>
<spanclass="catchall hidden">A catch-all alias captures all otherwise unmatched email to a domain.</span>
<spanclass="domainalias hidden">A domain alias forwards all otherwise unmatched email from one domain to another domain, preserving the part before the @-sign.</span>
<divstyle="margin-top: 3px; padding-left: 3px; font-size: 90%"class="text-muted">You may use international (non-ASCII) characters for the domain part of the email address only.</div>
Any mail user listed in the Fowards To box can send mail claiming to be from <spanclass="regularalias">the alias address</span><spanclass="catchall domainalias">any address on the alias domain</span>.
I’ll enter the mail users that can send mail claiming to be from <spanclass="regularalias">the alias address</span><spanclass="catchall domainalias">any address on the alias domain</span>.
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
# is allowed to send as. This is similar to virtual-alias-maps.cf (see below).
# Matches from the users table take priority over (direct) aliases.
# Postfix will query the exact address first, where the priority will be alias
# records first, then user records. If there are no matches for the exact
# 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;
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
# 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;
dbpath=$db_path
query = SELECT 1 FROM users WHERE email='%s'
...
...
@@ -127,9 +132,13 @@ EOF
# might be returned by the UNION, so the whole query is wrapped in
# another select that prioritizes the alias definition to preserve
# 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;
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)"])