Initial commit: Email alerts application
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
from flask import Flask, render_template, request, jsonify, redirect, url_for, flash
|
||||
import os
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from email_processor import EmailProcessor
|
||||
from dotenv import load_dotenv
|
||||
import sqlite3
|
||||
|
||||
load_dotenv()
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = os.getenv('SECRET_KEY', 'your-secret-key-here')
|
||||
|
||||
# Configuration file path
|
||||
CONFIG_FILE = 'config.json'
|
||||
|
||||
def load_config():
|
||||
"""Load configuration from JSON file"""
|
||||
if os.path.exists(CONFIG_FILE):
|
||||
with open(CONFIG_FILE, 'r') as f:
|
||||
return json.load(f)
|
||||
else:
|
||||
# Default configuration
|
||||
default_config = {
|
||||
'email_address': 'projects@manaknightdigital.com',
|
||||
'time_frames': [
|
||||
{'name': '1-24 hours', 'hours': 24, 'alert_level': 1},
|
||||
{'name': '24-48 hours', 'hours': 48, 'alert_level': 2},
|
||||
{'name': '48+ hours', 'hours': 72, 'alert_level': 3}
|
||||
],
|
||||
'email_days_back': 7,
|
||||
'agency_domains': ['projects@manaknightdigital.com'],
|
||||
'auto_process': False,
|
||||
'auto_process_interval': 30 # minutes
|
||||
}
|
||||
save_config(default_config)
|
||||
return default_config
|
||||
|
||||
def save_config(config):
|
||||
"""Save configuration to JSON file"""
|
||||
with open(CONFIG_FILE, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
|
||||
def auto_process_emails():
|
||||
"""Background function to automatically process emails"""
|
||||
while True:
|
||||
try:
|
||||
config = load_config()
|
||||
if config.get('auto_process', False):
|
||||
print(f"\n🔄 Auto-processing emails (interval: {config['auto_process_interval']} minutes)")
|
||||
processor = EmailProcessor(agency_domains=config['agency_domains'])
|
||||
result = processor.process_emails(
|
||||
max_results=None,
|
||||
send_alerts=True,
|
||||
days_back=config['email_days_back'],
|
||||
time_frames=config['time_frames']
|
||||
)
|
||||
if result.get('status') == 'success':
|
||||
print(f"✅ Auto-processing complete: {result.get('actionable_emails', 0)} actionable emails")
|
||||
else:
|
||||
print(f"❌ Auto-processing failed: {result.get('error', 'Unknown error')}")
|
||||
else:
|
||||
print("⏸️ Auto-processing disabled")
|
||||
|
||||
# Sleep for the configured interval
|
||||
interval_minutes = config.get('auto_process_interval', 30)
|
||||
time.sleep(interval_minutes * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Auto-processing error: {e}")
|
||||
time.sleep(60) # Wait 1 minute before retrying
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""Main dashboard page"""
|
||||
config = load_config()
|
||||
return render_template('index.html', config=config)
|
||||
|
||||
@app.route('/settings')
|
||||
def settings():
|
||||
"""Settings page"""
|
||||
config = load_config()
|
||||
return render_template('settings.html', config=config)
|
||||
|
||||
@app.route('/update_settings', methods=['POST'])
|
||||
def update_settings():
|
||||
"""Update system settings"""
|
||||
try:
|
||||
config = load_config()
|
||||
|
||||
# Update email address
|
||||
config['email_address'] = request.form.get('email_address', config['email_address'])
|
||||
|
||||
# Update email days back
|
||||
config['email_days_back'] = int(request.form.get('email_days_back', 7))
|
||||
|
||||
# Update agency domains
|
||||
agency_domains = request.form.get('agency_domains', '').split(',')
|
||||
config['agency_domains'] = [domain.strip() for domain in agency_domains if domain.strip()]
|
||||
|
||||
# Update time frames
|
||||
time_frames = []
|
||||
frame_names = request.form.getlist('frame_name[]')
|
||||
frame_hours = request.form.getlist('frame_hours[]')
|
||||
frame_levels = request.form.getlist('frame_level[]')
|
||||
|
||||
for i in range(len(frame_names)):
|
||||
if frame_names[i] and frame_hours[i] and frame_levels[i]:
|
||||
time_frames.append({
|
||||
'name': frame_names[i],
|
||||
'hours': int(frame_hours[i]),
|
||||
'alert_level': int(frame_levels[i])
|
||||
})
|
||||
|
||||
# Sort time frames by hours
|
||||
time_frames.sort(key=lambda x: x['hours'])
|
||||
config['time_frames'] = time_frames
|
||||
|
||||
# Update auto processing settings
|
||||
config['auto_process'] = request.form.get('auto_process') == 'on'
|
||||
config['auto_process_interval'] = int(request.form.get('auto_process_interval', 30))
|
||||
|
||||
save_config(config)
|
||||
flash('Settings updated successfully!', 'success')
|
||||
|
||||
except Exception as e:
|
||||
flash(f'Error updating settings: {str(e)}', 'error')
|
||||
|
||||
return redirect(url_for('settings'))
|
||||
|
||||
@app.route('/process_emails', methods=['POST'])
|
||||
def process_emails():
|
||||
"""Process emails and send alerts"""
|
||||
try:
|
||||
config = load_config()
|
||||
|
||||
# Initialize processor with current settings
|
||||
processor = EmailProcessor(agency_domains=config['agency_domains'])
|
||||
|
||||
# Process emails with configurable settings
|
||||
result = processor.process_emails(
|
||||
max_results=None,
|
||||
send_alerts=True,
|
||||
days_back=config['email_days_back'],
|
||||
time_frames=config['time_frames']
|
||||
)
|
||||
|
||||
if result.get('status') == 'success':
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'message': 'Email processing completed successfully',
|
||||
'data': {
|
||||
'total_emails': result.get('total_emails', 0),
|
||||
'actionable_emails': result.get('actionable_emails', 0),
|
||||
'sent_alerts': len(result.get('sent_alerts', []))
|
||||
}
|
||||
})
|
||||
else:
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': result.get('error', 'Unknown error occurred')
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': f'System error: {str(e)}'
|
||||
})
|
||||
|
||||
@app.route('/get_threads')
|
||||
def get_threads():
|
||||
"""Get current threads that need alerts"""
|
||||
try:
|
||||
config = load_config()
|
||||
processor = EmailProcessor(agency_domains=config['agency_domains'])
|
||||
|
||||
alert_threads = processor.tracker.get_threads_needing_alerts(config['time_frames'])
|
||||
|
||||
threads_data = []
|
||||
for thread in alert_threads:
|
||||
threads_data.append({
|
||||
'thread_id': thread.thread_id,
|
||||
'subject': thread.subject,
|
||||
'last_message': thread.last_external_message.strftime('%Y-%m-%d %H:%M'),
|
||||
'alert_level': thread.alert_level,
|
||||
'hours_since': int((datetime.now() - thread.last_external_message).total_seconds() / 3600)
|
||||
})
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'threads': threads_data
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': f'Error fetching threads: {str(e)}'
|
||||
})
|
||||
|
||||
@app.route('/test_connection')
|
||||
def test_connection():
|
||||
"""Test email connection"""
|
||||
try:
|
||||
config = load_config()
|
||||
processor = EmailProcessor(agency_domains=config['agency_domains'])
|
||||
|
||||
# Test connection by fetching a small number of emails
|
||||
emails = processor.zoho_client.fetch_emails(max_results=5, days_back=config['email_days_back'])
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'message': f'Connection successful! Found {len(emails)} emails in the last {config["email_days_back"]} days.',
|
||||
'email_count': len(emails)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': f'Connection failed: {str(e)}'
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Start auto-processing thread
|
||||
auto_thread = threading.Thread(target=auto_process_emails, daemon=True)
|
||||
auto_thread.start()
|
||||
print("🔄 Auto-processing thread started")
|
||||
|
||||
app.run(debug=True, host='0.0.0.0', port=5000)
|
||||
Reference in New Issue
Block a user