Development

Changeset 1322

You must first sign up to be able to contribute.

Changeset 1322

Show
Ignore:
Timestamp:
05/05/06 17:16:42 (3 years ago)
Author:
francois
Message:

updated email documentation

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/doc/book/content/email.txt

    r500 r1322  
    22==================== 
    33 
     4Overview 
     5-------- 
     6 
     7Sending mails from a web application is a very common tasks. Symfony uses its architecture to automate it in a familiar way (MVC separation) and provides a specific class to deal with the particularities of the emails (multiple mime types, enclosed media, attachments). 
     8 
    49Introduction 
    510------------ 
    611 
    7 Email sending is handled by the `sfMail` class. It is a proxy class that offers an interface with [PhpMailer](http://phpmailer.sourceforge.net/). 
    8  
    9 This proxy class allows you to define your own interface if required. 
    10  
    11 Example 
    12 ------- 
    13  
    14     [php] 
    15     require_once 'sf/sfMail.class.php'; 
    16      
    17     // class initialization 
    18     $mail = sfMail::newInstance('PhpMailer'); 
    19     $mail->initialize(); 
    20     $mail->setMailer('sendmail'); 
    21      
    22     // definition of the required parameters 
    23     $mail->addAddress('client@client.com'); 
    24     $mail->setSender('me@symfony-project.com', 'Symfony'); 
     12Symfony offers two ways to send emails from your web application:  
     13 
     14- Via the `sfMail` class, which is a proxy class that offers an interface with [PHPMailer](http://phpmailer.sourceforge.net/). This solution is simple and fast, but doesn't provide MVC separation and is hardly compatible with i18n. Complex emails are also harder to compose with the `sfMail` class alone. 
     15 
     16- Via a specific action and template. This solution is very versatile and deals with emails just as regular pages, with the addition of the specificities of this media. It is a little longer to put in place, but much more powerful than the first one. 
     17 
     18The implementation of both solution will be illustrated through the same example: the sending of a forgotten password requested by a user. 
     19 
     20Direct use of `sfMail` 
     21---------------------- 
     22 
     23The `sfMail` class will look familiar to those who know the `PHPMailer` class. It is simply a proxy class to `PHPMailer`, taking advantage of the symfony syntax. The `PHPMailer` class is included in the symfony package, so no additional installation is required. 
     24 
     25To send an email containing a password to a customer, an action has to do like the following: 
     26 
     27    [php] 
     28    public function executePasswordRequest() 
     29    { 
     30      // determine customer from the request 'id' parameter 
     31      $customer = CustomerPeer::retrieveByPk($this->getRequestParameter('id')); 
     32       
     33      require_once 'sf/sfMail.class.php'; 
     34       
     35      // class initialization 
     36      $mail = new sfMail(); 
     37      $mail->initialize(); 
     38      $mail->setMailer('sendmail'); 
     39      $mail->setCharset('utf-8'); 
     40       
     41      // definition of the required parameters 
     42      $mail->setSender('webmaster@my-company.com', 'My Company webmaster'); 
     43      $mail->setFrom('webmaster@my-company.com', 'My Company webmaster'); 
     44      $mail->addReplyTo('webmaster_copy@my-company.com'); 
     45   
     46      $mail->addAddress($customer->getEmail()); 
     47   
     48      $mail->setSubject('Your password request'); 
     49      $mail->setBody(' 
     50      Dear customer, 
     51       
     52      You are so absentminded. Next time, try to remember your password: 
     53      '.$customer->getPassword().' 
     54       
     55      Regards, 
     56      The My Company webmaster'); 
     57       
     58      // send the email 
     59      $mail->send(); 
     60    } 
     61   
     62Use of an alternate action 
     63-------------------------- 
     64 
     65In many cases, as the email sending process is just a detour in the logic of an action that does something else, it is often delegated to another action. Here is how it goes: 
     66 
     67    [php] 
     68    public function executePasswordRequest() 
     69    { 
     70      // send the email 
     71      $raw_email = $this->sendEmail('mail', 'sendPassword');   
     72       
     73      // log the email 
     74      $this->logMessage($raw_email, 'debug'); 
     75    } 
     76 
     77The email sending is delegated to a `sendPassword` action of a `mail` module. The `->sendEmail()` method of the `sfAction` class is a special kind of `->forward()` that executes another action but comes back afterward (it doesn't stop the execution of the current action). In addition, it returns a raw email that can be written into a log file (you will find more information about the way to log information in the [debug chapter](debug.txt)). 
     78 
     79The `mail/sendPassword` deals with the `sfMail` object, but it doesn't need to require the class (it is autoloaded) nor to define the mailer (it is taken from a configuration file): 
     80 
     81    [php] 
     82    public function executeSendPassword() 
     83    { 
     84      // determine customer from the request 'id' parameter 
     85      $customer = CustomerPeer::retrieveByPk($this->getRequestParameter('id')); 
     86       
     87      // class initialization 
     88      $mail = new sfMail(); 
     89      $mail->setCharset('utf-8');       
     90       
     91      // definition of the required parameters 
     92      $mail->setSender('webmaster@my-company.com', 'My Company webmaster'); 
     93      $mail->setFrom('webmaster@my-company.com', 'My Company webmaster'); 
     94      $mail->addReplyTo('webmaster_copy@my-company.com'); 
     95   
     96      $mail->addAddress($customer->getEmail()); 
     97   
     98      $mail->setSubject('Your password request'); 
     99       
     100      $this->password = $customer->getPassword(); 
     101      $this->mail = $mail;     
     102    } 
     103     
     104Notice that the action doesn't need to call the `->send()` method for the `sfMail` object; being called by a `->sendEmail()`, it knows that it needs to finish by sending its `$this->mail` `sfMail` object. And where is the mail? will you ask. That's the beauty of the MVC separation: the body of the mail itself is to be written in the template `sendPasswordSuccess.php`: 
     105 
     106    [php] 
     107    Dear customer, 
     108     
     109    You are so absentminded. Next time, try to remember your password: 
     110    <?php echo $password ?> 
     111     
     112    Regards, 
     113    The My Company webmaster 
     114 
     115>**Note**: If the `sendPassword` action ever determines that the email doesn't have to be sent, it can still abort the emailing process by returning `sfView::NONE`, just like a regular action. 
     116 
     117Mailer configuration 
     118-------------------- 
     119 
     120If you use the alternate action method, you can (you don't have to) set the mailer and activate it environment by environment through a configuration file. 
     121 
     122Create a `mailer.yml` configuration file in the `modules/mail/config/` directory  with: 
     123 
     124    dev: 
     125      deliver:    off 
     126     
     127    all: 
     128      mailer:     sendmail 
     129 
     130This stipulates the mailer program to be used to send mails, and deactivates the sending of mails in the development environment. 
     131 
     132Send HTML email 
     133--------------- 
     134 
     135Most of the time, emails are to be sent in HTML format, or even in a multipart format (enclosing both HTML and text format). To handle it directly with the `sfMail` object, use the `->setContentType()` method and specify an alternate body: 
     136 
     137    [php] 
     138    $mail->setContentType('text/html'); 
     139    $mail->setAltBody(' 
     140    <p>Dear customer</p>, 
     141    <p> 
     142      You are so <i>absentminded</i>. Next time, try to remember your password:<br> 
     143      <b>'.$customer->getPassword().'</b> 
     144    </p> 
     145    <p> 
     146      Regards,<br> 
     147      The My Company webmaster 
     148    </p>');     
     149    $mail->setAltBody(' 
     150    Dear customer, 
     151     
     152    You are so absentminded. Next time, try to remember your password: 
     153    '.$customer->getPassword().' 
     154     
     155    Regards, 
     156    The My Company webmaster');     
     157 
     158If you use an alternate action, you will just need to use an alternate template ending with `.altbody.php`. Symfony will automatically add it as alternate body: 
     159 
     160    [php] 
     161    // in sendPasswordSuccess.php 
     162    <p>Dear customer</p>, 
     163    <p> 
     164      You are so <i>absentminded</i>. Next time, try to remember your password:<br> 
     165      <b><?php echo $password ?></b> 
     166    </p> 
     167    <p> 
     168      Regards,<br> 
     169      The My Company webmaster 
     170    </p> 
     171         
     172    // in sendPasswordSuccess.altbody.php 
     173    Dear customer, 
     174     
     175    You are so absentminded. Next time, try to remember your password: 
     176    <?php echo $password ?> 
     177     
     178    Regards, 
     179    The My Company webmaster 
     180 
     181>**Note**: If you just use an HTML version without altbody template, you will need to set the content type to `text/html` in the `sendPassword` action. 
     182 
     183Embed images 
     184------------ 
     185 
     186HTML emails can contain images directly embedded in the body. To add an embedded image, use the `->addEmbeddedImage()` method of the `sfMail` object: 
     187 
     188    [php] 
     189    $mail->addEmbeddedImage(sfConfig::get('sf_web_dir').'/images/my_company_logo.gif', 'CID1', 'My Company Logo', 'base64', 'image/gif'); 
     190 
     191The first argument is the path to the image, the second is a reference of the image that you can use in the template to embed it: 
     192 
     193    [php] 
     194    // in sendPasswordSuccess.php 
     195    <p>Dear customer</p>, 
     196    <p> 
     197      You are so <i>absentminded</i>. Next time, try to remember your password:<br> 
     198      <b><?php echo $password ?></b> 
     199    </p> 
     200    <p> 
     201      Regards,<br> 
     202      The My Company webmaster 
     203      <img src="cid:CID1" /> 
     204    </p> 
     205 
     206Attachments 
     207----------- 
     208 
     209Attaching a document to a mail is as simple as you would expect it to be: 
     210 
     211    [php] 
     212    // document attachment 
     213    $mail->addAttachment(sfConfig::get('sf_data_dir').'/MyDocument.doc'); 
     214    // string attachment 
     215    $mail->addStringAttachment('this is some cool text to embed', 'file.txt'); 
     216 
     217Email addresses advanced syntax 
     218------------------------------- 
     219 
     220In addition to recipients, emails often need to be sent as carbon copy ('cc:') or blind carbon copy ('bcc:'). Here is how to do this with `sfMail`: 
     221 
     222    [php] 
     223    $mail->addAddress($customer->getEmail()); 
     224    $mail->addCc('carbon_copy@my-companyt.com ');     
     225    $mail->addBcc('blind_carbon_copy@my-company.com'); 
     226 
     227The `sfMail` methods used to set emails (`->setSender()`, `->setFrom()`, `->addReplyTo()`, `->addAddress()`, `->addCc()`, `->addBcc()`) can use two syntaxes: 
     228 
     229    [php] 
    25230    $mail->setFrom('me@symfony-project.com', 'Symfony'); 
    26     $mail->addReplyTo('you@symfony-project.com'); 
    27     $mail->setCharset('utf-8'); 
    28     $mail->setSubject('A very important matter'); 
    29     $mail->setBody('First of all, you should know that...'); 
    30      
    31     // send the email 
    32     $mail->send(); 
     231    // is equivalent to 
     232    $mail->setFrom('me@symfony-project.com <Symfony>'); 
     233 
     234In addition, to minimize the code in case of multiple recipients, `sfMail` has an `->addAddresses()` method: 
     235 
     236    [php] 
     237    $mail->addAddress('client1@client.com <Jules>'); 
     238    $mail->addAddress('client2@client.com <Jim>'); 
     239    // is equivalent to 
     240    $mail->addAddresses(array('client1@client.com <Jules>', 'client2@client.com <Jim>')); 
     241     
     242`sfMail` methods 
     243---------------- 
     244 
     245Once you've built your `sfMail` object, you might want to check its content. Fortunately, all the setter methods described above have an equivalent getter method, and you can clear the properties previously set: 
     246 
     247    [php] 
     248    ->setCharset($charset) 
     249    ->getCharset() 
     250    ->setContentType($content_type) 
     251    ->getContentType() 
     252    ->setPriority($priority) 
     253    ->getPriority() 
     254    ->setEncoding($encoding) 
     255    ->getEncoding() 
     256    ->setSubject($subject) 
     257    ->getSubject() 
     258    ->setBody($body) 
     259    ->getBody() 
     260    ->setAltBody($text) 
     261    ->getAltBody() 
     262    ->setMailer($type = 'mail') 
     263    ->getMailer() 
     264    ->setSender($address, $name = null) 
     265    ->getSender() 
     266    ->setFrom($address, $name = null) 
     267    ->getFrom() 
     268    ->addAddresses($addresses) 
     269    ->addAddress($address, $name = null) 
     270    ->addCc($address, $name = null) 
     271    ->addBcc($address, $name = null) 
     272    ->addReplyTo($address, $name = null) 
     273    ->clearAddresses() 
     274    ->clearCcs() 
     275    ->clearBccs() 
     276    ->clearReplyTos() 
     277    ->clearAllRecipients() 
     278    ->addAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') 
     279    ->addStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') 
     280    ->addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') 
     281    ->setAttachments($attachments) 
     282    ->clearAttachments() 
     283    ->addCustomHeader($name, $value) 
     284    ->clearCustomHeaders() 
     285    ->setWordWrap($wordWrap) 
     286    ->getWordWrap() 

The Sensio Labs Network

Since 1998, Sensio Labs has been promoting the Open-Source software movement by providing quality web application development, training, consulting, and supporting several large Open-Source projects.