È questo il modo corretto di inviare e-mail con PHP?
Domanda
Sono un po 'preoccupato se questa funzione invia e-mail che possono essere riconosciute correttamente sulla maggior parte dei client di posta elettronica e webmail come dovrebbe, in particolare sono più preoccupato per questi dubbi:
- Le dichiarazioni e gli allegati UTF-8 sono ben formati?
- Devo usare quoted_printable_decode ()? Se sì, dove?
- Codifica trasferimento contenuto: 7 o 8 bit? Ho sempre visto 7 ma dato che sto inviando una mail codificata UTF-8 non sono sicuro.
- Dovrei usare mb_send_mail () o mail () è abbastanza?
MODIFICA: non so perché ma il codice non viene visualizzato correttamente, l'ho reso disponibile @ http://gist.github.com/104818
MODIFICA 2: sono a conoscenza di altre alternative (librerie) per la gestione della posta elettronica, ma per motivi di curiosità e conoscenza desidero solo sapere se questo codice è buono al 100% o se è difettoso .
function Email($name, $from, $to, $subject, $message, $bcc = null, $attachments = null)
{
ini_set('SMTP', 'localhost');
ini_set('sendmail_from', $from);
$name = filter_var($name, FILTER_SANITIZE_STRING);
$from = filter_var($from, FILTER_SANITIZE_EMAIL);
$subject = filter_var($subject, FILTER_SANITIZE_STRING);
$boundary = '_Boundary_' . md5(microtime(true) . mt_rand(0, PHP_INT_MAX));
$headers = array
(
'MIME-Version: 1.0',
'Content-Type: multipart/mixed; boundary="Mixed' . $boundary . '"',
'Date: ' . date('r', time()),
'From: "' . $name . '" <' . $from . '>',
'Reply-To: "' . $name . '" <' . $from . '>',
'Return-Path: "' . $name . '" <' . $from . '>',
'X-Mailer: PHP ' . phpversion(),
'X-Priority: 2',
'X-MSMail-Priority: High',
'X-Originating-IP: ' . $_SERVER['SERVER_ADDR'],
);
if (is_null($to) === false)
{
if (is_array($to) === false)
{
$to = explode(',', $to);
}
foreach ($to as $key => $value)
{
$to[$key] = filter_var($value, FILTER_SANITIZE_EMAIL);
}
$to = implode(', ', array_filter($to));
}
if (is_null($bcc) === false)
{
if (is_array($bcc) === false)
{
$bcc = explode(',', $bcc);
}
foreach ($bcc as $key => $value)
{
$bcc[$key] = filter_var($value, FILTER_SANITIZE_EMAIL);
}
$headers[] = 'BCC: ' . implode(', ', array_filter($bcc));
}
if (is_null($attachments) === false)
{
settype($attachments, 'array');
foreach ($attachments as $key => $value)
{
if (is_file($value) === true)
{
$attachments[$key] = array
(
'',
'--Mixed' . $boundary,
'Content-Type: application/octet-stream; name="' . basename($value) . '"',
'Content-Disposition: attachment; filename="' . basename($value) . '"',
'Content-Transfer-Encoding: base64',
'',
trim(chunk_split(base64_encode(file_get_contents($value)))),
);
$attachments[$key] = implode("\n", $attachments[$key]);
}
else
{
unset($attachments[$key]);
}
}
$attachments = implode("\n", $attachments) . "\n";
}
$message = array
(
'This is a multi-part message in MIME format.',
'',
'--Mixed' . $boundary,
'Content-Type: multipart/alternative; boundary="Alt' . $boundary . '"',
'',
'--Alt' . $boundary,
'Content-Type: text/plain; charset="UTF-8"',
'Content-Disposition: inline',
'Content-Transfer-Encoding: 8bit',
'',
trim(strip_tags($message, '<a>')),
'',
'--Alt' . $boundary,
'Content-Type: text/html; charset="UTF-8"',
'Content-Disposition: inline',
'Content-Transfer-Encoding: 8bit',
'',
trim($message),
'',
'--Alt' . $boundary . '--',
$attachments,
'--Mixed' . $boundary . '--',
);
if (@mail($to, stripslashes($subject), implode("\n", $message), implode("\n", $headers)) === true)
{
return true;
}
return false;
}
Soluzione
Anche se dovrebbe funzionare, consiglio vivamente di utilizzare una classe Mail / SMTP precompilata come Zend_Mail . Anche se non credo che l'intero Zend Framework sia il pigiama del gatto, ho un'ottima opinione del loro codice di gestione della posta.
EDIT: dovrei anche aggiungere che l'uso di una classe Mail / SMTP precompilata astrarrà quasi tutta la complessità / struttura delle e-mail in più parti.
Aggiornamento 2009-05-06: risposta diretta alla tua domanda.
- Le dichiarazioni e gli allegati UTF-8 sono ben formati?
Sembrano abbastanza decenti.
- Devo usare
quoted_printable_decode()
? Se sì, dove?
No. Si desidera utilizzare quoted_printable_encode()
solo se si sta decodificando un messaggio e-mail. Non quando lo stai codificando. Dovresti usare trim(strip_tags($message, '<a>'))
? Ne discuterò dopo.
- Codifica trasferimento contenuto: 7 o 8 bit? Ho sempre visto 7 ma dato che sto inviando una mail codificata UTF-8 non sono sicuro.
Utilizza la codifica a 8 bit solo se sai che il server SMTP di destinazione può supportarla. Tuttavia, poiché stai inviando la tua e-mail all'MTA locale, non consiglierei di impostare questo valore. Il valore predefinito è la codifica a 7 bit, ma ha un proprio set di restrizioni: fino a 998 ottetti per riga dell'intervallo di codice 1-127 con CR e LF ammessi solo come parte della fine della riga CRLF ( http://tools.ietf.org/html/rfc2045#section-2.7 ).
Ti consiglierei di usare Quoted-Printable ( http: //tools.ietf. org / html / rfc2045 # section-6.7 ) Codifica trasferimento-contenuto. Dove stai chiamando trim($message)
e quoted_printable_encode(trim(...))
vorrai racchiudere quelli con mb_send_mail()
.
- Devo usare
mail()
onull
è abbastanza?
Se sai che non gestirai i messaggi Multibyte (giapponese, coreano, cinese, ecc.), $to
dovrebbe bastare.
Ora che ho risposto alle tue domande iniziali, lascia che ti dica dove esistono alcuni problemi.
- Stai specificando che il set di caratteri delle tue parti di contenuto di testo semplice e HTML sono UTF-8, tuttavia non appare in quanto ti stai assicurando che siano realmente codificati UTF-8.
- Stai controllando
$bcc
in$attachments
, <=>, <=> prima di elaborarli ulteriormente, tuttavia, non stai facendo nulla quando potrebbero effettivamente essere <=>. Quindi, se ti capita di ricevere un <=> per <=>, non elabori la variabile, ma continui a inviare un'email a <=>.
In questo momento, è tutto quello che ho intenzione di approfondire, ma continuerò a consigliare vivamente una soluzione pre-costruita poiché hanno avuto molti utenti / tempo per risolvere i bug.
Altri suggerimenti
Sono pronto per il roll-your-own nella maggior parte delle situazioni, ma quando si tratta di posta raccomanderei vivamente di semplificare te stesso e di usare qualcosa come Swift Mailer o PHPMailer (in questo ordine, per i miei soldi) .
Come bonus laterale (e supponendo che tu specifichi la risposta, ecc.), hai anche molte meno possibilità di essere taggato come spam.