From 953351e8a89b56fa7ab7d4ce0e2041f7e84c9248 Mon Sep 17 00:00:00 2001 From: Cyberes Date: Thu, 18 Jul 2024 18:21:05 -0600 Subject: [PATCH] support multiple accounts, fix misc server issues --- README.md | 3 ++- server.py | 54 +++++++++++++++++++++++++----------------- templates/account.html | 39 ++++++++++++++++++++++++++++++ templates/email.html | 2 +- templates/folder.html | 2 +- templates/index.html | 33 ++++---------------------- 6 files changed, 79 insertions(+), 54 deletions(-) create mode 100644 templates/account.html diff --git a/README.md b/README.md index b5c16b4..2f59066 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ Does not support different accounts. ```shell SQLITE3_DB= HTTP_AUTH_PASS= - ``` + EMAIL_ARCHIVE_ROOT= + ``` 5. `sudo chmod 600 /etc/secrets/imapviewer` 6. Reload and start the service. diff --git a/server.py b/server.py index 11af8de..0f5950e 100644 --- a/server.py +++ b/server.py @@ -15,6 +15,8 @@ if not os.environ.get('SQLITE3_DB'): raise Exception('SQLITE3_DB not set.') if not os.environ.get('HTTP_AUTH_PASS'): raise Exception('HTTP_AUTH_PASS not set.') +if not os.environ.get('EMAIL_ARCHIVE_ROOT'): + raise Exception('EMAIL_ARCHIVE_ROOT not set.') try: user_password = base64.b64decode(os.environ.get('HTTP_AUTH_PASS')).decode().replace('\n', '') @@ -34,12 +36,6 @@ def get_pw(username): return None -def get_db_connection(): - conn = sqlite3.connect(os.environ.get('SQLITE3_DB')) - conn.row_factory = sqlite3.Row - return conn - - def dict_from_row(row): return dict(zip(row.keys(), row)) @@ -47,45 +43,59 @@ def dict_from_row(row): @app.route('/') @auth.login_required def index(): - conn = get_db_connection() + return render_template('index.html', accounts=[x.name for x in list(Path(os.environ.get('EMAIL_ARCHIVE_ROOT')).iterdir())]) + + +@app.route('//') +@auth.login_required +def account(email_account): + conn = get_db_connection(email_account) folders = conn.execute('SELECT name, table_name FROM folders_mapping').fetchall() syncs = conn.execute('SELECT * FROM syncs ORDER BY timestamp DESC').fetchall() conn.close() syncs = [dict_from_row(sync) for sync in syncs] for sync in syncs: sync['timestamp'] = datetime.fromtimestamp(sync['timestamp']).strftime('%Y-%m-%d %H:%M:%S') - return render_template('index.html', folders=folders, syncs=syncs) + return render_template('account.html', folders=folders, syncs=syncs, email_account=email_account) -@app.route('/folder/') +@app.route('//folder/') @auth.login_required -def folder(table_name): - conn = get_db_connection() +def folder(email_account, table_name): + conn = get_db_connection(email_account) emails = conn.execute(f'SELECT * FROM {table_name} ORDER BY timestamp DESC').fetchall() conn.close() emails = [dict_from_row(email) for email in emails] for email in emails: email['timestamp'] = datetime.fromtimestamp(email['timestamp']).strftime('%Y-%m-%d %H:%M:%S') - return render_template('folder.html', emails=emails, table_name=table_name) + return render_template('folder.html', emails=emails, table_name=table_name, email_account=email_account) -@app.route('/email//') +@app.route('//email//') @auth.login_required -def email(table_name, id): - conn = get_db_connection() - email = conn.execute(f'SELECT * FROM {table_name} WHERE id = ?', (id,)).fetchone() +def email(email_account, table_name, id): + conn = get_db_connection(email_account) + email = dict_from_row(conn.execute(f'SELECT * FROM {table_name} WHERE id = ?', (id,)).fetchone()) conn.close() - email = dict_from_row(email) email['timestamp'] = datetime.fromtimestamp(email['timestamp']).strftime('%Y-%m-%d %H:%M:%S') attachments = json.loads(email['attachments']) - return render_template('email.html', email=email, attachments=attachments) + return render_template('email.html', email=email, attachments=attachments, email_account=email_account) -@app.route('/attachments/') +@app.route('//attachments/') @auth.login_required -def download_file(filename): - mimetype = magic.from_file(str(Path('attachments', filename)), mime=True) - return send_from_directory('attachments', filename, mimetype=mimetype) +def download_file(email_account, filename): + p = Path(os.environ.get('EMAIL_ARCHIVE_ROOT'), email_account, 'attachments', filename) + if not p.exists(): + return 404 + mimetype = magic.from_file(str(p), mime=True) + return send_from_directory(Path(os.environ.get('EMAIL_ARCHIVE_ROOT'), email_account, 'attachments'), filename, mimetype=mimetype) + + +def get_db_connection(email_account): + conn = sqlite3.connect(os.path.join(os.environ.get('EMAIL_ARCHIVE_ROOT'), email_account, 'emails.db')) + conn.row_factory = sqlite3.Row + return conn if __name__ == '__main__': diff --git a/templates/account.html b/templates/account.html new file mode 100644 index 0000000..bc5bb99 --- /dev/null +++ b/templates/account.html @@ -0,0 +1,39 @@ + + + + Email Folders + + +

Email Folders

+

{{ email_account }}

+ +

Last Syncs

+ + + + + + + + + {% for sync in syncs %} + + + + + + + + {% endfor %} +
TimestampTypeNew EmailsNew AttachmentsDuration
{{ sync.timestamp }}{{ sync.type }}{{ sync.new_emails }}{{ sync.new_attachments }}{{ sync.duration }}
+ + + diff --git a/templates/email.html b/templates/email.html index fc2bd10..88e0a98 100644 --- a/templates/email.html +++ b/templates/email.html @@ -8,7 +8,7 @@

Attachments

Content

diff --git a/templates/folder.html b/templates/folder.html index 4b9e686..2004be4 100644 --- a/templates/folder.html +++ b/templates/folder.html @@ -8,7 +8,7 @@
    {% for email in emails %}
  • - + {{ email.timestamp }} | {{ email.from_email }} - {{ email.subject }}
  • diff --git a/templates/index.html b/templates/index.html index c72c69e..e529a14 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,39 +1,14 @@ - Email Folders + Email Archive -

    Email Folders

    +

    Accounts

    -

    Last Syncs

    - - - - - - - - - - {% for sync in syncs %} - - - - - - - - {% endfor %} -
    TimestampTypeNew EmailsNew AttachmentsNew FoldersDuration
    {{ sync.timestamp }}{{ sync.type }}{{ sync.new_emails }}{{ sync.new_attachments }}{{ sync.duration }}
    -