# -*- coding: utf-8 -*- from flask import Flask, render_template, request, send_file, redirect, url_for, render_template_string import oracledb, json from datetime import datetime import io import oci import urllib.parse import extract_msg # ============================================================ # CONFIGURATION # ============================================================ with open("config", "r") as f: config_data = json.load(f) WALLET_PATH = config_data["WALLET_PATH"] DB_ALIAS = config_data["DB_ALIAS"] USERNAME = config_data["USERNAME"] PASSWORD = config_data["PASSWORD"] connection = oracledb.connect( user=USERNAME, password=PASSWORD, dsn=DB_ALIAS, config_dir=WALLET_PATH, wallet_location=WALLET_PATH, wallet_password=PASSWORD, ) # OCI client configuration (same standard as process_emails_v2_en.py) BUCKET_PROFILE = config_data["bucket-profile"] BUCKET_NAME = config_data["bucket"] COMPARTMENT_ID = config_data["compartment_id"] bucket_name = BUCKET_NAME + "/processed" # Initialize OCI client and get namespace config = oci.config.from_file("~/.oci/config", BUCKET_PROFILE) object_storage = oci.object_storage.ObjectStorageClient(config) namespace = object_storage.get_namespace().data app = Flask(__name__) # ============================================================ # HELPER FUNCTIONS # ============================================================ def get_distinct_status(): """Return all distinct statuses + 'Forwarded Email' option.""" with connection.cursor() as c: c.execute("SELECT DISTINCT STATUS FROM PROCESSED_EMAILS ORDER BY STATUS") values = [r[0] for r in c.fetchall() if r[0] and str(r[0]).strip()] if "Forwarded Email" not in values: values.append("Forwarded Email") return values # ============================================================ # MAIN ROUTE # ============================================================ @app.route("/", methods=["GET"]) def search_emails(): booking = request.args.get("booking", "").strip().upper() alert_flag = request.args.get("alert", "") status = request.args.get("status", "") start_date = request.args.get("start", "") end_date = request.args.get("end", "") include_forwarded = request.args.get("include_forwarded") == "on" sql = """ SELECT DATE_SENT, BOOKING, EMAIL_FROM, EMAIL_TO, SUBJECT, STATUS, BRIEF_DESCRIPTION, ALERT, FILE_NAME, THREAD_INDEX FROM PROCESSED_EMAILS_REDACTED WHERE 1=1 \ """ params = {} if booking: sql += " AND UPPER(BOOKING) LIKE :bk" params["bk"] = f"%{booking}%" if alert_flag in ("YES", "NO"): sql += " AND ALERT = :alert" params["alert"] = alert_flag if status: if status == "Forwarded Email": sql += " AND (STATUS IS NULL OR TRIM(STATUS) = '')" else: sql += " AND STATUS = :status" params["status"] = status else: # If the checkbox is NOT checked, exclude forwarded emails (STATUS is null) if not include_forwarded: sql += " AND (STATUS IS NOT NULL)" if start_date: sql += " AND DATE_SENT >= TO_TIMESTAMP(:start, 'YYYY-MM-DD')" params["start"] = start_date if end_date: sql += " AND DATE_SENT <= TO_TIMESTAMP(:end, 'YYYY-MM-DD') + INTERVAL '1' DAY" params["end"] = end_date sql += " ORDER BY DATE_SENT ASC" with connection.cursor() as c: c.execute(sql, params) rows = c.fetchall() cols = [d[0] for d in c.description] records = [dict(zip(cols, row)) for row in rows] for r in records: if isinstance(r["DATE_SENT"], datetime): r["DATE_SENT"] = r["DATE_SENT"].strftime("%Y-%m-%d %H:%M:%S") if not r.get("STATUS") or not str(r["STATUS"]).strip(): r["STATUS"] = "Forwarded Email" status_options = get_distinct_status() return render_template( "emails_filter.html", records=records, filters={ "booking": booking, "alert": alert_flag, "status": status, "start": start_date, "end": end_date, "include_forwarded": include_forwarded }, status_options=status_options ) # ============================================================ # ROUTE: VIEW EMAIL # ============================================================ @app.route("/view_email/") def view_email(file_name): try: # Fix URL encoding file_name = urllib.parse.unquote(file_name).strip() # Try multiple possible paths possible_paths = [ file_name, f"processed/{file_name}", f"inbox/{file_name}", f"emails/{file_name}", f"emails/processed/{file_name}", ] msg_obj = None for path in possible_paths: try: obj = object_storage.get_object(namespace, BUCKET_NAME, path) msg_obj = extract_msg.Message(io.BytesIO(obj.data.content)) print(f"[INFO] File found: {path}") break except oci.exceptions.ServiceError as e: if e.status == 404: continue raise if not msg_obj: return ( f"

❌ Email not found in any tested path.

" f"

Bucket: {BUCKET_NAME}
File: {file_name}

", 404, ) # Extract main fields from_field = getattr(msg_obj, "sender", "") to_field = getattr(msg_obj, "to", "") subject = getattr(msg_obj, "subject", "") date = getattr(msg_obj, "date", "") body = getattr(msg_obj, "body", "") # Basic HTML rendering for readability html = f""" {subject or "Viewed Email"}

From: {from_field}

To: {to_field}

Date: {date}

Subject: {subject}

{body}
""" return render_template_string(html) except Exception as e: return f"

Error reading the email:

{e}
", 500 # ============================================================ # MAIN ENTRY POINT # ============================================================ if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=5015)