fix send mail with python script
This commit is contained in:
66
README.md
66
README.md
@@ -49,13 +49,10 @@ Piattaforma completa per vendere videolezioni e lezioni live di Pilates. Svilupp
|
|||||||
### Requisiti
|
### Requisiti
|
||||||
- **PHP** 7.4 o superiore (8.0+ raccomandato)
|
- **PHP** 7.4 o superiore (8.0+ raccomandato)
|
||||||
- **MySQL** 5.7 o superiore (o MariaDB 10.3+)
|
- **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)
|
- **Web Server** (Apache, Nginx, o PHP built-in server per sviluppo)
|
||||||
- **Account PayPal** Sandbox (per test) o Business (per produzione)
|
- **Account PayPal** Sandbox (per test) o Business (per produzione)
|
||||||
- **FFmpeg** (opzionale, per conversione automatica video in MP4)
|
- **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
|
### Passo 1: Copia i File
|
||||||
```bash
|
```bash
|
||||||
@@ -115,7 +112,7 @@ define('SECRET_KEY', 'CAMBIA-QUESTA-CHIAVE-CON-STRINGA-CASUALE-LUNGA-E-SICURA');
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Email SMTP con Gmail ⭐ **IMPORTANTE**
|
#### 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
|
1. **Abilita verifica 2 fattori** sul tuo account Gmail
|
||||||
2. Vai su [Password per le app](https://myaccount.google.com/apppasswords)
|
2. Vai su [Password per le app](https://myaccount.google.com/apppasswords)
|
||||||
@@ -127,14 +124,30 @@ In `includes/config.php`:
|
|||||||
```php
|
```php
|
||||||
define('USE_SMTP', true); // Attiva SMTP
|
define('USE_SMTP', true); // Attiva SMTP
|
||||||
define('SMTP_HOST', 'smtp.gmail.com');
|
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_USERNAME', 'tua-email@gmail.com'); // La tua Gmail
|
||||||
define('SMTP_PASSWORD', 'abcd efgh ijkl mnop'); // Password app (16 caratteri)
|
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!
|
⚠️ **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)
|
#### PayPal Sandbox (per Test)
|
||||||
1. Vai su [PayPal Developer](https://developer.paypal.com/)
|
1. Vai su [PayPal Developer](https://developer.paypal.com/)
|
||||||
2. Accedi con il tuo account PayPal
|
2. Accedi con il tuo account PayPal
|
||||||
@@ -520,11 +533,39 @@ Crea `.htaccess` nella cartella `includes/`:
|
|||||||
- La piattaforma è già aggiornata per gestire valori null
|
- La piattaforma è già aggiornata per gestire valori null
|
||||||
- Se vedi ancora warning, verifica che tutti i file siano aggiornati
|
- Se vedi ancora warning, verifica che tutti i file siano aggiornati
|
||||||
|
|
||||||
### Reset Password non funziona
|
### Reset Password / Email non funzionano
|
||||||
- Verifica che le email vengano inviate correttamente
|
- Verifica che Python 3 sia installato: `python3 --version`
|
||||||
- Configura SMTP in `config.php` se `mail()` non funziona
|
- Controlla credenziali SMTP in `config.php`
|
||||||
- Il token scade dopo 1 ora per sicurezza
|
- Verifica che `send_email.py` abbia permessi esecuzione
|
||||||
- Controlla che la tabella `users` abbia i campi `reset_token` e `reset_expires`
|
- 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":"<p>Test email</p>"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**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":"<p>Test email</p>"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**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
|
├── process_payment.php # Elabora pagamento PayPal
|
||||||
├── stream_video.php # Streaming protetto video (verifica permessi)
|
├── stream_video.php # Streaming protetto video (verifica permessi)
|
||||||
├── convert_videos.php # Conversione batch video in MP4 H.264
|
├── 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_password.php # Utility test hash password (debug)
|
||||||
├── test_email.php # Utility test invio email SMTP (debug)
|
├── test_email.php # Utility test invio email SMTP (debug)
|
||||||
└── README.md # Questo file
|
└── README.md # Questo file
|
||||||
|
|||||||
@@ -74,7 +74,9 @@ define('MAIL_FROM_NAME', 'Pilates Studio');
|
|||||||
define('USE_SMTP', true); // Imposta false per usare mail() PHP di base
|
define('USE_SMTP', true); // Imposta false per usare mail() PHP di base
|
||||||
|
|
||||||
// Impostazioni SMTP - Gmail
|
// 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
|
// 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_HOST', 'smtp.gmail.com');
|
||||||
define('SMTP_PORT', 587);
|
define('SMTP_PORT', 587);
|
||||||
define('SMTP_USERNAME', 'pyco.networking@gmail.com'); // Inserisci la tua email Gmail
|
define('SMTP_USERNAME', 'pyco.networking@gmail.com'); // Inserisci la tua email Gmail
|
||||||
|
|||||||
@@ -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 $to Email destinatario
|
||||||
* @param string $subject Oggetto email
|
* @param string $subject Oggetto email
|
||||||
@@ -441,6 +441,53 @@ function send_email($to, $subject, $message) {
|
|||||||
* @return bool True se inviata, false altrimenti
|
* @return bool True se inviata, false altrimenti
|
||||||
*/
|
*/
|
||||||
function send_smtp_email($to, $subject, $message) {
|
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 {
|
try {
|
||||||
// Connessione al server SMTP con supporto SSL/TLS
|
// Connessione al server SMTP con supporto SSL/TLS
|
||||||
$context = stream_context_create([
|
$context = stream_context_create([
|
||||||
|
|||||||
149
send_email.py
Normal file
149
send_email.py
Normal file
@@ -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 <json_data>'
|
||||||
|
}))
|
||||||
|
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()
|
||||||
43
test_python.py
Normal file
43
test_python.py
Normal file
@@ -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())
|
||||||
Reference in New Issue
Block a user