File size: 9,050 Bytes
0ff7b30
 
 
 
 
 
 
 
 
 
 
750c75a
0ff7b30
 
 
 
750c75a
0ff7b30
 
 
 
 
 
 
 
 
 
750c75a
3959ff2
 
45a55f0
750c75a
45a55f0
750c75a
 
 
 
 
 
45a55f0
750c75a
 
 
 
 
3959ff2
750c75a
 
 
0ff7b30
 
750c75a
3959ff2
750c75a
0ff7b30
3959ff2
 
750c75a
3959ff2
 
0ff7b30
3959ff2
 
 
 
 
 
750c75a
3959ff2
45a55f0
3959ff2
45a55f0
 
3959ff2
45a55f0
 
3959ff2
45a55f0
 
750c75a
3959ff2
 
45a55f0
3959ff2
 
750c75a
3959ff2
750c75a
45a55f0
3959ff2
750c75a
3959ff2
 
 
750c75a
45a55f0
 
 
3959ff2
45a55f0
 
3959ff2
45a55f0
3959ff2
45a55f0
750c75a
 
0ff7b30
45a55f0
3959ff2
45a55f0
3959ff2
0ff7b30
3959ff2
45a55f0
3959ff2
750c75a
3959ff2
45a55f0
3959ff2
45a55f0
3959ff2
45a55f0
3959ff2
 
 
45a55f0
3959ff2
0ff7b30
 
3959ff2
 
 
 
 
 
 
 
 
750c75a
3959ff2
 
750c75a
0ff7b30
 
 
 
750c75a
0ff7b30
 
 
 
 
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from flask import Flask, request, jsonify
from flask_cors import CORS
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# from email.mime.base import MIMEBase # Not used in simplified version
# from email import encoders             # Not used in simplified version
import base64
import os
import socket 
import traceback

# <<<--- FLASK APP INITIALIZATION MUST BE HERE (TOP LEVEL) --->>>
app = Flask(__name__)
CORS(app)
# <<<--------------------------------------------------------->>>

# Environment variables will be set as Secrets in Hugging Face Space settings
SMTP_SERVER_HOST = os.environ.get("SMTP_SERVER_HOST")
SMTP_SERVER_PORT = os.environ.get("SMTP_SERVER_PORT")
SMTP_SENDER_EMAIL = os.environ.get("SMTP_SENDER_EMAIL")
SMTP_SENDER_PASSWORD = os.environ.get("SMTP_SENDER_PASSWORD")

SMTP_CONNECTION_TIMEOUT = 30
SMTP_COMMAND_TIMEOUT = 30

@app.route('/send-report-via-email', methods=['POST']) # This decorator now correctly sees 'app'
def handle_send_email():
    request_id = base64.b64encode(os.urandom(6)).decode('utf-8')
    print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Received request at /send-report-via-email")

    if not all([SMTP_SERVER_HOST, SMTP_SERVER_PORT, SMTP_SENDER_EMAIL, SMTP_SENDER_PASSWORD]):
        error_msg = "EMAIL_SENDER_API (HF) [{request_id}]: ERROR - SMTP environment variables (Secrets) not fully set."
        print(error_msg)
        return jsonify({"status": "error", "message": "Email server configuration incomplete on the API."}), 500
    
    try:
        SMTP_PORT_INT = int(SMTP_SERVER_PORT)
    except ValueError:
        error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: ERROR - Invalid SMTP_SERVER_PORT: '{SMTP_SERVER_PORT}'."
        print(error_msg)
        return jsonify({"status": "error", "message": "Invalid email server port configured on the API."}), 500

    data = request.json
    if not data:
        print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - No JSON data received.")
        return jsonify({"status": "error", "message": "No data received by email API."}), 400

    recipient_email = data.get('recipient_email')
    # pdf_base64_data = data.get('pdf_base64_data') # Not using these in simplified test
    # pdf_filename = data.get('pdf_filename')       # Not using these in simplified test

    print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Attempting to send to: {recipient_email}")

    if not recipient_email: 
        print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Missing recipient_email in JSON payload.")
        return jsonify({"status": "error", "message": "Missing required data: recipient_email."}), 400

    try:
        # Create a simple plain text message
        simple_msg = MIMEMultipart() 
        simple_msg['From'] = SMTP_SENDER_EMAIL
        simple_msg['To'] = recipient_email
        simple_msg['Subject'] = "EPIC-AMP - Simple Connectivity Test"
        
        simple_body = f"Hello {recipient_email},\n\nThis is a simple plain text email to test SMTP connectivity from the EPIC-AMP Hugging Face Space.\n\nIf you receive this, basic SMTP connection, authentication, and sending are working.\n\nRegards,\nThe EPIC-AMP Test System"
        simple_msg.attach(MIMEText(simple_body, 'plain'))

        print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Preparing to connect to SMTP server {SMTP_SERVER_HOST}:{SMTP_PORT_INT} with timeout {SMTP_CONNECTION_TIMEOUT}s")
        
        server = None
        try:
            if SMTP_PORT_INT == 465: # SSL
                print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Using SMTP_SSL for port 465.")
                server = smtplib.SMTP_SSL(SMTP_SERVER_HOST, SMTP_PORT_INT, timeout=SMTP_CONNECTION_TIMEOUT)
            else: # Standard port, try STARTTLS (e.g., for 587)
                print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Using standard SMTP for port {SMTP_PORT_INT}.")
                server = smtplib.SMTP(SMTP_SERVER_HOST, SMTP_PORT_INT, timeout=SMTP_CONNECTION_TIMEOUT)
            
            server.set_debuglevel(1) 
            print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Connected. Sending EHLO/HELO...")
            server.ehlo()

            if SMTP_PORT_INT == 587:
                print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Port is 587, attempting STARTTLS...")
                server.starttls()
                print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - STARTTLS successful. Re-sending EHLO...")
                server.ehlo()
            
            print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Attempting login with user: {SMTP_SENDER_EMAIL}...")
            server.login(SMTP_SENDER_EMAIL, SMTP_SENDER_PASSWORD)
            print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Login successful. Sending mail to {recipient_email}...")
            server.sendmail(SMTP_SENDER_EMAIL, recipient_email, simple_msg.as_string())
            print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Mail sent successfully.")
        
        finally:
            if server:
                try:
                    print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Quitting SMTP server connection.")
                    server.quit()
                except Exception as e_quit:
                    print(f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Error during server.quit(): {e_quit}")

        success_msg = f"SIMPLE TEST: Email successfully sent to {recipient_email}."
        print(f"EMAIL_SENDER_API (HF) [{request_id}]: {success_msg}")
        return jsonify({"status": "success", "message": success_msg}), 200

    # Keep all the specific exception handling blocks
    except smtplib.SMTPConnectError as e:
        error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - SMTP Connect Error. {e}"
        print(error_msg); traceback.print_exc()
        return jsonify({"status": "error", "message": f"SIMPLIFIED TEST - Could not connect: {e.strerror if hasattr(e, 'strerror') else e}"}), 503
    except smtplib.SMTPHeloError as e: 
        error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - SMTP Helo/Ehlo Error. {e}"
        print(error_msg); traceback.print_exc()
        return jsonify({"status": "error", "message": "SIMPLIFIED TEST - Server HELO/EHLO error."}), 502
    except smtplib.SMTPAuthenticationError as e:
        error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - SMTP Authentication Error. {e}"
        print(error_msg); traceback.print_exc()
        return jsonify({"status": "error", "message": "SIMPLIFIED TEST - Email server authentication failed."}), 500
    except socket.timeout as e:
        error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Socket Timeout. {e}"
        print(error_msg); traceback.print_exc()
        return jsonify({"status": "error", "message": "SIMPLIFIED TEST - Connection timed out."}), 504
    except socket.gaierror as e:
        error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - Address-related error. {e}"
        print(error_msg); traceback.print_exc()
        return jsonify({"status": "error", "message": "SIMPLIFIED TEST - Could not resolve hostname."}), 503
    except OSError as e: 
        if e.errno == 101: 
            error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - OSError [Errno 101] Network is unreachable. {e}"
            print(error_msg); traceback.print_exc()
            return jsonify({"status": "error", "message": "SIMPLIFIED TEST - Network is unreachable from API server."}), 503
        else:
            error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - An OS error occurred: {e}"
            print(error_msg); traceback.print_exc()
            return jsonify({"status": "error", "message": f"SIMPLIFIED TEST - OS Error: {type(e).__name__}"}), 500
    except Exception as e: 
        error_msg = f"EMAIL_SENDER_API (HF) [{request_id}]: SIMPLIFIED TEST - An unexpected error: {e}"
        print(error_msg)
        traceback.print_exc()
        return jsonify({"status": "error", "message": f"SIMPLIFIED TEST - Unexpected API error: {type(e).__name__}"}), 500

# The if __name__ == '__main__': block for local testing:
# On Hugging Face Spaces with Gunicorn, Gunicorn directly imports and runs the 'app' object,
# so this block isn't strictly executed by Gunicorn.
# It's useful if you want to run this script directly with `python email_sender_api.py` for local testing.
# if __name__ == '__main__':
#     # For local testing, set your ENV VARS in this terminal session before running
#     api_port = int(os.environ.get("PORT", 5002)) # Default to 5002 for local test
#     print(f"Starting Email Sender API Service locally on port {api_port}...")
#     # ... (rest of the local startup print messages and app.run) ...
#     app.run(host='0.0.0.0', port=api_port, debug=True)