Invio di email usando Zend_Mail

Allo script appena visto però manca ancora qualche cosa. Cosa succede se l'utente inserisce un indirizzo email sbagliato? Come evitare un utilizzo improprio dello script, ad esempio per inviare spam?

Nessun problema, Zend Framework fornisce un oggetto per controllare la validità di un indirizzo email: Zend_Validate_EmailAddress. Includiamo quindi questo controllo nello script precedente (referenziato da $validator) bloccando l'esecuzione dello script nel caso l'email fornita non sia valida.
Invece per limitare l'uso improprio del form ed evitare lo spam, Zend Framework mette a disposizione due componenti: Zend_Captcha e Zend_Service_ReCaptcha. Nell'esempio che segue vedremo l'utilizzo di quest'ultimo. E' necessario essere registrati al servizio ReCaptha e possedere le relative chiavi per poterlo utilizzare.

L'uso è molto semplice, basta istanziare l'oggetto e inserire il controllo a monte, subito dopo aver verificato che l'array POST abbia degli elementi al suo interno. Bisogna inoltre modificare anche il codice HTML del form per poter inserire al suo interno anche il codice di ReCaptcha.

Invece di modificare il file HTML, stavolta lo includiamo direttamente all'interno dello script send.php. In questo modo avremo un unico script. Il form HTML subirà un piccolo mutamento in modo tale che i dati vengano inviati a se stesso (il campo action del tag form sarà pertanto vuoto).
Cambieremo inoltre la logica dello script. Zend_Service_ReCaptcha tramite il metodo getHTML fornisce l'output del codice per ReCaptcha, sposteremo quindi l'inizializzazione di Zend_Loader_Autoloader al di fuori del controllo dell'array POST. Un'altra piccola modifica la facciamo sul messaggio di errore: se non viene compilato correttamente perché non far visualizzare nuovamente il form?

Ecco dunque come si presenta lo script finale.

<?php
    // includo la cartella del framework
    // Attenzione, il path impostato è per server windows, se si è su un server linux il path dovrebbe essere del tipo: /directory/zendframework/library
    set_include_path(get_include_path().PATH_SEPARATOR."C:\Programmi\ZendFramework\library");

    /**
     * Richiamo il file contenente la mia classe Zend_Loader_Autoloader
     *
     * in questo modo posso caricare facilmente tutte le classi di
     * Zend Framework agevolmente senza dover ogni volta fare un require
     * come sto facendo ora
     */
    require_once("Zend/Loader/Autoloader.php");
    
    $autoloader = Zend_Loader_Autoloader::getInstance();
    
    /**
     * Voglio essere sicuro che sia una persona a scrivermi e non una macchina
     * uso il servizo di ReCaptcha con Zend_Service_ReCaptcha
     */
    $recaptcha = new Zend_Service_ReCaptcha('inserire_la_chiave_pubblica', 'inserire_la_chiave_privata');
    // Abbellisco un po' l'output di recaptcha, la lingua italiana non è ancora disponibile
    $recaptcha->setOptions(array(
		'theme'=>'clean',
		'lang'=>'it',
		'tabindex'=>5
		)); 
	
    /**
     * Se il form è stato riempito procedo con l'invio della email  
     */
    if($_POST){
	// Controllo se il recaptcha inserito è corretto
	$result = $recaptcha->verify(
	    $_POST['recaptcha_challenge_field'],
	    $_POST['recaptcha_response_field']
	);
	// Se i codici inseriti dall'utente sono validi allora posso proseguire
	if($result->isValid()){
	    /**
	     * Controllo la validità dell'email, se è valida proseguo con l'Invio
	     * altrimenti stampo un messaggio di errore 
	     */
	    $validator = new Zend_Validate_EmailAddress(); // Istanzio l'oggetto

	    if ($validator->isValid($_POST['email'])) {
		/**
		 * Istanzio il mio oggetto Zend_Mail 
		 */
		$mail = new Zend_Mail();

		/**
		 *  Compongo la mia email 
		 *  impostando le varie parti dell'email
		 */
		$mail->addTo('mario@example.com', 'Mario Santagiuliana');
		
		$mail->setFrom($_POST['email'], $_POST['name']);
		$mail->setSubject($_POST['subject']);
		$mail->setBodyText($_POST['testo']);

		/**
		 *  Voglio usare il mio server smtp, imposto i
		 *  parametri di configurazione per la connessione smtp 
		 */
		$config = array('auth' => 'login',
			'username' => 'mario@example.com',
			'password' => 'la_mia_password',
			'port' => 25);
		/**
		 *  Istanzio l'oggetto Zend_Mail_Transport_Smtp indicandogli i
		 *  parametri di connessione e di accesso
		 */
		$transport = new Zend_Mail_Transport_Smtp('smtp.example.com', $config);
		
		/**
		 * Invio l'email tramite il mio server smtp appena configurato
		 * e stampo un messaggio di corretta esecuzione dello script
		 */
		$mail->send($transport);
		$messaggio = "Email inviata correttamente";
	    } else {
		$messaggio = "L'indirizzo email fornito non è valido";
	    }
	} else {
	    $messaggio = "Il codice captcha che hai inserito non è valido";
	}
    } else {
	/**
	 * Se non ho niente nell'array POST visualizzo il form HTML
	 * Un eventuale messaggio di errore lo stampo successivamente
	 */
	?>
	<form method="post" action="" name="form">
	<table border="0px">
	<tr>
	 <td style="text-align: right">
	   Tuo Nome:
	 </td>
	 <td>
	   <input type="text" name="name" size="40" maxlength="80" />
	 </td>
	</tr>
	<tr>
	 <td style="text-align: right">
	   Tua Email:
	 </td>
	 <td>
	   <input type="text" name="email" size="40" />
	 </td>
	</tr>
	<tr>
	 <td style="text-align: right">
	   Oggetto:
	 </td>
	 <td>
	   <input type="text" name="subject" size="40" maxlength="80" />
	 </td>
	</tr>
	<tr>
	 <td style="text-align: right">
	   Testo:
	 </td>
	 <td>
	   <textarea name="testo" cols="60" rows="10"></textarea>
	 </td>
	</tr>
	<tr>
	 <td>
	</table>
	<?php
	// Visualizzo il codice HTML di ReCaptcha
	echo $recaptcha->getHTML();
	?>
	 </td>
	 <td style="text-align: right">
	   <input type="submit" value="Invia" />
	 </td>
	</tr>
	</form>
	<?php
    }

    // Stampo il messaggio ma solo se esiste
    if($messaggio)
	echo $messaggio;
?>

Come si può vedere, Zend Framework è un ottimo strumento anche per la creazione di piccoli script. Il framework fornisce molti elementi utili per creare in poco tempo script che non necessariamente devono risiedere all'interno di un'applicazione web basata sul paradigma MVC. Gli oggetti del framework, infatti, possono essere richiamati e inizializzati a piacere.
Lo script che ho proposto può essere ulteriormente migliorato. Per il form HTML si potrebbe utilizzare Zend_Form e tramite Zend_Validate fare anche un'ulteriore serie di controlli sulla compilazione del form da parte dell'utente.
Rimando dunque alla documentazione ufficiale di Zend Framework per scoprire altre opzioni ed utilizzi dei componenti citati.

Pagine: precedente 1 2

5 commenti

1 Vincenzo Vincenzo mercoledì 29 dicembre 2010, ore 22:05
ciao Mario,
innanzitutto complimenti per l'articolo.
Ho implementato nella mia web application il form contattaci.Il form come si può facilmente intuire, dovrebbe inviare un email all'indirizzo email di riferimento dell'applicazione, utilizzando con indirizzo email mittente quello specificato dal cliente nel form.
Ebbene nell'utilizzo del componente Zend_Mail, ho riscontrato il seguente problema:
Se l'indirizzo mittente cioè quello specificato su "setFrom" è lo stesso di quello utilizzato come parametro di connessione ("username") dell'oggetto Zend_Mail_Transport_Smtp, tutto funziona perfettamnte. Se invece sono diversi non funziona sollevando l'eccezione con il messaggio "MAIL".
Sai come risolvere questo problema?

Grazie anticipatamente

Ciao
2 Gianni Tomasicchio Gianni Tomasicchio mercoledì 29 dicembre 2010, ore 22:16
Probabilmente è il server SMTP che, per limitare lo spam, si rifiuta di inviare mail che hanno per mittente un utente diverso dall'utente che si è loggato.

Zend_Mail_Transport_Smtp, cominicando direttamente con il server SMTP, restituisce subito questo tipo di errori che invece, con la classica funzione mail() di PHP di presentavano in maniera più subdola, ad esempio con il fatto che la mail non veniva recapitata.

Prova ad utilizzare un altro server SMTP.
3 Vincenzo Vincenzo mercoledì 29 dicembre 2010, ore 22:36
Ho provato con Gmail, e l'email arriva, ma non riporta come mittente l'indirizzo l'email del cliente, ma quello di login. Invece il server SMTP, con il quale solleva l'eccezione è libero.it.
Conosci server SMTP che non presentano questo problema?
4 Gianni Tomasicchio Gianni Tomasicchio mercoledì 29 dicembre 2010, ore 22:40
No, ma temo che i server SMTP "pubblici" si comportino più o meno tutti così. La cosa cambia se il server SMTP lo gestisci tu...
5 Vincenzo Vincenzo mercoledì 29 dicembre 2010, ore 22:50
Ok grazie mille per le dritte.

Ciao
Effettua l'accesso o registrati per inserire un commento