Yii 1.1: mailbox

Sitebased mailbox. Send messages between users/admins etc.
37 followers

Features

  • Enable/disable user-to-user messaging, Ie. disable to make simple customer support messaging between admin/users only.
  • Enable/Disable Inbox/Sent/Trash
  • Works with Yii-User / Rights modules
  • Custom themes / multiple layouts
  • Enable/disable trashcan/recycling
  • Enable/disable dragndrop trash
  • Enable/disable users can see when recipient reads their message.
  • Html Purify Admin/User input separately
  • Create site news plugin using publicly accessible mailbox

To Do

I will try to get these features working within a few days...

  • CC Your newsletter etc to local mailbox using templates

Notes

I am currently developing this module as part of another project. As the project progresses I will continue to update this extension. So please be warned that right now this module is still being developed and unknown bugs/issues may exists. Once all the features have been implemented I will do more extensive bug/browser compatibility checks and hopefully have a stable release candidate for v1.0. So if you decide to use this module in your project it's recommended that you follow this extension for updates until I get a stable version released (ie. v1.0).

Requirements

Yii 1.1 or above

Browser Requirements

This module uses Javascript for some of it's features, however, you do not need Javascript enabled to use this module. All features in this module using Javascript should degrade gracefully.

The only known compatibility issues so far are in the HTML/CSS.

  • FF 3+
  • IE 5.5+
  • Chrome 1+
  • Safari 4+
  • Minefield 3+
  • Flock 2+
  • Seamonkey 2+
  • Konqueror 3+
  • Epiphany 2+
  • Iceape 2+
  • Iceweasal 3.5+

I have also tested this module on Netscape 10 and Opera 9 but could not find older versions to test. I will get all browsers to display properly before releasing v1.0.

Usage

Unzip to modules directory.
Install data/structure.sql

If you want to alter the table names edit the following lines in MailboxModule.php

const TBL_CONV = '{{mailbox_conversation}}';
    const TBL_MSG = '{{mailbox_message}}';

Add Module

Add the module inside your main config file.

return array( 
...
'modules'=array(
...
'mailbox'=>
    array(  
    'userClass' => 'User',
    'userIdColumn' => 'id',
    'usernameColumn' =>  'username',
        ....more options here....
      ),
    ...
);

Module Options

Full list of module config options.

  • NOTE: The following options do not have an affect if you are using an authManager such as Rights. In this case the authManager will control the access.
    • sendMsgs
    • sentbox
    • trashbox
  • userClass - the name of the user model class.
  • userIdColumn - the name of the id column in the user table.
  • usernameColumn - the name of the username column in the user table.
  • superuserColumn - the name of the column in your User model that defines whether user is an admin or not.
  • deletedUser - text to display if user not found.
  • pageSize - number of conversations to display per page.
  • authManager - if you want to use an authManager (such as the Rights module) to control the access rules then set to true, if your using the Rights module specifically set to 'rights' in order to include the Rights filter.
  • readOnly - enable a read-only mailbox for regular users. Admins will still have fully functional mailbox.
  • userToUser - whether to allow user's to message other users. False would means users can only contact admins.
  • sendMsgs - whether or not to allow users to send messages.
  • sentbox - whether or not to enable/disable sent folder for viewing sent messages.
  • trashbox - whether or not to enable/disable trash folder for recycling deleted messages. If trashbox is enabled then you must run the cron() method at least once daily, ideally after midnight or each morning.
  • recyclePeriod - number of days to keep deleted items in trash folder before being permanently deleted by the cron() method.
  • dragDelete - enable/disable drag-n-drop deleting.
  • confirmDelete - wether to ask the user for confirmation before deleting messages. Note that if trashbox is turned off, values of 1 and 2 have the same effect (since messages are always deleted permanently).
    • 0 - Never ask for user confirmation.
    • 1 - Ask for user confirmation, but only when deleting permanently.
    • 2 - Ask for user confirmation when moving messages to trash, and when deleting permanently (ie. deleting from trash).
  • recipientRead - whether to allow users, when viewing the sent folder, to see if recipient has read the sent message.
  • cssFile - set to custom css file location relative to base URL or set to false to skip css includes.
  • menuPosition - set to either 'left' or 'top' to position the mailbox menu. If readOnly set to true this is ignored for user and only applied for admins (since there is no menu in readOnly mode).
  • cssFileColumn - custom left menu css.
  • juiThemes - apply jQuery UI widget styles. Can be one of the following:
    • 'none' Don't add any jQuery UI themes.
    • 'basic' Add themes to buttons and some elements but keep the background/font color of the parent element. Ie. <body> or #content
    • 'widget' Full jQuery UI styling.
  • juiButtons - enable/disable the JUI themes for buttons. Eg. if you want to use Twitter Bootstrap buttons instead.
  • juiIcons - whether to add icons to menu buttons (only if juiButtons is enabled)
  • defaultSubject - default subject to use when no subject is provided.
  • allowableCharsSubject - list of allowable characters to check Subject field against using case-insensitive regular expression. Square brackets '[]', dashes, single quotes, and slashes need to be escaped in order to be used literally.
  • adminHtml - HTML Purify options array used to purify HTML input from admins. See http://htmlpurifier.org/live/configdoc/plain.html for list of options. Set to an empty string to strip all HTML tags from message input.
  • html - HTML Purify options array used to purify HTML input from non-admins. See http://htmlpurifier.org/live/configdoc/plain.html for list of options. Set to an empty string to strip all HTML tags from message input.
  • allowLookupById - whether to allow users to be able to enter user Id's instead of username when sending messages.
  • allowUsernameSearch - whether to allow users to be able to search list of usernames to contact when sending messages.
  • editToField - whether to allow users to be able to edit the To field when sending messages.
  • userSupportList - whether to create a drop down menu for the To field ( from array created by getUserSupportList() method). This attribute is always true for admins unless the getUserSupportList() method returns false.
  • linkUser - whether to create a link for the From field to user's profile etc (link created by getUrl() method). This attribute is always true for admins unless the getUrl() method returns false.
  • checksums - whether to use checksums when storing messages. Checksums can be used not only for validating data but also to help implement certain spam protection. Eg. if a user copy and paste a message and sends it to multiple users you can easily find these messages by searching for other messages with the same checksum.
  • alternateRows - whether to alternate the row colors when viewing message list (ie. inbox etc).
  • newsUserId - the Id of the user account used for the site news.

Define Wrapper Functions

Edit the following functions in the file /module/mailbox/MailboxModule.php

*Note if you are using the User module from Yii extensions (Yii-User) then you do not need to configure the following functions. Unless if you'd like to customize the From label or modify how the auto complete is handled.

getUserId($username='')
getUserName($userid='')
getFromLabel($userid)
getUrl($userid)
isAdmin($userid='')

If you want auto complete enabled for the To field (adds selection for usernames).

autoComplete($term)

/**
     * Lookup user id by username. If no username supplied return current user id.
     * 
     * @param string $username
     * @return integer user Id that belongs to $username
     */
    public function getUserId($username='') { ... }
    /**
     * Lookup user id by username. If no user id is supplied return current user's username.
     * @param integer $userid
     * @return string username belonging to $userid
     */
    public function getUserName($userid=0) { ... }
    /**
     * Build the label for the From field when viewing the message. Ie. use the userid input to create a string like 'Username', 'Username "First Last"', '<div> ... </div>' , etc
     * @param type $userid
     * @return string label used for From field
     */
    public function getFromLabel($userid) { ... }
    /**
     * 
     * @param integer $userid
     * @return string url to users profile page etc. 
     */
    public function getUrl($userid) { ... }
    /**
     * Check whether given userid belongs to an administrator. If no userid is supplied check whether the current user is an administrator.
     * @return boolean 
     */
    public function isAdmin($userid=0) { ... }
 
    /**
    * Autocomplete function for 'To' field in view/compose. Search for usernames etc that match the string.
    *  
    * @param string $term
    * #return array output json array of usernames and labels.
    */
    public function autoComplete($term) { ... }
 
 
    /**
     * If the config var userSupport is enabled then the module will use this method to
     * create a drop down list of contacts in the To field when the user is creating a 
     * new message. This script should return an array, with keys set to the username 
     * and the value set to the username's label (may be the same). If userToUser messaging 
     * is enabled then this will create a drop down along with regular user input. If 
     * userToUser is disabled then the users will only be able to select contacts from this list.
     * 
     * Tip: If using an authManager you could create a new role called "support" and use 
     * this method to fetch an array of users who are assigned to the "support" role.
     * 
     * @return array array of admin usernames who provide customer support
     */
    public function getUserSupportList() { ... }

Cronjob

Add the following to your PHP cron script...

MailboxModule::cron();

Site News

To setup the site news plugin first create a new user in your database. Add the news user's Id to the module config...

return array( 
...
'modules'=array(
...
'mailbox'=>
    array(
        ...
    'newsUserId' => the news user Id here,
        ...
      ),
    ...
);

You can now create news updates by messaging the site news user (admins only). The site news user can also be added to a drop down list for the admins in the getUserSupportList() method. When you message the news user the subject and message will be publicly viewable via mailbox/news.

Change Log

0.2.1

  • Fixed CSS/display issues
  • Browser compatibility testing (display only)

0.2

  • Reorganized module - Changed all config variables to be regular class properties (ie. not static vars) so that they can now be set in the config array.
  • Added JUI widget styling
  • Added basic site news feature (still in development)
  • Added qTip 2 for tooltips and growls (may also be used for other features in the future ie. calendar etc.)
  • Added more options to module config
  • Added user support list - dropdown/combobox that lets user select from a predefined list of user's to contact.
  • Fixed one major bug/issue - In previous version all messages would be deleted when conversation was destroyed.

0.1

  • Initial public release

Bug Fixes

If you are using v0.1 please change line 473 in models/Mailbox.php from this...

$msg_count=Message::model()->conversation($this->conversation_id)->deleteAll();

to this..

$msg_count=Message::model()->deleteAll('conversation_id=:cid',array(':cid'=>$this->conversation_id));

Resources

View Demo

Total 20 comments

#16889 report it
ghimau at 2014/04/09 03:55am
Send to multiple user

Is it possible to send message to multiple user/group using this extension. I found this code in MessageController.php (from openschool community edition). How do i create the view for this controller

public function actionNewgroup()
    {
        $this->module->registerConfig($this->getAction()->getId());
        $cs = $this->module->getClientScript();
        $cs->registerScriptFile($this->module->getAssetsUrl().'/js/compose.js');
        $cs->registerScriptFile($this->module->getAssetsUrl().'/js/jquery.combobox.contacts.js');
        $js = '$(".mailbox-compose").yiiMailboxCompose('.$this->module->getOptions().");";
        $cs->registerScript('mailbox-js',$js,CClientScript::POS_READY);
        if(!$this->module->authManager && (!$this->module->sendMsgs  || ($this->module->readOnly && !$this->module->isAdmin()) ))
           $this->redirect(array('message/inbox'));
 
        if(isset($_POST['Mailbox']['to']) and $_POST['Mailbox']['to']!=NULL)
        { 
 
           $users = AuthAssignment::model()->findAllByAttributes(array('itemname'=>$_POST['Mailbox']['to']));
            if($users!=NULL)
            {
                foreach($users as $user)
            {
 
            $t = time();
            $conv = new Mailbox();
            $conv->subject = ($_POST['Mailbox']['subject'])? $_POST['Mailbox']['subject'] : $this->module->defaultSubject;
            $conv->to = $user->userid;
            $conv->initiator_id = $this->module->getUserId();
 
 
            $conv->interlocutor_id = $user->userid;
 
 
 
            if($conv->interlocutor_id && $conv->initiator_id == $conv->interlocutor_id) {
                $conv->addError('to', "Can't send message to self!");
            }
 
            if(!$this->module->isAdmin() && $conv->interlocutor_id == $this->module->newsUserId){
                $conv->addError('to', "User not found?");
            }
 
            // check user-to-user perms
            if(!$conv->hasErrors() && !$this->module->userToUser && !$this->module->isAdmin())
            {
                if(!$this->module->isAdmin($conv->to))
                    $conv->addError('to', "Invalid user!");
            }
 
            $conv->modified = $t;
            $conv->bm_read = Mailbox::INITIATOR_FLAG;
            if($this->module->isAdmin())
                $msg = new Message('admin');
            else
                $msg = new Message('user');
            $msg->text = $_POST['Message']['text'];
            $validate = $conv->validate(array('text'),false); // html purify
            $msg->created = $t;
            $msg->sender_id = $conv->initiator_id;
            $msg->recipient_id = $conv->interlocutor_id;
            if($this->module->checksums) {
                $msg->crc64 = Message::crc64($msg->text); // 64bit INT
            }
            else
                $msg->crc64 = 0;
            // Validate
            $validate = $conv->validate(null,false); // don't clear errors
            $validate = $msg->validate() && $validate;
 
            if($validate)
            {
                $conv->save();
                $msg->conversation_id = $conv->conversation_id;
                $msg->save();
 
            }
            Yii::app()->user->setFlash('success', "Message has been sent!");
 
            }
 
            $this->redirect(array('message/inbox'));
        }
        else
            {
                Yii::app()->user->setFlash('error', "Error sending message!");
                Yii::app()->user->setFlash('success', "Check Sent Mail");
 
            }     
 
        }
        else{
            $conv = new Mailbox();
            if(isset($_GET['id']))
                $conv->to = $this->module->getUserName($_GET['id']);
            elseif(isset($_GET['to']))
                $conv->to = $_GET['to'];
            else
                $conv->to = '';
            $msg = new Message();
        }
        $this->render('composegroup',array('conv'=>$conv,'msg'=>$msg));
    }
#16554 report it
darioo at 2014/03/05 10:06am
autocomplete

I don't get it, what I need to do to get auto complete working

#15886 report it
Gogu87 at 2013/12/26 02:52pm
The solutions of comment #c10766

I found the problem of this comment: http://www.yiiframework.com/extension/mailbox#c10766

the error is the MySQL query writhed on Line 221 in Models->Maibox.php The correct SQL is this:

$query = "SELECT SQL_CACHE COUNT(c.conversation_id) AS num_messages
            FROM ".MailboxModule::TBL_CONV." AS c
            INNER JOIN (
                SELECT message_id,conversation_id FROM ".MailboxModule::TBL_MSG."
                WHERE recipient_id=:userid  ORDER BY created DESC
            ) AS m ON(m.conversation_id=c.conversation_id)
            WHERE (c.initiator_id=:userid OR c.interlocutor_id=:userid)
            AND (c.bm_read & IF(c.initiator_id=:userid, :bminit, :bminter)) = 0
            AND (c.bm_deleted & IF(c.initiator_id=:userid, :bminit, :bminter)) = 0
            GROUP BY c.conversation_id
            ";

The name of this table {{mailbox_message}} remain hard-coded in the sql sintax.

#14372 report it
Rajith R at 2013/08/07 02:52am
solve error ""Only variables should be assigned by reference""

"Only variables should be assigned by reference"

just search in the module for =& and replace it with =

means remove & sign .

#11331 report it
skworden at 2013/01/06 04:11pm
Just to get it "working"

Please note the userClass changes are because I'm using yii-user module.

in config/main.php

change

'mailbox'=> array(
    'userClass' => 'User',
 
    ....other settings
),

to

'mailbox'=> array(
    'userClass' => 'users',
 
    ....other settings
),

modules/mailbox/MailboxModule.php

change

public $userClass = 'User';

to

public $userClass = 'users';

modules/mailbox/controllers/MessageController.php

find and replace all (lines 37, 105, and 267)

$cs =& $this->module->getClientScript();

with

$script = $this->module->getClientScript(); $cs =& $script;

modules/mailbox/views/message/_list.php

Line 3 change

$userid =& $this->module->getUserId();

to

$userid = $this->module->getUserId();

There are a lot of bugs still with how I did this. i.e. when you delete a message it doesn't really delete it, it will still show in the trash folder. However, it is sending the messages between the users.

Maybe it's not the best way but it's a start for someone with more time. I just did this in about 3 minutes so I will over the next few days mess with it some more and hopefully get it fully working like in the demo and post how i did it here.

However, if someone does it first please post how you got it to work.

Also, Rvr101 I assume if you use the same names in your db you will not have to make changes or just edit the main.php and the mailboxmodule.php accordingly to use your table name and structure. Read the instructions above it lays it out somewhat

Edit the following functions in the file /module/mailbox/MailboxModule.php

*Note if you **are using ** the User module from Yii extensions (Yii-User) then you do not need to configure the following functions. Unless if you'd like to customize the From label or modify how the auto complete is handled.

getUserId($username='')
getUserName($userid='')
getFromLabel($userid)
getUrl($userid)
isAdmin($userid='')
#11296 report it
RvR at 2013/01/04 05:16am
Without Yii-user

How this extension can use without using the yii-user extension? Which changes and tables are needed without yii-user extension?

#11015 report it
liaolliso at 2012/12/10 11:07am
how can admin send message to all users?

As the title said, how can admin send message to all the users? Is there a simple way to do this or i need to add some code in actionNew to send message to every user manually? thanks in advance.

#10935 report it
basem at 2012/12/05 01:07am
Re: Error

Reply tomyself, found that I have to make the code for any occurance of this

            $cs = $this->module->getClientScript();

To this: $script = $this->module->getClientScript(); $cs =& $script;

but I got myself into another problem now... 'delete', 'read', 'unread' functions are not working or actually not sending a request, I have defined the module in the main.php as follows:

            'mailbox'=>array(  
                    'userClass' => 'User',
                    'userIdColumn' => 'id',
                    'usernameColumn' => 'full_name',
                    'superuserColumn'=>'id',

kindly advise basem

#10920 report it
basem at 2012/12/03 09:20am
Error

Im getting this error : "Only variables should be assigned by reference"

I have configured my main.php like this:

            'mailbox'=>array(  
                    'userClass' => 'User',
                    'userIdColumn' => 'id',
                    'usernameColumn' => 'full_name',
                    'superuserColumn'=>'user_type',
                   // 'pageSize' => 50,
                    'newsUserId' => 'basem@mail.com',
            ),

any suggestions pls?

#10766 report it
ranairfan at 2012/11/22 06:44am
what kind of error ?

CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{mailbox_message}} WHERE recipient_id='10' ORDER BY created DESC ) AS m ' at line 4. The SQL statement executed was: SELECT SQL_CACHE COUNT(c.conversation_id) AS num_messages FROM mailbox_conversation AS c INNER JOIN ( SELECT message_id,conversation_id FROM {{mailbox_message}} WHERE recipient_id=:userid ORDER BY created DESC ) AS m ON(m.conversation_id=c.conversation_id) WHERE (c.initiator_id=:userid OR c.interlocutor_id=:userid) AND (c.bm_read & IF(c.initiator_id=:userid, :bminit, :bminter)) = 0 AND (c.bm_deleted & IF(c.initiator_id=:userid, :bminit, :bminter)) = 0 GROUP BY c.conversation_id

#10684 report it
Rajith R at 2012/11/15 02:22am
@ Maclein Got the solution for chrome problem

@ Maclein Got the solution for chrome problem..

just replace the mailbox.js with source js of the online demo

http://www.cgihub.com/mailbox/

forum post

http://www.yiiframework.com/forum/index.php/topic/37562-yii-mailbox-extension-google-chrome-problem/page__gopid__181208

#10504 report it
RvR at 2012/11/01 03:45am
PHP error-

I used the user module for this. But error not changed. Still have the same problem. Is there any method for using this extension without using user module?

#10503 report it
hiral darji at 2012/11/01 03:05am
reply:php Error

I think this error is raised becuae it cant get user id.. so r you using user module?

if not then in config/mail.php

'mailbox'=>
            array(  
            'userClass' => 'User',
          //  'userIdColumn' => 'id',
            'userIdColumn' => 'user_id',
            'usernameColumn' => 'user_organization_email_id',
            //'usernameColumn' => 'username',
            'superuserColumn'=>'user_type',
           // 'pageSize' => 50,
            'newsUserId' => 'admin@rudrasoftech.com',
              ),

userIdColumn and usernameColumn of your user table and also add,

'tablePrefix' => 'tbl_',

in db configuration array

and in mailbox module change MailboxModule.php like this,

public function getUserId($username='')
    {
        if($username)
        {
            $r = call_user_func(array($this->userClass, 'model'))
                ->findByAttributes(array($this->usernameColumn=>$username));
 
            if(!is_null($r)) return $r->{$this->userIdColumn};
        }
        else    
        {
            if(!$this->_userid)
                $this->_userid = Yii::app()->user->id;
            return $this->_userid;
        }
 
    }
#10490 report it
RvR at 2012/10/31 09:33am
PHP error-

This is my error in this case- "Only variables should be assigned by reference" C:\xampp\htdocs\yii\demos\mailbox\protected\modules\mailbox\controllers\MessageController.php(37)

public function actionInbox($ajax=null) 35 { 36 $this->module->registerConfig($this->getAction()->getId()); 37 $cs =& $this->module->getClientScript(); 38 $cs->registerScriptFile($this->module->getAssetsUrl().'/js/mailbox.js',CClientScript::POS_END); 39 //$js = '$("#mailbox-list").yiiMailboxList('.$this->module->getOptions().');console.log(1)'; 40 41 //$cs->registerScript('mailbox-js',$js,CClientScript::POS_READY); 42
43
44 if(isset($_POST['convs'])) 45 { 46 $this->buttonAction('inbox'); 47 } 48 $dataProvider = new CActiveDataProvider( Mailbox::model()->inbox($this->module->getUserId()) ); 49 if(isset($ajax))

#10487 report it
hiral darji at 2012/10/31 08:30am
reply:Use of php cron script

hii Rvr101,

Is this mailbox working in your application or not? If not working proper then please tell what is the error? Because for basic use of mailbox, Cron job configuration not required at first stage as per my knowledge,i used this mailbox. its working best for me.

#10482 report it
RvR at 2012/10/31 03:24am
Use of php cron script

I really like this mailbox demo. But i can't implement that in my application. I completed the steps till "Define Wrapper Functions". Where i put this code "MailboxModule::cron();" in my application? i dont knowthe path of php cron script...

#10235 report it
hiral darji at 2012/10/13 02:50am
hide the dropdown menu from to field

Hii jiaming,

you change in modules/mailbox/views/message/compose.php on line no 28,

from here you have to just remove 'id'=>'message-to' and you are done.

#10201 report it
jiaming at 2012/10/10 04:16pm
Is this project still alive...? Is there a way to hide the dropdown menu?

Is this project still alive...?...Is there a way to hide the dropdown menu so the user can not see all the user list ?

#9922 report it
Maclein at 2012/09/22 01:25pm
Error in Chrome while deleting an element

Hi I am facing a problem in chrome. While i am going to delete any item after selecting and deleting its not deleting. not even read and unread.

In console its giving error

"Uncaught TypeError: Cannot call method 'attr' of null mailbox.js:303 $.yiimailbox.submitAjax mailbox.js:303 $.yiimailbox.updateMailbox.$.draggable.containment mailbox.js:61 jQuery.event.dispatch jquery.js:3332 jQuery.event.add.elemData.handle.eventHandle"

While the same code is running in firefox and Ie.

don't know why.. Please help me. I am stuck.

#9455 report it
jiaming at 2012/08/12 03:45pm
God bless you.

@derek

What just happened???

God bless you.

Best wishes, jimmy

Leave a comment

Please to leave your comment.

Create extension