Zend_Mail provides a great and simple in use and configuration mechanizm to send emails. The problem begins when you would like to specify fully templated and layouted messages.
In my current project I have several kinds of mails: customer invoices and messages, users notifications, admin notifications, webmaster email about critical errors in scheduled system tasks. In this case the Zend_Layout fits perfectly to redner rich text content by Zend_View, but it is implemented in Zend_Mail, wchih provies simply setBodyText() and setBodyHTML() methods.
This inconvenience is understandable by the way, mainly in context simpe, clear and flexible extendable code of Zend Framework. We will strive to extend the functionality od Zend_Mail following ZF developers concepts.
Writing class extending Zend_Mail I kept a several concepts:
Simply paste several lines to application.ini configuration, theare are self-commented, description is not neccessary at this point. We will use SMTP transport:
resources.mail.transport.type = smtp resources.mail.transport.host = YOUR_HOSTNAME resources.mail.transport.auth = login resources.mail.transport.username = "YOUR_ACCOUNT" resources.mail.transport.password = "YOUR_PASSWORD" resources.mail.transport.register = true resources.mail.defaultFrom.email = YOUR_ACCOUNT resources.mail.defaultFrom.name = "MyService.com" resources.mail.defaultReplyTo.email = YOUR_ACCOUNT resources.mail.defaultReplyTo.name = "MyService.com"
In addition we will create tho additional directories and files:
/application/views/scripts/email/- just add a subdirectory /email to existing view scripts directory./application/layouts/scripts/email/ – the same story as above/application/views/layouts/ to unify structure of application. Just change in application.ini this line:resources.layout.layoutPath = APPLICATION_PATH "/modules/default/views/layouts/scripts/"
To test our class let’s create additional two files:
/application/layouts/scripts/email/html.phtml
< ?php echo $this->layout()->content ?> <p>--<br />Best Regards,<br />MyService.com</p>
and scond one, the information about successfull account register with your own content:
/application/views/scripts/email/AccountRegister.phtml
<p>Thanks for register.</p>
Before we will write a code, let’s think abous its usage, wchih should be the same as in Zend_Mail documentation witch additional methods:
$mail = new ZendUtil_Mail('utf-8'); $mail->addTo('athlanster@gmail.com', 'Piotr Pelczar'); $mail->setSubject('Testowy mail z zenda'); $mail->setBodyView('AccountRegister.phtml'); $mail->send();
Above code should send mail from AccountRegister.phtml view script nested in html.phtml layout.
If you want to change layout simply call setViewLayoutScript($script) method with string or set false to disable layouts. For change paths setViewPathDirectory($path), setViewLayoutPathDirectory($path) are available.
ZendUtil_Mail has been extended by Zend_Mail and _prepareBody() method has been added. It is called just before parent::send() method.
NOTE: I have added ZendUtil_ namespace.
I hope it will help.
I have just started introducing Zend Framework when I had to face the problem with output multiple error messages in form while email address validation. Checking domain (whith is enabled by default) causes additional error messages indicates anomalies in hostname segment of provided by user email address. In result, we receive several errors assigned to one email field.
The problem is easy to slove by overriding default behaviour of Zend_Validate_EmailAddress clearing all messages generating while validation and setup a new single error message.
Simply add namespace MyOwn_ for own needs and provide class in file /libraries/MyOwn/Validate/EmailAddess.php
class MyOwn_Validate_EmailAddress extends Zend_Validate_EmailAddress { const INVALID = 'emailAddressInvalid'; protected $_messageTemplates = array( self::INVALID => "Invalid Email Address." ); public function isValid($value) { parent::setOptions(array( 'allow' => Zend_Validate_Hostname::ALLOW_DNS, 'domain' => true, 'mx' => true, 'deep' => true) ); if(!parent::isValid($value)) { $this->_messages = array(); // clear all previous messages $this->_error(self::INVALID); return false; } return true; } }
And provide above custom validator to form element in /application/forms/AccountRegister.php:
class Form_AccountRegister extends Zend_Form { public function init() { $this->setMethod('post') ->setName('Account_Register'); $email = new Zend_Form_Element_Text('email'); $email ->setLabel('Email address') ->addValidator(new ZendUtil_Validate_EmailAddress) ->setRequired(true); $this->addElement($email); } }
NOTE:
Hope it will help.
Pisząc nowy projekt natknąłem na problem z procesem uploadu filmiku do serwisu YouTube. Sam upload jest bardzo łatwy do napisania z Zend_Gdata_YouTube – przykład można znaleźć w manualu. Myślę, że zainteresowani przeczytają manual i wszystko będzie jasne. Więc jeżeli to takie proste, to w czym problem?
Zakładamy, że userzy uloadują filmiki bezpośrednio na nasz serwis. Nasz serwer ma za zadanie:
Pierwsze 2 kroki wykonają się błyskawicznie w porównaniu do trzeciego. Kompresja i nałożenie watermarku na 30 megowy plik z wykorzystaniem FFMPEG to nic nadzwyczajnego. Natomiast wysyłka pliku na serwery Youtube’a może zawiesić apache’a, gdy jest ich kilka.
Rozwiązanie? Wpadłem na pomysł, aby upload filmików ustawiony był w pewnego rodzaju kolejce, która uruchamiana by była co minutę (cron), a czas jednego wysłania elemntu nie mógłby przekroczyć 50 sekund. Oczywiście takie działanie uruchamiałoby swój osobny proces apache’a. Ten sposób jest ograniczony dwoma limitami: wielkością pliku oraz czasem jego uploadu na serwer (jednocześniem interwałem uruchamiania kolejki).