support multiple accounts, fix misc server issues

This commit is contained in:
Cyberes 2024-07-18 18:21:05 -06:00
parent fb1180ae60
commit 953351e8a8
6 changed files with 79 additions and 54 deletions

View File

@ -32,7 +32,8 @@ Does not support different accounts.
```shell ```shell
SQLITE3_DB=<path to your sqlite3 database> SQLITE3_DB=<path to your sqlite3 database>
HTTP_AUTH_PASS=<your encoded password> HTTP_AUTH_PASS=<your encoded password>
``` EMAIL_ARCHIVE_ROOT=<archive root path>
```
5. `sudo chmod 600 /etc/secrets/imapviewer` 5. `sudo chmod 600 /etc/secrets/imapviewer`
6. Reload and start the service. 6. Reload and start the service.

View File

@ -15,6 +15,8 @@ if not os.environ.get('SQLITE3_DB'):
raise Exception('SQLITE3_DB not set.') raise Exception('SQLITE3_DB not set.')
if not os.environ.get('HTTP_AUTH_PASS'): if not os.environ.get('HTTP_AUTH_PASS'):
raise Exception('HTTP_AUTH_PASS not set.') raise Exception('HTTP_AUTH_PASS not set.')
if not os.environ.get('EMAIL_ARCHIVE_ROOT'):
raise Exception('EMAIL_ARCHIVE_ROOT not set.')
try: try:
user_password = base64.b64decode(os.environ.get('HTTP_AUTH_PASS')).decode().replace('\n', '') user_password = base64.b64decode(os.environ.get('HTTP_AUTH_PASS')).decode().replace('\n', '')
@ -34,12 +36,6 @@ def get_pw(username):
return None 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): def dict_from_row(row):
return dict(zip(row.keys(), row)) return dict(zip(row.keys(), row))
@ -47,45 +43,59 @@ def dict_from_row(row):
@app.route('/') @app.route('/')
@auth.login_required @auth.login_required
def index(): 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('/<email_account>/')
@auth.login_required
def account(email_account):
conn = get_db_connection(email_account)
folders = conn.execute('SELECT name, table_name FROM folders_mapping').fetchall() folders = conn.execute('SELECT name, table_name FROM folders_mapping').fetchall()
syncs = conn.execute('SELECT * FROM syncs ORDER BY timestamp DESC').fetchall() syncs = conn.execute('SELECT * FROM syncs ORDER BY timestamp DESC').fetchall()
conn.close() conn.close()
syncs = [dict_from_row(sync) for sync in syncs] syncs = [dict_from_row(sync) for sync in syncs]
for sync in syncs: for sync in syncs:
sync['timestamp'] = datetime.fromtimestamp(sync['timestamp']).strftime('%Y-%m-%d %H:%M:%S') 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/<table_name>') @app.route('/<email_account>/folder/<table_name>')
@auth.login_required @auth.login_required
def folder(table_name): def folder(email_account, table_name):
conn = get_db_connection() conn = get_db_connection(email_account)
emails = conn.execute(f'SELECT * FROM {table_name} ORDER BY timestamp DESC').fetchall() emails = conn.execute(f'SELECT * FROM {table_name} ORDER BY timestamp DESC').fetchall()
conn.close() conn.close()
emails = [dict_from_row(email) for email in emails] emails = [dict_from_row(email) for email in emails]
for email in emails: for email in emails:
email['timestamp'] = datetime.fromtimestamp(email['timestamp']).strftime('%Y-%m-%d %H:%M:%S') 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/<table_name>/<id>') @app.route('/<email_account>/email/<table_name>/<id>')
@auth.login_required @auth.login_required
def email(table_name, id): def email(email_account, table_name, id):
conn = get_db_connection() conn = get_db_connection(email_account)
email = conn.execute(f'SELECT * FROM {table_name} WHERE id = ?', (id,)).fetchone() email = dict_from_row(conn.execute(f'SELECT * FROM {table_name} WHERE id = ?', (id,)).fetchone())
conn.close() conn.close()
email = dict_from_row(email)
email['timestamp'] = datetime.fromtimestamp(email['timestamp']).strftime('%Y-%m-%d %H:%M:%S') email['timestamp'] = datetime.fromtimestamp(email['timestamp']).strftime('%Y-%m-%d %H:%M:%S')
attachments = json.loads(email['attachments']) 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/<path:filename>') @app.route('/<email_account>/attachments/<path:filename>')
@auth.login_required @auth.login_required
def download_file(filename): def download_file(email_account, filename):
mimetype = magic.from_file(str(Path('attachments', filename)), mime=True) p = Path(os.environ.get('EMAIL_ARCHIVE_ROOT'), email_account, 'attachments', filename)
return send_from_directory('attachments', filename, mimetype=mimetype) 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__': if __name__ == '__main__':

39
templates/account.html Normal file
View File

@ -0,0 +1,39 @@
<!doctype html>
<html>
<head>
<title>Email Folders</title>
</head>
<body>
<h1>Email Folders</h1>
<h3>{{ email_account }}</h3>
<ul>
{% for folder in folders %}
<li><a href="{{ url_for('folder', email_account=email_account, table_name=folder.table_name) }}">{{ folder.name }}</a></li>
{% endfor %}
</ul>
<h1>Last Syncs</h1>
<table>
<tr>
<th>Timestamp</th>
<th>Type</th>
<th>New Emails</th>
<th>New Attachments</th>
<th>Duration</th>
</tr>
{% for sync in syncs %}
<tr>
<td>{{ sync.timestamp }}</td>
<td>{{ sync.type }}</td>
<td>{{ sync.new_emails }}</td>
<td>{{ sync.new_attachments }}</td>
<td>{{ sync.duration }}</td>
</tr>
{% endfor %}
</table>
</body>
<style>
ul {
list-style-type: none;
}
</style>
</html>

View File

@ -8,7 +8,7 @@
<h2>Attachments</h2> <h2>Attachments</h2>
<ul> <ul>
{% for attachment in attachments %} {% for attachment in attachments %}
<a href="{{ url_for('download_file', filename='F' + attachment.hash) }}">{{ attachment.filename }}</a> <a href="{{ url_for('download_file', email_account=email_account, filename='F' + attachment.hash) }}">{{ attachment.filename }}</a>
{% endfor %} {% endfor %}
</ul> </ul>
<h2>Content</h2> <h2>Content</h2>

View File

@ -8,7 +8,7 @@
<ul> <ul>
{% for email in emails %} {% for email in emails %}
<li> <li>
<a href="{{ url_for('email', table_name=table_name, id=email.id) }}"> <a href="{{ url_for('email', email_account=email_account, table_name=table_name, id=email.id) }}">
{{ email.timestamp }} | <i>{{ email.from_email }}</i> - <strong>{{ email.subject }}</strong> {{ email.timestamp }} | <i>{{ email.from_email }}</i> - <strong>{{ email.subject }}</strong>
</a> </a>
</li> </li>

View File

@ -1,39 +1,14 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<title>Email Folders</title> <title>Email Archive</title>
</head> </head>
<body> <body>
<h1>Email Folders</h1> <h3>Accounts</h3>
<ul> <ul>
{% for folder in folders %} {% for account in accounts %}
<li><a href="{{ url_for('folder', table_name=folder.table_name) }}">{{ folder.name }}</a></li> <li><a href="/{{ account }}">{{ account }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<h1>Last Syncs</h1>
<table>
<tr>
<th>Timestamp</th>
<th>Type</th>
<th>New Emails</th>
<th>New Attachments</th>
<th>New Folders</th>
<th>Duration</th>
</tr>
{% for sync in syncs %}
<tr>
<td>{{ sync.timestamp }}</td>
<td>{{ sync.type }}</td>
<td>{{ sync.new_emails }}</td>
<td>{{ sync.new_attachments }}</td>
<td>{{ sync.duration }}</td>
</tr>
{% endfor %}
</table>
</body> </body>
<style>
ul {
list-style-type: none;
}
</style>
</html> </html>