diff --git a/Web/modules/database/settings.py b/Web/modules/database/settings.py index 0d9bb00..78bf876 100644 --- a/Web/modules/database/settings.py +++ b/Web/modules/database/settings.py @@ -278,6 +278,7 @@ INVENTORY_MODULE_ENABLED = _TenantAwareBool('inventory', _get(_conf, ['modules', TERMINPLAN_MODULE_ENABLED = _TenantAwareBool('terminplan', _get(_conf, ['modules', 'terminplan', 'enabled'], DEFAULTS['modules']['terminplan']['enabled'])) LIBRARY_MODULE_ENABLED = _TenantAwareBool('library', _get(_conf, ['modules', 'library', 'enabled'], DEFAULTS['modules']['library']['enabled'])) STUDENT_CARDS_MODULE_ENABLED = _TenantAwareBool('student_cards', _get(_conf, ['modules', 'student_cards', 'enabled'], DEFAULTS['modules']['student_cards']['enabled'])) +MAIL_ADD_ON_ENABLED = _TenantAwareBool('mail', _get(_conf, ['email', 'enabled'], False)) def _match_inventory(path): if not path: return False @@ -297,11 +298,16 @@ def _match_student_cards(path): if not path: return False return path.startswith(('/student_cards')) +def _match_mail(path): + if not path: return False + return path.startswith(('/')) + # Register core modules into the pipeline MODULES.register('inventory', INVENTORY_MODULE_ENABLED, _match_inventory) MODULES.register('terminplan', TERMINPLAN_MODULE_ENABLED, _match_terminplan) MODULES.register('library', LIBRARY_MODULE_ENABLED, _match_library) MODULES.register('student_cards', STUDENT_CARDS_MODULE_ENABLED, _match_student_cards) +MODULES.register('mail', MAIL_ADD_ON_ENABLED, _match_mail) STUDENT_DEFAULT_BORROW_DAYS = int(_get(_conf, ['modules', 'student_cards', 'default_borrow_days'], DEFAULTS['modules']['student_cards']['default_borrow_days'])) STUDENT_MAX_BORROW_DAYS = int(_get(_conf, ["modules", "student_cards", "max_borrow_days"], DEFAULTS["modules"]["student_cards"]["max_borrow_days"])) diff --git a/Web/modules/emailservice/email.py b/Web/modules/emailservice/email.py index 699aa9c..dc7d488 100644 --- a/Web/modules/emailservice/email.py +++ b/Web/modules/emailservice/email.py @@ -1,51 +1,98 @@ -from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart -from modules.module_registry import ModuleRegistry as mr +from email.mime.text import MIMEText import smtplib +import time import Web.modules.database.settings as cfg def _build_smtp_client(): - smtp = smtplib.SMTP(cfg.EMAIL_SMTP_HOST, cfg.EMAIL_SMTP_PORT, timeout=cfg.EMAIL_TIMEOUT_SECONDS) + smtp = smtplib.SMTP( + cfg.EMAIL_SMTP_HOST, + cfg.EMAIL_SMTP_PORT, + timeout=cfg.EMAIL_TIMEOUT_SECONDS, + ) smtp.ehlo() if cfg.EMAIL_USE_TLS: smtp.starttls() smtp.ehlo() if cfg.EMAIL_USERNAME: - smtp.login(cfg.EMAIL_USERNAME, cfg.EMAIL_PASSWORD or '') + smtp.login(cfg.EMAIL_USERNAME, cfg.EMAIL_PASSWORD or "") return smtp -def send(email: list, subject: str, note: str, sender: str) -> bool: - """ - Sends the email with the link to the Clients - Input: - - email: Email list of all the addresses to send the link to ["","",""] - - subject: Subject of the email - - note: Note that is send with the Emails +def send(email: list | str, subject: str, note: str, sender: str) -> bool: + """Sends the email with the link to the Clients.""" + if not cfg.MODULES.is_enabled("mail"): + print("Debug: Module not enabled") + return False + + if isinstance(email, str): + email = [email] + + body_message = note + + HTML_SIGNATURE = f""" + + + + +
+

Mit freundlichen Grüßen

+

Automatisierter Email Verteiler für die Schule: {cfg.get_school_info().get("name")}

+

Invario UG
Am Sportplatz 10
83052 Bruckmühl

+
+ """ + + text_content = f"{body_message}\n\nMit freundlichen Grüßen\n{sender}\nInvario UG" + + html_content = f""" + + +

{body_message}

+
+ {HTML_SIGNATURE} + + + """ + + mails_per_second = 10 + interval = 1.0 / mails_per_second - Output: - - bool: true if the sending worked and false if it didnt - """ - if not mr.registry.is_enabled('mail'): - return False - else: - msg = MIMEMultipart() - msg['Subject'] = subject - msg['From'] = sender or cfg.EMAIL_FROM_ADDRESS or cfg.EMAIL_USERNAME - msg['To'] = ', '.join(email) if isinstance(email, (list, tuple)) else str(email) - msg.attach(MIMEText(note)) smtp = None try: - smtp = _build_smtp_client() - smtp.sendmail(from_addr=msg['From'], to_addrs=email, msg=msg.as_string()) - return True - except Exception: - return False + smtp = _build_smtp_client() + + for i, recipient in enumerate(email): + start_time = time.time() + + msg = MIMEMultipart("alternative") + msg["Subject"] = str(subject) + msg["From"] = f"{sender} <{cfg.EMAIL_USERNAME}>" + msg["To"] = str(recipient) + + msg.attach(MIMEText(text_content, "plain")) + msg.attach(MIMEText(html_content, "html")) + + smtp.sendmail( + from_addr=cfg.EMAIL_USERNAME, + to_addrs=[recipient], + msg=msg.as_string() + ) + + elapsed_time = time.time() - start_time + sleep_time = interval - elapsed_time + + if sleep_time > 0 and i < len(email) - 1: + time.sleep(sleep_time) + + return True + except Exception as e: + print(f"Debug: Fehler beim Senden der E-Mail: {e}") + return False finally: - try: if smtp: - smtp.quit() - except Exception: - pass \ No newline at end of file + try: + smtp.quit() + except Exception: + pass \ No newline at end of file diff --git a/Web/modules/terminplaner/backend_server.py b/Web/modules/terminplaner/backend_server.py index 376723a..57d7c18 100644 --- a/Web/modules/terminplaner/backend_server.py +++ b/Web/modules/terminplaner/backend_server.py @@ -22,7 +22,7 @@ def _resolve_public_base_url() -> str: subdomain = '' if tenant_context: subdomain = getattr(tenant_context, 'subdomain', '') or getattr(tenant_context, 'tenant_id', '') or '' - return f"https://{subdomain}.invario.eu" if subdomain else "https://invario.eu" + return (f"https://{subdomain}.invario-software.de") if subdomain else "https://invario-software.de" def _current_tenant_id() -> str: diff --git a/config.json b/config.json index 74bf877..4bcafd2 100755 --- a/config.json +++ b/config.json @@ -20,14 +20,14 @@ "key": "Web/certs/key.pem" }, "email": { - "enabled": false, - "smtp_host": "smtp.gmail.com", + "enabled": true, + "smtp_host": "mail.invario-software.de", "smtp_port": 587, "use_tls": true, - "username": "", - "password": "", - "from_address": "", - "default_sender_name": "Invario Inventarprogramm", + "username": "no-reply@invario-software.de", + "password": "#,EATwIn,68", + "from_address": "no-reply@invario-software.de", + "default_sender_name": "Invario Email Service", "timeout_seconds": 30 }, "images": {