Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > it.comp.www.php > #22091 > unrolled thread

mail() fallisce solo se tutti i destinatari vengono respinti?

Started byUmberto Salsi <salsi@icosaedro.it>
First post2018-06-12 13:16 +0200
Last post2018-06-18 12:05 +0200
Articles 4 — 2 participants

Back to article view | Back to it.comp.www.php


Contents

  mail() fallisce solo se tutti i destinatari vengono respinti? Umberto Salsi <salsi@icosaedro.it> - 2018-06-12 13:16 +0200
    Re: mail() fallisce solo se tutti i destinatari vengono respinti? Alessandro Pellizzari <shuriken@amiran.it> - 2018-06-12 12:35 +0100
      Re: mail() fallisce solo se tutti i destinatari vengono respinti? Umberto Salsi <salsi@icosaedro.it> - 2018-06-13 11:24 +0200
    Re: mail() fallisce solo se tutti i destinatari vengono respinti? Umberto Salsi <salsi@icosaedro.it> - 2018-06-18 12:05 +0200

#22091 — mail() fallisce solo se tutti i destinatari vengono respinti?

FromUmberto Salsi <salsi@icosaedro.it>
Date2018-06-12 13:16 +0200
Subjectmail() fallisce solo se tutti i destinatari vengono respinti?
Message-ID<pfoa20$66j$1@gioia.aioe.org>
Sto esplorando l'affidabilità di mail() per l'invio "massivo" a due o
più destinatari. Sebbene il manuale non lo dica, sembra che:

1. Non si può avere retroazione del motivo del fallimento.

2. Se fallisce, nessun messaggio viene inviato.

3. Sa ha successo, QUALCUNO dei destinatari potrebbe ricevere il
messaggio.

4. Se c'è un solo destinatario (To, Cc e Bcc) e questo viene respinto
dal server SMTP, allora mail() fallisce.

5. Se ci sono due o più destinatari (To, Cc e Bcc) e almeno uno di
questi viene accettato, allora mail() ha successo; non c'è modo di
sapere quali destinatari sono stati respinti se non andando a vedere i
log files del server o aspettanto i bounce.

Test code minimalista delle varie combinazioni che compila il campo To
(ma con Cc e Bcc sembra che le cose vadano nello stesso modo):

<?php
error_reporting(-1);
echo "PHP version: ", PHP_VERSION, "\n";
$good = "test@icosaedro.it";
$bad  = "<<<>>>";
$unknown = "DoesNotExist@DoesNotExists";

$attempts = [
        $good,
        $bad,
        $unknown,
        "$good, $bad",
        "$good, $unknown",
        "$bad, $unknown"
];

foreach($attempts as $to){
        echo "Sending to $to:\n";
        var_dump( mail($to, "This message sent to $to", "Testing.") );
        var_dump( error_get_last() );
}
?>

Esito del codice precedente, commentato:

PHP version: 7.2.4
Sending to test@icosaedro.it:
bool(true)   {atteso}
NULL
Sending to <<<>>>:
bool(false)   {atteso}
NULL         {peccato che non si abbia il motivo del fallimento}
Sending to DoesNotExist@DoesNotExists:
bool(true)   {evidentemente il mio SMTP non fa una verifica dominio preventiva, ok}
NULL
Sending to test@icosaedro.it, <<<>>>:
bool(true)   {inaspettato, ma il primo destinatario riceve}
NULL
Sending to test@icosaedro.it, DoesNotExist@DoesNotExists:
bool(true)   {a questo punto è il risultato atteso}
NULL
Sending to <<<>>>, DoesNotExist@DoesNotExists:
bool(true)   {a questo punto, esito atteso}
NULL
You have new mail in /var/mail/test {sono arrivati i bounce!}

Sto cercando di irrobustire il metodo di trasporto mail() di PHPMailer,
ma senza successo.

Sono corrette le mie deduzioni?

C'è un altro modo di sapere perché mail() fallisce?

O bisogna proprio inviare un email alla volta?

Ciao,
 ___ 
/_|_\  Umberto Salsi
\/_\/  www.icosaedro.it

[toc] | [next] | [standalone]


#22092

FromAlessandro Pellizzari <shuriken@amiran.it>
Date2018-06-12 12:35 +0100
Message-ID<fo9pfiF2rn5U1@mid.individual.net>
In reply to#22091
On 12/06/2018 12:16, Umberto Salsi wrote:

> Sto esplorando l'affidabilità di mail() per l'invio "massivo" a due o
> più destinatari. Sebbene il manuale non lo dica, sembra che:

Dipende tutto dal server mail sottostante.

mail() non fa altro che accodare una mail nel server SMTP che hai 
configurato. In Windows mi pare lo faccia via SMTP stesso, mentre in 
Linux chiama il binario di sendmail (o l'equivalente fornito da postfix. 
Non so come funzioni per exim).

Cosa succede poi dipende tutto da quello.

Se il binario/SMTP invocato torna un codice di errore che mail() 
riconosce, puoi avere un minimo di feedback, altrimenti è semplicemente 
"fire and forget".

L'unico modo di irrobustirlo è di non usare mail(), ma di implementare 
un client SMTP e gestire la comunicazione col server, cosa che mi pare 
Zend Mail e altre librerie fanno.

Bye.

[toc] | [prev] | [next] | [standalone]


#22093

FromUmberto Salsi <salsi@icosaedro.it>
Date2018-06-13 11:24 +0200
Message-ID<pfqnsr$6uq$1@gioia.aioe.org>
In reply to#22092
Alessandro Pellizzari <shuriken@amiran.it> wrote:

> Dipende tutto dal server mail sottostante.
> 
> mail() non fa altro che accodare una mail nel server SMTP che hai 
> configurato. In Windows mi pare lo faccia via SMTP stesso, mentre in 
> Linux chiama il binario di sendmail (o l'equivalente fornito da postfix. 
> Non so come funzioni per exim).

Con exim se invio a un solo destinatario e il suo indirizzo viene
respinto dal server, mail() fallisce e tutto va bene.  Invece, se
ci sono 2 o più destinatari dove almeno uno viene accettato, allora
mail() ha successo e io non sò quali sono stati accettati e quali no;
fortunatamente exim ritorna in bounce sia gli indirizzi respinti, sia
gli invii che sono falliti per altri motivi, ma temo che la cosa dipenda
dal server specifico e dalla sua configurazione.

Morale: con mail() bisogna inviare a un solo destinatario alla volta
perché non è garantito che vengano poi segnalati gli indirizzi respinti
in bounce.

> Cosa succede poi dipende tutto da quello.
> 
> Se il binario/SMTP invocato torna un codice di errore che mail() 
> riconosce, puoi avere un minimo di feedback, altrimenti è semplicemente 
> "fire and forget".
> 
> L'unico modo di irrobustirlo è di non usare mail(), ma di implementare 
> un client SMTP e gestire la comunicazione col server, cosa che mi pare 
> Zend Mail e altre librerie fanno.

Sto mettendo mano alla mia implementazione di PHPMailer, che supporta
diversi metodi di trasporto, incluso SMTP, sendmail/qmail. Il metodo
mail() sembra il meno raccomandabile. Per sendmail/qmail sto cercando
di catturare qualche feedback dai processi; si vedrà.

Ciao,
 ___ 
/_|_\  Umberto Salsi
\/_\/  www.icosaedro.it

[toc] | [prev] | [next] | [standalone]


#22099

FromUmberto Salsi <salsi@icosaedro.it>
Date2018-06-18 12:05 +0200
Message-ID<pg8051$1t1u$1@gioia.aioe.org>
In reply to#22091
Umberto Salsi <salsi@icosaedro.it> wrote:

> Sto esplorando l'affidabilità di mail() per l'invio "massivo" a due o
> più destinatari. Sebbene il manuale non lo dica, sembra che:
> 
> 1. Non si può avere retroazione del motivo del fallimento.

Aggiornamenti sulla mia indagine:

Sembra che qualcuno sia riuscito ad ottenere il motivo del
fallimento di mail() andando a guardare l'ultimo errore generato con
error_get_last()['message']), ma non è chiaro il contesto di questi
casi; a me risulta invece che non viene mai settato, e neppure mail()
genera E_WARNING per cui non c'è nessun errore da gestire.

Ho scoperto che in realtà qualche retroazione si può ottenere sfruttando
il parametro opzionale di mail() che consente di impostare opzioni
custom. L'effetto di queste opzioni dipende dallo specifico processo
"sendmail" usato. Per esempio, con Exim e Sendmail si può mettere "-oep
-oeq -oi" per cui mail() ha sempre successo anche se alcuni destinatari
vengono respinti e anche se il messaggio è formalmente sbagliato (cioè
non rispetta il formato RFC822); in tali casi:

- l'errore viene loggato da sendmail nello stderr e quindi va a finire
nel log degli errori del server;

- il messaggio non viene inviato a nessun destinatario, neanche quelli
validi;

- nessun bounce viene generato.

Ne segue che il programma non ha più retroazione del fallimento, però
rimane una traccia permanente nel log file del server e si riducono i
fastidiosi bounce.

Per avere retroazione dell'errore a livello del programma bisogna per
forza usare direttamente il processo sendmail e catturarne lo stderr con
la triade popen(), fwrite() e pclose(), una cosa abbastanza acrobatica
che sto cercando di far fare a PHPMailer.

L'ultima possibilità è ricorrere direttamente al protocollo SMTP
perché solo questo dà il massimo controllo su quello che accade e
permette di saper quali destinatari sono stati accettati e quali no,
e sapere se alla fine della fiera il messaggio è stato accettato per
il recapito oppure no; anche questo sto cercando di curarlo in PHPMailer.

Spero che possa tornare utile a qualcuno.

Ciao,
 ___ 
/_|_\  Umberto Salsi
\/_\/  www.icosaedro.it

[toc] | [prev] | [standalone]


Back to top | Article view | it.comp.www.php


csiph-web