Spaces:
Sleeping
Sleeping
| 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__) | |
| 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) |