8 min read

Automated email responses

Symfony comes with a default mailer library that is based on Swift Mailer 4, the detailed documentation is available from their web site at http://swiftmailer.org.

After a user has signed up to our mailing list, we would like an email verification to be sent to the user’s email address. This will inform the user that he/she has signed up, and will also ask him or her to activate their subscription.

To use the library, we have to complete the following three steps:

  1. Store the mailing settings in the application settings file.
  2. Add the application logic to the action.
  3. Create the email template.

Adding the mailer settings to the application

Just like all the previous settings, we should add all the settings for sending emails to the module.yml file for the signup module. This will make it easier to implement any modifications required later. Initially, we should set variables like the email subject, the from name, the from address, and whether we want to send out emails within the dev environment. I have added the following items to our signup module’s setting file, apps/frontend/config/module.yml:

dev:
  mailer_deliver: true
all:
   mailer_deliver: true
   mailer_subject: Milkshake Newsletter
   mailer_from_name: Tim
   mailer_from_email: no-reply@milkshake

All of the settings can be contained under the all label. However, you can see that I have introduced a new label called dev. These labels represent the environments, and we have just added a specific variable to the dev environment. This setting will allow us to eventually turn off the sending of emails while in the dev environment.

Creating the application logic

Triggering the email should occur after the user’s details have been saved to the database. To demonstrate this, I have added the highlighted amends to the submit action in the apps/frontend/modules/signup/actions/actions.class.php file, as shown in the following code:

public function executeSubmit(sfWebRequest $request)
 {
   $this->form = new NewsletterSignupForm();
   if ($request->isMethod('post') && $this->form->
               bindAndSave($request->getParameter($this->form->
                                                   getName())))
   {
    //Include the swift lib
    require_once('lib/vendor/swift-mailer/lib/swift_init.php');
try{
//Sendmail
$transport = Swift_SendmailTransport::newInstance();
$mailBody = $this->getPartial('activationEmail',
array('name' => $this->form->getValue('first_name')));
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance();
$message->setSubject(sfConfig::get('app_mailer_subject'));
$message->setFrom(array(sfConfig:: get('app_mailer_from_email')
=> sfConfig::get('app_mailer_from_name')));
$message->setTo(array($this->form->getValue('email')=> $this->
form->getValue('first_name')));
$message->setBody($mailBody, 'text/html');
if(sfConfig::get('app_mailer_deliver'))
{
$result = $mailer->send($message);
}
}
catch(Exception $e)
{
var_dump($e);
exit;
} $this->redirect('@signup'); } //Use the index template as it contains the form $this->setTemplate('index'); }

Symfony comes with a sfMailer class that extends Swift_Mailer. To send mails you could simply implement the following Symfony method:
$this->getMailer()->composeAndSend(‘[email protected]’,
[email protected]’, ‘Subject’, ‘Body’);

Let’s walk through the process:

  1. Instantiate the Swift Mailer.
  2. Retrieve the email template (which we will create next) using the $this->getPartial(‘activationEmail’, array(‘name’ => $this->form->getValue(‘first_name’))) method. Breaking this down, the function itself retrieves a partial template. The first argument is the name of the template to retrieve (that is activationEmail in our example) which, if you remember, means that the template will be called _activationEmail.php. The next argument is an array that contains variables related to the partial template. Here, I have set a name variable. The value for the name is important. Notice how I have used the value within the form object to retrieve the first_name value. This is because we know that these values have been cleaned and are safe to use.
  3. Set the subject, from, to, and the body items. These functions are Swift Mailer specific:
    • setSubject(): It takes a string as an argument for the subject
    • setFrom(): It takes the name and the mailing address
    • setTo(): It takes the name and the mailing address
    • setBody(): It takes the email body and mime type. Here we passed in our template and set the email to text/html
  4. Finally we send the email.

There are more methods in Swift Mailer. Check out the documentation on the Swift Mailer web site (http://swiftmailer.org/).

The partial email template

Lastly, we need to create a partial template that will be used in the email body. In the templates folder of the signup module, create a file called _activationEmail.php and add the following code to it:

Hi <?php echo $name; ?>, <br /><br />
Thank you for signing up to our newsletter.
<br /><br />
Thank you,
<br />
<strong>The Team</strong>

The partial is no different from a regular template. We could have opted to pass on the body as a string, but using the template keeps our code uniform. Our signup process now incorporates the functionality to send an email.

The purpose of this example is to show you how to send an automated email using a third-party library. For a real application, you should most certainly implement a two-phase option wherein the user must verify his or her action.

Flashing temporary values

Sometimes it is necessary to set a temporary variable for one request, or make a variable available to another action after forwarding but before having to delete the variable. Symfony provides this level of functionality within the sfUser object known as a flash variable. Once a flash variable has been set, it lasts until the end of the overall request before it is automatically destroyed.

Setting and getting a flash attribute is managed through two of the sfUser methods. Also, you can test for a flash variable’s existence using the third method of the methods listed here:

  • $this->getUser()->setFlash($name, $value, $persist = true)
  • $this->getUser()->getFlash($name)
  • $this->getUser()->hasFlash($name)

Although a flash variable will be available by default when a request is forwarded to another action, setting the argument to false will delete the flash variable before it is forwarded.

To demonstrate how useful flash variables can be, let’s readdress the signup form. After a user submits the signup form, the form is redisplayed. I further mentioned that you could create another action to handle a ‘thank you’ template. However, by using a flash variable we will not have to do so.

As a part of the application logic for the form submission, we can set a flash variable. Then after the action redirects the request, the template can test whether there is a flash variable set. If there is one, the template should show a message rather than the form.

Let’s add the $this->getUser()->setFlash() function to the submit action in the apps/frontend/modules/signup/actions/actions.class.php file:

//Include the swift lib
require_once('lib/vendor/swift-mailer/lib/swift_init.php');
//set Flash
$this->getUser()->setFlash('Form', 'completed');
try{

I have added the flash variable just under the require_once() statement. After the user has submitted a valid form, this flash variable will be set with the name of the Form and have a value completed.

Next, we need to address the template logic. The template needs to check whether a flash variable called Form is set. If it is not set, the template shows the form. Otherwise it shows a thank you message. This is implemented using the following code:

<?php if(!$sf_user->hasFlash('Form')): ?>
<form action="<?php echo url_for('@signup_submit') ?>"
      method="post" name="Newsletter">
   <div style="height: 30px;">
      <div style="width: 150px; float: left">
        <?php echo $form['first_name']->renderLabel() ?></div>
      <?php echo $form['first_name']->render(($form['first_name']->
          hasError())? array('class'=>'boxError'): array
                                              ('class'=>'box')) ?>
        <?php echo ($form['first_name']->hasError())?
         ' <span class="errorMessage">*
         '.$form['first_name']->getError(). '</span>': '' ?>
      <div style="clear: both"></div>
    </div>
....
</form>
<?php else: ?>
<h1>Thank you</h1>
You are now signed up.
<?php endif ?>

The form is now wrapped inside an if/else block. Accessing the flash variables from a template is done through $sf_user. To test if the variable has been set, I have used the hasFlash() method, $sf_user->hasFlash(‘Form’). The else part of the statement contains the text rather than the form. Now if you submit your form, you will see the result as shown in the following screenshot:

User Interaction and Email Automation in Symfony 1.3: Part2

We have now implemented an entire module for a user to sign up for our newsletter. Wouldn’t it be really good if we could add this module to another application without all the copying, pasting, and fixing?

LEAVE A REPLY

Please enter your comment!
Please enter your name here