Untested, created email generation + styling

This commit is contained in:
Uthman Fatih 2025-10-13 20:41:45 +01:00
parent 80a354c484
commit fa8103051f

110
main.py
View File

@ -10,6 +10,8 @@ import time
import services.apt import services.apt
import services.mail import services.mail
from socket import gethostname
from dotenv import load_dotenv from dotenv import load_dotenv
from os import getenv from os import getenv
from os.path import dirname, join from os.path import dirname, join
@ -20,28 +22,116 @@ import typer
dotenv_path = join(dirname(__file__), ".env") dotenv_path = join(dirname(__file__), ".env")
load_dotenv(dotenv_path) load_dotenv(dotenv_path)
# TODO: Logging # FIXME: Error handling
# TODO: Email alerts + structure # FIXME: Add json email list that if not added will use parameters
# TODO: Use typer for CLI # FIXME: Handle no updates available
# TODO: Fix readme and git.uthmn.com page for final release.
# TODO: Error handling all round
app = typer.Typer() app = typer.Typer()
@app.command() @app.command()
def main(): def serve():
""" """
Checks for updates and emails hourly for security, daily for general as a daemon. Checks for updates and emails hourly for security, daily for general as a daemon.
""" """
pass
@app.command() @app.command()
def now(): def now(receiver_email: str):
""" """
Checks for apt upgrades and emails them then exits. Checks for apt upgrades and emails them then exits.
""" """
# TODO: Flag --now to run temporarily and just execute hourly tasks instantly then exit generate_email(receiver_email)
pass
def generate_email(receiver_email: str):
services.apt.require_root()
if not services.apt.detect_apt():
print("Apt not found on this system.")
exit(1)
updates = services.apt.check_updates()
# Get how many security updates are available
security_updates = 0
for package in updates:
if package["security"]:
security_updates += 1
# Get how many total updates are available
total_updates = len(updates)
# Get how many general updates are available
general_updates = total_updates - security_updates
# Get system hostname
hostname = gethostname()
# Create email subject
subject = f"{hostname}> {security_updates} security updates, {general_updates} general updates available"
# Iterate over each security package and create a list of updates in html
security_chunks = ""
for package in updates:
if not package["security"]:
continue
chunk = f'''
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">{package}</td>
<td style="border: 1px solid #ddd; padding: 8px;">{package["installed_version"]}</td>
<td style="border: 1px solid #ddd; padding: 8px;">{package["latest_version"]}</td>
<td style="border: 1px solid #ddd; padding: 8px;">{package["repo"]}</td>
</tr>
'''
security_chunks += chunk
security = f'''
<h1 style="font-family: Arial, sans-serif;">Security</h1>
<table style="border-collapse: collapse; width: 100%; font-family: Arial, sans-serif;">
<tr>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Package</th>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Installed</th>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Latest</th>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Repository</th>
</tr>
{security_chunks}
</table>
'''
# Iterate over each general package and create a list of updates in html
general_chunks = ""
for package in updates:
if package["security"]:
continue
chunk = f'''
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">{package}</td>
<td style="border: 1px solid #ddd; padding: 8px;">{package["installed_version"]}</td>
<td style="border: 1px solid #ddd; padding: 8px;">{package["latest_version"]}</td>
<td style="border: 1px solid #ddd; padding: 8px;">{package["repo"]}</td>
</tr>
'''
general_chunks += chunk
general = f'''
<h1 style="font-family: Arial, sans-serif;">General</h1>
<table style="border-collapse: collapse; width: 100%; font-family: Arial, sans-serif;">
<tr>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Package</th>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Installed</th>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Latest</th>
<th style="border: 1px solid #ddd; background-color: #f2f2f2; padding: 8px;">Repository</th>
</tr>
{general_chunks}
</table>
'''
html += security
html += general
services.mail.send_email(receiver_email, subject, html)
@app.callback() @app.callback()
def callback(): def callback():