Purtroppo PHP non offre un metodo intuitivo ed immediato per l’invio di email con allegati; per questo motivo, spesso si fa ricorso a delle apposite classi (come PHPMailer) per gestire con maggior semplicitร questa esigenza. L’utilizzo di classi esterne, seppur comodo, non รจ tuttavia indispensabile. Con un poco di pazienza, possiamo scrivere noi stessi il codice PHP per l’invio di email con allegati (cd: attachments) utilizzando la classica funzione mail() integrata nativamente nel linguaggio.
L’allegato, infatti, altro non รจ che una sorta di “inclusione” di un file all’interno di una mail. Per fare ciรฒ, si ricorre al formato MIME multi-part, che consente, appunto, di creare una mail suddivisa in diverse parti. La nostra mail, quindi, avrร una semplice parte testuale (il messaggio vero e proprio) ed una parte piรน complessa contenente l’allegato.
In questo articolo vedremo come creare una sorta di formmail attraverso il quale gli utenti del nostro sito potranno inviarci file in allegato tramite un semplice modulo di upload.
Per raggiungere il nostro scopo, realizzeremo due file distinti: un semplice file .html contenente il form ed un file .php che svolgerร tutto il lavoro di elaborazione. Precisamente, il nostro script PHP (che chiameremo formmail.php) dovrร occuparsi dei seguenti compiti:
- Recupero delle informazioni inserite nel form
- Recupero e verifica del file allegato
- Creazione del messaggio MIME multi-part
- Spedizione della email
Ma per prima cosa vediamo il file .html contenente il form:
<form action="formmail.php" method="POST" enctype="multipart/form-data">
<table border="0">
<tr>
<td>Tua Mail:</td>
<td><input type="text" name="mittente" value="" /></td>
</tr>
<tr>
<td>Oggetto:</td>
<td><input type="text" name="oggetto" value="" /></td>
</tr>
<tr>
<td>Messaggio:</td>
<td><textarea cols="20" rows="4" name="messaggio"></textarea></td>
</tr>
<tr>
<td>Allega file:</td>
<td><input type="file" name="allegato" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Invia" /></td>
</tr>
</table>
</form>
Non credo sia necessario soffermarsi sul codice visto sopra, poichรฉ si tratta di una semplice tabella HTML contenente un semplice form. L’unica cosa degna di nota รจ l’aggiunta di:
enctype="multipart/form-data"
al tag FORM. Questo accorgimento รจ necessario per la corretta gestione, tramite protocollo HTTP, dell’invio di file mediante il modulo.
Vediamo ora il codice PHP vero e proprio. Data la complessitร di alcuni passaggi, ho ritenuto opportuno aggiungere ampi commenti che, una volta compresi, potrete agevolmente eliminare dal vostro script:
<?php
// Recupero il valore dei campi del form
$destinatario = 'info@mail-del-sito.com';
$mittente = $_POST['mittente'];
$oggetto = $_POST['oggetto'];
$messaggio = $_POST['messaggio'];
// Valorizzo le variabili relative all'allegato
$allegato = $_FILES['allegato']['tmp_name'];
$allegato_type = $_FILES['allegato']['type'];
$allegato_name = $_FILES['allegato']['name'];
// Creo altre due variabili ad uno interno
$headers = "From: " . $mittente;
$msg = "";
// Verifico se il file รจ stato caricato correttamente via HTTP
// In caso affermativo proseguo nel lavoro...
if (is_uploaded_file($allegato))
{
// Apro e leggo il file allegato
$file = fopen($allegato,'rb');
$data = fread($file, filesize($allegato));
fclose($file);
// Adatto il file al formato MIME base64 usando base64_encode
$data = chunk_split(base64_encode($data));
// Genero il "separatore" per dividere le varie parti del messaggio
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// Aggiungo le intestazioni necessarie per l'allegato
$headers .= "\nMIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed;\n";
$headers .= " boundary=\"{$mime_boundary}\"";
// Definisco il tipo di messaggio (MIME/multi-part)
$msg .= "This is a multi-part message in MIME format.\n\n";
// Metto il separatore
$msg .= "--{$mime_boundary}\n";
// Questa รจ la parte "testuale" del messaggio
$msg .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n";
$msg .= "Content-Transfer-Encoding: 7bit\n\n";
$msg .= $messaggio . "\n\n";
// Metto il separatore
$msg .= "--{$mime_boundary}\n";
// Aggiungo l'allegato al messaggio
$msg .= "Content-Disposition: attachment; filename=\"{$allegato_name}\"\n";
$msg .= "Content-Transfer-Encoding: base64\n\n";
$msg .= $data . "\n\n";
// chiudo con il separatore
$msg .= "--{$mime_boundary}--\n";
}
// se non รจ stato caricato alcun file
// preparo un semplice messaggio testuale
else
{
$msg = $messaggio;
}
// Invio la mail
if (mail($destinatario, $oggetto, $msg, $headers))
{
echo "<p>Mail inviata con successo!</p>";
}else{
echo "<p>Errore!</p>";
}
?>
Da segnalare, nella gestione dell’allegato, l’utilizzo dell’encoding base64. ร stato, pertanto, necessario compiere alcune operazioni sul file: lo abbiamo aperto (abbiamo usato fopen con "rb" – read binary), ne abbiamo estratto il contenuto (usando fread) e lo abbiamo passato alla funzione base64_encode (abbiamo usato chunk_split per suddividere la stringa restituita da base64_encode in segmenti piรน ridotti).
Concludo ricordando che il codice qui proposto ha puramente finalitร didattica; prima di essere messo in produzione, infatti, dovrebbe essere arricchito di una serie di controlli circa la corretta compilazione dei campi del form, oltre che sul tipo di file che l’utente sta cercando di inviarci. ร fondamentale implementare ulteriori sicurezze per evitare l’inserimento di file dannosi nel sistema.
In aggiunta, รจ possibile migliorare ulteriormente l’esperienza utente implementando feedback visivi, come messaggi di errore personalizzati o conferme di invio, e implementare una limitazione della dimensione degli allegati nell’upload. Queste funzionalitร servono a garantire non solo un’esperienza piรน fluida, ma anche una maggiore sicurezza nell’invio di contenuti attraverso il vostro modulo di contatto.