381 lines
14 KiB
Python
381 lines
14 KiB
Python
# imports
|
|
|
|
import requests
|
|
from configparser import ConfigParser
|
|
from bottle import route, run, template, error, get, \
|
|
post, request, response, redirect, \
|
|
static_file
|
|
|
|
|
|
# config
|
|
|
|
configfile = "app.conf"
|
|
config = ConfigParser()
|
|
config.read(configfile)
|
|
|
|
if config['DEFAULT']['miab_admin']:
|
|
miab_admin = config['DEFAULT']['miab_admin']
|
|
else:
|
|
miab_admin = "norealadmin@domain.ltd"
|
|
|
|
if config['DEFAULT']['miab_passwd']:
|
|
miab_passwd = config['DEFAULT']['miab_passwd']
|
|
else:
|
|
miab_passwd = "norealpassword"
|
|
|
|
if config['DEFAULT']['miab_url']:
|
|
miab_url = config['DEFAULT']['miab_url']
|
|
else:
|
|
miab_url = "https://norealmiab.domain.tld"
|
|
|
|
if config['DEFAULT']['app_name']:
|
|
app_name = config['DEFAULT']['app_name']
|
|
else:
|
|
app_name = "Accounts"
|
|
|
|
if config['DEFAULT']['static_files']:
|
|
static_files = config['DEFAULT']['static_files']
|
|
else:
|
|
static_files = "static"
|
|
|
|
if config['DEFAULT']['cookie_secret']:
|
|
cookie_secret = config['DEFAULT']['cookie_secret']
|
|
else:
|
|
cookie_secret = "norealsecretDTR46SNI2390LGFsnDTRLASED2309h"
|
|
|
|
if config['DEFAULT']['cookie_max_age']:
|
|
cookie_max_age = int(config['DEFAULT']['cookie_max_age'])
|
|
else:
|
|
cookie_max_age=1800
|
|
|
|
if config['DEFAULT']['cookie_name']:
|
|
cookie_name = config['DEFAULT']['cookie_name']
|
|
else:
|
|
cookie_name = "accounts"
|
|
|
|
if config['DEFAULT']['max_aliases']:
|
|
max_aliases = int(config['DEFAULT']['max_aliases'])
|
|
else:
|
|
max_aliases=5
|
|
|
|
|
|
# functions
|
|
|
|
# verify session
|
|
# if valid we return the username
|
|
def logged_in():
|
|
#read remote cookie
|
|
username = request.get_cookie(cookie_name, secret=cookie_secret)
|
|
if username:
|
|
return username
|
|
else:
|
|
return False
|
|
|
|
# do actual authentication against miab
|
|
def miab_auth(username, password):
|
|
#authenticate against miab api
|
|
a = requests.get(miab_url + "/mail/users", auth=(username, password))
|
|
# if valid set cookie and return True
|
|
if a.text == 'You are not an administrator.\n' or a.status_code == 200:
|
|
response.set_cookie(cookie_name, username, secret=cookie_secret, max_age=cookie_max_age)
|
|
return True
|
|
else:
|
|
#or False
|
|
return False
|
|
|
|
# get all aliases for a username
|
|
def get_aliases(username):
|
|
a = requests.get(miab_url + "/mail/aliases?format=json", auth=(miab_admin, miab_passwd))
|
|
data = a.json()
|
|
i=1 #start with 1 to skip miab main domain
|
|
aliases = []
|
|
while i < len(data):
|
|
j=0
|
|
while j < len(data[i]['aliases']):
|
|
if len(data[i]['aliases'][j]['forwards_to']) == 1:
|
|
if data[i]['aliases'][j]['forwards_to'][0] == username:
|
|
aliases.append(data[i]['aliases'][j]['address'])
|
|
j+=1
|
|
i+=1
|
|
return aliases
|
|
|
|
# get all addresses available on miab
|
|
def get_addresses():
|
|
addresses = []
|
|
# get alias data
|
|
a = requests.get(miab_url + "/mail/aliases?format=json", auth=(miab_admin, miab_passwd))
|
|
aliases = a.json()
|
|
i=0
|
|
while i < len(aliases):
|
|
j=0
|
|
while j < len(aliases[i]['aliases']):
|
|
addresses.append(aliases[i]['aliases'][j]['address'])
|
|
j+=1
|
|
i+=1
|
|
|
|
# get user data
|
|
u = requests.get(miab_url + "/mail/users?format=json", auth=(miab_admin, miab_passwd))
|
|
users = u.json()
|
|
i=0
|
|
while i < len(users):
|
|
j=0
|
|
while j < len(users[i]['users']):
|
|
addresses.append(users[i]['users'][j]['email'])
|
|
j+=1
|
|
i+=1
|
|
return addresses
|
|
|
|
# get all valid domains from miab
|
|
def get_domains():
|
|
domains = []
|
|
u = requests.get(miab_url + "/mail/users?format=json", auth=(miab_admin, miab_passwd))
|
|
users = u.json()
|
|
i=0
|
|
while i < len(users):
|
|
domains.append(users[i]['domain'])
|
|
i+=1
|
|
return domains
|
|
|
|
# get forwarding alias for user
|
|
def get_forward(username):
|
|
a = requests.get(miab_url + "/mail/aliases?format=json", auth=(miab_admin, miab_passwd))
|
|
aliases = a.json()
|
|
i=0
|
|
while i < len(aliases):
|
|
j=0
|
|
while j < len(aliases[i]['aliases']):
|
|
if aliases[i]['aliases'][j]['address'] == username:
|
|
forward = aliases[i]['aliases'][j]['forwards_to'][0]
|
|
return forward
|
|
j+=1
|
|
i+=1
|
|
return None
|
|
|
|
# routing
|
|
|
|
# render main page
|
|
@get('/')
|
|
def home():
|
|
username = logged_in()
|
|
message = request.get_cookie(cookie_name + "_message", secret=cookie_secret)
|
|
if username:
|
|
aliases = get_aliases(username)
|
|
forward = get_forward(username)
|
|
# render homepage
|
|
return template('default', username=username, app_name=app_name, message=message, aliases=aliases, max_aliases=max_aliases, forward=forward)
|
|
else:
|
|
# render login
|
|
message = request.get_cookie(cookie_name + "_message", secret=cookie_secret)
|
|
return template('login', app_name=app_name, cookie_max_age=cookie_max_age, message=message)
|
|
|
|
# get login credentials
|
|
@post('/login')
|
|
def post_login():
|
|
username = request.forms.get('username')
|
|
password = request.forms.get('password')
|
|
if miab_auth(username, password):
|
|
message = { "message": "You have logged in successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5)
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Email address or password wrong", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5)
|
|
redirect('/')
|
|
|
|
# delete cookie
|
|
@get('/logout')
|
|
@get('/logout/')
|
|
def logout():
|
|
if logged_in():
|
|
response.delete_cookie(cookie_name)
|
|
message = { "message": "You have logged out successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5)
|
|
redirect('/')
|
|
else:
|
|
redirect('/')
|
|
|
|
# serve static files
|
|
@get('/static/<filename:path>')
|
|
def send_static(filename):
|
|
return static_file(filename, root=static_files)
|
|
|
|
# change account password
|
|
@post('/password')
|
|
def post_password():
|
|
username = logged_in()
|
|
if username:
|
|
oldpassword = request.forms.get('oldpassword')
|
|
newpassword = request.forms.get('newpassword')
|
|
if miab_auth(username, oldpassword):
|
|
data = { "email": username, }
|
|
r = requests.post(miab_url + "/mail/users/remove", data=data, auth=(miab_admin, miab_passwd))
|
|
data = { "email": username, "password": newpassword }
|
|
a = requests.post(miab_url + "/mail/users/add", data=data, auth=(miab_admin, miab_passwd))
|
|
if r.status_code == 200 and a.status_code == 200:
|
|
message = { "message": "Your password has been changed successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5)
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Something went wrong while changing your password", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5)
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Your supplied password is wrong", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5)
|
|
redirect('/')
|
|
else:
|
|
redirect('/')
|
|
|
|
# create an email alias
|
|
@post('/alias/add')
|
|
def add_alias():
|
|
username = logged_in()
|
|
if username:
|
|
add = request.forms.get('add')
|
|
aliases = get_aliases(username)
|
|
#it must be below max_aliases
|
|
if len(aliases) < max_aliases:
|
|
#it must be in domains
|
|
domains = get_domains()
|
|
addresses = get_addresses()
|
|
for domain in domains:
|
|
if domain == add[(add.find("@")+1):]:
|
|
#it must not be in addresses
|
|
for address in addresses:
|
|
if address == add:
|
|
#match found. break
|
|
message = { "message": str(add) + " does already exist", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
#create the alias
|
|
data = { "address": add, "forwards_to": username }
|
|
r = requests.post(miab_url + "/mail/aliases/add", data=data, auth=(miab_admin, miab_passwd))
|
|
if r.status_code == 200:
|
|
message = { "message": str(add) + " has been created successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Something went wrong while creating " + str(add), "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
message = { "message": str(add[(add.find("@")+1):]) + " is not a valid domain", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "You have reached the alias limit", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
redirect("/")
|
|
|
|
# delete an email alias
|
|
@post('/alias/delete')
|
|
def delete_alias():
|
|
username = logged_in()
|
|
if username:
|
|
delete = request.forms.get('delete')
|
|
aliases = get_aliases(username)
|
|
for alias in aliases:
|
|
if alias == delete:
|
|
#remove the alias
|
|
data = { "address": delete, }
|
|
r = requests.post(miab_url + "/mail/aliases/remove", data=data, auth=(miab_admin, miab_passwd))
|
|
if r.status_code == 200:
|
|
message = { "message": "The alias " + str(delete) + " has been removed successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Something went wrong while removing an alias", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
message = { "message": "You're trying to do something filthy", "alert": "danger"}
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
redirect('/')
|
|
|
|
# configure email forwarding
|
|
@post('/forward/add')
|
|
def add_forward():
|
|
username = logged_in()
|
|
forward = request.forms.get('forward')
|
|
if username:
|
|
if get_forward(username):
|
|
message = { "message": "Email forwarding is already configured", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
data = { "address": username, "forwards_to": forward }
|
|
c = requests.post(miab_url + "/mail/aliases/add", data=data, auth=(miab_admin, miab_passwd))
|
|
if c.status_code == 200:
|
|
message = { "message": "Email forwarding to " + str(forward) + " has been configured successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Something went wrong while configuring email forwarding", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
redirect('/')
|
|
|
|
# deconfigure email forwarding
|
|
@post('/forward/delete')
|
|
def delete_forward():
|
|
username = logged_in()
|
|
forward = request.forms.get('forward')
|
|
if username:
|
|
forwarded = get_forward(username)
|
|
if forward == forwarded:
|
|
data = { "address": username, }
|
|
d = requests.post(miab_url + "/mail/aliases/remove", data=data, auth=(miab_admin, miab_passwd))
|
|
if d.status_code == 200:
|
|
message = { "message": "Email forwarding has been deconfigured successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Something went wrong while deconfiguring email forwarding", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Your delete request does not match the configured forwarding", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
redirect('/')
|
|
|
|
|
|
|
|
@post('/delete')
|
|
def delete_account():
|
|
username = logged_in()
|
|
password = request.forms.get('password')
|
|
if username:
|
|
if miab_auth(username, password):
|
|
data = { "email": username, }
|
|
d = requests.post(miab_url + "/mail/users/remove", data=data, auth=(miab_admin, miab_passwd))
|
|
if d.status_code == 200:
|
|
message = { "message": "Your account has been deleted successfully", "alert": "success" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
response.delete_cookie(cookie_name)
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Something went wrong deleting your account", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
message = { "message": "Your supplied password is wrong", "alert": "danger" }
|
|
response.set_cookie(cookie_name + "_message", message, secret=cookie_secret, max_age=5, path="/")
|
|
redirect('/')
|
|
else:
|
|
redirect('/')
|
|
|
|
|
|
|
|
|
|
|
|
# run development webserver
|
|
#run(host='localhost', port=8000, debug=True, reloader=True)
|
|
|
|
# run prod server
|
|
run(host='localhost', port=8000)
|