Newsgroup: it.comp.www.php
Titolo: newsletter

Ho installato una macchina linux equipaggiata con la distribuzione
Fedora.
Devo usarla per spedire una news letter(*no spam*) agli utenti (circa
un migliaio). Ho provato a dare un'occhiata a questa soluzione
http://phpmailer.sourceforge.net/extending.html
 (il primo codice) che
ho implementato.
Sostanzialmente e' un ciclo del tipo:
while ($row = mysql_fetch_array ($result))
in cui spedisce ad ogni giro ad un destinatario.
Quali soluzioni piu' furbe ci sono ?
Conviene spedire al mail con x indirizzi nel campo ccn ?
Conviene spedire a blocchi per "dare fiato" all'smtp server ?
Chiedo a voi una soluzione ... grazie a chi mi dara' una mano
Ciao

 in cui spedisce ad ogni giro ad un destinatario.
Questa è sicuramente la soluzione più semplice dal punto di vista del
codice.
Ma è forse la peggiore, almeno nel tuo caso.
Per il semplice motivo che rischi il timeout dello script.
Potresti mettere tutti gli indirizzi nel campo ccn, ma se sono molti (tuo
caso) non è una buona idea.
La soluzione migliore è quella di spedire "a blocchi", che possono anche
essere unitari.
Puoi farti uno script init.php che recupera il primo email e richiama
sendmail.php passandogli l'indirizzo.
A questo punto sendmail.php invia la mail, recupera il prossimo indirizzo
dal db e richiama se stesso passandogli l'indirizzo.
Questo finchè ci sono indirizzi da processare.
Generalizzando il ragionamento, puoi crearti dei blocchi per inviare più di
1 mail alla volta.
Oppure puoi sempre crearti un processo cron che invia tutto in batch.
Ciao
Marco

dal db e richiama se stesso passandogli l'indirizzo.
Il "richiama se stesso" mi disorienta un pochino,
hai sottomano qualche link o codice che mi spiega ?
intanto cerco...

 hai sottomano qualche link o codice che mi spiega ?
sendmail.php
<?
   // ricevo l'indirizzo mediante $_GET[email]
   // faccio quello che devo fare
   // alla fine di tutto recupero il nuovo indirizzo
   $email = ...
   if(// non è l'ultimo indirizzo)
      // richiamo me stesso
      header("location: $PHP_SELF?email=$email");
   else
      // ho finito l'invio e stampo l'output
      header("location: output.php");
?>
Ciao
Marco

Visto che mi dai una mano ti spego bene quello che faccio
(semplifico):
Ho un db mysql esterno all'azienda in cui sono memorizzati degli
articoli (id_articolo, testo).
Ho una macchina linux in azienda.
La segretaria apre una paginetta in cui inserisce dieci codici di
articoli.
Il codice php, genera un file xml, carica un foglio di stile, lo
applica e salva il risultato in un file html.
-- fine generazione newsletter --
Da un'altra pagina effettuo la spedizione, carico il file html e per
ogni email (estratta da un db mysql) lo spedisco, la query non estrae
solo l'indirizzo email ma anche nome e cognome cosi' che la email e' +
personalizzata.
Ecco quello che devo fare, l'unica cosa che manca e' la spedizione che
nel mio caso e' il punto piu' delicato dato che devo spedire a 2000 /
4000 utenti.
La spedizione per ora e' gestita da una societa' esterna e in
previsione di "risparmiare" si e' pensato di farlo noi.
Ciao e grazie per i passati e spero futuri aiuti.
Alberto


 personalizzata.
Ok, quindi partiamo dal fatto che hai un file da spedire in allegato a TANTI
utenti.
Tralasciando il fatto che potresti usare altre soluzioni in alternativa
all'allegato (vedi 3D "inviare una pagina in email" del 28-01), ecco come
potresti fare.
Do per scontato che nella tabella utenti ci sia una chiave primaria numerica
che chiamerò "id", per semplicità.
Invocherai lo script semplicemente chiamando "sendmail.php".
// sendmail.php
// verifichi l'esistenza della variabile $_GET[id]
// se non c'è significa che sei al primo invio
if(!isset($_GET[id]))
    $primo = true;
else
    $primo = false;
// a questo punto devi recuperare i dati dell'utente
if($primo){
    // recuperi 2 utenti, il corrente e il successivo
    $rs = mysql_query("SELECT * FROM utenti ORDER BY id LIMIT 0,2");
    // recuperi i dati del primo utente usando le tue variabili
    ....
    // poi recuperi l'id dell'utente successivo
    $id = mysql_result($rs,2,"id");
}
else{
    // recuperi 2 utenti, il corrente e il successivo
    $rs = mysql_query("SELECT * FROM utenti WHERE id >= $_GET[id] ORDER BY
id LIMIT 0,2");
    // recuperi i dati del primo utente usando le tue variabili
    ....
    // poi recuperi l'id dell'utente successivo
    $id = mysql_result($rs,2,"id");
}
// alla fine richiami passando l'id del prossimo utente
header("location: $PHP_SELF?id=$id");
Nel codice sopra non ho inserito nessun controllo di errore e nessun
controllo sulla fine dell'invio. Lascio a te questo compito.
Ciao
Marco

 essere unitari.
Questa e' la soluzione che avevo adottato tempo fa, poi avevamo sospeso il
servizio di newsletter perche' successivamente ad un cambio di server a
molti utenti arrivavano le e-mail doppie o triple e avevamo ricevuto
parecchie lamentele.
Ora, volendo riattivare il servizio, il mio dubbio e': se il file con lo
script lo richiamo dal crontab, non c'e' un problema di time-out di
esecuzione, giusto?
Posso quindi effettuare la query su tutta la tabella senza impostare dei
limiti. Sbaglio?
Grazie
Max


penso proprio che tu sbagli, in quanto cmq la pagina php deve essere 
processata con le stesse "impostazioni" di una normale chiamata http
io invio 300 email a botta ogni 5 minuti nelle ore notturne di minor 
traffico tramite crontab(questo tool è una libidine assurda ^_^)
cmq esiste anche la funzione set_timeout, per un numero basso di email 
basta agire su questo valore
dalle mie passate esperienze ricordo di essere riuscito a spedire senza 
problemi oltre 3000 email a botta agendo solo su quel valore

ok provo grazie

>    $rs = mysql_query("SELECT * FROM utenti WHERE id >= $_GET[id] ORDER BY
= mi suona male non deve essere solo >

 = mi suona male non deve essere solo >
No, perchè il valore $_GET[id] che ricevi è quello dell'utente a cui spedire
la mail.
Quindi dal db devi recuperare anche i suoi dati e quelli del successivo.
Ciao
Marco

 processata con le stesse "impostazioni" di una normale chiamata http
Ok grazie, peccato.
Purtroppo sono due tabelle con circa 8000 indirizzi per tabella, inviavo in
blocchi da 500 per volta.
Adottero' la stessa strategia.
Max

ora provo a riscrivere lo script.
Una domanda...
dato che la spedizione la schedulero' con crontab la logica dello
script che mi hai proposto rimane la stessa ?
L'errore del timeout vale anche se lancio lo script da linea comando ?
Il GET funziona anche se lancio lo script da linea comando ?

 Il GET funziona anche se lancio lo script da linea comando ?
Dunque, cron manda in esecuzione un programma.
Per lanciare uno script php da linea di comando, devi avere php
opportunamente compilato per fare ciò (ora non ricordo i dettagli).
Io non mi riferivo ad avviare uno script php con cron, ma realizzare una
piccola applicazione che fecesse gli invii.
Per usare php, dovresti in qualche modo generare una chiamata http al web
server. Ma in questo modo rimarrebbe il problema del timeout.
Ciao
Marco

 Marco
Andrea

> per agire sul timeout funzione set_timeout(secondi)
La funzione sarebbe set_time_limit(sec).
http://it.php.net/manual/it/function.set-time-limit.php
Comunque occhio alla nota:
set_time_limit() has no effect when PHP is running in safe mode. There is no
workaround other than turning off safe mode or changing the time limit in
the php.ini.
Ciao
Marco

>header("location: $PHP_SELF?id=$id");
questo pero' implica che tutte le connessioni al db mysql vengano
chiuse e riaperte ad ogni giro ?

un'altra cosa che chiedo a tutti.
per spedire la mail io uno la classe phpmailer e il codice che
personalizzo e' :
require("class.phpmailer.php");
$mail = new phpmailer();
$mail->From     = "
mioe...@dominio.it
";
$mail->FromName = "X_5";
$mail->Subject = "X_5";
$mail->IsSMTP();
$mail->Host     = "
mail.dominioooo.it
;";
$mail->IsHTML(true);
$mail->Body    = $body;
 $mail->AddAddress($row["email"], $row["nome"]);
...
        if(!$mail->Send())
pero' per spedire una semplice mail forse e' troppo pesante (la classe
e' circa un migliaio di righe!). Posso usare una soluzione piu' snella
usando direttamente la funzione di mysql mai() ???
Come specifico il mio smtp server nei paremetri della funzione ?

 Come specifico il mio smtp server nei paremetri della funzione ?
http://it.php.net/manual/it/function.mail.php
E' tutto scritto lě.
Inoltre l'SMTP lo setti in php.ini non nella funzione.
Ciao
Marco

 chiuse e riaperte ad ogni giro ?
Le connessioni vengono sempre aperte e chiuse nell'ambito di vita dello
script.
A meno che tu non usi le connessioni persistenti, se abilitate dal provider,
ma non sono il massimo in termine di prestazioni.
Ciao
Marco

per il primo punto hai ragione, con linux e' ok se uso:
ini_set("SMTP",........

 ini_set("SMTP",........
Ma se la macchina è la tua, perchè non la configuri direttamente nel
php.ini?
Ciao
Marco