48. Inviare email con allegati

Inviare email con allegati è relativamente semplice dal punto di vista comprensivo, ma al momento in cui scrivo non sono riuscito a trovare una documentazione chiara e semplice in italiano, allora ho deciso di scrivere questo capitolo che comunque non fornirà una documentazione completa e dettagliata sull'argomento, ma vi consentirà di capire il meccanismo per realizzare degli script PHP funzionanti, anche se non escludo dei possibili problemi di compatibilità con alcuni client di posta.

Per allegare dei file ad una email, il nostro script differirà principalmente per due fattori.

Inizialmente dovremo impostare il formato dell'email come multipart/mixed invece dei classici text/plain o text/html, questo per indicare che l'email sarà divisa in sottoparti di contenuto diverso (es. testo del messaggio in HTML + file allegato).

Per fare questo è sufficiente impostare correttamente il Content-Type nell'header utilizzando una codifica a 7 o a 8 bit (Content Transfer Encoding).

Fatto questo procediamo indicando un boundary, ossia una stringa che utilizzeremo per indicare la fine e l'inizio di ogni sottoparte all'interno del corpo del messaggio.

Non è necessario impostare altri parametri nell'header, procediamo quindi inserendo i dati nel corpo del messaggio, separando correttamente i contenuti dai file allegati attraverso il boundary sopracitato preceduto da due trattini --.

Per ogni sottoblocco nel corpo del messaggio dovremo indicare il Content-Type adatto, e nel caso in cui il sottoblocco sia un file allegato sarà necessario utilizzare la codifica Base64 (Content-Transfer-Encoding: base64).

<?php

	define("EOL", "\r\n");

	$boundary = "a08gunwtggjga0a89hg0a72hg93"; // Stringa generata premendo tasti a caso

	$header = "MIME-Version: 1.0" . EOL;
	$header .= "Content-Type: multipart/mixed; boundary=\"$boundary\"" . EOL;
	$header .= "Content-Transfer-Encoding: 8bit" . EOL;

	$object = "Oggetto del messaggio";

	/* Leggo il contenuto del file da allegare e lo memorizzo in $allegato */
	$file = @fopen("immagine.jpg", "r");
	$allegato = fread($file, filesize("immagine.jpg"));
	$allegato = base64_encode($allegato);

	/* Inserisco il testo del messaggio in formato HTML */
	$message = "--" . $boundary . EOL;
	$message .= "Content-Type: text/html; charset=iso-8859-1" . EOL;
	$message .= "Content-Transfer-Encoding: 8bit" . EOL;
	$message .= "TESTO DEL MESSAGGIO IN FORMATO HTML" . EOL;
	$message .= "--" . $boundary . EOL;

	/* Ora inserisco un nuovo sottblocco che conterrà il file allegato */
	$message .= "--" . $boundary . EOL;
	$message .= "Content-Type: image/jpeg; name=\"immagine.jpg\"" . EOL;
	$message .= "Content-Transfer-Encoding: base64" . EOL;
	$message .= "Content-Description: Immagine" . EOL;
	$message .= "Content-Disposition: attachment; filename=\"immagine.jpg\"" . EOL;
	$message .= $allegato . EOL;
	$message .= "--" . $boundary . EOL;

	mail("posta@realizzazione-sito.info", $object, $message, $header);

?>

Eseguendo lo script soprastante viene prodotto questo risultato.

Lo script è stato testato correttamente con GMail, ma potrebbe non funzionare correttamente con altri client di posta.
In questi casi provate a cambiare l'EOL o ad esempio la sintassi del boundary di chiusura blocco.