Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| import os | |
| import resend | |
| from datetime import datetime | |
| import threading | |
| # Fallback to the environment variable or use the hardcoded one we verified | |
| RESEND_API_KEY = os.getenv('RESEND_API_KEY', 're_KB1gXW59_GKPa3ivLTAYgpafiY5HKPrCH') | |
| resend.api_key = RESEND_API_KEY | |
| SENDER_EMAIL = "onboarding@resend.dev" | |
| SUPPORT_EMAIL = "support@larshield.com" | |
| LOGO_URL = "https://i.ibb.co/3sXZbYm/larshieldlogowhite.png" # Temporary placeholder for LarShield logo | |
| DASHBOARD_URL = "https://wss.larshield.com/dashboard" # Update with actual frontend URL | |
| # Base path for templates depending on where the script runs from | |
| TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'templates', 'emails') | |
| def render_template(template_name, context): | |
| """Reads the HTML file and replaces {{ keys }} with context values.""" | |
| filepath = os.path.join(TEMPLATES_DIR, template_name) | |
| try: | |
| with open(filepath, 'r', encoding='utf-8') as f: | |
| content = f.read() | |
| # Inject standard variables | |
| context["{{ year }}"] = str(datetime.now().year) | |
| context["{{ logo_url }}"] = LOGO_URL | |
| context["{{ support_email }}"] = SUPPORT_EMAIL | |
| for key, value in context.items(): | |
| content = content.replace(key, str(value)) | |
| return content | |
| except Exception as e: | |
| print(f"[EmailService] Failed to render template {template_name}: {e}") | |
| return "" | |
| def _send_email_async(to_email, subject, html_content): | |
| """Sends the email in a background thread to avoid blocking the main request.""" | |
| def send(): | |
| import psycopg2 | |
| import uuid | |
| db_url = os.environ.get('DATABASE_URL') | |
| log_id = str(uuid.uuid4()) | |
| status = 'sent' | |
| error_msg = None | |
| try: | |
| # FORCE ALL EMAILS TO THE TESTER EMAIL FOR RESEND FREE TIER LIMITATIONS | |
| actual_to_email = "dhruvpatel14016@gmail.com" | |
| r = resend.Emails.send({ | |
| "from": SENDER_EMAIL, | |
| "to": actual_to_email, | |
| "subject": subject, | |
| "html": html_content | |
| }) | |
| print(f"[EmailService] Email sent to {actual_to_email}. ID: {r['id']}") | |
| except Exception as e: | |
| status = 'failed' | |
| error_msg = str(e) | |
| print(f"[EmailService] Failed to send email to {to_email}: {e}") | |
| finally: | |
| if db_url: | |
| try: | |
| conn = psycopg2.connect(db_url) | |
| cur = conn.cursor() | |
| cur.execute( | |
| "INSERT INTO email_logs (id, recipient, subject, status, error_message, sent_at) VALUES (%s, %s, %s, %s, %s, %s)", | |
| (log_id, to_email, subject, status, error_msg, datetime.utcnow()) | |
| ) | |
| conn.commit() | |
| cur.close() | |
| conn.close() | |
| except Exception as db_err: | |
| print(f"[EmailService] Failed to log email to database: {db_err}") | |
| thread = threading.Thread(target=send) | |
| thread.start() | |
| def send_welcome_email(user_email, user_name): | |
| context = { | |
| "{{ user_name }}": user_name, | |
| "{{ dashboard_link }}": DASHBOARD_URL | |
| } | |
| html = render_template('welcome.html', context) | |
| if html: | |
| _send_email_async(user_email, "Welcome to LarShield!", html) | |
| def send_scan_started(user_email, user_name, target_url, scan_type, estimated_time="~15 minutes"): | |
| context = { | |
| "{{ user_name }}": user_name, | |
| "{{ target_url }}": target_url, | |
| "{{ scan_type }}": scan_type, | |
| "{{ estimated_time }}": estimated_time, | |
| "{{ dashboard_link }}": DASHBOARD_URL | |
| } | |
| html = render_template('scan_started.html', context) | |
| if html: | |
| _send_email_async(user_email, "Scan Initiated Successfully", html) | |
| def send_scan_completed(user_email, user_name, target_url, duration, vulns_count, report_link, crit="0", high="0", med="0", low="0"): | |
| context = { | |
| "{{ user_name }}": user_name, | |
| "{{ target_url }}": target_url, | |
| "{{ duration }}": duration, | |
| "{{ vulns_count }}": vulns_count, | |
| "{{ report_link }}": report_link, | |
| "{{ crit_count }}": crit, | |
| "{{ high_count }}": high, | |
| "{{ med_count }}": med, | |
| "{{ low_count }}": low | |
| } | |
| html = render_template('scan_completed.html', context) | |
| if html: | |
| _send_email_async(user_email, "Scan Completed Successfully", html) | |
| def send_critical_alert(user_email, user_name, target_url, duration, vulns_count, report_link, crit="0", high="0", med="0", low="0"): | |
| context = { | |
| "{{ user_name }}": user_name, | |
| "{{ target_url }}": target_url, | |
| "{{ duration }}": duration, | |
| "{{ vulns_count }}": vulns_count, | |
| "{{ report_link }}": report_link, | |
| "{{ crit_count }}": crit, | |
| "{{ high_count }}": high, | |
| "{{ med_count }}": med, | |
| "{{ low_count }}": low | |
| } | |
| html = render_template('critical_alert.html', context) | |
| if html: | |
| _send_email_async(user_email, "🚨 URGENT: Critical Vulnerabilities Detected", html) | |
| def send_scan_failed(user_email, user_name, target_url, scan_type, error_message): | |
| context = { | |
| "{{ user_name }}": user_name, | |
| "{{ target_url }}": target_url, | |
| "{{ scan_type }}": scan_type, | |
| "{{ error_message }}": error_message, | |
| "{{ dashboard_link }}": DASHBOARD_URL | |
| } | |
| html = render_template('scan_failed.html', context) | |
| if html: | |
| _send_email_async(user_email, "Scan Failed Alert", html) | |
| def send_password_reset(user_email, user_name, reset_token): | |
| reset_link = f"{DASHBOARD_URL}/reset-password?token={reset_token}" | |
| context = { | |
| "{{ user_name }}": user_name, | |
| "{{ reset_link }}": reset_link | |
| } | |
| html = render_template('password_reset.html', context) | |
| if html: | |
| _send_email_async(user_email, "Password Reset Request", html) | |