2023-04-10 15:07:53 +02:00
#!/usr/bin/python3
2025-02-21 13:16:42 +01:00
import sys
2023-04-10 15:07:53 +02:00
import sqlite3
from pathlib import Path
from sqlite3 import Error
import urllib.request
import json
import logging
import argparse
import os
2025-03-03 13:57:02 +01:00
import time
from rich import print
2023-04-10 15:07:53 +02:00
from datetime import datetime
from string import ascii_letters , digits
from argparse import RawTextHelpFormatter
2024-04-10 13:40:00 +02:00
from operator import itemgetter
2025-03-03 13:57:02 +01:00
import httpx
2023-04-10 15:07:53 +02:00
# Info pages for dev
# https://mailcow.docs.apiary.io/#reference/aliases/get-aliases/get-aliases
# https://demo.mailcow.email/api/#/Aliases
2025-03-03 13:57:02 +01:00
# HTTPx ref -> https://www.python-httpx.org/
2023-04-10 15:07:53 +02:00
homefilepath = Path . home ()
2025-03-03 13:57:02 +01:00
filepath = homefilepath . joinpath ( '.config/malias2' )
database = filepath . joinpath ( 'malias2.db' )
logfile = filepath . joinpath ( 'malias2.log' )
2023-04-10 15:07:53 +02:00
Path ( filepath ) . mkdir ( parents = True , exist_ok = True )
logging . basicConfig ( filename = logfile , level = logging . INFO , format = ' %(message)s ' )
2025-03-03 13:57:02 +01:00
logging . getLogger ( "httpx" ) . setLevel ( logging . ERROR )
app_version = '2.0'
db_version = '2.0.0'
footer = 'malias version %s ' % ( app_version )
2023-04-10 15:07:53 +02:00
2023-09-06 12:29:32 +02:00
def get_latest_release ():
2025-03-03 13:57:02 +01:00
version = 'N/A'
req = httpx . get ( 'https://gitlab.pm/api/v1/repos/rune/malias/releases/latest' ,
headers = { "Content-Type" : "application/json" }
)
version = req . json ()[ 'tag_name' ]
return version
2023-09-06 12:29:32 +02:00
def release_check ():
2023-10-03 10:15:50 +02:00
latest_release = get_latest_release ()
2023-09-06 12:29:32 +02:00
if app_version != latest_release :
print ( '[b]New version available @ [i]https://iurl.no/malias[/b][/i]' )
else :
2023-10-03 10:15:50 +02:00
print ( 'You have the the latest version. Version: %s ' % ( app_version ))
2024-04-10 13:40:00 +02:00
2023-09-06 12:29:32 +02:00
2025-03-03 13:57:02 +01:00
2023-04-10 15:07:53 +02:00
def connect_database ():
Path ( filepath ) . mkdir ( parents = True , exist_ok = True )
conn = None
try :
conn = sqlite3 . connect ( database )
except Error as e :
logging . error ( time . strftime ( "%Y-%m- %d %H:%M" ) + ' - Error : ' + str ( e ))
print ( e )
finally :
if conn :
c = conn . cursor ()
2023-04-11 13:01:37 +02:00
c . execute ( '''CREATE TABLE IF NOT EXISTS settings (
id INTEGER NOT NULL PRIMARY KEY,
2023-04-13 09:29:07 +02:00
first_run INTEGER,
server TEXT,
2025-03-03 13:57:02 +01:00
apikey TEXT NOT NULL,
2023-04-16 18:04:24 +02:00
data_copy INTEGER
2023-04-11 13:01:37 +02:00
)''' )
2023-04-10 15:07:53 +02:00
c . execute ( '''CREATE TABLE IF NOT EXISTS aliases
2023-04-11 13:01:37 +02:00
(id integer NOT NULL PRIMARY KEY,
alias text NOT NULL,
goto text NOT NULL,
created text NOT NULL)''' )
2024-04-10 13:40:00 +02:00
c . execute ( '''CREATE TABLE IF NOT EXISTS timedaliases
(id integer NOT NULL PRIMARY KEY,
alias text NOT NULL,
goto text NOT NULL,
validity text NOT NULL)''' )
2025-03-03 13:57:02 +01:00
c . execute ( '''CREATE TABLE IF NOT EXISTS dbversion
(version integer NOT NULL DEFAULT 0)''' )
c . execute ( '''CREATE TABLE IF NOT EXISTS timedaliases
(id integer NOT NULL PRIMARY KEY,
alias text NOT NULL,
goto text NOT NULL,
validity text NOT NULL)''' )
2024-04-10 13:40:00 +02:00
2023-04-11 13:01:37 +02:00
conn . commit ()
first_run ( conn )
2023-04-10 15:07:53 +02:00
return conn
2023-04-11 13:01:37 +02:00
def first_run ( conn ):
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
2023-04-10 15:07:53 +02:00
cursor = conn . cursor ()
2023-04-11 13:01:37 +02:00
cursor . execute ( 'SELECT count(*) FROM settings' )
2023-04-10 15:07:53 +02:00
count = cursor . fetchone ()[ 0 ]
if count == 0 :
2023-04-11 13:01:37 +02:00
logging . error ( now + ' - First run!' )
2025-03-03 13:57:02 +01:00
cursor . execute ( 'INSERT INTO settings values(?,?,?,?,?)' , ( 0 , 1 , 'dummy.server' , 'DUMMY_KEY' , 0 ))
cursor . execute ( 'INSERT INTO dbversion values(?)' , ( db_version ,))
2023-04-11 13:01:37 +02:00
conn . commit ()
2023-04-10 15:07:53 +02:00
return None
2023-04-11 13:01:37 +02:00
2024-04-10 13:40:00 +02:00
2023-04-11 13:01:37 +02:00
def get_settings ( kind ):
2025-03-03 13:57:02 +01:00
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
2023-04-11 13:01:37 +02:00
cursor = conn . cursor ()
cursor . execute ( 'SELECT * FROM settings' )
2024-04-10 13:40:00 +02:00
data = cursor . fetchall ()
2025-03-03 13:57:02 +01:00
first_run_status = data [ 0 ][ 1 ] # pyright: ignore
server = data [ 0 ][ 2 ] # pyright: ignore
api_key = data [ 0 ][ 3 ] # pyright: ignore
copy_status = data [ 0 ][ 4 ] # pyright: ignore
if kind == 'connection' :
if server == 'dummy.server' or api_key == 'DUMMY_KEY' :
print ( 'Error: No mailcow server or API key registered. Please add with [b]malias -s [i]your.server APIKEY[/i][/b]' )
2023-04-11 13:01:37 +02:00
exit ( 0 )
else :
2025-03-03 13:57:02 +01:00
connection = { 'key' : api_key , 'server' : server }
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/domain/0' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
code = str ( req )
if code . find ( '200' ) != - 1 :
return connection # pyright: ignore
else :
logging . error ( now + ' - Error : Server returned error: %s , ' % ( data [ 'msg' ]))
print ( ' \n [b red]Error[/b red] : Server returned error [b] %s [/b] \n\n ' % ( data [ 'msg' ]))
exit ( 0 )
2023-04-11 13:01:37 +02:00
if kind == 'first_run_status' :
return first_run_status
2023-04-16 18:04:24 +02:00
if kind == 'copy_status' :
return copy_status
2023-04-11 13:01:37 +02:00
2024-04-10 13:40:00 +02:00
2025-03-03 13:57:02 +01:00
def get_last_timed ( username ):
connection = get_settings ( 'connection' )
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/time_limited_aliases/ %s ' % username ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
data . sort ( key = itemgetter ( 'validity' ), reverse = True )
return ( data [ 0 ])
2024-04-10 13:40:00 +02:00
2025-03-03 13:57:02 +01:00
def set_conection_info ( server , apikey ):
2023-04-11 13:01:37 +02:00
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
2023-04-10 15:07:53 +02:00
cursor = conn . cursor ()
2025-03-03 13:57:02 +01:00
cursor . execute ( 'UPDATE settings SET server = ?, apikey = ? WHERE id = 0' ,( server , apikey ))
logging . info ( now + ' - Info : Connectioninformations updated' )
print ( 'Your connection information has been updated.' )
2023-04-11 13:01:37 +02:00
conn . commit ()
2023-10-03 10:15:50 +02:00
2023-09-01 11:22:54 +02:00
2023-04-13 09:29:07 +02:00
def copy_data ():
2025-03-03 13:57:02 +01:00
connection = get_settings ( 'connection' )
2023-04-16 18:04:24 +02:00
if get_settings ( 'copy_status' ) == 0 :
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
cursor = conn . cursor ()
2025-03-03 13:57:02 +01:00
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
if not data :
print ( ' \n [b red]Error[/b red] : No aliases on server %s . Nothing to copy! \n\n ' % ( connection [ 'server' ]))
exit ( 0 )
i = 0
for data in data :
cursor . execute ( 'INSERT INTO aliases values(?,?,?,?)' , ( data [ 'id' ], data [ 'address' ], data [ 'goto' ], now ))
2023-04-16 18:04:24 +02:00
i = i + 1
2025-03-03 13:57:02 +01:00
cursor . execute ( 'UPDATE settings SET data_copy = ? WHERE id = 0' ,( 1 ,))
2023-04-16 18:04:24 +02:00
conn . commit ()
2025-03-03 13:57:02 +01:00
logging . info ( now + ' - Info : Imported %s new aliases from %s ' % ( str ( i ), connection [ 'server' ]))
print ( ' \n [b]Info[/b] : %s aliases imported from the mailcow instance %s to local DB \n ' % ( i , connection [ 'server' ]))
2023-04-16 18:04:24 +02:00
else :
2025-03-03 13:57:02 +01:00
print ( ' \n [b]Info[/b] : aliases alreday imported from the mailcow instance %s to local DB \n\n [i]Updating with any missing aliases![/i]' % ( connection [ 'server' ]))
2023-09-04 15:12:57 +02:00
update_data ()
def update_data ():
2025-03-03 13:57:02 +01:00
connection = get_settings ( 'connection' )
2023-09-04 15:12:57 +02:00
if get_settings ( 'copy_status' ) == 1 :
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
2025-03-03 13:57:02 +01:00
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
2023-09-04 15:12:57 +02:00
i = 0
count_alias = 0
cursor = conn . cursor ()
2025-03-03 13:57:02 +01:00
for data in data :
cursor . execute ( 'SELECT count(*) FROM aliases where alias like ? and goto like ?' , ( data [ 'address' ], data [ 'goto' ],))
2023-09-04 15:12:57 +02:00
count = cursor . fetchone ()[ 0 ]
if count >= 1 :
i += 1
else :
2025-03-03 13:57:02 +01:00
cursor . execute ( 'INSERT INTO aliases values(?,?,?,?)' , ( data [ 'id' ], data [ 'address' ], data [ 'goto' ], now ))
2023-09-04 15:12:57 +02:00
count_alias += 1
i += 1
conn . commit ()
if count_alias > 0 :
2025-03-03 13:57:02 +01:00
logging . info ( now + ' - Info : Local DB updated with %s new aliases from %s ' % ( str ( count_alias ), connection [ 'server' ]))
print ( ' \n [b]Info[/b] : Local DB update with %s new aliases from %s \n ' % ( str ( count_alias ), connection [ 'server' ]))
2023-09-04 15:12:57 +02:00
else :
print ( ' \n [b]Info[/b] : No missing aliases from local DB \n ' )
2025-03-03 13:57:02 +01:00
def create ( alias , to_address ):
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
connection = get_settings ( 'connection' ) # pyright: ignore
check = checklist ( alias )
if check [ 0 ] == True :
logging . error ( now + ' - Error : alias %s exists on the mailcow instance %s ' % ( alias , connection [ 'server' ]))
print ( ' \n [b]Error[/b] : alias %s exists on the mailcow instance %s \n ' % ( alias , connection [ 'server' ]))
exit ( 0 )
elif check [ 1 ] == True :
logging . error ( now + ' - Error : alias %s exists in local database.' % ( alias ))
print ( ' \n [b]Error[/b] : alias %s exists in local database. \n ' % ( alias ))
exit ( 0 )
else :
try :
new_data = { 'address' : alias , 'goto' : to_address , 'active' : "1" }
new_data = json . dumps ( new_data )
req = httpx . post ( 'https://' + connection [ 'server' ] + '/api/v1/add/alias' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
},
data = new_data
)
except httpx . HTTPError as exc :
print ( f "Error while requesting { exc . request . url !r} ." )
mail_id = alias_id ( alias )
if mail_id == None :
logging . error ( now + ' - Error : alias %s not created on the mailcow instance %s ' % ( alias , connection [ 'server' ]))
print ( ' \n [b]Error[/b] : alias %s exists on the mailcow instance %s \n ' % ( alias , connection [ 'server' ]))
else :
cursor = conn . cursor ()
cursor . execute ( 'INSERT INTO aliases values(?,?,?,?)' , ( mail_id , alias , to_address , now ))
conn . commit ()
logging . info ( now + ' - Info : alias %s created for %s on the mailcow instance %s ' % ( alias , to_address , connection [ 'server' ]))
print ( ' \n [b]Info[/b] : alias %s created for %s on the mailcow instance %s \n ' % ( alias , to_address , connection [ 'server' ]))
2023-04-10 15:07:53 +02:00
def checklist ( alias ):
2025-03-03 13:57:02 +01:00
alias_e = None
alias_i = None
connection = get_settings ( 'connection' )
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
2023-04-10 15:07:53 +02:00
i = 0
2025-03-03 13:57:02 +01:00
for data in data :
if alias == data [ 'address' ] or alias in data [ 'goto' ]:
alias_e = True
2023-04-10 15:07:53 +02:00
i = i + 1
2023-04-18 14:41:11 +02:00
cursor = conn . cursor ()
2023-11-09 12:02:11 +01:00
cursor . execute ( 'SELECT count(*) FROM aliases where alias == ? or goto == ?' , ( alias , alias ,))
2023-04-18 14:41:11 +02:00
count = cursor . fetchone ()[ 0 ]
if count >= 1 :
2025-03-03 13:57:02 +01:00
alias_i = True
alias_exist = [ alias_e , alias_i ]
2023-04-18 14:41:11 +02:00
return alias_exist
2023-04-10 15:07:53 +02:00
2023-04-12 11:57:35 +02:00
def alias_id ( alias ):
2025-03-03 13:57:02 +01:00
connection = get_settings ( 'connection' )
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
2023-04-12 11:57:35 +02:00
i = 0
2025-03-03 13:57:02 +01:00
for data in data :
if data [ 'address' ] == alias :
return data [ 'id' ]
2023-04-12 11:57:35 +02:00
i = i + 1
return None
2023-04-11 13:01:37 +02:00
def number_of_aliases_in_db ():
cursor = conn . cursor ()
cursor . execute ( 'SELECT count(*) FROM aliases' )
count = cursor . fetchone ()[ 0 ]
return count
2023-04-16 18:04:24 +02:00
def number_of_aliases_on_server ():
2025-03-03 13:57:02 +01:00
connection = get_settings ( 'connection' )
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
return len ( data )
2023-04-16 18:04:24 +02:00
2024-04-10 13:40:00 +02:00
2025-03-03 13:57:02 +01:00
def search ( alias ):
connection = get_settings ( 'connection' )
2023-04-16 18:04:24 +02:00
cursor = conn . cursor ()
2025-03-03 13:57:02 +01:00
search_term = '%' + alias + '%'
cursor . execute ( 'SELECT alias,goto from aliases where alias like ? or goto like ?' ,( search_term , search_term ,))
localdata = cursor . fetchall ()
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
remotedata = req . json ()
remote = []
i = 0
for data in remotedata :
if alias in remotedata [ i ][ 'address' ] or alias in remotedata [ i ][ 'goto' ]:
remote . append (( remotedata [ i ][ 'address' ], remotedata [ i ][ 'goto' ]))
i = i + 1
finallist = localdata + list ( set ( remote ) - set ( localdata ))
i = 0
print ( ' \n Aliases on %s containg search term [b] %s [/b]' % ( connection [ 'server' ], alias ))
print ( '=================================================================' )
for data in finallist :
the_alias = finallist [ i ][ 0 ] . ljust ( 20 , ' ' )
print ( the_alias + ' \t goes to \t\t ' + finallist [ i ][ 1 ])
i = i + 1
print ( ' \n ' + footer + ' \n ' )
2024-04-10 13:40:00 +02:00
2023-04-16 18:04:24 +02:00
2025-03-03 13:57:02 +01:00
def get_mail_domains ( info ):
connection = get_settings ( 'connection' )
2023-04-17 14:02:58 +02:00
cursor = conn . cursor ()
2025-03-03 13:57:02 +01:00
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/domain/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
remoteData = req . json ()
if info :
total_aliases = 0
i = 0
print ( ' \n [b]malias[/b] - All email domains on %s ' % ( connection [ 'server' ]))
print ( '==================================================================' )
for domains in remoteData :
cursor . execute ( 'SELECT count(*) FROM aliases where alias like ? or goto like ?' , ( '%' + remoteData [ i ][ 'domain_name' ] + '%' , '%' + remoteData [ i ][ 'domain_name' ] + '%' ,))
count = cursor . fetchone ()[ 0 ]
total_aliases += count
print ( ' %s \t\t with %s aliases' % ( remoteData [ i ][ 'domain_name' ], count ))
i += 1
print ( ' \n\n There is a total of %s domains with %s aliases. \n %s ' % ( str ( i ), str ( total_aliases ), footer ))
2023-10-03 10:15:50 +02:00
2023-04-11 13:01:37 +02:00
else :
2025-03-03 13:57:02 +01:00
return ( remoteData )
2024-04-10 13:40:00 +02:00
2023-04-11 13:01:37 +02:00
def show_current_info ():
2025-03-03 13:57:02 +01:00
connection = get_settings ( 'connection' )
2023-10-03 10:15:50 +02:00
latest_release = get_latest_release ()
2023-04-11 13:01:37 +02:00
aliases_server = number_of_aliases_on_server ()
alias_db = number_of_aliases_in_db ()
2023-09-05 11:36:39 +02:00
mail_domains = get_mail_domains ( False )
domain = ""
i = 0
for domains in mail_domains :
if i != 0 :
domain = domain + ', ' + str ( mail_domains [ i ][ 'domain_name' ])
else :
domain = domain + str ( mail_domains [ i ][ 'domain_name' ])
i += 1
2025-02-21 13:16:42 +01:00
print ( ' \n [b]malias[/b] - Manage aliases on mailcow Instance.' )
2023-04-11 13:01:37 +02:00
print ( '===================================================' )
2025-03-03 13:57:02 +01:00
print ( 'API key : [b] %s [/b]' % ( connection [ 'key' ]))
print ( 'Mailcow Instance : [b] %s [/b]' % ( connection [ 'server' ]))
2025-02-21 13:16:42 +01:00
print ( 'Active domains : [b] %s [/b]' % ( domain ))
print ( 'Logfile : [b] %s [/b]' % ( logfile ))
print ( 'Databse : [b] %s [b]' % ( database ))
print ( 'Aliases on server : [b] %s [/b]' % ( aliases_server ))
print ( 'Aliases in DB : [b] %s [/b]' % ( alias_db ))
print ( '' )
2025-03-03 13:57:02 +01:00
if float ( app_version ) < float ( latest_release ):
2025-02-21 13:16:42 +01:00
print ( 'App version : [b] %s [/b] a new version ( %s ) is available @ https://iurl.no/malias' % ( app_version , latest_release ))
else :
print ( 'App version : [b] %s [/b]' % ( app_version ))
2023-04-11 13:01:37 +02:00
print ( '' )
2024-04-10 13:40:00 +02:00
2025-03-03 13:57:02 +01:00
def delete_alias ( alias ):
status_e = None
status_i = None
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
connection = get_settings ( 'connection' )
check = checklist ( alias )
if check [ 0 ] == None and check [ 1 ] == None :
print ( ' \n [b]Error[/b] : The alias %s not found' )
exit ( 0 )
if check [ 0 ] or check [ 1 ] == True :
alias_server_id = alias_id ( alias )
data = { 'id' : alias_server_id }
delete_data = json . dumps ( data )
if check [ 0 ] == True and alias_server_id != None :
req = httpx . post ( 'https://' + connection [ 'server' ] + '/api/v1/delete/alias' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
},
data = delete_data
)
data = req . json ()
code = str ( req )
if code . find ( '200' ) != - 1 :
status_e = True
else :
status_e = None
if check [ 1 ] == True :
cursor = conn . cursor ()
cursor . execute ( 'DELETE from aliases where id = ?' ,( alias_server_id ,))
conn . commit ()
status_i = True
if status_e == True and status_i == True :
logging . info ( now + ' - Info : alias %s deleted from the mailcow instance %s and Local DB' % ( alias , connection [ 'server' ]))
print ( ' \n [b]Info[/b] : alias %s deleted from the mailcow instance %s and local DB' % ( alias , connection [ 'server' ]))
if status_e == True and status_i == None :
logging . info ( now + ' - Info : alias %s deleted from the mailcow instance %s .' % ( alias , connection [ 'server' ]))
print ( ' \n [b]Info[/b] : alias %s deleted from the mailcow instance %s .' % ( alias , connection [ 'server' ]))
if status_e == None and status_i == True :
logging . info ( now + ' - Info : alias %s deleted from the local database.' % ( alias ))
print ( ' \n [b]Info[/b] : alias %s deleted from the local database.' % ( alias ))
2024-04-10 13:40:00 +02:00
2025-03-03 13:57:02 +01:00
def create_timed ( username , domain ):
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
connection = get_settings ( 'connection' )
data = { 'username' : username , 'domain' : domain , 'description' : 'malias v' + app_version }
data_json = json . dumps ( data )
req = httpx . post ( 'https://' + connection [ 'server' ] + '/api/v1/add/time_limited_alias' , data = data_json ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
response = json . loads ( req . text )
if response [ 0 ][ 'type' ] == 'danger' and response [ 0 ][ 'msg' ] == 'domain_invalid' :
logging . error ( now + ' - Error : the domain %s does not exist.' % ( domain ))
print ( '[b][red]Error[/red][/b] : the domain %s does not exist.' % ( domain ))
exit ( 0 )
if response [ 0 ][ 'type' ] == 'danger' and response [ 0 ][ 'msg' ] == 'access_denied' :
logging . error ( now + ' - Error : something went wrong. The server responded with access denied.' )
print ( '[b][red]Error[/red][/b] : something went wrong. The server responded with [b]access denied[/b].' )
exit ( 0 )
alias = get_last_timed ( username )
validity = datetime . utcfromtimestamp ( alias [ 'validity' ]) . strftime ( ' %d -%m-%Y %H:%M' )
print ( 'The timed alias %s was created. The alias is valid until %s UTC \n ' % ( alias [ 'address' ], validity ))
2024-04-10 13:40:00 +02:00
cursor = conn . cursor ()
2025-03-03 13:57:02 +01:00
cursor . execute ( 'INSERT INTO timedaliases values(?,?,?,?)' , ( alias [ 'validity' ], alias [ 'address' ], username , validity ))
2024-04-10 13:40:00 +02:00
conn . commit ()
2025-03-03 13:57:02 +01:00
logging . info ( now + ' - Info : timed alias %s created for %s and valid too %s UTC on the mailcow instance %s ' % ( alias [ 'address' ], username , validity , connection [ 'server' ]))
2023-04-11 13:01:37 +02:00
2023-04-10 15:07:53 +02:00
2025-03-03 13:57:02 +01:00
def check_local_db ( alias_id ):
cursor = conn . cursor ()
cursor . execute ( 'SELECT count(*) FROM aliases where id = ?' ,( alias_id ,))
count = cursor . fetchone ()[ 0 ]
return count
2024-04-10 13:40:00 +02:00
2023-04-10 15:07:53 +02:00
2025-03-03 13:57:02 +01:00
def list_alias ():
now = datetime . now () . strftime ( "%m- %d -%Y %H:%M" )
connection = get_settings ( 'connection' )
cursor = conn . cursor ()
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
i = 0
l = 0
print ( ' \n [b]malias[/b] - All aliases on %s ([b]*[/b] also in local db)' % ( connection [ 'server' ]))
print ( '==================================================================' )
for search in data :
the_alias = data [ i ][ 'address' ] . ljust ( 20 , ' ' )
the_goto = data [ i ][ 'goto' ] . ljust ( 20 , ' ' )
cursor . execute ( 'SELECT count(*) FROM aliases where alias like ? or goto like ?' , ( data [ i ][ 'address' ], data [ i ][ 'address' ],))
count = cursor . fetchone ()[ 0 ]
if count >= 1 :
print ( the_alias + ' \t goes to \t\t ' + the_goto + ' \t [b]*[/b]' )
l = l + 1
else :
print ( the_alias + ' \t goes to \t\t ' + the_goto )
i = i + 1
print ( ' \n\n Total number of aliases %s on instance [b] %s [/b] and %s on [b]local DB[/b].' % ( str ( i ), connection [ 'server' ], str ( l )))
print ( ' \n ' + footer )
2023-04-10 15:07:53 +02:00
2025-03-03 13:57:02 +01:00
def export_data ():
connection = get_settings ( 'connection' )
cursor = conn . cursor ()
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
with open ( "alias.json" , "w" ) as outfile :
json . dump ( data , outfile , ensure_ascii = False , indent = 4 )
2023-04-11 13:01:37 +02:00
2025-03-03 13:57:02 +01:00
# For Testing purposes
2024-04-10 13:40:00 +02:00
2025-03-03 13:57:02 +01:00
def list_all ():
connection = get_settings ( 'connection' )
req = httpx . get ( 'https://' + connection [ 'server' ] + '/api/v1/get/alias/all' ,
headers = { "Content-Type" : "application/json" ,
'X-API-Key' : connection [ 'key' ]
}
)
data = req . json ()
print ( data )
2023-04-16 18:04:24 +02:00
2025-03-03 13:57:02 +01:00
def updatedb ():
# Function for updatimg DB when we have to
2023-10-03 10:15:50 +02:00
2025-03-03 13:57:02 +01:00
# 26.02.2025
# Placeholder for future updates and functions.
exit ( 1 )
2023-04-10 15:07:53 +02:00
2025-03-03 13:57:02 +01:00
conn = connect_database ()
parser = argparse . ArgumentParser ( prog = 'malias' ,
description = 'Malias is an application for adding, creating, and deleting aliases on a Mailcow instance. \n\n Use the issues section in the git repo for any problems or suggestions. https://gitlab.pm/rune/malias' ,
formatter_class = RawTextHelpFormatter ,
epilog = 'Making mailcow easier...' )
2023-04-16 18:04:24 +02:00
parser . add_argument ( '-c' , '--copy' , help = 'Copy alias data from mailcow server to local DB. \n\n ' ,
required = False , action = 'store_true' )
2025-03-03 13:57:02 +01:00
parser . add_argument ( '-s' , '--set' , help = 'Set connection information. \n\n ' ,
nargs = 2 , metavar = ( 'server' , 'APIKey' ), required = False , action = "append" )
parser . add_argument ( '-a' , '--add' , help = 'Add new alias. \n\n ' ,
nargs = 2 , metavar = ( 'alias@domain.com' , 'to@domain.com' ), required = False , action = "append" )
parser . add_argument ( '-f' , '--find' , help = 'Search for alias. \n\n ' ,
nargs = 1 , metavar = ( 'alias@domain.com' ), required = False , action = "append" )
parser . add_argument ( '-d' , '--delete' , help = 'Delete alias. \n\n ' ,
nargs = 1 , metavar = ( 'alias@domain.com' ), required = False , action = "append" )
parser . add_argument ( '-t' , '--timed' , help = 'Add new time limited alias for user on domain. \n The user@domain.com is where you want the alias to be delivered to. \n The domain.com is which domain to use when creating the timed-alias. \n One year validity \n\n ' ,
nargs = 2 , metavar = ( 'user@domain.com' , 'domain.com' ), required = False , action = "append" )
2023-04-16 18:04:24 +02:00
parser . add_argument ( '-l' , '--list' , help = 'List all aliases on the Mailcow instance. \n\n ' ,
2023-04-13 09:29:07 +02:00
required = False , action = 'store_true' )
2023-09-01 11:22:54 +02:00
parser . add_argument ( '-o' , '--domains' , help = 'List all mail domains on the Mailcow instance. \n\n ' ,
required = False , action = 'store_true' )
2025-03-03 13:57:02 +01:00
parser . add_argument ( '-e' , '--export' , help = 'List all mail domains on the Mailcow instance. \n\n ' ,
required = False , action = 'store_true' )
parser . add_argument ( '-v' , '--version' , help = 'Show current version and information \n\n ' ,
required = False , action = 'store_true' )
2023-09-01 11:22:54 +02:00
2023-04-16 18:04:24 +02:00
2023-04-10 15:07:53 +02:00
args = vars ( parser . parse_args ())
2025-03-03 13:57:02 +01:00
if args [ 'copy' ]:
copy_data ()
elif args [ 'set' ]:
set_conection_info ( args [ 'set' ][ 0 ][ 0 ], args [ 'set' ][ 0 ][ 1 ])
2023-04-11 13:01:37 +02:00
elif args [ 'add' ]:
create ( args [ 'add' ][ 0 ][ 0 ], args [ 'add' ][ 0 ][ 1 ])
2025-03-03 13:57:02 +01:00
elif args [ 'find' ]:
search ( args [ 'find' ][ 0 ][ 0 ])
2023-10-03 10:15:50 +02:00
elif args [ 'version' ]:
2024-04-10 13:40:00 +02:00
show_current_info ()
2025-03-03 13:57:02 +01:00
elif args [ 'delete' ]:
delete_alias ( args [ 'delete' ][ 0 ][ 0 ])
elif args [ 'timed' ]:
create_timed ( args [ 'timed' ][ 0 ][ 0 ], args [ 'timed' ][ 0 ][ 1 ])
2023-04-16 18:04:24 +02:00
elif args [ 'list' ]:
list_alias ()
2023-09-01 11:22:54 +02:00
elif args [ 'domains' ]:
2023-09-05 11:36:39 +02:00
get_mail_domains ( True )
2025-03-03 13:57:02 +01:00
elif args [ 'export' ]:
export_data ()
2023-04-10 15:07:53 +02:00
else :
2024-04-10 13:40:00 +02:00
print ( ' \n\n Eh, sorry! I need something more to help you! If you write [b]malias -h[/b] I \' ll show a help screen to get you going!!! \n\n\n ' )
2025-03-03 13:57:02 +01:00
#export_data()