blog site of branko ajzele, senior developer / project manager

Magento – Custom email contact form with notification system

In this article, hopefully, you will learn how to create a module that uses its own controller, programatically creates a block based on core template and assigned via file, handles form submission and utilizes Magento notification system to output the notifications to user.

Although the module it self might look relatively simple in the end, keep in mind that these are powerful concepts that you can latter reuse for much more complex requirements.

file 1:
/app/etc/modules/ActiveCodeline_SimpleContact.xml

content of file 1:

<?xml version="1.0"?>
 
<config>
    <modules>
        <ActiveCodeline_SimpleContact>
            <active>true</active>
            <codePool>local</codePool>
        </ActiveCodeline_SimpleContact>
    </modules>    
</config>

file 2: app/code/local/ActiveCodeline/SimpleContact/etc/config.xml

content of file 2:

<?xml version="1.0"?>
 
<config>
    <modules>
        <ActiveCodeline_SimpleContact>
            <version>0.1.0</version>
        </ActiveCodeline_SimpleContact>
    </modules>   
 
    <frontend>
        <routers>
            <JustSomeFreeRouterNameHereNo1>
                <use>standard</use>
                <args>
                    <module>ActiveCodeline_SimpleContact</module>
                    <frontName>activecodeline-simplecontact</frontName>
                </args>
            </JustSomeFreeRouterNameHereNo1>
        </routers>
    </frontend>    
</config>

As we dissect our module, the first thing that pops up is the “frontend” element. We can see it has lot of sub-elements of which “routers” is first. In order for something in Magento to be accessible on certain url, that something needs to have controller, like all Zend powered applications. Unlike pure Zend apps, Magento has its own way of mapping controllers, trough xml definitions.

I intentionally used “JustSomeFreeRouterNameHereNo1″ for element name making it self explanatory. You can freely assign name to a router wheres “use” and “args” are two parameters each router should have. Parametar “module” if the full name of your module and “frontName” is the actual url path trough which you acccess your controller. In example above I would access my controller indexAction() method trough url like http://shop.local/index.php/activecodeline-simplecontact/index/ or http://shop.local/index.php/activecodeline-simplecontact/. In case we have url rewrite set up we can even access it by omitting the “index.php” part from url.

Now we will look into the content of IndexController.php.

file 3: app/code/local/ActiveCodeline/SimpleContact/controllers/IndexController.php

content of file 3:

<?php
 
class ActiveCodeline_SimpleContact_IndexController extends Mage_Core_Controller_Front_Action
{
    public function indexAction()
    {
        //Get current layout state
        $this->loadLayout();   
 
        $block = $this->getLayout()->createBlock(
            'Mage_Core_Block_Template',
            'activecodeline.simple_contact',
            array(
                'template' => 'activecodeline/simple_contact.phtml'
            )
        );
 
        $this->getLayout()->getBlock('content')->append($block);
        //$this->getLayout()->getBlock('right')->insert($block, 'catalog.compare.sidebar', true);
 
        $this->_initLayoutMessages('core/session');
 
        $this->renderLayout();
    }
 
    public function sendemailAction()
    {
        //Fetch submited params
        $params = $this->getRequest()->getParams();
 
        $mail = new Zend_Mail();
        $mail->setBodyText($params['comment']);
        $mail->setFrom($params['email'], $params['name']);
        $mail->addTo('somebody_else@example.com', 'Some Recipient');
        $mail->setSubject('Test ActiveCodeline_SimpleContact Module for Magento');
        try {
            $mail->send();
        }        
        catch(Exception $ex) {
            Mage::getSingleton('core/session')->addError('Unable to send email. Sample of a custom notification error from ActiveCodeline_SimpleContact.');
 
        }
 
        //Redirect back to index action of (this) activecodeline-simplecontact controller
        $this->_redirect('activecodeline-simplecontact/');
    }
}
 
?>

Above file, although simple, demonstrates two powerful concepts. First we have an example of creating a block “on the fly”. There are several ways one can add an output block to be shown in Magento, this is the “hardest” way. Most of the materials you will find on the web will show you how to do it from xml files. However, I want you to know how to do it from code.

There is one important reason why you should now how to do this from code: Simplicity! If you were to output the block from layout files then you are adding at leas one more file to your module. The more files you have in your module, bigger the chance for bugs. This is really something you should consider and keep in mind for modules who actually require controllers and are not very user centric.

When I say “not very user centric” I think in terms where designer needs to have full control of layout and the way it is arranged. However in cases where not much layout modifications will be required on custom made controller output I believe that “saving yourself” from writing another layout file is the right way to go.

Note that inside the method call createBlock i use ‘Mage_Core_Block_Template’ as one of the parameters. This is the block class. In this example core block template is used. However, you can freely use one of your own declared blocks (will be shown in latter modules). Created block is appended (inserted actualy) in existing block named “content”. Block “content” is one that is almost always present in the output.

Inside the sendemailAction method we have another important concept, the notification system example. Catch exception block triggers the “adding in the notification message” to the session storage. There are few different storage mechanism inside the Magento. Most of them simply extend core/session without any noticeable diference, therefore unles you wish to extend the existing and write your own, you can use the Mage::getSingleton(‘core/session’). You can use 4 diferent types of notification messages: error, warning, notice, success. Which you can call respectively like trough methods addError(’Custom error here’), addWarning(’Custom warning here’), addNotice(’Custom notice here’), addSuccess(’Custom success here’) as shown above.

Any notifications added to ‘core/session’ storage are outputted to frontend trough view files. For instance one such example is app/design/frontend/default/default/template/page/3columns.phtml file. Inside the file there is the getChildHtml(‘global_messages’) ?> line of code that outputs all global notifications. Note that the “global_messages” referes to block name from within the page.xml layout file, which in turn referes to Magento “core/messages” (Mage_Core_Block_Messages) class type.

Final file for our module is the view file itself. As you might notice from the IndexController, we are using the ‘activecodeline/simple_contact.phtml’ as one of the parameters passed to createBlock method. What this means is that our module is going to look for app/design/frontend/default/default/template/activecodeline/simple_contact.phtml file. Note that if we were to assign diferent template then “default” to be used for our site then ‘activecodeline/simple_contact.phtml’ would refer to folder and file from within that template. If that file is not find in this “other” template then the system would look for one in default template.

file 4: app/design/frontend/default/default/template/activecodeline/simple_contact.phtml

content of file 4:

<div class="box simple_contact">
 
<form id="simple_contact_form" name="simple_contact_form" action="<?php echo $this->getUrl('activecodeline-simplecontact/') ?>index/sendemail" method="post">
 
    <fieldset class="group-select">
        <h4 class="legend">ActiveCodeline_SimpleContact module sample</h4>
        <ul>
        <li>
                <div class="input-box">
                    <label for="name">Gimme your name <span class="required">*</span></label><br />
 
                    <input name="name" id="name" title="Name" value="" class="required-entry input-text" type="text" />
                </div>
 
                <div class="input-box">
                    <label for="email">And your email <span class="required">*</span></label><br />
                    <input name="email" id="email" title="Email" value="" class="required-entry input-text validate-email" type="text" />
                </div>
 
                <div class="clear"></div>
 
                <div class="input-box">
           &nbsp;        <label for="comment">Some comment?</label><br />
 
                    <textarea name="comment" id="comment" title="Comment" class="required-entry input-text" style="height:100px;" cols="50" rows="3"></textarea>
                </div>
                </li>
                </ul>
    </fieldset>
    <div class="button-set">
        <p class="required">* Required Fields</p>
        <button class="form-button" type="submit"><span>Submit</span></button>
 
    </div>
</form>
 
</div>

Content of above file is mostly HTML related so there is not much to talk about it.

That’s it, the end.

  • atoz
    Hello all,
    I have made a payment extension and that will create a pdf after the successful checkout. for that i want to put a link in the success page so the user can download the pdf from there. how coukld i make this happen from my module itself please help ........
  • hello dear
    i want to send body of mail would be like
    name:
    email:
    comments:

    but i am using this $mail->setBodyText($params['comment']);

    so it is sending only comments in mail, so can u tell me how m i gonna do what i wrote above. thanks
    plz mail me vaseem@doomshell.com
    Thanks
    http://www.vaseemansari.blogspot.com
  • Soraerae
    I am having the same problem, that I need more than just the comments to be sent to me. Did you figure out a solution to this?
  • hello dear Soraerae
    this is vaseem ansari and i have figured out how to send more text or more description in comments
    suppose u want to send email id, phone no and comments and other fields also, then i can help u,
    if u have resolved the issue then its okey and if u have not u can mail me at vaseem@doomshell.com
    i can provide u the solution for this problem.
  • Soraerae
    Hello I sent you an email, did you get it? I am still looking for a solution
  • Paul
    when the fields are empty and you press send i get an error message. this works great. but how do i get a succes message when the fom is send? any ideas how i can fix this?
  • ChefMaha
    Hey Paul,

    for some reason, with me it's the opposite. I get a success msg but no error message for submitting empty form.

    any idea?
  • Paul
    nevermind. fixed it :)

    code:

    try {
    $mail->send();

    Mage::getSingleton('core/session')->addSuccess('Your succes message.');
    $this->_redirect('*/*/');
    }
  • Ben
    What file is this code placed in?
  • Ben
    i found it use this code to replace line 43 in your indexController.php file
  • pg
    How can i set the page template to 1 column ?
  • ChefMaha
    Hi

    does anybody know how to

    1.include a validation for required fields
    2. preserve the values of the fields when the page refreshes

    thank you
  • Ben
    Just add

    <script type="text/javascript">
    //<![CDATA[
    var contactForm = new VarienForm('contactForm', true);
    //]]>

    to the bottom of your simple_contact.phtml file
    </script>

    to your
  • ChefMaha
    Hey Ben,

    thanks for the solution. But adding those lines of code does not change a thing: No validation. No value preserve.

    thanks again
  • Himali
    This is perfect. working great
  • ChefMaha
    thanks alot for this useful tuturial.

    I'd like to know how to change the page layout from 3-columns to 2-columns right.

    thank you
  • Thanks this is really good article.
    It has help me lot.

    Would you please tell how to do validation in magento way (as done on contact form)?
  • ali
    i follow all the instillation but not working
  • For those of you wanting to use a email template, this code is from the Mage_Contact module and demonstrates how (in the IndexController.php):


    $mailTemplate = Mage::getModel('core/email_template');
    /* @var $mailTemplate Mage_Core_Model_Email_Template */
    $mailTemplate->setDesignConfig(array('area' => 'frontend'))
    ->setReplyTo($post['email'])
    ->sendTransactional(
    Mage::getStoreConfig(self::XML_PATH_EMAIL_TEMPLATE),
    Mage::getStoreConfig(self::XML_PATH_EMAIL_SENDER),
    Mage::getStoreConfig(self::XML_PATH_EMAIL_RECIPIENT),
    null,
    array('data' => $postObject)
    );

    if (!$mailTemplate->getSentSuccess()) {
    throw new Exception();
    }
  • Thanks for this walk through. Worked great.

    Steve
  • Nexus Rex
    Got it working—stupid mistake on my part. Now any idea how to get form validation added into this?
  • San
    Hello,
    I got the same error 404, please tell us, what was the mistake you did.

    San.
  • Nexus Rex
    I too cannot get this to work. I get the "404 Not Found" page:
    http://www.clearprotector.com/activecodeline-si...

    Thanks for any help.

    -Travis Cable
  • Bryan Houghton II
    Hi Slimshock,

    I've managed to get it working. Are there any error messages being displayed.

    One of the problem I came across with is that the email isn't sending. Is this is the problem you are encountering?
  • Umang
    yes.. how did you counter this? No error messages or email coming through
  • slimshock
    I can't make this stuff working.. i follow everything butstill no luck.. anybody try this stuff working?..
  • amadex
    Hi all, a bit off topic: can anybody help me use the url rewrite management to redirect a main category to a sub-category?!... I've searched, searched, searched and found no solution! :(
  • Bryan Houghton II
    Hi Guys,

    I've managed to found a solution for getting an email template.


    Here is my solution, Hope it helps.

    Email Template - brands.phtml



    customer_name; ?>
    Welcome!!!

    New products for brandname; ?>


    <img src="product_image; ?>" />

    Thank you very much for subscribing





    PHP Code

    setScriptPath(ROOT_DIR);

    Mage::log($html->getScriptPaths());

    // assign values
    $html->assign('customer_name', 'John Doe');
    $html->assign('brandname', 'MyBrandname');
    $html->assign('product_image', 'Your Image');

    // render view
    $bodyText = $html->render('brands.phtml');

    ?>
  • pg
    Where and how I do that?

    TIA
  • Bryan Houghton II
    Thank you very much for a very informative tutorial. This is really helpful especially for magento beginners like me.

    I'm following it right now. By the way do you have an idea on how you can send an email to a customer using a custom template? Similar to a product alert.


    Thanks again. Really good articles. :)
blog comments powered by Disqus
Powered by Wordpress | Designed by Elegant Themes