diff --git a/README.md b/README.md index a001a26..1d55aec 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,10 @@ Piattaforma completa per vendere videolezioni e lezioni live di Pilates. Svilupp ### Requisiti - **PHP** 7.4 o superiore (8.0+ raccomandato) - **MySQL** 5.7 o superiore (o MariaDB 10.3+) +- **Python** 3.6 o superiore (per invio email SMTP) - **Web Server** (Apache, Nginx, o PHP built-in server per sviluppo) - **Account PayPal** Sandbox (per test) o Business (per produzione) - **FFmpeg** (opzionale, per conversione automatica video in MP4) -- **PHP** 7.4 o superiore -- **MySQL** 5.7 o superiore (o MariaDB 10.3+) -- **Web Server** (Apache, Nginx, o PHP built-in server per sviluppo) -- **Account PayPal** Sandbox (per test) o Business (per produzione) ### Passo 1: Copia i File ```bash @@ -115,7 +112,7 @@ define('SECRET_KEY', 'CAMBIA-QUESTA-CHIAVE-CON-STRINGA-CASUALE-LUNGA-E-SICURA'); ``` #### Email SMTP con Gmail ⭐ **IMPORTANTE** -Per inviare email (recupero password), configura Gmail SMTP: +Per inviare email (recupero password, registrazione), configura Gmail SMTP: 1. **Abilita verifica 2 fattori** sul tuo account Gmail 2. Vai su [Password per le app](https://myaccount.google.com/apppasswords) @@ -127,14 +124,30 @@ In `includes/config.php`: ```php define('USE_SMTP', true); // Attiva SMTP define('SMTP_HOST', 'smtp.gmail.com'); -define('SMTP_PORT', 587); +define('SMTP_PORT', 587); // 587 per TLS, 465 per SSL define('SMTP_USERNAME', 'tua-email@gmail.com'); // La tua Gmail define('SMTP_PASSWORD', 'abcd efgh ijkl mnop'); // Password app (16 caratteri) -define('SMTP_ENCRYPTION', 'tls'); +define('SMTP_ENCRYPTION', 'tls'); // tls (porta 587) o ssl (porta 465) ``` ⚠️ **Non usare la password normale di Gmail**, usa solo la password applicazione! +**Sistema di invio email:** +- Le email vengono inviate tramite script Python (`send_email.py`) +- Python 3.6+ deve essere installato sul server +- Lo script legge automaticamente le credenziali da `config.php` +- Più affidabile e stabile rispetto a SMTP nativo PHP + +Verifica installazione Python: +```bash +python3 --version +``` + +Se Python non è installato: +- **Ubuntu/Debian**: `sudo apt install python3` +- **CentOS/RHEL**: `sudo yum install python3` +- **Windows**: Scarica da [python.org](https://www.python.org/downloads/) + #### PayPal Sandbox (per Test) 1. Vai su [PayPal Developer](https://developer.paypal.com/) 2. Accedi con il tuo account PayPal @@ -520,11 +533,39 @@ Crea `.htaccess` nella cartella `includes/`: - La piattaforma è già aggiornata per gestire valori null - Se vedi ancora warning, verifica che tutti i file siano aggiornati -### Reset Password non funziona -- Verifica che le email vengano inviate correttamente -- Configura SMTP in `config.php` se `mail()` non funziona -- Il token scade dopo 1 ora per sicurezza -- Controlla che la tabella `users` abbia i campi `reset_token` e `reset_expires` +### Reset Password / Email non funzionano +- Verifica che Python 3 sia installato: `python3 --version` +- Controlla credenziali SMTP in `config.php` +- Verifica che `send_email.py` abbia permessi esecuzione +- Testa invio dal profilo admin: pulsante "🧪 Testa Invio Email" +- Il token reset scade dopo 1 ora per sicurezza +- Controlla log errori PHP per dettagli (`error_log()`) + +**Test manuale script Python:** +```bash +cd /path/to/pilates-platform +python3 send_email.py '{"to":"test@esempio.com","subject":"Test","html":"

Test email

"}' +``` + +**Errori comuni:** +- `python3: command not found` → Installa Python 3 +- `Authentication failed` → Verifica password applicazione Gmail +- `Connection refused` → Controlla porta (587 per TLS, 465 per SSL) +- `Script not found` → Verifica che `send_email.py` esista nella root del progetto +- `Permission denied` → Su Linux: `chmod +x send_email.py` +- Il token reset scade dopo 1 ora per sicurezza +- Controlla log errori PHP per dettagli + +**Test manuale script Python:** +```bash +cd /path/to/pilates-platform +python3 send_email.py '{"to":"test@esempio.com","subject":"Test","html":"

Test email

"}' +``` + +**Errori comuni:** +- `python3: command not found` → Installa Python 3 +- `Authentication failed` → Verifica password applicazione Gmail +- `Connection refused` → Controlla porta (587 per TLS, 465 per SSL) --- @@ -550,6 +591,7 @@ pilates-platform/ ├── process_payment.php # Elabora pagamento PayPal ├── stream_video.php # Streaming protetto video (verifica permessi) ├── convert_videos.php # Conversione batch video in MP4 H.264 +├── send_email.py # Script Python per invio email SMTP ├── test_password.php # Utility test hash password (debug) ├── test_email.php # Utility test invio email SMTP (debug) └── README.md # Questo file diff --git a/includes/config.php b/includes/config.php index b070f5b..7f78668 100644 --- a/includes/config.php +++ b/includes/config.php @@ -74,7 +74,9 @@ define('MAIL_FROM_NAME', 'Pilates Studio'); define('USE_SMTP', true); // Imposta false per usare mail() PHP di base // Impostazioni SMTP - Gmail +// NOTA: Le email vengono inviate tramite script Python (send_email.py) per maggiore affidabilità // Per Gmail: usa password applicazione da https://myaccount.google.com/apppasswords +// Requisito: Python 3.6+ installato sul server (testa con: python3 --version) define('SMTP_HOST', 'smtp.gmail.com'); define('SMTP_PORT', 587); define('SMTP_USERNAME', 'pyco.networking@gmail.com'); // Inserisci la tua email Gmail diff --git a/includes/functions.php b/includes/functions.php index ac30bdb..ff6d760 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -433,7 +433,7 @@ function send_email($to, $subject, $message) { } /** - * Invia email tramite SMTP (Gmail) + * Invia email tramite script Python * * @param string $to Email destinatario * @param string $subject Oggetto email @@ -441,6 +441,53 @@ function send_email($to, $subject, $message) { * @return bool True se inviata, false altrimenti */ function send_smtp_email($to, $subject, $message) { + try { + // Prepara dati JSON per lo script Python + $data = json_encode([ + 'to' => $to, + 'subject' => $subject, + 'html' => $message + ], JSON_UNESCAPED_UNICODE); + + // Percorso dello script Python + $script_path = __DIR__ . '/../send_email.py'; + + // Verifica che lo script esista + if (!file_exists($script_path)) { + error_log("Email Error: Script send_email.py non trovato"); + return false; + } + + // Esegui script Python + $command = 'python3 ' . escapeshellarg($script_path) . ' ' . escapeshellarg($data) . ' 2>&1'; + exec($command, $output, $return_code); + + // Parse risposta JSON + $result = json_decode(implode("\n", $output), true); + + if ($return_code === 0 && isset($result['success']) && $result['success']) { + return true; + } else { + $error_msg = isset($result['error']) ? $result['error'] : 'Errore sconosciuto'; + error_log("Email Error: " . $error_msg); + return false; + } + + } catch (Exception $e) { + error_log("Email Error: " . $e->getMessage()); + return false; + } +} + +/** + * Invia email tramite SMTP PHP nativo (deprecato - usa send_smtp_email) + * + * @param string $to Email destinatario + * @param string $subject Oggetto email + * @param string $message Corpo email (HTML) + * @return bool True se inviata, false altrimenti + */ +function send_smtp_email_legacy($to, $subject, $message) { try { // Connessione al server SMTP con supporto SSL/TLS $context = stream_context_create([ diff --git a/send_email.py b/send_email.py new file mode 100644 index 0000000..25e04c9 --- /dev/null +++ b/send_email.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +""" +Script Python per invio email SMTP +Legge le credenziali da config.php e invia email tramite Gmail +""" + +import sys +import json +import re +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from pathlib import Path + +def parse_php_config(config_path): + """Estrae le configurazioni SMTP dal file config.php""" + config = {} + + try: + with open(config_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Estrai le define con regex + patterns = { + 'SMTP_HOST': r"define\('SMTP_HOST',\s*'([^']+)'\)", + 'SMTP_PORT': r"define\('SMTP_PORT',\s*(\d+)\)", + 'SMTP_USERNAME': r"define\('SMTP_USERNAME',\s*'([^']+)'\)", + 'SMTP_PASSWORD': r"define\('SMTP_PASSWORD',\s*'([^']+)'\)", + 'SMTP_ENCRYPTION': r"define\('SMTP_ENCRYPTION',\s*'([^']+)'\)", + 'MAIL_FROM': r"define\('MAIL_FROM',\s*'([^']+)'\)", + 'MAIL_FROM_NAME': r"define\('MAIL_FROM_NAME',\s*'([^']+)'\)", + } + + for key, pattern in patterns.items(): + match = re.search(pattern, content) + if match: + value = match.group(1) + # Converti porta in intero + if key == 'SMTP_PORT': + config[key] = int(value) + else: + config[key] = value + + return config + except Exception as e: + print(json.dumps({ + 'success': False, + 'error': f'Errore lettura config.php: {str(e)}' + })) + sys.exit(1) + +def send_email(to_email, subject, html_body, config): + """Invia email tramite SMTP""" + try: + # Crea messaggio + msg = MIMEMultipart('alternative') + msg['From'] = f"{config['MAIL_FROM_NAME']} <{config['MAIL_FROM']}>" + msg['To'] = to_email + msg['Subject'] = subject + + # Aggiungi corpo HTML + html_part = MIMEText(html_body, 'html', 'utf-8') + msg.attach(html_part) + + # Connetti al server SMTP + if config['SMTP_ENCRYPTION'] == 'ssl': + # SSL diretto (porta 465) + server = smtplib.SMTP_SSL(config['SMTP_HOST'], config['SMTP_PORT'], timeout=30) + else: + # TLS con STARTTLS (porta 587) + server = smtplib.SMTP(config['SMTP_HOST'], config['SMTP_PORT'], timeout=30) + server.ehlo() + server.starttls() + server.ehlo() + + # Login + server.login(config['SMTP_USERNAME'], config['SMTP_PASSWORD']) + + # Invia email + server.send_message(msg) + server.quit() + + return { + 'success': True, + 'message': f'Email inviata con successo a {to_email}' + } + + except smtplib.SMTPAuthenticationError as e: + return { + 'success': False, + 'error': f'Autenticazione SMTP fallita: {str(e)}' + } + except smtplib.SMTPException as e: + return { + 'success': False, + 'error': f'Errore SMTP: {str(e)}' + } + except Exception as e: + return { + 'success': False, + 'error': f'Errore generico: {str(e)}' + } + +def main(): + """Funzione principale""" + if len(sys.argv) < 2: + print(json.dumps({ + 'success': False, + 'error': 'Uso: python send_email.py ' + })) + sys.exit(1) + + try: + # Parse input JSON + data = json.loads(sys.argv[1]) + + if 'to' not in data or 'subject' not in data or 'html' not in data: + print(json.dumps({ + 'success': False, + 'error': 'Parametri mancanti: to, subject, html sono obbligatori' + })) + sys.exit(1) + + # Leggi configurazione + script_dir = Path(__file__).parent + config_path = script_dir / 'includes' / 'config.php' + config = parse_php_config(config_path) + + # Invia email + result = send_email(data['to'], data['subject'], data['html'], config) + print(json.dumps(result)) + + sys.exit(0 if result['success'] else 1) + + except json.JSONDecodeError as e: + print(json.dumps({ + 'success': False, + 'error': f'JSON non valido: {str(e)}' + })) + sys.exit(1) + except Exception as e: + print(json.dumps({ + 'success': False, + 'error': f'Errore: {str(e)}' + })) + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/test_python.py b/test_python.py new file mode 100644 index 0000000..ca58d54 --- /dev/null +++ b/test_python.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +""" +Test rapido per verificare che Python e le librerie necessarie siano installate +""" + +import sys + +def test_imports(): + """Verifica che tutte le librerie necessarie siano disponibili""" + required_modules = { + 'smtplib': 'Libreria SMTP (built-in)', + 'email': 'Libreria email (built-in)', + 'json': 'Libreria JSON (built-in)', + 're': 'Libreria regex (built-in)', + 'pathlib': 'Libreria path (built-in)' + } + + print("🐍 Test Python per Pilates Platform") + print(f" Python version: {sys.version}") + print() + + all_ok = True + + for module, description in required_modules.items(): + try: + __import__(module) + print(f"✅ {module:12} - {description}") + except ImportError: + print(f"❌ {module:12} - MANCANTE!") + all_ok = False + + print() + + if all_ok: + print("✅ Tutte le librerie necessarie sono installate!") + print("✅ Python è pronto per inviare email.") + return 0 + else: + print("❌ Alcune librerie sono mancanti. Installa Python 3.6+") + return 1 + +if __name__ == '__main__': + sys.exit(test_imports())