Remove email functionality

This commit is contained in:
Minecon724 2025-05-13 15:14:29 +02:00
commit 63de15b808
Signed by: Minecon724
GPG key ID: A02E6E67AB961189
6 changed files with 10 additions and 327 deletions

View file

@ -2,9 +2,8 @@ from flask import request, render_template, redirect, url_for, flash, session
from functools import wraps
from . import app, db, limiter, csrf
from .models import Inquiry, Message, Settings, Admin
from .notifiers import webhooks, emails
from .notifiers import webhooks
from .notifiers.webhooks import WebhookError
from .notifiers.emails import EmailNotificationError
def is_admin():
return 'admin_authenticated' in session and session['admin_authenticated']
@ -174,43 +173,4 @@ def admin_settings_webhook():
else:
flash('Webhook settings saved', 'success')
return redirect(url_for('admin_settings'))
@app.route('/admin/settings/email', methods=['POST'])
@admin_required
def admin_settings_email():
settings = Settings.query.first()
if not settings:
settings = Settings()
db.session.add(settings)
settings.email_notifications_enabled = request.form.get('email_notifications_enabled') == 'on'
settings.smtp_server = request.form.get('smtp_server', '')
settings.smtp_use_ssl = request.form.get('smtp_use_ssl') == 'on'
settings.smtp_username = request.form.get('smtp_username', '')
settings.smtp_password = request.form.get('smtp_password', '')
settings.recipient_email = request.form.get('recipient_email', '')
db.session.commit()
if settings.email_notifications_enabled:
result = emails.verify_email_settings(settings)
if result['errors']:
flash(f'Email settings verification failed: {", ".join(result["errors"])}', 'error')
else:
try:
emails.send_email(
title='Inquiry #1234abcd1234abcd Created',
inquiry_id='1234abcd1234abcd',
data={
'message': 'This is a test message'
},
is_async=False
)
flash('Email settings saved and test sent successfully')
except EmailNotificationError as e:
flash(f'Email test failed: {str(e)}', 'error')
else:
flash('Email notifications svaed', 'success')
return redirect(url_for('admin_settings'))
return redirect(url_for('admin_settings'))

View file

@ -1,49 +0,0 @@
from sqlalchemy import Column, Boolean, String, inspect
from sqlalchemy.sql import text
from flask import current_app
def run_migration(db):
"""Add email notification settings columns to the Settings table if they don't exist."""
current_app.logger.info("Running migration: add_email_settings")
# Check if the table exists first
inspector = inspect(db.engine)
if 'settings' not in inspector.get_table_names():
current_app.logger.info("Settings table doesn't exist yet, skipping migration")
return False
# Check existing columns
columns = [col['name'] for col in inspector.get_columns('settings')]
# Track if we need to commit changes
changes_made = False
# Dictionary of columns to add with their types
columns_to_add = {
'email_notifications_enabled': 'BOOLEAN DEFAULT FALSE',
'smtp_server': 'VARCHAR(255)',
'smtp_use_ssl': 'BOOLEAN DEFAULT FALSE',
'smtp_username': 'VARCHAR(255)',
'smtp_password': 'VARCHAR(255)',
'recipient_email': 'VARCHAR(255)',
'notification_show_message': 'BOOLEAN DEFAULT FALSE',
'auto_delete_hours': 'INTEGER DEFAULT 48'
}
# Add each column if it doesn't exist
for column_name, column_type in columns_to_add.items():
if column_name not in columns:
current_app.logger.info(f"Adding {column_name} column to settings table")
with db.engine.connect() as conn:
conn.execute(text(f"ALTER TABLE settings ADD COLUMN {column_name} {column_type}"))
conn.commit()
changes_made = True
else:
current_app.logger.info(f"{column_name} column already exists in settings table")
if changes_made:
current_app.logger.info("Migration completed successfully")
else:
current_app.logger.info("No changes needed, all columns already exist")
return changes_made

View file

@ -8,14 +8,6 @@ class Settings(db.Model):
webhook_url = db.Column(db.String(255), nullable=True)
webhook_secret = db.Column(db.String(255), nullable=True)
# Email notification settings
email_notifications_enabled = db.Column(db.Boolean, default=False)
smtp_server = db.Column(db.String(255), nullable=True)
smtp_use_ssl = db.Column(db.Boolean, default=False)
smtp_username = db.Column(db.String(255), nullable=True)
smtp_password = db.Column(db.String(255), nullable=True) # Consider storing this securely
recipient_email = db.Column(db.String(255), nullable=True)
notification_show_message = db.Column(db.Boolean, default=False)
auto_delete_hours = db.Column(db.Integer, default=48)

View file

@ -1,7 +1,7 @@
from flask import current_app
from .emails import send_email
from .webhooks import send_webhook
MESSAGE_PREVIEW_LENGTH = 30
EVENT_TYPES = {
'inquiry_created': 'Inquiry #{} Created',
@ -46,15 +46,6 @@ def inquiry_message(inquiry_id: str, message: str = None, is_async: bool = True)
### Private methods ###
def _send_event(event_type: str, inquiry_id: str, message: str = None, is_async: bool = True) -> None:
_send_email_ignore_errors(
title=EVENT_TYPES[event_type].format(inquiry_id),
inquiry_id=inquiry_id,
data={
'message': _get_message_preview(message) if message else None
},
is_async=is_async
)
_send_webhook_ignore_errors(
event_type=event_type,
data={
@ -64,12 +55,6 @@ def _send_event(event_type: str, inquiry_id: str, message: str = None, is_async:
is_async=is_async
)
def _send_email_ignore_errors(title, inquiry_id, data, is_async=True):
try:
send_email(title, inquiry_id, data, is_async)
except:
pass
def _send_webhook_ignore_errors(event_type, data, is_async=True):
try:
send_webhook(event_type, data, is_async)

View file

@ -1,156 +0,0 @@
import smtplib
from email.message import EmailMessage
import threading
from datetime import datetime
from flask import current_app
from ..models import Settings
class EmailNotificationError(Exception):
"""Exception raised for errors in the email notification process.
Attributes:
message -- explanation of the error
original_exception -- the original exception that caused this error (optional)
"""
def __init__(self, message, original_exception=None):
self.message = message
self.original_exception = original_exception
super().__init__(self.message)
def verify_email_settings(settings: Settings = None):
"""
Verifies that email notification settings are properly configured.
Returns:
dict: A dictionary containing:
- 'valid' (bool): Whether settings are valid for sending emails
- 'errors' (list): List of error messages if any settings are invalid
- 'settings' (dict): Current settings state (without sensitive values)
"""
if settings is None:
settings = Settings.query.first()
result = {
'valid': False,
'errors': [],
'settings': {}
}
# Check if settings exist and notifications are enabled
if not settings:
result['errors'].append("Settings not found in database")
return result
result['settings']['email_notifications_enabled'] = settings.email_notifications_enabled
if not settings.email_notifications_enabled:
result['errors'].append("Email notifications are disabled")
return result
# Required fields
required_fields = {
'smtp_server': settings.smtp_server,
'smtp_username': settings.smtp_username,
'recipient_email': settings.recipient_email
}
# Check required fields
for field, value in required_fields.items():
result['settings'][field] = value
if not value:
result['errors'].append(f"Missing required setting: {field}")
# Test SMTP connection if desired (commented out to avoid actual connection attempts)
# This could be implemented as a separate function that calls this one first
# Mark as valid if no errors
result['valid'] = len(result['errors']) == 0
return result
def send_email(title: str, inquiry_id: str, data: dict = {}, is_async=False):
"""Sends an email notification, either synchronously or asynchronously."""
app = current_app._get_current_object()
if is_async:
_send_email_async(app, title, inquiry_id, data)
else:
_send_email_worker(app, title, inquiry_id, data)
def _send_email_async(app, title: str, inquiry_id: str, data: dict = {}):
"""Queue email to be sent in a background thread"""
thread = threading.Thread(target=_send_email_worker, args=(app, title, inquiry_id, data))
thread.daemon = True # Thread will exit when main thread exits
thread.start()
def _send_email_worker(app, title: str, inquiry_id: str, data: dict = {}):
"""Worker function that sends the email notification."""
try:
with app.app_context():
settings = Settings.query.first()
if not settings or not settings.email_notifications_enabled:
return False
verification_result = verify_email_settings(settings)
if not verification_result['valid']:
raise EmailNotificationError(f"Invalid email settings: {', '.join(verification_result['errors'])}")
# Construct email message
msg = EmailMessage()
msg['Subject'] = "[AnonChat] " + title
msg['From'] = settings.smtp_username
msg['To'] = settings.recipient_email
content = f"""
Title: {title}
Timestamp: {datetime.utcnow().isoformat()} UTC
Inquiry ID: {inquiry_id}
{data.get('message', '') if settings.notification_show_message else ''}"""
msg.set_content(content)
_send_smtp_message(settings, msg)
app.logger.info(f"Email notification sent for title: {title}")
except Exception as e:
app.logger.error(f"Email error: {e}")
if isinstance(e, EmailNotificationError):
raise e
raise EmailNotificationError(f"Exception: {e}", original_exception=e)
def _get_smtp_server(smtp_server: str):
smtp_server_parts = smtp_server.split(':')
smtp_host = smtp_server_parts[0]
if len(smtp_server_parts) > 1:
smtp_port = int(smtp_server_parts[1])
else:
smtp_port = 0
return (smtp_host, smtp_port)
def _send_smtp_message(settings, msg):
smtp_server = None
smtp_host, smtp_port = _get_smtp_server(settings.smtp_server)
try:
if settings.smtp_use_ssl:
smtp_server = smtplib.SMTP_SSL(smtp_host, smtp_port, timeout=10)
else:
smtp_server = smtplib.SMTP(smtp_host, smtp_port, timeout=10)
if settings.smtp_username and settings.smtp_password:
smtp_server.login(settings.smtp_username, settings.smtp_password)
smtp_server.send_message(msg)
except smtplib.SMTPException as e:
raise EmailNotificationError(f"SMTP Error: {e}", original_exception=e)
finally:
if smtp_server:
smtp_server.quit()

View file

@ -45,13 +45,6 @@
This will have no effect on inquiries that are already closed.
</small>
</label>
<br>
<label>
<input type="checkbox" name="notification_show_message" {% if settings.notification_show_message %}checked{% endif %}>
Include message content in email notifications
</label>
<br>
@ -84,6 +77,13 @@
</label>
</div>
<br>
<label>
<input type="checkbox" name="notification_show_message" {% if settings.notification_show_message %}checked{% endif %}>
Include message content
</label>
<div style="margin-top: 1rem;">
<label for="webhook_url">Webhook URL:</label>
<input type="text" id="webhook_url" name="webhook_url" value="{{ settings.webhook_url or '' }}" placeholder="https://example.com/webhook">
@ -112,53 +112,4 @@
}</pre>
</div>
</div>
<br>
<div class="email-settings">
<h3>Email Notification Settings</h3>
<div style="margin-bottom: 2rem;">
<p>Configure email settings to receive notifications for new inquiries and responses.</p>
</div>
<form method="POST" action="{{ url_for('admin_settings_email') }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<div>
<label>
<input type="checkbox" name="email_notifications_enabled" {% if settings.email_notifications_enabled %}checked{% endif %}>
Enable Email Notifications
</label>
</div>
<div style="margin-top: 1rem;">
<label for="smtp_server">SMTP Server:</label>
<input type="text" id="smtp_server" name="smtp_server" value="{{ settings.smtp_server or '' }}" placeholder="smtp.example.com">
</div>
<div style="margin-top: 1rem;">
<label>
<input type="checkbox" name="smtp_use_ssl" {% if settings.smtp_use_ssl %}checked{% endif %}>
Use SSL
</label>
</div>
<div style="margin-top: 1rem;">
<label for="smtp_username">SMTP Username / Sender Email:</label>
<input type="text" id="smtp_username" name="smtp_username" value="{{ settings.smtp_username or '' }}" placeholder="username@example.com">
</div>
<div style="margin-top: 1rem;">
<label for="smtp_password">SMTP Password:</label>
<input type="password" id="smtp_password" name="smtp_password" value="{{ settings.smtp_password or '' }}" placeholder="Password">
</div>
<div style="margin-top: 1rem;">
<label for="recipient_email">Recipient Email:</label>
<input type="email" id="recipient_email" name="recipient_email" value="{{ settings.recipient_email or '' }}" placeholder="admin@example.com">
</div>
<button type="submit" style="margin-top: 1rem;">Save Email Settings</button>
</form>
</div>
{% endblock %}