In un precedente articolo ho parlato di come scrivere un’application resource per Zend Framework per utilizzare il plugin ZFDebug. In questo articolo vedremo come utilizzare lo stesso meccanismo per un’operazione più semplice ma di utilizzo molto più frequente, ovvero configurare il default transport per l’invio di messaggi di posta elettronica tramite il componente Zend_Mail.
Normalmente per configurare l’invio dei messaggi si utilizza il seguente codice (ad esempio nel bootstrap):
$config = array('auth' => 'login',
'username' => 'myusername',
'password' => 'password');
$transport = new Zend_Mail_Transport_Smtp('mail.server.com', $config);
Zend_Mail::setDefaultTransport($transport);
Per liberarci di questo codice in ogni applicazione che utilizzi la classe Zend_Mail ho scritto una classe Application Resource da inserire nella propria libreria. Il codice della classe è piuttosto semplice
/**
* Resource for creating smtp transports
*
* @uses Zend_Application_Resource_ResourceAbstract
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zenit_Application_Resource_Smtp extends Zend_Application_Resource_ResourceAbstract {
/**
* Transport
*
* @var Zend_Mail_Transport_Abstract
*/
protected $_transport = null;
/**
* Parameters to use
*
* @var array
*/
protected $_params = array ();
/**
* Server name
*
* @var string
*/
protected $_server = '127.0.0.1';
/**
* @var string
*/
protected $_transportClass;
/**
* Set the adapter params
*
* @param $params array
*/
public function setParams(array $params) {
$this->_params = $params;
return $this;
}
/**
* Validates the hostname provided as server
*
* @param string $server
*/
public function setServer($server) {
if (Zend_Validate::is($server, 'Hostname')) {
$this->_server = $server;
} else {
throw new Zend_Mail_Exception("Invalid server name $server");
}
}
/**
* Returns the hostname for the server
*
* @return string
*/
public function getServer() {
return $this->_server;
}
/**
* Transport parameters
*
* @return array
*/
public function getParams() {
return $this->_params;
}
/**
* Determine the type of transport to use
*
* @param string $class
* @throws Zend_Mail_Transport_Exception if the given class doesn't exists
*/
public function setTransport($class) {
if (false === strpos($class, '_')) {
// allow short names such as smtp
$class = 'Zend_Mail_Transport_' . ucfirst($class);
}
if (!class_exists($class)) {
throw new Zend_Mail_Transport_Exception(
"Unexistant transport class $class");
}
$this->_transportClass = $class;
}
/**
* Return the transport class to use
*
* @return null|Zend_Mail_Transport_Abstract
*/
public function getTransport() {
if (null == $this->_transport && $this->_transportClass) {
$class = $this->_transportClass;
// instantiate class
switch ($class) {
case 'Zend_Mail_Transport_Smtp':
case 'Zenit_Mail_Transport_Smtp':
$transport = new $class($this->getServer(),
$this->getParams());
break;
case 'Zend_Mail_Transport_Sendmail':
default:
$transport = new $class();
break;
}
// check transport type
if (!$transport instanceof Zend_Mail_Transport_Abstract) {
throw new Zend_Mail_Transport_Exception(
"Class $class is not a valid Zend_Mail_Transport_Abstract");
}
// set transport as default transport
Zend_Mail::setDefaultTransport($transport);
// assign it to local field
$this->_transport = $transport;
}
return $this->_transport;
}
/**
* Defined by Zend_Application_Resource_Resource
*
* @return null|Zend_Mail_Transport_Abstract
*/
public function init() {
return $this->getTransport();
}
}
Come nel caso precedente, è sufficiente inserire questa classe nel proprio include_path e cambiare/registrare il namespace della libreria (nel mio caso Zenit).
Fatto ciò per configurare il trasporto da usare usando il file application.ini è sufficiente inserire queste righe:
; smtp stuff resources.smtp.transport = "smtp" resources.smtp.server = "smtp.example.org" resources.smtp.params.auth = "login" resources.smtp.params.username = "myusername" resources.smtp.params.password = "mypassword"
Et voilà, il gioco è fatto. Ora si può usare in qualsiasi punto della propria applicazione la classe Zend_Mail per l’invio di messaggi ed il metodo di invio usato sarà quello configurato tramite il file application.ini.
È possibile usare anche classi personalizzate come transport, è sufficiente che tali classi estendano la classe Zend_Mail_Transport_Abstract e che prevedano un costruttore vuoto (in alternativa è necessario personalizzare il metodo getTransport per adattarlo alle proprie esigenze). Per utilizzare una classe personalizzata è sufficiente passare il nome completo della classe come valore dell’opzione resources.smtp.transport, mentre per le classi predefinite si può anche usare il nome breve della classe senza il namespace completo (nell’esempio “smtp”).
Se il server smtp non necessita di autenticazione per l’invio è sufficiente rimuovere le relative righe dal file di configurazione (4-6).
Per quanto mi riguarda attualmente sto utilizzando come transport l’estensione della classe Zend_Mail_Transport_Smtp consigliatami in questo thread del forum di Zend_Framework, in quanto la classe originale soffre di un memory leak nel momento in cui si invia un numero consistente di email nello stesso script, a causa di un log interno che viene salvato in una stringa in memoria. Non appena verrà rilasciato l’aggiornamento che includa la correzione discussa qui, tornerò ad usare la classe ufficiale (di conseguenza la linea case 'Zenit_Mail_Transport_Smtp': nel metodo getTransport verrà rimossa dal codice).



















