mirror of
https://github.com/iredmail/iRedMail
synced 2026-06-08 14:51:59 +00:00
178 lines
5.5 KiB
Python
178 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
# This file is used to migrate SQL table `vmail.alias` for SQL backends.
|
|
#
|
|
# Requirements:
|
|
#
|
|
# * Python 3
|
|
# * Make sure you have new SQL tables ready: alias_moderators, forwardings.
|
|
# * For PostgreSQL, please make sure SQL user 'vmail' has 'SELECT' privilege on
|
|
# newly created sql tables.
|
|
|
|
import sys
|
|
import web
|
|
|
|
web.config.debug = False
|
|
|
|
# Read iRedAdmin config file `settings.py` from one of expected paths
|
|
sys.path.insert(0, '/usr/local/www/iredadmin') # FreeBSD
|
|
sys.path.insert(0, '/opt/www/iredadmin') # Debian/Ubuntu
|
|
sys.path.insert(0, '/var/www/iredadmin') # CentOS/OpenBSD
|
|
sys.path.insert(0, '/usr/share/apache2/iredadmin') # Debian/Ubuntu (old iRedMail releases)
|
|
|
|
import settings
|
|
print("* Read SQL username/password from iRedAdmin config file:", settings.__file__)
|
|
print("* Backend:", settings.backend)
|
|
|
|
if settings.backend in ['ldap', 'mysql']:
|
|
sql_dbn = 'mysql'
|
|
elif settings.backend in ['pgsql']:
|
|
sql_dbn = 'postgres'
|
|
else:
|
|
sys.exit('* << ERROR >>: Unsupported backend (%s).' % settings.backend)
|
|
|
|
try:
|
|
if sql_dbn == 'postgres':
|
|
db = web.database(dbn=sql_dbn,
|
|
host=settings.vmail_db_host,
|
|
port=int(settings.vmail_db_port),
|
|
db=settings.vmail_db_name,
|
|
user=settings.vmail_db_user,
|
|
pw=settings.vmail_db_password)
|
|
else:
|
|
db = web.database(dbn=sql_dbn,
|
|
host=settings.vmail_db_host,
|
|
port=int(settings.vmail_db_port),
|
|
db=settings.vmail_db_name,
|
|
user=settings.vmail_db_user,
|
|
pw=settings.vmail_db_password,
|
|
charset='utf8',
|
|
use_unicode=False)
|
|
|
|
db.supports_multiple_insert = True
|
|
except Exception as e:
|
|
print("<< ERROR >> Cannot connecting to SQL server:", e)
|
|
sys.exit()
|
|
|
|
def __bytes2str(b) -> str:
|
|
"""Convert object `b` to string."""
|
|
if isinstance(b, str):
|
|
return b
|
|
|
|
if isinstance(b, (bytes, bytearray)):
|
|
return b.decode()
|
|
elif isinstance(b, memoryview):
|
|
return b.tobytes().decode()
|
|
else:
|
|
return repr(b)
|
|
|
|
|
|
def bytes2str(b):
|
|
"""Convert `b` from bytes-like type to string."""
|
|
if isinstance(b, (list, web.db.ResultSet)):
|
|
s = [bytes2str(i) for i in b]
|
|
elif isinstance(b, tuple):
|
|
s = tuple([bytes2str(i) for i in b])
|
|
elif isinstance(b, set):
|
|
s = {bytes2str(i) for i in b}
|
|
elif isinstance(b, (dict, web.utils.Storage)):
|
|
new_dict = {}
|
|
for (k, v) in list(b.items()):
|
|
new_dict[k] = bytes2str(v) # v could be list/tuple/dict
|
|
s = new_dict
|
|
else:
|
|
s = __bytes2str(b)
|
|
|
|
return s
|
|
|
|
|
|
# Check required tables
|
|
for tbl in ['forwardings', 'alias_moderators']:
|
|
try:
|
|
db.select(tbl, limit=1)
|
|
except:
|
|
print("<<< ERROR >>> SQL table '%s' doesn't exist. Please create it first." % tbl)
|
|
sys.exit()
|
|
|
|
# Get all existing accounts
|
|
records = db.select('alias', what='address,goto,moderators,domain,active,islist,is_alias')
|
|
|
|
total = len(records)
|
|
counter = 1
|
|
for r in records:
|
|
# standard mail alias account
|
|
is_list = 0
|
|
# per-account alias address
|
|
is_alias = 0
|
|
# forwarding addresses of mail user
|
|
is_forwarding = 0
|
|
|
|
if r.islist == 1:
|
|
is_list = 1
|
|
_type = 'mail alias'
|
|
elif r.is_alias == 1:
|
|
is_alias = 1
|
|
_type = 'per-account alias address'
|
|
else:
|
|
is_forwarding = 1
|
|
_type = 'mail user'
|
|
|
|
account = bytes2str(r.address).lower()
|
|
active = int(r.active)
|
|
domain = bytes2str(r.domain).lower()
|
|
|
|
goto = bytes2str(r.goto).strip(' ')
|
|
goto = goto.replace(' ', '')
|
|
goto = goto.replace(';', ',')
|
|
members = list(set([i.strip().lower() for i in goto.strip(' ').split(',')]))
|
|
|
|
# Migrating forwardings
|
|
print("* [%d/%d] Migrating %s %s" % (counter, total, _type, account))
|
|
for m in members:
|
|
if m:
|
|
try:
|
|
dest_domain = m.split('@', 1)[-1]
|
|
|
|
db.insert('forwardings',
|
|
address=account,
|
|
forwarding=m,
|
|
domain=domain,
|
|
dest_domain=dest_domain,
|
|
active=active,
|
|
is_list=is_list,
|
|
is_alias=is_alias,
|
|
is_forwarding=is_forwarding)
|
|
|
|
except Exception as e:
|
|
if e[0] == 1062 or 'duplicate' in repr(e):
|
|
# Duplicate record
|
|
pass
|
|
else:
|
|
print("Error while migrating %s %s: %s" % (_type, m, repr(e)))
|
|
|
|
# Migrating moderators of mail alias account
|
|
moderators = []
|
|
if is_list == 1:
|
|
if r.moderators:
|
|
moderators = [i.lower() for i in set(r.moderators.strip(' ').split(','))]
|
|
|
|
if moderators:
|
|
for m in moderators:
|
|
try:
|
|
dest_domain = m.split('@', 1)[-1]
|
|
|
|
db.insert('alias_moderators',
|
|
address=account,
|
|
moderator=m,
|
|
domain=domain,
|
|
dest_domain=dest_domain)
|
|
except Exception as e:
|
|
if e[0] == 1062 or 'duplicate' in repr(e):
|
|
# Duplicate record
|
|
pass
|
|
else:
|
|
print("Error while migrating moderators of alias account %s: %s" % (m, repr(e)))
|
|
|
|
counter += 1
|
|
|
|
print("* DONE.")
|