16 Commits
0.1 ... 0.3

Author SHA1 Message Date
8000779fe8 Added app version checks. 2023-09-06 12:29:32 +02:00
8814127cf8 Added some functionality 2023-09-05 11:36:39 +02:00
f653a20d35 Added function updating local DB from aliases on Mailcow instance 2023-09-04 15:12:57 +02:00
7f12bd3743 Added function for listing mail domains 2023-09-01 11:22:54 +02:00
8a6eceb9a5 Added some small fixes and some pepper 2023-08-20 15:53:43 +02:00
2bd8ddeb04 Update README.md 2023-08-13 18:32:35 +02:00
f3ba4f7d67 Update README.md 2023-08-13 18:31:49 +02:00
37d670b54e Added screenshot 2023-08-13 18:30:16 +02:00
12215074d6 Changes in list function 2023-04-19 08:49:22 +02:00
15e8f8ac90 Changes in list function 2023-04-19 08:04:44 +02:00
0e1a5d7314 Fixed error in a function 2023-04-18 14:41:11 +02:00
5d1c11d42d remove .DS_Store 2023-04-17 14:04:53 +02:00
d461290730 remove .DS_Store 2023-04-17 14:04:24 +02:00
38261bb0a2 Better search function 2023-04-17 14:02:58 +02:00
01c158db6d Merge branch 'main' of https://gitlab.pm/rune/malias 2023-04-16 19:07:35 +02:00
7f7c562455 Refined search function 2023-04-16 19:07:01 +02:00
5 changed files with 211 additions and 32 deletions

5
.gitignore vendored
View File

@@ -1 +1,4 @@
list_alias.py
list_alias.py
malias.zip
malias_local.py
.DS_Store

View File

@@ -4,7 +4,7 @@ _malias_ is a helper for mailcow instances. You can create, delete, search and l
## Installation
Download the latest relase from https://gitlab.pm/rune/malias/releases. Unzip and move to a folder in you path (ease of use). You can also rename the file ```malias.py``` to just ```malias``` and make the file executable with ```chmod +x malias```. To install required python modules run ```pip3 install -r requirements.txt```
Download the latest release from https://gitlab.pm/rune/malias/releases. Unzip and move to a folder in you path (ease of use). I also recommend rename the file ```malias.py``` to just ```malias``` and make the file executable with ```chmod +x malias```. To install required python modules run ```pip3 install -r requirements.txt```
## Usage
@@ -14,6 +14,10 @@ For instructions run
malias -h
```
## Screenshot
![Screenshot of malias](https://gitlab.pm/rune/malias/raw/branch/main/malias.png)
## Contributing
Pull requests are welcome. For major changes, please open an issue first

BIN
malias.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 KiB

227
malias.py Normal file → Executable file
View File

@@ -10,12 +10,12 @@ import requests
import os
import time
import sys
import git
from types import SimpleNamespace
from datetime import datetime
from string import ascii_letters, digits
from rich import print
from argparse import RawTextHelpFormatter
#from urllib import Request, urlopen
from urllib.request import urlopen
# Info pages for dev
@@ -29,9 +29,27 @@ database = filepath.joinpath('malias.db')
logfile = filepath.joinpath('malias.log')
Path(filepath).mkdir(parents=True, exist_ok=True)
logging.basicConfig(filename=logfile,level=logging.INFO,format='%(message)s')
app_version = '0.1'
app_version = '0.3'
def get_latest_release():
req = urllib.request.Request('https://gitlab.pm/api/v1/repos/rune/malias/releases/latest')
req.add_header('Content-Type', 'application/json')
current = urllib.request.urlopen(req)
remote = current.read().decode('utf-8')
remoteData = json.loads(remote)
return remoteData['tag_name']
latest_release = get_latest_release()
def release_check():
if app_version != latest_release:
print('[b]New version available @ [i]https://iurl.no/malias[/b][/i]')
else:
print ('')
def connect_database():
Path(filepath).mkdir(parents=True, exist_ok=True)
conn = None
@@ -99,6 +117,7 @@ def get_settings(kind):
def get_api():
latest_release = get_latest_release()
cursor = conn.cursor()
cursor.execute('SELECT api FROM apikey')
apikey = cursor.fetchone()[0]
@@ -116,7 +135,7 @@ def set_mailserver(server):
logging.info(now + ' - Info : mailcow server updated')
print('Your mail server has been updated.')
conn.commit()
release_check()
def apikey(key):
@@ -126,7 +145,34 @@ def apikey(key):
logging.info(now + ' - Info : API key updated')
print('Your API key has been updated.')
conn.commit()
release_check()
def get_mail_domains(info):
apikey = get_api()
cursor = conn.cursor()
mail_server = get_settings('mail_server')
req = urllib.request.Request('https://'+mail_server+'/api/v1/get/domain/all')
req.add_header('Content-Type', 'application/json')
req.add_header('X-API-Key', apikey)
current = urllib.request.urlopen(req)
remote = current.read().decode('utf-8')
remoteData = json.loads(remote)
if info:
total_aliases = 0
i=0
print('\n[b]malias[/b] - All email domains on %s' %(mail_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\twith %s aliases' %(remoteData[i]['domain_name'],count))
i+=1
print('\n\nThere is a total of %s domains with %s aliases.' %(str(i),str(total_aliases)))
release_check()
else:
return(remoteData)
def create(alias,to_address):
now = datetime.now().strftime("%m-%d-%Y %H:%M")
@@ -151,7 +197,7 @@ def create(alias,to_address):
conn.commit()
logging.info(now + ' - Info : alias %s created for %s on the mailcow instance %s ' %(alias,to_address,server))
print('\n[b]Info[/b] : alias %s created for %s on the mailcow instance %s \n' %(alias,to_address,server))
release_check()
def delete_alias(alias):
@@ -164,8 +210,6 @@ def delete_alias(alias):
response = requests.post('https://'+server+'/api/v1/delete/alias',
data=json.dumps(data), headers=headers)
response_data = response.json()
print(response_data)
exit(0)
if response_data[0]['type'] == 'success':
if check_local_db(the_alias_id) == 1:
now = datetime.now().strftime("%m-%d-%Y %H:%M")
@@ -184,6 +228,8 @@ def delete_alias(alias):
else:
print('\n[b]Error[/b] : The alias %s not found')
release_check()
def copy_data():
@@ -208,10 +254,45 @@ def copy_data():
logging.info(now + ' - Info : aliases imported from the mailcow instance %s to local DB' %(mail_server))
print('\n[b]Info[/b] : aliases imported from the mailcow instance %s to local DB\n' %(mail_server))
else:
print('\n[b]Info[/b] : aliases alreday imported from the mailcow instance %s to local DB\n' %(mail_server))
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]' %(mail_server))
update_data()
release_check()
def update_data():
apikey = get_api()
mail_server = get_settings('mail_server')
if get_settings('copy_status') == 1:
now = datetime.now().strftime("%m-%d-%Y %H:%M")
cursor = conn.cursor()
req = urllib.request.Request('https://'+mail_server+'/api/v1/get/alias/all')
req.add_header('Content-Type', 'application/json')
req.add_header('X-API-Key', apikey)
current = urllib.request.urlopen(req)
remote = current.read().decode('utf-8')
remoteData = json.loads(remote)
i = 0
count_alias = 0
cursor = conn.cursor()
for data in remoteData:
cursor.execute('SELECT count(*) FROM aliases where alias like ? and goto like ?', (remoteData[i]['address'],remoteData[i]['goto'],))
count = cursor.fetchone()[0]
if count >= 1 :
i+=1
else:
cursor.execute('INSERT INTO aliases values(?,?,?,?)', (remoteData[i]['id'], remoteData[i]['address'],remoteData[i]['goto'],now))
count_alias+=1
i+=1
conn.commit()
if count_alias > 0:
logging.info(now + ' - Info : Local DB updated with %s new aliases from %s ' %(str(count_alias),mail_server))
print('\n[b]Info[/b] : Local DB update with %s new aliases from %s \n' %(str(count_alias),mail_server))
else:
print('\n[b]Info[/b] : No missing aliases from local DB \n')
def checklist(alias):
alias_exist = None
apikey = get_api()
mail_server = get_settings('mail_server')
req = urllib.request.Request('https://'+mail_server+'/api/v1/get/alias/all')
@@ -222,14 +303,21 @@ def checklist(alias):
remoteData = json.loads(remote)
i = 0
for search in remoteData:
if alias in remoteData[i]['address']:
return True
if alias in remoteData[i]['address'] or alias in remoteData[i]['goto']:
alias_exist = True
i=i+1
return None
cursor = conn.cursor()
cursor.execute('SELECT count(*) FROM aliases where alias like ? or goto like ?', (alias,alias,))
count = cursor.fetchone()[0]
if count >= 1 :
alias_exist = True
return alias_exist
def list_alias():
apikey = get_api()
cursor = conn.cursor()
mail_server = get_settings('mail_server')
req = urllib.request.Request('https://'+mail_server+'/api/v1/get/alias/all')
req.add_header('Content-Type', 'application/json')
@@ -238,14 +326,22 @@ def list_alias():
remote = current.read().decode('utf-8')
remoteData = json.loads(remote)
i = 0
print('\n[b]malias[/b] - All aliases on %s' %(mail_server))
print('===================================================')
l = 0
print('\n[b]malias[/b] - All aliases on %s ([b]*[/b] also in local db)' %(mail_server))
print('==================================================================')
for search in remoteData:
the_alias = remoteData[i]['address'].ljust(20,' ')
print(the_alias + '\tgoes to\t\t' + remoteData[i]['goto'])
the_goto = remoteData[i]['goto'].ljust(20,' ')
cursor.execute('SELECT count(*) FROM aliases where alias like ? or goto like ?', (remoteData[i]['address'],remoteData[i]['address'],))
count = cursor.fetchone()[0]
if count >= 1:
print(the_alias + '\tgoes to\t\t' + the_goto + '\t[b]*[/b]')
l=l+1
else:
print(the_alias + '\tgoes to\t\t' + the_goto)
i=i+1
print('\n\nTotal number of aliases %s on instance [b]%s[/b] and %s on [b]local DB[/b].' %(str(i),mail_server,str(l)))
release_check()
def alias_id(alias):
apikey = get_api()
@@ -292,17 +388,69 @@ def check_local_db(alias_id):
def search(alias):
results = checklist(alias)
apikey = get_api()
mail_server = get_settings('mail_server')
if results == True:
print('\n\nThe mail address %s exists. Using the mailcow instance : %s\n\n'%(alias,mail_server))
cursor = conn.cursor()
cursor.execute('SELECT data_copy FROM settings where id = 1')
result = cursor.fetchone()[0]
if result == 1:
search_term = '%'+alias+'%'
cursor.execute('SELECT * from aliases where alias like ? or goto like ?',(search_term,search_term,))
remoteData = cursor.fetchall()
i = 0
print('\nAliases on %s that contains [b]%s[/b]' %(mail_server,alias))
print('=================================================================')
for search in remoteData:
the_alias = remoteData[i][1].ljust(20,' ')
print(the_alias + '\tgoes to\t\t' + remoteData[i][2])
i=i+1
print('\n\nData from local DB\n Run [i]malias -c to get any aliases on the server but [b]not[/b] in the local DB![/i]')
release_check()
else:
print('\n\nThe mail address %s [b]does not[/b] exists. Using the mailcow instance : %s\n\n'%(alias,mail_server))
req = urllib.request.Request('https://'+mail_server+'/api/v1/get/alias/all')
req.add_header('Content-Type', 'application/json')
req.add_header('X-API-Key', apikey)
current = urllib.request.urlopen(req)
remote = current.read().decode('utf-8')
remoteData = json.loads(remote)
i = 0
print('\nAliases on %s that contains [b]%s[/b]' %(mail_server,alias))
print('=================================================')
for search in remoteData:
if alias in remoteData[i]['address'] or alias in remoteData[i]['goto']:
print(remoteData[i]['address'] + '\tgoes to\t\t' + remoteData[i]['goto'])
i=i+1
print('\n\nData from server')
release_check()
def get_mailcow_version():
apikey = get_api()
mail_server = get_settings('mail_server')
req = urllib.request.Request('https://'+mail_server+'/api/v1/get/status/version')
req.add_header('Content-Type', 'application/json')
req.add_header('X-API-Key', apikey)
current = urllib.request.urlopen(req)
remote = current.read().decode('utf-8')
remoteData = json.loads(remote)
#repo = Repo("https://github.com/mailcow/mailcow-dockerized")
# info = repo.git.ls_remote()
# tags = repo.tags
remote_heads = git.cmd.Git().ls_remote('https://github.com/mailcow/mailcow-dockerized', tags=True)
# tags = remote_heads.rstrip('refs/tags/')
tags = remote_heads.splitlines()
for x in tags:
string = x.rsplit('/',2)
if remoteData['version'] != string[2]:
versionInfo = 'Your Mailcow version is %s and the latest is %s' %(remoteData['version'], string[2])
else:
versionInfo = 'You have the latest Mailcow version %s' %remoteData['version']
return (versionInfo)
def show_current_info():
API = get_api()
mail_server = get_settings('mail_server')
@@ -315,16 +463,31 @@ def show_current_info():
aliases_server = number_of_aliases_on_server()
alias_db = number_of_aliases_in_db()
mailcow_version = get_mailcow_version()
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
print('\n[b]malias[/b] - Manage aliases on mailcow Instance.')
print('===================================================')
print('API key : [b]%s[/b]' % (API))
print('mailcow Instance : [b]%s[/b]' % (mail_server))
print('Mailcow Instance : [b]%s[/b]' % (mail_server))
print('Active domains : [b]%s[/b]' % (domain))
print('Mailcow version : [b]%s[/b]' % (mailcow_version))
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('')
print('App version : [b]%s[/b] (https://gitlab.pm/rune/malias)' % (app_version))
if app_version != latest_release:
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))
print('')
@@ -353,7 +516,7 @@ parser.add_argument('-d', '--delete', help='Delete alias.\n\n',
nargs=1, metavar=('alias@domain.com'), required=False, action="append")
parser.add_argument('-v', '--version', help='Show current version and config info\n\n',
parser.add_argument('-i', '--info', help='Show current version and config info\n\n',
required=False, action='store_true')
parser.add_argument('-c', '--copy', help='Copy alias data from mailcow server to local DB.\n\n',
@@ -362,6 +525,9 @@ parser.add_argument('-c', '--copy', help='Copy alias data from mailcow server to
parser.add_argument('-l', '--list', help='List all aliases on the Mailcow instance.\n\n',
required=False, action='store_true')
parser.add_argument('-o', '--domains', help='List all mail domains on the Mailcow instance.\n\n',
required=False, action='store_true')
args = vars(parser.parse_args())
@@ -375,13 +541,16 @@ elif args['add']:
create(args['add'][0][0],args['add'][0][1])
elif args['delete']:
delete_alias(args['delete'][0][0])
elif args['version']:
elif args['info']:
show_current_info()
elif args['copy']:
copy_data()
elif args['list']:
list_alias()
elif args['domains']:
get_mail_domains(True)
else:
# get_api()
print('\n\nEh, 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')

View File

@@ -11,7 +11,9 @@ click==8.1.3
docopt==0.6.2
docutils==0.19
frozenlist==1.3.3
gpg==1.19.0
gitdb==4.0.10
GitPython==3.1.32
gpg==1.21.0
idna==3.4
importlib-metadata==6.1.0
jaraco.classes==3.2.3
@@ -36,6 +38,7 @@ requests-toolbelt==0.10.1
rfc3986==2.0.0
rich==13.3.1
six==1.16.0
smmap==5.0.0
tqdm==4.65.0
twine==4.0.2
urllib3==1.26.14