Sunil Mohan Adapa 678ca1a9d1
email: Fix creation of aliases for security@ and usenet@
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2022-11-21 19:37:50 -05:00

105 lines
2.7 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""Manage email aliases stored in sqlite database."""
import contextlib
import pwd
import sqlite3
from dataclasses import dataclass
from . import privileged
@dataclass
class Alias:
value: str
name: str
@contextlib.contextmanager
def _get_cursor():
"""Return a DB cursor as context manager."""
# Turn ON autocommit mode
db_path = '/var/lib/postfix/freedombox-aliases/aliases.sqlite3'
connection = sqlite3.connect(db_path, isolation_level=None)
connection.row_factory = sqlite3.Row
try:
cursor = connection.cursor()
yield cursor
finally:
connection.close()
def get(username):
"""Get all aliases of a user."""
query = 'SELECT name, value FROM alias WHERE value=?'
with _get_cursor() as cursor:
rows = cursor.execute(query, (username, ))
return [Alias(**row) for row in rows]
def exists(name):
"""Return whether alias is already taken."""
try:
pwd.getpwnam(name)
return True
except KeyError:
pass
with _get_cursor() as cursor:
query = 'SELECT COUNT(*) FROM alias WHERE name=?'
cursor.execute(query, (name, ))
return cursor.fetchone()[0] != 0
def put(username, name):
"""Insert if not exists a new alias."""
query = 'INSERT INTO alias (name, value) VALUES (?, ?)'
with _get_cursor() as cursor:
try:
cursor.execute(query, (name, username))
except sqlite3.IntegrityError:
pass # Alias exists, rare since we are already checking
def delete(username, aliases):
"""Delete a set of aliases."""
query = 'DELETE FROM alias WHERE value=? AND name=?'
parameter_seq = ((username, name) for name in aliases)
with _get_cursor() as cursor:
cursor.execute('BEGIN')
cursor.executemany(query, parameter_seq)
cursor.execute('COMMIT')
def first_setup():
"""Create the database file and schema inside it."""
privileged.aliases.setup_aliases()
# Create schema if not exists
query = '''
BEGIN;
CREATE TABLE IF NOT EXISTS alias (
name TEXT NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY (name)
);
COMMIT;
'''
with _get_cursor() as cursor:
cursor.executescript(query)
def setup_common_aliases(username):
"""Create aliases for common mailboxes described in RFC2142.
See: https://datatracker.ietf.org/doc/html/rfc2142
"""
aliases = [
'mailer-daemon', 'postmaster', 'nobody', 'webmaster', 'www',
'hostmaster', 'info', 'support', 'abuse', 'noc', 'security', 'usenet',
'news', 'ftp'
]
for alias in aliases:
if not exists(alias):
put(username, alias)