Jason Green avatar Jason Green committed 7ff900a Merge

Merge with emailNotificationsRefactor

Comments (0)

Files changed (42)

app/protected/commands/EmailCommand.php

     public function actionSend($username,
                                $toAddress,
                                $subject          = 'A test email from Zurmo',
-                               $textContent      = 'A test text message from Zurmo',
-                               $htmlContent      = 'A test html message from Zurmo',
+                               $textContent      = 'A test text message from Zurmo.',
+                               $htmlContent      = 'A test html message from Zurmo.',
                                $host             = null,
                                $port             = null,
                                $outboundUsername = null,

app/protected/extensions/zurmoinc/framework/data/DemoEmailNotifications.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    /**
+     * Base class for sending out sample email notifications during development and testing.
+     */
+    abstract class DemoEmailNotifications
+    {
+        abstract public function run(User $userToSendTo, $messageLogger);
+    }
+?>

app/protected/extensions/zurmoinc/framework/models/RedBeanModel.php

             }
             else
             {
-                throw new NotSupportedException();
+                throw new NotSupportedException('Invalid Attribute: ' . $attributeName);
             }
         }
 

app/protected/extensions/zurmoinc/framework/views/DetailsView.php

             parent::assertMetadataIsValid($metadata);
             $attributeNames = array();
             $derivedTypes   = array();
-            assert('is_int($metadata["global"]["panelsDisplayType"])');
+            assert('!isset($metadata["global"]["panelsDisplayType"]) || is_int($metadata["global"]["panelsDisplayType"])');
         }
 
         /**

app/protected/extensions/zurmoinc/framework/views/ModelView.php

             parent::assertMetadataIsValid($metadata);
             $attributeNames = array();
             $derivedTypes   = array();
-            assert('is_array($metadata["global"]["panels"])');
-            foreach ($metadata["global"]["panels"] as $panel)
+            if (isset($metadata['global']['panels']))
             {
-                assert('is_array($panel["rows"])');
-                foreach ($panel["rows"] as $row)
+                foreach ($metadata["global"]["panels"] as $panel)
                 {
-                    $cellCount = 0;
-                    assert('is_array($row["cells"])');
-                    foreach ($row["cells"] as $cell)
+                    assert('is_array($panel["rows"])');
+                    foreach ($panel["rows"] as $row)
                     {
-                        if (is_array($cell['elements']))
+                        $cellCount = 0;
+                        assert('is_array($row["cells"])');
+                        foreach ($row["cells"] as $cell)
                         {
-                            assert('count($cell["elements"]) == 1');
-                            $elementInformation = $cell['elements'][0];
-                            if ($elementInformation['attributeName'] == 'null')
+                            if (is_array($cell['elements']))
                             {
-                                assert('!in_array($elementInformation["type"], $derivedTypes)');
-                                $derivedTypes[] = $elementInformation['type'];
-                                $elementclassname = $elementInformation['type'] . 'Element';
-                                assert('class_exists($elementclassname)');
+                                assert('count($cell["elements"]) == 1');
+                                $elementInformation = $cell['elements'][0];
+                                if ($elementInformation['attributeName'] == 'null')
+                                {
+                                    assert('!in_array($elementInformation["type"], $derivedTypes)');
+                                    $derivedTypes[] = $elementInformation['type'];
+                                    $elementclassname = $elementInformation['type'] . 'Element';
+                                    assert('class_exists($elementclassname)');
+                                }
+                                elseif ($elementInformation['attributeName'] == null)
+                                {
+                                    assert('$elementInformation["type"] == "Null"'); // Not Coding Standard
+                                }
+                                else
+                                {
+                                    /* Is attribute present more than once on the view? */
+                                    assert('!in_array($elementInformation["attributeName"], $attributeNames)');
+                                    $attributeNames[] = $elementInformation['attributeName'];
+                                    assert('is_string($elementInformation["attributeName"])');
+                                }
                             }
-                            elseif ($elementInformation['attributeName'] == null)
-                            {
-                                assert('$elementInformation["type"] == "Null"'); // Not Coding Standard
-                            }
-                            else
-                            {
-                                /* Is attribute present more than once on the view? */
-                                assert('!in_array($elementInformation["attributeName"], $attributeNames)');
-                                $attributeNames[] = $elementInformation['attributeName'];
-                                assert('is_string($elementInformation["attributeName"])');
-                            }
+                            $cellCount++;
+                            $designerRules = DesignerRulesFactory::createDesignerRulesByView(get_called_class());
+                            assert('$cellCount <= $designerRules->maxCellsPerRow()');
                         }
-                        $cellCount++;
-                        $designerRules = DesignerRulesFactory::createDesignerRulesByView(get_called_class());
-                        assert('$cellCount <= $designerRules->maxCellsPerRow()');
                     }
                 }
             }

app/protected/modules/comments/messages/de/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/comments/messages/es/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/comments/messages/fr/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/comments/messages/it/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/conversations/data/ConversationsDemoDataMaker.php

                 $explicitReadWriteModelPermissions = ExplicitReadWriteModelPermissionsUtil::
                                                      makeBySecurableItem($conversation);
                 ConversationParticipantsUtil::resolveConversationHasManyParticipantsFromPost(
-                                                $conversation, $postData, $explicitReadWriteModelPermissions);
+                                                $conversation, $postData, $explicitReadWriteModelPermissions, false);
                 $saved = $conversation->save();
                 assert('$saved');
                 $success = ExplicitReadWriteModelPermissionsUtil::

app/protected/modules/conversations/data/ConversationsDemoEmailNotifications.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    class ConversationsDemoEmailNotifications extends DemoEmailNotifications
+    {
+        public function run(User $userToSendTo, $messageLogger)
+        {
+            $conversation              = new Conversation();
+            $conversation->owner       = Yii::app()->user->userModel;
+            $conversation->subject     = 'My test subject';
+            $conversation->description = 'My test description';
+            if(!$conversation->save())
+            {
+                throw new FailedToSaveModelException();
+            }
+            ConversationParticipantsUtil::sendEmailInviteToParticipant($conversation, $userToSendTo);
+            $messageLogger->addInfoMessage('Sending conversation invite message');
+        }
+    }
+
+?>

app/protected/modules/conversations/messages/de/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/conversations/messages/es/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/conversations/messages/fr/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/conversations/messages/it/Default.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    // KEEP these in alphabetical order.
+    // KEEP them indented correctly.
+    // KEEP all the language files up-to-date with each other.
+    // DON'T MAKE A MESS!
+    return array(
+
+    );
+?>

app/protected/modules/conversations/tests/unit/ConversationParticipantsUtilTest.php

 
             //test no existing participants. Do not add owner of conversation
             $postData            = array();
-            $postData['itemIds'] = $super->id;
+            $postData['itemIds'] = $super->getClassId('Item');
             ConversationParticipantsUtil::resolveConversationHasManyParticipantsFromPost(
                                             $conversation, $postData, $explicitReadWriteModelPermissions);
             $readWritePermitables              = $explicitReadWriteModelPermissions->getReadWritePermitables();

app/protected/modules/conversations/tests/unit/walkthrough/ConversationsUserWalkthroughTest.php

             //should update latest activity stamp
             $this->assertNotEquals($oldStamp, $conversations[0]->latestDateTime);
             $newStamp = $conversations[0]->latestDateTime;
-
+            sleep(2); // Sleeps are bad in tests, but I need some time to pass
             //Mary is not a participant, so she should not be able to add a comment
             $mary = $this->logoutCurrentUserLoginNewUserAndGetByUsername('mary');
             $this->setGetArray(array('relatedModelId'             => $conversations[0]->id,

app/protected/modules/conversations/utils/ConversationParticipantsUtil.php

          * @param object $explicitReadWriteModelPermissions - ExplicitReadWriteModelPermissions model
          */
         public static function resolveConversationHasManyParticipantsFromPost(
-                                    Conversation $conversation, $postData, $explicitReadWriteModelPermissions)
+                                    Conversation $conversation, $postData, $explicitReadWriteModelPermissions,
+                                    $sendNotifications = true)
         {
             assert('$explicitReadWriteModelPermissions instanceof ExplicitReadWriteModelPermissions');
             if (isset($postData['itemIds']) && strlen($postData['itemIds']) > 0)
                     {
                         $explicitReadWriteModelPermissions->addReadWritePermitable($personOrUserModel);
                     }
-                    static::sendEmailInviteToParticipant($conversation, $personOrUserModel);
+                    if($sendNotifications)
+                    {
+                        static::sendEmailInviteToParticipant($conversation, $personOrUserModel);
+                    }
                 }
             }
             else
             return $conversationParticipant;
         }
 
-        protected static function sendEmailInviteToParticipant(Conversation $conversation, $person)
+        public static function sendEmailInviteToParticipant(Conversation $conversation, $person)
         {
             assert('$person instanceof User || $person instanceof Contact');
-            if ($person->primaryEmail->emailAddress !== null)
+            if ($person->primaryEmail->emailAddress !== null &&
+                (($person instanceof User &&
+                !UserConfigurationFormAdapter::resolveAndGetTurnOffEmailNotificationsValue($person)) ||
+                 $person instanceof Contact))
             {
                 $userToSendMessagesFrom     = $conversation->owner;
                 $emailMessage               = new EmailMessage();
                 $emailMessage->owner        = Yii::app()->user->userModel;
                 $emailMessage->subject      = Yii::t('Default', 'You have been invited to participate in a conversation');
                 $emailContent               = new EmailMessageContent();
-                $emailContent->textContent  = static::getPartipantInviteEmailTextContent ($conversation);
-                $emailContent->htmlContent  = static::getPartipantInviteEmailHtmlContent($conversation);
+                $emailContent->textContent  = EmailNotificationUtil::
+                                                resolveNotificationTextTemplate(
+                                                static::getParticipantInviteEmailTextContent($conversation));
+                $emailContent->htmlContent  = EmailNotificationUtil::
+                                                resolveNotificationHtmlTemplate(
+                                                static::getParticipantInviteEmailHtmlContent($conversation));
                 $emailMessage->content      = $emailContent;
                 $sender                     = new EmailMessageSender();
                 $sender->fromAddress        = Yii::app()->emailHelper->resolveFromAddressByUser($userToSendMessagesFrom);
             }
         }
 
-        protected static function getPartipantInviteEmailTextContent(Conversation $conversation)
+        protected static function getParticipantInviteEmailTextContent(Conversation $conversation)
         {
-            $url      = static::getUrlToConversationDetailAndRelationsView($conversation->id);
-            $content  = Yii::t('Default', '{ownerName} would like you to join a conversation "{conversationSubject}".',
-                               array('{ownerName}'           => $conversation->owner,
+            $url     = static::getUrlToConversationDetailAndRelationsView($conversation->id);
+            $content = Yii::t('Default', '{headerStartTag}Join the Conversation{headerEndTag}{headerLineBreak}{ownerName} ' .
+                                         'would like you to join a conversation {strongStartTag}"{conversationSubject}"{strongEndTag}',
+                               array('{headerStartTag}'	     => null,
+                                     '{headerEndTag}'		 => null,
+                                     '{headerLineBreak}'	 => "\n\n",
+                                     '{strongStartTag}'		 => null,
+                                     '{strongEndTag}'		 => null,
+                                     '{ownerName}'           => $conversation->owner,
                                      '{conversationSubject}' => $conversation->subject));
             $content .= "\n\n";
             $content .= CHtml::link($url, $url);
             return $content;
         }
 
-        protected static function getPartipantInviteEmailHtmlContent(Conversation $conversation)
+        protected static function getParticipantInviteEmailHtmlContent(Conversation $conversation)
         {
             $url     = static::getUrlToConversationDetailAndRelationsView($conversation->id);
-            $content = Yii::t('Default', '{ownerName} would like you to join a conversation "{conversationSubject}".',
-                               array('{ownerName}'           => $conversation->owner,
+            $content = Yii::t('Default', '{headerStartTag}Join the Conversation{headerEndTag}{headerLineBreak}{ownerName} ' .
+                                         'would like you to join a conversation {strongStartTag}"{conversationSubject}"{strongEndTag}',
+                               array('{headerStartTag}'	     => '<h2 class="h2">',
+                                     '{headerEndTag}'		 => '</h2>',
+                                     '{headerLineBreak}'	 => null,
+                                     '{strongStartTag}'		 => '<strong>',
+                                     '{strongEndTag}'		 => '</strong>',
+                                     '{ownerName}'           => $conversation->owner,
                                      '{conversationSubject}' => $conversation->subject));
-            $content .= "<br/><br/>";
+            $content .= "<br/>";
             $content .= CHtml::link(Yii::t('Default', 'Click Here'), $url);
             return $content;
         }

app/protected/modules/emailMessages/controllers/DefaultController.php

                     $emailHelper->outboundSecurity = $configurationForm->security;
                     $userToSendMessagesFrom        = User::getById((int)$configurationForm->userIdOfUserToSendNotificationsAs);
 
-                    $emailMessage              = new EmailMessage();
-                    $emailMessage->owner       = Yii::app()->user->userModel;
-                    $emailMessage->subject     = Yii::t('Default', 'A test email from Zurmo');
-                    $emailContent              = new EmailMessageContent();
-                    $emailContent->textContent = Yii::t('Default', 'A test text message from Zurmo');
-                    $emailContent->htmlContent = Yii::t('Default', 'A test text message from Zurmo');
-                    $emailMessage->content     = $emailContent;
-                    $sender                    = new EmailMessageSender();
-                    $sender->fromAddress       = $emailHelper->resolveFromAddressByUser($userToSendMessagesFrom);
-                    $sender->fromName          = strval($userToSendMessagesFrom);
-                    $emailMessage->sender      = $sender;
-                    $recipient                 = new EmailMessageRecipient();
-                    $recipient->toAddress      = $configurationForm->aTestToAddress;
-                    $recipient->toName         = 'Test Recipient';
-                    $recipient->type           = EmailMessageRecipient::TYPE_TO;
-                    $emailMessage->recipients->add($recipient);
-                    $box                       = EmailBox::resolveAndGetByName(EmailBox::NOTIFICATIONS_NAME);
-                    $emailMessage->folder      = EmailFolder::getByBoxAndType($box, EmailFolder::TYPE_DRAFT);
-                    $validated                 = $emailMessage->validate();
-                    if (!$validated)
-                    {
-                        throw new NotSupportedException();
-                    }
+                    $emailMessage = EmailMessageHelper::sendTestEmail($emailHelper, $userToSendMessagesFrom,
+                                                                      $configurationForm->aTestToAddress);
                     $messageContent  = null;
-                    $emailHelper->sendImmediately($emailMessage);
                     if (!$emailMessage->hasSendError())
                     {
                         $messageContent .= Yii::t('Default', 'Message successfully sent') . "\n";

app/protected/modules/emailMessages/controllers/DemoController.php

                 throw new NotSupportedException();
             }
         }
+
+        public function actionSendDemoEmailNotifications()
+        {
+            if (Yii::app()->user->userModel->username != 'super')
+            {
+                throw new NotSupportedException();
+            }
+            $template        = "{message}<br/>";
+            $messageStreamer = new MessageStreamer($template);
+            $messageStreamer->setExtraRenderBytes(0);
+            $messageLogger = new MessageLogger($messageStreamer);
+
+            if(Yii::app()->user->userModel->primaryEmail->emailAddress == null)
+            {
+                $messageLogger->addErrorMessage('Cannot send test emails because the current user does not have an email address');
+                Yii::app()->end(0, false);
+            }
+            $messageLogger->addInfoMessage('Using type:' . Yii::app()->emailHelper->outboundType);
+            $messageLogger->addInfoMessage('Using host:' . Yii::app()->emailHelper->outboundHost);
+            $messageLogger->addInfoMessage('Using port:' . Yii::app()->emailHelper->outboundPort);
+            $messageLogger->addInfoMessage('Using username:' . Yii::app()->emailHelper->outboundUsername);
+            if(Yii::app()->emailHelper->outboundPassword != null)
+            {
+                $messageLogger->addInfoMessage('Using password: Yes');
+            }
+            else
+            {
+                $messageLogger->addInfoMessage('Using password: No');
+            }
+            $modules = Module::getModuleObjects();
+            foreach ($modules as $module)
+            {
+                $notificationClassNames = $module::getAllClassNamesByPathFolder('data');
+                foreach ($notificationClassNames as $notificationClassName)
+                {
+                    if (!strpos($notificationClassName, 'DemoEmailNotifications') === false)
+                    {
+                        $demoNotification = new $notificationClassName();
+                        $demoNotification->run(Yii::app()->user->userModel, $messageLogger);
+                    }
+                }
+            }
+            Yii::app()->emailHelper->sendQueued();
+        }
     }
 ?>

app/protected/modules/emailMessages/data/EmailMessagesDemoEmailNotifications.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    class EmailMessagesDemoEmailNotifications extends DemoEmailNotifications
+    {
+        public function run(User $userToSendTo, $messageLogger)
+        {
+            $emailMessage = EmailMessageHelper::sendTestEmail(Yii::app()->emailHelper, Yii::app()->user->userModel,
+                                                              Yii::app()->user->userModel->primaryEmail->emailAddress);
+            $messageLogger->addInfoMessage('Sending test SMTP setup message');
+        }
+    }
+
+?>

app/protected/modules/emailMessages/jobs/TestOutboundEmailJob.php

             $emailMessage->owner       = Yii::app()->user->userModel;
             $emailMessage->subject     = Yii::t('Default', 'A test email from Zurmo');
             $emailContent              = new EmailMessageContent();
-            $emailContent->textContent = Yii::t('Default', 'A test text message from Zurmo');
-            $emailContent->htmlContent = Yii::t('Default', 'A test text message from Zurmo');
+            $emailContent->textContent = Yii::t('Default', 'A test text message from Zurmo.');
+            $emailContent->htmlContent = Yii::t('Default', 'A test text message from Zurmo.');
             $emailMessage->content     = $emailContent;
             $sender                    = new EmailMessageSender();
             $sender->fromAddress       = Yii::app()->emailHelper->resolveFromAddressByUser($userToSendMessagesFrom);

app/protected/modules/emailMessages/messages/de/Default.php

             => 'Bitte geben Sie eine E-Mail-Adresse.',
         'A test email from Zurmo'
             => 'Eine Testnachricht von Zurmo',
-        'A test text message from Zurmo'
-            => 'Eine Textnachricht von Zurmo',
+        'A test text message from Zurmo.'
+            => 'Eine Textnachricht von Zurmo.',
         'Access Email Configuration'
             => 'Zugriff auf die E-Mail Konfiguration',
         'Access Emails Tab'

app/protected/modules/emailMessages/messages/es/Default.php

             => 'Por favor, introduzca una dirección de email.',
         'A test email from Zurmo'
             => 'Un mensaje de prueba de  Zurmo',
-        'A test text message from Zurmo'
-            => 'Un mensaje de texto de Zurmo',
+        'A test text message from Zurmo.'
+            => 'Un mensaje de texto de Zurmo.',
         'Access Email Configuration'
             => 'Acceso a la configuración email',
         'Access Emails Tab'

app/protected/modules/emailMessages/messages/fr/Default.php

             => 'Veuillez saisir une adresse email.',
         'A test email from Zurmo'
             => 'Un message de test de Zurmo',
-        'A test text message from Zurmo'
-            => 'Une message texte de Zurmo',
+        'A test text message from Zurmo.'
+            => 'Une message texte de Zurmo.',
         'Access Email Configuration'
             => 'Accès à la configuration email',
         'Access Emails Tab'

app/protected/modules/emailMessages/messages/it/Default.php

             => 'Si prega di inserire un indirizzo e-mail per inviare una email di prova.',
         'A test email from Zurmo'
             => 'Un messaggio di prova da Zurmo',
-        'A test text message from Zurmo'
-            => 'Un messaggio SMS di prova da Zurmo',
+        'A test text message from Zurmo.'
+            => 'Un messaggio SMS di prova da Zurmo.',
         'Access Email Configuration'
             => 'Accesso alla configurazione di mail',
         'Access Emails Tab'

app/protected/modules/emailMessages/utils/EmailMessageHelper.php

                 return false;
             }
         }
+
+        public static function sendTestEmail(EmailHelper $emailHelper, User $userToSendMessagesFrom, $toAddress)
+        {
+            $emailMessage              = new EmailMessage();
+            $emailMessage->owner       = Yii::app()->user->userModel;
+            $emailMessage->subject     = Yii::t('Default', 'A test email from Zurmo');
+            $emailContent              = new EmailMessageContent();
+            $emailContent->textContent = EmailNotificationUtil::
+                                            resolveNotificationTextTemplate(
+                                            Yii::t('Default', 'A test text message from Zurmo.'));
+            $emailContent->htmlContent = EmailNotificationUtil::
+                                            resolveNotificationHtmlTemplate(
+                                            Yii::t('Default', 'A test text message from Zurmo.'));
+            $emailMessage->content     = $emailContent;
+            $sender                    = new EmailMessageSender();
+            $sender->fromAddress       = $emailHelper->resolveFromAddressByUser($userToSendMessagesFrom);
+            $sender->fromName          = strval($userToSendMessagesFrom);
+            $emailMessage->sender      = $sender;
+            $recipient                 = new EmailMessageRecipient();
+            $recipient->toAddress      = $toAddress;
+            $recipient->toName         = 'Test Recipient';
+            $recipient->type           = EmailMessageRecipient::TYPE_TO;
+            $emailMessage->recipients->add($recipient);
+            $box                       = EmailBox::resolveAndGetByName(EmailBox::NOTIFICATIONS_NAME);
+            $emailMessage->folder      = EmailFolder::getByBoxAndType($box, EmailFolder::TYPE_DRAFT);
+            $validated                 = $emailMessage->validate();
+            if (!$validated)
+            {
+                throw new NotSupportedException();
+            }
+            $emailHelper->sendImmediately($emailMessage);
+            return $emailMessage;
+        }
     }

app/protected/modules/emailMessages/utils/EmailNotificationUtil.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    class EmailNotificationUtil
+    {
+        /**
+         * Based on the current theme, retrieve the email notification template for html content and replace the
+         * content tags with the appropriate strings
+         */
+        public static function resolveNotificationHtmlTemplate($bodyContent)
+        {
+            assert('is_string($bodyContent)');
+            $url                                = Yii::app()->createAbsoluteUrl('users/default/edit',
+                                                  array('id' => Yii::app()->user->userModel->id));
+            $htmlTemplate                       = self::getNotificationHtmlTemplate();
+            $htmlContent                        = array();
+            $htmlContent['{bodyContent}']       = $bodyContent;
+            $htmlContent['{sourceContent}']     = Yii::t('Default', 'This message sent from Zurmo');
+            $htmlContent['{preferenceContent}'] = ZurmoHtml::link(Yii::t('Default', 'Manage your email preferences'), $url);
+            return strtr($htmlTemplate, $htmlContent);
+        }
+
+        protected static function getNotificationHtmlTemplate()
+        {
+            $theme        = Yii::app()->theme->name;
+            $name         = 'NotificationEmailTemplate';
+            $templateName = "themes/$theme/templates/$name.html";
+            if (!file_exists($templateName))
+            {
+                $templateName = "themes/default/templates/$name.html";
+            }
+            if (file_exists($templateName))
+            {
+                return file_get_contents($templateName);
+            }
+        }
+
+        /**
+         * Based on the current theme, retrieve the email notification template for text content and replace the
+         * content tags with the appropriate strings
+         */
+        public static function resolveNotificationTextTemplate($bodyContent)
+        {
+            assert('is_string($bodyContent)');
+            $url                                = Yii::app()->createAbsoluteUrl('users/default/configurationEdit',
+                                                  array('id' => Yii::app()->user->userModel->id));
+            $htmlTemplate                       = self::getNotificationTextTemplate();
+            $htmlContent                        = array();
+            $htmlContent['{bodyContent}']       = $bodyContent;
+            $htmlContent['{sourceContent}']     = Yii::t('Default', 'This message sent from Zurmo');
+            $htmlContent['{preferenceContent}'] = Yii::t('Default', 'Manage your email preferences') . ZurmoHtml::link(null, $url);
+            return strtr($htmlTemplate, $htmlContent);
+        }
+
+        protected static function getNotificationTextTemplate()
+        {
+            $theme        = Yii::app()->theme->name;
+            $name         = 'NotificationEmailTemplate';
+            $templateName = "themes/$theme/templates/$name.txt";
+            if (!file_exists($templateName))
+            {
+                $templateName = "themes/default/templates/$name.txt";
+            }
+            if (file_exists($templateName))
+            {
+                return file_get_contents($templateName);
+            }
+        }
+    }
+?>

app/protected/modules/install/tests/unit/AutoBuildDatabaseTest.php

             $beforeRowCount             = DatabaseCompatibilityUtil::getTableRowsCountTotal();
             InstallUtil::autoBuildDatabase($messageLogger);
             $afterRowCount              = DatabaseCompatibilityUtil::getTableRowsCountTotal();
-            //There are only 3 extra rows that are not being removed during the autobuild process.
+            //There are only 1 extra rows that are not being removed during the autobuild process.
             //These need to eventually be fixed so they are properly removed, except currency which is ok.
-            //contact_Opportunity, (1) _group__user (1), currency (1)
-            $this->assertEquals($beforeRowCount, ($afterRowCount - 3));
+            //currency (1)
+            $this->assertEquals($beforeRowCount, ($afterRowCount - 1));
             if ($unfreezeWhenDone)
             {
                 RedBeanDatabase::freeze();

app/protected/modules/jobsManager/data/JobsManagerDemoEmailNotifications.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    class JobsManagerDemoEmailNotifications extends DemoEmailNotifications
+    {
+        public function run(User $userToSendTo, $messageLogger)
+        {
+            MonitorJob::makeJobStuckNotification();
+            $messageLogger->addInfoMessage('Sending a job is stuck message');
+            JobsManagerUtil::makeMonitorStuckJobNotification();
+            $messageLogger->addInfoMessage('Sending monitor job stuck message');
+
+            //Clear out notifications for super user
+            $searchAttributeData = array();
+            $searchAttributeData['clauses'] = array(
+                1 => array(
+                    'attributeName'        => 'owner',
+                    'relatedAttributeName' => 'id',
+                    'operatorType'         => 'equals',
+                    'value'                => Yii::app()->user->userModel->id,
+                ),
+            );
+            $searchAttributeData['structure'] = '1';
+            $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter('Notification');
+            $where = RedBeanModelDataProvider::makeWhere('Notification', $searchAttributeData, $joinTablesAdapter);
+            $models = Notification::getSubset($joinTablesAdapter, null, null, $where, null);
+            foreach($models as $model)
+            {
+                $model->delete();
+            }
+        }
+    }
+
+?>

app/protected/modules/jobsManager/jobs/MonitorJob.php

             {
                 if (JobsManagerUtil::isJobInProcessOverThreashold($jobInProcess, $jobInProcess->type))
                 {
-                    $message                    = new NotificationMessage();
-                    $message->textContent       = Yii::t('Default', 'The system has detected there are jobs that are stuck.');
-                    $rules                      = new StuckJobsNotificationRules();
-                    NotificationsUtil::submit($message, $rules);
+                    self::makeJobStuckNotification();
                 }
             }
             $jobLogs = static::getNonMonitorJobLogsUnprocessed();
             $where = RedBeanModelDataProvider::makeWhere('JobLog', $searchAttributeData, $joinTablesAdapter);
             return JobLog::getSubset($joinTablesAdapter, null, null, $where, null);
         }
+
+        public static function makeJobStuckNotification()
+        {
+            $message                    = new NotificationMessage();
+            $message->textContent       = Yii::t('Default', 'The system has detected there are jobs that are stuck.');
+            $message->htmlContent       = Yii::t('Default', 'The system has detected there are jobs that are stuck.');
+            $rules                      = new StuckJobsNotificationRules();
+            NotificationsUtil::submit($message, $rules);
+        }
     }
 ?>

app/protected/modules/jobsManager/utils/JobsManagerUtil.php

                 if (static::isJobInProcessOverThreashold($jobInProcess, 'Monitor'))
                 {
                     $messageLogger->addInfoMessage("Existing monitor job is stuck");
-                    $message                    = new NotificationMessage();
-                    $message->textContent       = MonitorJob::getStuckStringContent();
-                    $rules                      = new StuckMonitorJobNotificationRules();
-                    NotificationsUtil::submit($message, $rules);
+                    self::makeMonitorStuckJobNotification();
                 }
             }
             catch (NotFoundException $e)
             }
         }
 
+        public static function makeMonitorStuckJobNotification()
+        {
+            $message                    = new NotificationMessage();
+            $message->textContent       = MonitorJob::getStuckStringContent();
+            $message->htmlContent       = MonitorJob::getStuckStringContent();
+            $rules                      = new StuckMonitorJobNotificationRules();
+            NotificationsUtil::submit($message, $rules);
+        }
+
         /**
          * Given a 'type' of job, run the job.  This is for non-monitor jobs only.
          * @param string $type

app/protected/modules/notifications/utils/NotificationsUtil.php

 
         protected static function sendEmail(Notification $notification)
         {
-            if ($notification->owner->primaryEmail->emailAddress !== null)
+            if ($notification->owner->primaryEmail->emailAddress !== null &&
+                !UserConfigurationFormAdapter::resolveAndGetTurnOffEmailNotificationsValue($notification->owner))
             {
                 $userToSendMessagesFrom     = Yii::app()->emailHelper->getUserToSendNotificationsAs();
                 $emailMessage               = new EmailMessage();
                 $emailMessage->owner        = Yii::app()->user->userModel;
                 $emailMessage->subject      = static::getEmailSubject();
                 $emailContent               = new EmailMessageContent();
-                $emailContent->textContent  = $notification->notificationMessage->textContent;
-                $emailContent->htmlContent  = $notification->notificationMessage->htmlContent;
+                $emailContent->textContent  = EmailNotificationUtil::
+                                                resolveNotificationTextTemplate(
+                                                $notification->notificationMessage->textContent);
+                $emailContent->htmlContent  = EmailNotificationUtil::
+                                                resolveNotificationHtmlTemplate(
+                                                $notification->notificationMessage->htmlContent);
                 $emailMessage->content      = $emailContent;
                 $sender                     = new EmailMessageSender();
                 $sender->fromAddress        = Yii::app()->emailHelper->resolveFromAddressByUser($userToSendMessagesFrom);

app/protected/modules/users/adapters/UserConfigurationFormAdapter.php

         public static function makeFormFromUserConfigurationByUser(User $user)
         {
             assert('$user instanceOf User && $user->id > 0');
-            $form                           = new UserConfigurationForm($user->id);
-            $form->listPageSize             = Yii::app()->pagination->getByUserAndType($user, 'listPageSize');
-            $form->subListPageSize          = Yii::app()->pagination->getByUserAndType($user, 'subListPageSize');
-            $form->hideWelcomeView          = static::resolveAndGetHideWelcomeViewValue($user);
+            $form                            = new UserConfigurationForm($user->id);
+            $form->listPageSize              = Yii::app()->pagination->getByUserAndType($user, 'listPageSize');
+            $form->subListPageSize           = Yii::app()->pagination->getByUserAndType($user, 'subListPageSize');
+            $form->hideWelcomeView           = static::resolveAndGetHideWelcomeViewValue($user);
+            $form->turnOffEmailNotifications = static::resolveAndGetTurnOffEmailNotificationsValue($user);
             return $form;
         }
 
             Yii::app()->pagination    ->setByUserAndType($user, 'listPageSize',    (int)$form->listPageSize);
             Yii::app()->pagination    ->setByUserAndType($user, 'subListPageSize', (int)$form->subListPageSize);
             static::setHideWelcomeViewValue($user, (bool)$form->hideWelcomeView);
+            static::setTurnOffEmailNotificationsValue($user, (bool)$form->turnOffEmailNotifications);
         }
 
         /**
         {
             Yii::app()->pagination    ->setForCurrentUserByType('listPageSize',    (int)$form->listPageSize);
             Yii::app()->pagination    ->setForCurrentUserByType('subListPageSize', (int)$form->subListPageSize);
-            static::setHideWelcomeViewValue(Yii::app()->user->userModel, (bool)$form->hideWelcomeView);
+            static::setHideWelcomeViewValue          (Yii::app()->user->userModel, (bool)$form->hideWelcomeView);
+            static::setTurnOffEmailNotificationsValue(Yii::app()->user->userModel, (bool)$form->turnOffEmailNotifications);
         }
 
         public static function resolveAndGetHideWelcomeViewValue(User $user)
             assert('is_bool($value)');
             ZurmoConfigurationUtil::setByUserAndModuleName($user, 'ZurmoModule', 'hideWelcomeView', $value);
         }
+
+        public static function resolveAndGetTurnOffEmailNotificationsValue(User $user)
+        {
+            assert('$user instanceOf User && $user->id > 0');
+            if ( null != $turnOff = ZurmoConfigurationUtil::getByUserAndModuleName($user, 'ZurmoModule', 'turnOffEmailNotifications'))
+            {
+                return $turnOff;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        public static function setTurnOffEmailNotificationsValue(User $user, $value)
+        {
+            assert('is_bool($value)');
+            ZurmoConfigurationUtil::setByUserAndModuleName($user, 'ZurmoModule', 'turnOffEmailNotifications', $value);
+        }
     }
 ?>

app/protected/modules/users/forms/UserConfigurationForm.php

 
         public $hideWelcomeView = false;
 
+        public $turnOffEmailNotifications = false;
+
         public function __construct($userId)
         {
             assert('is_int($userId) && $userId > 0');
         public function rules()
         {
             return array(
-                array('listPageSize',             'required'),
-                array('listPageSize',             'type',      'type' => 'integer'),
-                array('listPageSize',             'numerical', 'min' => 1),
-                array('subListPageSize',          'required'),
-                array('subListPageSize',          'type',      'type' => 'integer'),
-                array('subListPageSize',          'numerical', 'min' => 1),
-                array('hideWelcomeView',          'boolean'),
+                array('listPageSize',              'required'),
+                array('listPageSize',              'type',      'type' => 'integer'),
+                array('listPageSize',              'numerical', 'min' => 1),
+                array('subListPageSize',           'required'),
+                array('subListPageSize',           'type',      'type' => 'integer'),
+                array('subListPageSize',           'numerical', 'min' => 1),
+                array('hideWelcomeView',           'boolean'),
+                array('turnOffEmailNotifications', 'boolean')
             );
         }
 
                 'listPageSize'              => Yii::t('Default', 'List page size'),
                 'subListPageSize'           => Yii::t('Default', 'Sublist page size'),
                 'hideWelcomeView'           => Yii::t('Default', 'Hide welcome page'),
+                'turnOffEmailNotifications' => Yii::t('Default', 'Turn off email notifications')
             );
         }
     }

app/protected/modules/users/tests/unit/UserConfigurationFormAdapterTest.php

             $this->assertEquals(50,                 $form->listPageSize);
             $this->assertEquals(51,                 $form->subListPageSize);
             $this->assertFalse(UserConfigurationFormAdapter::resolveAndGetHideWelcomeViewValue($sally));
+            $this->assertFalse(UserConfigurationFormAdapter::resolveAndGetTurnOffEmailNotificationsValue($sally));
             //Confirm billy's configuration is the defaults.
             $form = UserConfigurationFormAdapter::makeFormFromUserConfigurationByUser($billy);
             $this->assertEquals(50,                 $form->listPageSize);
             $this->assertEquals(51,                 $form->subListPageSize);
             $this->assertFalse(UserConfigurationFormAdapter::resolveAndGetHideWelcomeViewValue($billy));
+            $this->assertFalse(UserConfigurationFormAdapter::resolveAndGetTurnOffEmailNotificationsValue($billy));
             //Now change configuration for Billy.
-            $form->listPageSize      = 60;
-            $form->subListPageSize   = 61;
-            $form->hideWelcomeView   = true;
+            $form->listPageSize                = 60;
+            $form->subListPageSize             = 61;
+            $form->hideWelcomeView             = true;
+            $form->turnOffEmailNotifications   = true;
             UserConfigurationFormAdapter::setConfigurationFromForm($form, $billy);
             //Confirm billy's settings are changed correctly.
             $form = UserConfigurationFormAdapter::makeFormFromUserConfigurationByUser($billy);
             $this->assertEquals(60,                 $form->listPageSize);
             $this->assertEquals(61,                 $form->subListPageSize);
             $this->assertTrue(UserConfigurationFormAdapter::resolveAndGetHideWelcomeViewValue($billy));
+            $this->assertTrue(UserConfigurationFormAdapter::resolveAndGetTurnOffEmailNotificationsValue($billy));
             $this->assertFalse(UserConfigurationFormAdapter::resolveAndGetHideWelcomeViewValue($sally));
+            $this->assertFalse(UserConfigurationFormAdapter::resolveAndGetTurnOffEmailNotificationsValue($sally));
             //Now set configuration settings for sally and confirm they are correct.
             Yii::app()->user->userModel = $sally;
             UserConfigurationFormAdapter::setConfigurationFromFormForCurrentUser($form);
             $this->assertEquals(60,                 $form->listPageSize);
             $this->assertEquals(61,                 $form->subListPageSize);
             $this->assertTrue(UserConfigurationFormAdapter::resolveAndGetHideWelcomeViewValue($sally));
+            $this->assertTrue(UserConfigurationFormAdapter::resolveAndGetTurnOffEmailNotificationsValue($sally));
         }
     }
 ?>

app/protected/modules/users/views/UserConfigurationEditView.php

                                         ),
                                     )
                                 ),
+                                array('cells' =>
+                                    array(
+                                        array(
+                                            'elements' => array(
+                                                array('attributeName' => 'turnOffEmailNotifications', 'type' => 'CheckBox'),
+                                            ),
+                                        ),
+                                    )
+                                ),
                             ),
                         ),
                     ),

app/protected/modules/zurmo/elements/security/ExplicitReadWriteModelPermissionsElement.php

             {
                 return null;
             }
-            else
+            elseif(current($permitables) instanceof Group)
             {
-                assert(current($permitables) instanceof Group); // Not Coding Standard
                 if (current($permitables)->name == Group::EVERYONE_GROUP_NAME)
                 {
                     return ExplicitReadWriteModelPermissionsUtil::MIXED_TYPE_EVERYONE_GROUP;

app/protected/modules/zurmo/tests/unit/RightsFormUtilTest.php

                         'effective'   => Right::DENY,
                     ),
                 ),
+                'ConversationsModule'  => array(
+                    'RIGHT_CREATE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_CREATE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_DELETE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_DELETE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_ACCESS_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_ACCESS_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                ),
                 'DesignerModule' => array(
                     'RIGHT_ACCESS_DESIGNER'   => array(
                         'displayName' => DesignerModule::RIGHT_ACCESS_DESIGNER,
                         'effective'   => Right::DENY,
                     ),
                 ),
+                'ConversationsModule'  => array(
+                    'RIGHT_CREATE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_CREATE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_DELETE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_DELETE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_ACCESS_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_ACCESS_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                ),
                 'DesignerModule' => array(
                     'RIGHT_ACCESS_DESIGNER'   => array(
                         'displayName' => DesignerModule::RIGHT_ACCESS_DESIGNER,
                         'effective'   => Right::DENY,
                     ),
                 ),
+                'ConversationsModule'  => array(
+                    'RIGHT_CREATE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_CREATE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_DELETE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_DELETE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_ACCESS_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_ACCESS_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                ),
                 'DesignerModule' => array(
                     'RIGHT_ACCESS_DESIGNER'   => array(
                         'displayName' => DesignerModule::RIGHT_ACCESS_DESIGNER,
                         'effective'   => Right::DENY,
                     ),
                 ),
+                'ConversationsModule'  => array(
+                    'RIGHT_CREATE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_CREATE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_DELETE_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_DELETE_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                    'RIGHT_ACCESS_CONVERSATIONS'   => array(
+                        'displayName' => ConversationsModule::RIGHT_ACCESS_CONVERSATIONS,
+                        'explicit'    => null,
+                        'inherited'   => null,
+                        'effective'   => Right::DENY,
+                    ),
+                ),
                 'DesignerModule' => array(
                     'RIGHT_ACCESS_DESIGNER'   => array(
                         'displayName' => DesignerModule::RIGHT_ACCESS_DESIGNER,

app/themes/default/templates/NotificationEmailTemplate.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <title>Title</title>
+        <style type="text/css">
+            #outlook a{padding:0;}
+            body{width:100% !important;} .ReadMsgBody{width:100%;} .ExternalClass{width:100%;}
+            body{-webkit-text-size-adjust:none;}
+            body{margin:0; padding:0;}
+            img{border:0; height:auto; line-height:100%; outline:none; text-decoration:none;}
+            table td{border-collapse:collapse;}
+            #backgroundTable{height:100% !important; margin:0; padding:0; width:100% !important;}
+            body, #backgroundTable{
+                background-color:#DDDEDE;
+            }
+            #templateContainer{
+                border:0;
+            }
+            h1, .h1{
+                color:#202020;
+                display:block;
+                font-family:Arial;
+                font-size:40px;
+                font-weight:bold;
+                line-height:100%;
+                margin-top:2%;
+                margin-right:0;
+                margin-bottom:1%;
+                margin-left:0;
+                text-align:left;
+            }
+            h2, .h2{
+                color:#262877;
+                display:block;
+                font-family:Arial;
+                font-size:18px;
+                font-weight:bold;
+                line-height:100%;
+                margin-top:2%;
+                margin-right:0;
+                margin-bottom:1%;
+                margin-left:0;
+                text-align:left;
+            }
+            h3, .h3{
+                color:#606060;
+                display:block;
+                font-family:Arial;
+                font-size:16px;
+                font-weight:bold;
+                line-height:100%;
+                margin-top:2%;
+                margin-right:0;
+                margin-bottom:1%;
+                margin-left:0;
+                text-align:left;
+            }
+            h4, .h4{
+                color:#808080;
+                display:block;
+                font-family:Arial;
+                font-size:14px;
+                font-weight:bold;
+                line-height:100%;
+                margin-top:2%;
+                margin-right:0;
+                margin-bottom:1%;
+                margin-left:0;
+                text-align:left;
+            }
+            #templatePreheader{
+                background-color:#DDDEDE;
+            }
+            .preheaderContent div{
+                color:#707070;
+                font-family:Arial;
+                font-size:10px;
+                line-height:100%;
+                text-align:left;
+                background-color:#DDDEDE;
+            }
+            .preheaderContent div a:link, .preheaderContent div a:visited, .preheaderContent div a .yshortcuts {
+                color:#262877;
+                font-weight:normal;
+                text-decoration:underline;
+            }
+            #social div{
+                text-align:right;
+            }
+            #templateHeader{
+                background-color:#FFFFFF;
+                border-bottom:5px solid #CCCCCC;
+            }
+            .leftHeaderContent{
+                background-color: #FAFAFA;
+            }
+            .leftHeaderContent div{
+                color:#202020;
+                font-family:Arial;
+                font-size:32px;
+                font-weight:bold;
+                line-height:100%;
+                text-align:right;
+                vertical-align:middle;
+            }
+            .rightHeaderContent div{
+                color:#202020;
+                font-family:Arial;
+                font-size:32px;
+                font-weight:bold;
+                line-height:100%;
+                text-align:left;
+                vertical-align:middle;
+            }
+            .leftHeaderContent div a:link, .leftHeaderContent div a:visited, .rightHeaderContent div a:link, .rightHeaderContent div a:visited{
+                color:#262877;
+                font-weight:normal;
+                text-decoration:underline;
+            }
+
+            #headerImage{
+                height:auto;
+                max-width:200px !important;
+            }
+            #templateContainer, .bodyContent{
+                background-color:#FDFDFD;
+            }
+            .bodyContent div{
+                color:#545454;
+                font-family:Arial;
+                font-size:13px;
+                line-height:150%;
+                text-align:left;
+            }
+            .bodyContent div a:link, .bodyContent div a:visited, .bodyContent div a .yshortcuts{
+                color:#262877;
+                font-weight:normal;
+                text-decoration:underline;
+            }
+
+            .bodyContent img{
+                display:inline;
+                height:auto;
+            }
+            #templateFooter{
+                background-color:#FAFAFA;
+                border-top:3px solid #DFDFDF;
+            }
+            .footerContent div{
+                color:#707070;
+                font-family:Arial;
+                font-size:11px;
+                line-height:125%;
+                text-align:left;
+            }
+            .footerContent div a:link, .footerContent div a:visited, .footerContent div a .yshortcuts{
+                color:#999999;
+                font-weight:normal;
+                text-decoration:underline;
+            }
+            .footerContent img{
+                display:inline;
+            }
+            #social{
+                background-color:#FFFFFF;
+                border:0;
+            }
+            #social div{
+                text-align:left;
+            }
+            #utility{
+                background-color:#FAFAFA;
+                border-top:0;
+            }
+            #utility div{
+                text-align:left;
+            }
+            #monkeyRewards img{
+                max-width:170px !important;
+            }
+        </style>
+    </head>
+    <body leftmargin="0" marginwidth="0" topmargin="0" marginheight="0" offset="0">
+        <center>
+            <table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="backgroundTable">
+                <tr>
+                    <td align="center" valign="top">
+                        <table border="0" cellpadding="10" cellspacing="0" width="600" id="templatePreheader">
+                            <tr>
+                                <td valign="top" class="preheaderContent"><div></div></td>
+                            </tr>
+                        </table>
+                        <table border="0" cellpadding="0" cellspacing="0" width="600" id="templateContainer">
+                            <tr>
+                                <td align="center" valign="top">
+                                    <table border="0" cellpadding="0" cellspacing="0" width="600" id="templateHeader">
+                                        <tr>
+                                            <td class="headerContent">
+                                                <table border="0" cellpadding="10" cellspacing="0" width="100%">
+                                                    <tr>
+                                                        <td class="leftHeaderContent">
+                                                             <img src="http://zurmo.org/assets/images/logo.png" style="max-width:150px;" id="headerImage campaign-icon" />
+                                                        </td>
+                                                    </tr>
+                                                </table>
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td align="center" valign="top">
+                                    <table border="0" cellpadding="10" cellspacing="0" width="600" id="templateBody">
+                                        <tr>
+                                            <td valign="top" class="bodyContent">
+                                                <table border="0" cellpadding="10" cellspacing="0" width="100%">
+                                                    <tr>
+                                                        <td valign="top">
+                                                            <div>
+                                                                {bodyContent}
+                                                            </div>
+                                                        </td>
+                                                    </tr>
+                                                </table>
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td align="center" valign="top">
+                                    <table border="0" cellpadding="0" cellspacing="0" width="600" id="templateFooter">
+                                        <tr>
+                                            <td valign="top" class="footerContent">
+                                                <table border="0" cellpadding="10" cellspacing="0" width="100%">
+
+                                                    <tr>
+                                                        <td colspan="2" valign="middle" id="utility">
+                                                            <div>
+                                                                {sourceContent}<br/>
+                                                                {preferenceContent}<br/>
+                                                                Zurmo: www.zurmo.com
+                                                            </div>
+                                                        </td>
+                                                    </tr>
+                                                </table>
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </td>
+                            </tr>
+                        </table>
+                        <br />
+                    </td>
+                </tr>
+            </table>
+        </center>
+    </body>
+</html>

app/themes/default/templates/NotificationEmailTemplate.txt

+{bodyContent}
+--------------------------------------------------------------------------------------------------
+{sourceContent}
+{preferenceContent}
+Zurmo: www.zurmo.com

app/themes/default/templates/NotificationHTMLEmail.html

-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
-    <head>
-        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-        <title>Title</title>
-		<style type="text/css">
-			#outlook a{padding:0;}
-			body{width:100% !important;} .ReadMsgBody{width:100%;} .ExternalClass{width:100%;}
-			body{-webkit-text-size-adjust:none;}
-			body{margin:0; padding:0;}
-			img{border:0; height:auto; line-height:100%; outline:none; text-decoration:none;}
-			table td{border-collapse:collapse;}
-			#backgroundTable{height:100% !important; margin:0; padding:0; width:100% !important;}
-			body, #backgroundTable{
-				background-color:#DDDEDE;
-			}
-			#templateContainer{
-				border:0;
-			}
-			h1, .h1{
-				color:#202020;
-				display:block;
-				font-family:Arial;
-				font-size:40px;
-				font-weight:bold;
-				line-height:100%;
-				margin-top:2%;
-				margin-right:0;
-				margin-bottom:1%;
-				margin-left:0;
-				text-align:left;
-			}
-			h2, .h2{
-				color:#262877;
-				display:block;
-				font-family:Arial;
-				font-size:18px;
-				font-weight:bold;
-				line-height:100%;
-				margin-top:2%;
-				margin-right:0;
-				margin-bottom:1%;
-				margin-left:0;
-				text-align:left;
-			}
-			h3, .h3{
-				color:#606060;
-				display:block;
-				font-family:Arial;
-				font-size:16px;
-				font-weight:bold;
-				line-height:100%;
-				margin-top:2%;
-				margin-right:0;
-				margin-bottom:1%;
-				margin-left:0;
-				text-align:left;
-			}
-			h4, .h4{
-				color:#808080;