email / app.py
bigbossmonster's picture
Update app.py
8b46509 verified
import nest_asyncio
import re
import os
from flask import Flask
from protonmail import ProtonMail, exceptions
# REMOVED webbrowser and threading as they are not needed on the server
# Apply the patch needed for asyncio
nest_asyncio.apply()
# --- Configuration ---
# SECURE: We now read your credentials from Hugging Face Space Secrets
PROTONMAIL_USERNAME = "totalleecher@proton.me"
PROTONMAIL_PASSWORD = "htz175039"
# --- 1. The Core Proton Mail Logic ---
def find_verification_codes():
"""Logs into Proton Mail and extracts verification codes."""
pm = None
found_codes = []
if not PROTONMAIL_USERNAME or not PROTONMAIL_PASSWORD:
print("ERROR: Credentials not found in Space Secrets.")
return [{"sender": "Configuration Error", "subject": "Please set secrets in your Space settings.", "code": "!!!"}]
try:
pm = ProtonMail()
print("Attempting to log in...")
pm.login(PROTONMAIL_USERNAME, PROTONMAIL_PASSWORD)
print("Login successful!")
print("Fetching latest emails...")
messages = pm.get_messages(limit=15)
keywords = ['verify', 'code', 'authenticate', 'verification']
for msg in messages:
is_verification_email = any(keyword in msg.subject.lower() for keyword in keywords) or \
any(keyword in msg.sender.name.lower() for keyword in keywords)
if is_verification_email:
code = None
subject_match = re.search(r'\d{6}', msg.subject)
if subject_match:
code = subject_match.group(0)
else:
body_match = re.search(r'\d{6}', msg.body)
if body_match:
code = body_match.group(0)
if code:
found_codes.append({
"sender": msg.sender.name,
"subject": msg.subject,
"code": code
})
except exceptions.ProtonMailException as e:
print(f"A Proton Mail error occurred: {e}")
return [{"sender": "Error", "subject": "Could not log in or fetch mail.", "code": "Error"}]
except Exception as e:
print(f"A general error occurred: {e}")
return [{"sender": "Error", "subject": "An unexpected error occurred.", "code": "Error"}]
finally:
if pm and hasattr(pm, 'user') and pm.user:
print("Session will time out automatically.")
pass
unique_codes = list({v['code']: v for v in found_codes}.values())
return sorted(unique_codes, key=lambda x: x['subject'], reverse=True)[:5]
# --- 2. The HTML, CSS, and JavaScript as Python Strings ---
def build_html_page(codes):
"""Generates the full HTML page with embedded CSS and JS."""
cards_html = ""
if codes:
for item in codes:
cards_html += f"""
<div class="card">
<div class="details">
<p><strong>From:</strong> {item['sender']}</p>
<p><strong>Subject:</strong> {item['subject']}</p>
</div>
<div class="code-section">
<span class="code-display">{item['code']}</span>
<button class="copy-btn" data-code="{item['code']}">Copy</button>
</div>
</div>
"""
else:
cards_html = '<p class="no-codes">No new verification codes found.</p>'
# The entire page is built using an f-string
return f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Verification Codes</title>
<style>
body {{
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #f0f2f5; color: #333; display: flex;
justify-content: center; align-items: flex-start;
min-height: 100vh; margin: 0; padding-top: 40px;
}}
.container {{
background-color: #ffffff; padding: 20px 40px; border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); width: 100%; max-width: 600px;
}}
h1 {{ text-align: center; color: #1c1e21; }}
p {{ text-align: center; color: #606770; }}
hr {{ border: none; border-top: 1px solid #dddfe2; margin: 20px 0; }}
.card {{
display: flex; justify-content: space-between; align-items: center;
padding: 15px; border: 1px solid #dddfe2;
border-radius: 8px; margin-bottom: 15px;
}}
.details p {{ margin: 2px 0; text-align: left; font-size: 0.9em; }}
.details p strong {{ color: #333; }}
.code-section {{ display: flex; align-items: center; gap: 15px; }}
.code-display {{ font-size: 1.8em; font-weight: bold; color: #007bff; letter-spacing: 2px; }}
.copy-btn {{
background-color: #007bff; color: white; border: none; border-radius: 6px;
padding: 10px 15px; font-size: 0.9em; font-weight: bold;
cursor: pointer; transition: background-color 0.2s;
}}
.copy-btn:hover {{ background-color: #0056b3; }}
.no-codes {{ text-align: center; color: #888; padding: 20px; }}
</style>
</head>
<body>
<div class="container">
<h1>Proton Mail Verification Codes</h1>
<p>Showing the latest unique codes found. Refresh the page to check again.</p>
<hr>
{cards_html}
</div>
<script>
// --- CORRECTED JavaScript with escaped curly braces ---
document.addEventListener('DOMContentLoaded', () => {{
const copyButtons = document.querySelectorAll('.copy-btn');
copyButtons.forEach(button => {{
button.addEventListener('click', () => {{
const codeToCopy = button.dataset.code;
navigator.clipboard.writeText(codeToCopy).then(() => {{
const originalText = button.textContent;
button.textContent = 'Copied!';
setTimeout(() => {{ button.textContent = originalText; }}, 2000);
}}).catch(err => console.error('Failed to copy text: ', err));
}});
}});
}});
</script>
</body>
</html>
"""
# --- 3. The Flask Web Server ---
app = Flask(__name__)
@app.route('/')
def index():
"""Main page route that fetches codes and builds the HTML."""
codes = find_verification_codes()
return build_html_page(codes)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=7860)