File size: 5,120 Bytes
d712cef
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""
OutreachAgent.py
────────────────
Background worker that polls the "Ready to Send" (Outbox) databases and triggers
the actual Gmail sending process. Once sent, records are cleared from the outbox
and persist in the master "Follow-up Journey" database.
"""

import time
import sqlite3
import os
import json
import sys
from datetime import datetime

# ── Paths ─────────────────────────────────────────────────────────────────────
COLD_OUTBOX_DB = os.path.join(os.environ.get('WORKSPACE_ROOT', '.'), 'Database/EmailsSent/email_to_be_sent.db')
FOLLOWUP_OUTBOX_DB = os.path.join(os.environ.get('WORKSPACE_ROOT', '.'), 'Database/EmailsSent/followups_sent.db')
DATABASE_JSON = os.path.join(os.environ.get('WORKSPACE_ROOT', '.'), 'backend/database.json')

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from Email_sender import send_email_from_database

def process_cold_outbox():
    if not os.path.exists(COLD_OUTBOX_DB): return
    
    conn = sqlite3.connect(COLD_OUTBOX_DB)
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    try:
        # Fetch records that haven't been processed yet
        # (We delete them after success, but we skip 'sent' status just in case)
        cursor.execute("SELECT * FROM ready_emails WHERE company_email != 'not updated' AND status != 'sent'")
        rows = cursor.fetchall()
        
        for row in rows:
            print(f"πŸš€ [OutreachAgent] Processing cold email to {row['company_email']}...")
            
            # Prepare row for Email_sender
            db_row = {
                "body_json": row["body_json"],
                "company_email": row["company_email"],
                "company_name": row["company_name"],
                "generated_subject": row["generated_subject"]
            }
            
            try:
                # Send the email
                result = send_email_from_database(db_row, DATABASE_JSON)
                
                if result and result.get('id'):
                    # Success! Remove from outbox
                    print(f"βœ… [OutreachAgent] Sent successfully (ID: {result['id']}). Clearing from outbox.")
                    cursor.execute("DELETE FROM ready_emails WHERE id = ?", (row['id'],))
                    conn.commit()
                else:
                    print(f"⚠️ [OutreachAgent] Send failed for {row['company_email']}. Will retry next loop.")
            except Exception as e:
                print(f"❌ [OutreachAgent] Error sending cold email: {e}")
                
    except sqlite3.Error as e:
        print(f"❌ [OutreachAgent] Cold outbox DB error: {e}")
    finally:
        conn.close()

def process_followup_outbox():
    if not os.path.exists(FOLLOWUP_OUTBOX_DB): return
    
    conn = sqlite3.connect(FOLLOWUP_OUTBOX_DB)
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    try:
        cursor.execute("SELECT * FROM sent_followups WHERE company_email != 'not updated'")
        rows = cursor.fetchall()
        
        for row in rows:
            print(f"πŸš€ [OutreachAgent] Processing follow-up to {row['company_email']} (ID: {row['Unique_application_id']})...")
            
            db_row = {
                "body_json": row["body_json"],
                "company_email": row["company_email"],
                "company_name": row["company_name"],
                "generated_subject": row["generated_subject"]
            }
            
            try:
                # Send the email and preserve the unique ID thread
                result = send_email_from_database(db_row, DATABASE_JSON, existing_unique_id=row["Unique_application_id"])
                
                if result and result.get('id'):
                    print(f"βœ… [OutreachAgent] Follow-up sent. Clearing from outbox.")
                    cursor.execute("DELETE FROM sent_followups WHERE id = ?", (row['id'],))
                    conn.commit()
                else:
                    print(f"⚠️ [OutreachAgent] Follow-up send failed. Will retry.")
            except Exception as e:
                print(f"❌ [OutreachAgent] Error sending follow-up: {e}")
                
    except sqlite3.Error as e:
        print(f"❌ [OutreachAgent] Follow-up outbox DB error: {e}")
    finally:
        conn.close()

def run_agent():
    print("πŸ”₯ Outreach Background Agent Started.")
    print(f"Monitoring Cold Outbox: {os.path.basename(COLD_OUTBOX_DB)}")
    print(f"Monitoring Follow-up Outbox: {os.path.basename(FOLLOWUP_OUTBOX_DB)}")
    
    while True:
        try:
            # 1. Process Cold Outreach
            process_cold_outbox()
            
            # 2. Process Follow-ups
            process_followup_outbox()
            
        except Exception as e:
            print(f"‼️ [OutreachAgent] Fatal loop error: {e}")
        
        # Poll every 30 seconds
        time.sleep(30)

if __name__ == "__main__":
    run_agent()