Email Folder Selection Not Working

When selecting a subordinate mailbox folder in email list view, the inbox folder always shows no matter what. I have noticed that the default folder ID in the URL string matches the ID field on the folders table in the DB. When I click the “sent” sub folder for example, the URL string changes to present the correct folder ID, but the UI still presents the parent inbox.

I suspect that the code behind the folder switch request is substituting the parent_folder_id value on the record for the id value when selecting the child folder. I just don’t know which file is being used to check the code.

Can anyone advise further? I expect this is going to be a remarkably simple fix.

SuiteCRM 7.13.2
PHP 7.4
MySQL 5.7
CentOS shared Blue Host server

To test a hunch, I created a second personal inbound email account to a separate mailbox on the same mail server. I CAN switch between the parent INBOX folders of each account with ease. I still cannot switch into the child folders (INBOX.sent, etc) of any of the mail accounts.

I now wonder if this means that there is a mailbox selector hard coded in source code to “INBOX” instead of using a user submitted variable. I ran a grep search in the application root recursively on the term “INBOX” and went file by file. I changed the occurrence of “INBOX” to “INBOX.sent” and refreshed the UI numerous times, also trying to select different folders. For each occurrence I saw no change and wrote the code value back to “INBOX”, basically leaving each file as I had found it.

Anybody else having thoughts on the cause? Anybody having similar problems?

Looks like this article is also related. @pgr, this has apparently been going on for years across numerous upgrades. Is there ANY progress on this issue?

I know this is a problem, I don’t have any idea how to solve it.

I would like to see at least one of these threads include more technical troubleshooting information. A PHP log with a stack trace is a great starting point for fixing.

@pgr, I’m happy to provide one. What function do I insert the debug_stack_trace() into? I don’t have any logs reporting out and out php errors.

With logging set to ‘Warn’ and a folder switch operation staged, I ran a new chunk of log, clicked the folder select, and grabbed the log which results. Here it is:

Fri Apr 21 11:57:37 2023 [142043][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] Array
(
)

Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] Array
(
)

Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] CSS File Day/yui.css not found
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] Email ID is Empty
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] Using row number in fetchByAssoc is not portable and no longer supported. Please fix your code.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] Trying to get property of non-object: list view data "order by" is not defined
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] Trying to get property of non-object: list view data "sort order" is not defined
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] Using row number in fetchByAssoc is not portable and no longer supported. Please fix your code.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] User::getPreference() should not be used statically.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] User::getPreference() should not be used statically.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] User::getPreference() should not be used statically.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] unknown or undefined folder type (we will use 'imap' instead): inbound
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] Request ssl value not found.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] ImapHandler trying to use a non valid resource stream.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] ImapHandler trying to use a non valid resource stream.
Fri Apr 21 11:57:40 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] $value must be a string
Fri Apr 21 11:57:41 2023 [142043][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] User::getPreference() should not be used statically.
Fri Apr 21 11:57:41 2023 [142043][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] User::getPreference() should not be used statically.
Fri Apr 21 11:57:41 2023 [142043][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] User::getPreference() should not be used statically.
Fri Apr 21 11:57:41 2023 [142043][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] Array
(
)

Fri Apr 21 11:57:43 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][DEPRECATED] Array
(
)

Fri Apr 21 11:57:43 2023 [142189][7356b911-2136-7ab5-05b1-642dc5a54da7][WARN] CSS File Day/yui.css not found

I notice that there are three deprecation lines about not using User::getPreference() statically, and there are three lines (sent, draft, archive) which are available in the email folder selection. Yes, I realize that this is hardly evidence based connectivity of ideas, but it’s something I’ll fiddle with and report back any success.

DEPRECATEDs are typically of little interest, they are a warning about future changes.

I read in another thread that someone had solved this by installing the php-imap and php-zip plug-in on server.

So, tracking this down further, I got to modules/User/User.php - User::getPreference() at line 525.
At the end of the function, I stuck the following in:

$e = new \Exception;
echo '<pre>';
print_r( $e->getTraceAsString() );
echo '</pre>';

That particular trace dump seems to display a little more organized than others.

I refreshed my email list view and was presented with hundreds of lines of stack trace, likely having to do with numerous calls to User::getPreference() simultaneously. I ctrl-F searched on ‘Email’ and my attention was called to the following since it started concerning email folders.

#0 /home3/bluelir5/public_html/crm/modules/Emails/Folder.php(148): User->getPreference('defaultIEAccoun...', 'Emails')
#1 /home3/bluelir5/public_html/crm/modules/Emails/include/ListView/ListViewDataEmails.php(714): Folder->loadMailboxFolder(Array)
#2 /home3/bluelir5/public_html/crm/modules/Emails/include/ListView/ListViewSmartyEmails.php(110): ListViewDataEmails->getListViewData(Object(Email), '', 0, -1, Array, Array, 'id', true, NULL)
#3 /home3/bluelir5/public_html/crm/include/MVC/View/views/view.list.php(283): ListViewSmartyEmails->setup(Object(Email), 'include/ListVie...', '', Array)
#4 /home3/bluelir5/public_html/crm/include/MVC/View/views/view.list.php(391): ViewList->listViewProcess()
#5 /home3/bluelir5/public_html/crm/include/MVC/View/SugarView.php(210): ViewList->display()
#6 /home3/bluelir5/public_html/crm/include/MVC/Controller/SugarController.php(432): SugarView->process()
#7 /home3/bluelir5/public_html/crm/include/MVC/Controller/SugarController.php(363): SugarController->processView()
#8 /home3/bluelir5/public_html/crm/include/MVC/SugarApplication.php(101): SugarController->execute()
#9 /home3/bluelir5/public_html/crm/index.php(52): SugarApplication->execute()
#10 {main}

and

#0 /home3/bluelir5/public_html/crm/modules/InboundEmail/InboundEmail.php(7360): User->getPreference('defaultIEAccoun...', 'Emails', Object(User))
#1 /home3/bluelir5/public_html/crm/modules/InboundEmail/InboundEmail.php(6893): InboundEmail->getUsersDefaultOutboundServerId(Object(User))
#2 /home3/bluelir5/public_html/crm/modules/InboundEmail/InboundEmail.php(6842): InboundEmail->calculateDefault()
#3 /home3/bluelir5/public_html/crm/modules/InboundEmail/InboundEmail.php(6833): InboundEmail->fill_in_additional_detail_fields()
#4 /home3/bluelir5/public_html/crm/data/SugarBean.php(4323): InboundEmail->fill_in_additional_list_fields()
#5 /home3/bluelir5/public_html/crm/data/SugarBean.php(3526): SugarBean->process_list_query(' SELECT  inboun...', 0, 20, 20, '((inbound_email...')
#6 /home3/bluelir5/public_html/crm/modules/InboundEmail/InboundEmail.php(6737): SugarBean->get_list('', '((inbound_email...')
#7 /home3/bluelir5/public_html/crm/include/SugarFolders/SugarFolders.php(1563): InboundEmail->getUserInboundAccounts()
#8 /home3/bluelir5/public_html/crm/include/SugarFolders/SugarFolders.php(789): SugarFolder->getUserAccessibleInboundIds(Object(User))
#9 /home3/bluelir5/public_html/crm/include/SugarFolders/SugarFolders.php(865): SugarFolder->retrieveFoldersForProcessing(Object(User), false)
#10 /home3/bluelir5/public_html/crm/include/SugarFolders/SugarFolders.php(1514): SugarFolder->getFoldersForSettings(Object(User))
#11 /home3/bluelir5/public_html/crm/modules/Emails/Folder.php(204): SugarFolder->isToDisplay('9d5e2d50-69ce-e...')
#12 /home3/bluelir5/public_html/crm/modules/Emails/Folder.php(158): Folder->isSelectedForDisplay('9d5e2d50-69ce-e...')
#13 /home3/bluelir5/public_html/crm/modules/Emails/include/ListView/ListViewDataEmails.php(714): Folder->loadMailboxFolder(Array)
#14 /home3/bluelir5/public_html/crm/modules/Emails/include/ListView/ListViewSmartyEmails.php(110): ListViewDataEmails->getListViewData(Object(Email), '', 0, -1, Array, Array, 'id', true, NULL)
#15 /home3/bluelir5/public_html/crm/include/MVC/View/views/view.list.php(283): ListViewSmartyEmails->setup(Object(Email), 'include/ListVie...', '', Array)
#16 /home3/bluelir5/public_html/crm/include/MVC/View/views/view.list.php(391): ViewList->listViewProcess()
#17 /home3/bluelir5/public_html/crm/include/MVC/View/SugarView.php(210): ViewList->display()
#18 /home3/bluelir5/public_html/crm/include/MVC/Controller/SugarController.php(432): SugarView->process()
#19 /home3/bluelir5/public_html/crm/include/MVC/Controller/SugarController.php(363): SugarController->processView()
#20 /home3/bluelir5/public_html/crm/include/MVC/SugarApplication.php(101): SugarController->execute()
#21 /home3/bluelir5/public_html/crm/index.php(52): SugarApplication->execute()
#22 {main}

Are lines 11 and 12 in this last stack the lines at issue @pgr?

I read in another thread that someone had solved this by installing the php-imap and php-zip plug-in on server.

php-imap and php-zip are installed.

I don’t know which of your errors is the one we need to fix. If any - it could be something else that is not even communicated in a log message.

But as I said, I would not focus on DEPRECATEDs. That’s is just a message a developer wrote to warn other developers that some future change will affect this code. Supposedly, the code still works well.

The WARNINGS look more promising. But still it is difficult to understand everything that is going on.

If we knew which error is the one we want (typically FATALs are the best candidates), then the stack trace would come in handy.

All fair enough and makes sense. Perhaps you can point me toward the function call series that occurs when someone clicks the folder in the tree that they want displayed. If I know what function gets called, I can wade through the details til hopefully I hit the offending line and work a solution from there. I’ll certainly report my work back here if I should come to any successful fix.

To get to that function, can you get me the exact web request that it generates? Grab it from the web developer tools of your browser, network tab

Is this the output you’re looking for?

(anonymous) @ https://crm.bluelinecountry.com/modules/Emails/include/ListView/FoldersViewModal.js?v=BcRBMvB7Jsc74ywWs3Nq0A:90
dispatch @ https://crm.bluelinecountry.com/cache/include/javascript/sugar_grp1_jquery.js?v=BcRBMvB7Jsc74ywWs3Nq0A:2
v.handle @ https://crm.bluelinecountry.com/cache/include/javascript/sugar_grp1_jquery.js?v=BcRBMvB7Jsc74ywWs3Nq0A:2
trigger @ https://crm.bluelinecountry.com/cache/include/javascript/sugar_grp1_jquery.js?v=BcRBMvB7Jsc74ywWs3Nq0A:2
triggerHandler @ https://crm.bluelinecountry.com/cache/include/javascript/sugar_grp1_jquery.js?v=BcRBMvB7Jsc74ywWs3Nq0A:2
trigger @ https://crm.bluelinecountry.com/include/javascript/jstree/dist/jstree.js?v=BcRBMvB7Jsc74ywWs3Nq0A:3
select_node @ https://crm.bluelinecountry.com/include/javascript/jstree/dist/jstree.js?v=BcRBMvB7Jsc74ywWs3Nq0A:3
activate_node @ https://crm.bluelinecountry.com/include/javascript/jstree/dist/jstree.js?v=BcRBMvB7Jsc74ywWs3Nq0A:3
(anonymous) @ https://crm.bluelinecountry.com/include/javascript/jstree/dist/jstree.js?v=BcRBMvB7Jsc74ywWs3Nq0A:3
dispatch @ https://crm.bluelinecountry.com/cache/include/javascript/sugar_grp1_jquery.js?v=BcRBMvB7Jsc74ywWs3Nq0A:2
v.handle @ https://crm.bluelinecountry.com/cache/include/javascript/sugar_grp1_jquery.js?v=BcRBMvB7Jsc74ywWs3Nq0A:2

It’s from the first line of this…

The part I meant is what is shown in blue in your screenshot (and also in the “hover” tooltip). That helps find the code that is getting called server-side.

That initial call only seems to run regular list view code.

I tried that over here and further down I noticed a call to the emails controller with action “GetFolders”. That is the one that populates to top-right “folder” dropdown, I think.

It takes you here:

Well, I’m fairly certain I have a solution!

Go to this file:

/include/SugarFolders/SugarFolders.php line 1528

    /**
     * @param array $folders
     * @param string $folderId
     * @return bool
     */
    protected function shouldFolderDisplay(array $folders, string $folderId): bool
    {
        if (empty($folders)) {
            return false;
        }

        foreach ($folders as $folder) {
            $isSelected = $folder['selected'] ?? false;
            if (isFalse($isSelected)) {
                continue;
            }
            $id = $folder['id'] ?? '';

            if ($id === $folderId) {
                return true;
            }
        }

        return false;
    }

The last condition of the function compares $id to $folderId. The problem is that $id is always going to be the ID of the parent folder (INBOX) even if the folder you’re trying to display is the child (like INBOX.Sent). So, instead of checking to see if $folderId matches the single value of the parent ID, which of course it won’t, I run the entire $folders array (including children) looking for the [‘id’] values and assembling them into a separate array. Then I just check to see if the $folderId value is present in the array. If it is, we return true. The resulting function is below, and requires an additional function be written in below it:

    /**
     * @param array $folders
     * @param string $folderId
     * @return bool
     */
    protected function shouldFolderDisplay(array $folders, string $folderId): bool
    {
        if (empty($folders)) {
            return false;
        }
        
        $idValues = $this->recursiveFind( $folders, 'id' );

        foreach ($folders as $folder) {
            $isSelected = $folder['selected'] ?? false;
            if (isFalse($isSelected)) {
                continue;
            }
            
            $id = $folder['id'] ?? '';

            //if ($id === $folderId) {
            if( in_array( $folderId, $idValues ) ) {
                return true;
            }
        }

        return false;
    }
    
    protected function recursiveFind(array $array, $needle)
    {
        $iterator  = new RecursiveArrayIterator($array);
        $recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
        $aHitList = array();
        foreach ($recursive as $key => $value) {
            if ($key === $needle) {
                array_push($aHitList, $value);
            }
        }
        return $aHitList;
    }

This DOES get the desired behavior out of the email inbox folders. I don’t think it defeats security measures either, as I’ve tried accessing accounts that my user account isn’t supposed to and it does kick back to my properly assigned inboxes. This holds true even if I force a known good value to someone else’s mailbox into the URL bar.

NOTE: This issue is also present in SuiteCRM 8, and though I haven’t tested the solution there, the source file is the same, so I suspect that it will work there too.

1 Like

Nice work. Maybe you can consider creating a Pull Request on Github to contribute this fix to the Community.

That’s next on my to do list for this one. Thanks for your help.

1 Like

@ctucker1984 does this screenshot look similar to the problem you were getting?

No, this seems an issue of another making. I did manage to cause this a couple of times resolving this matter though. It’s likely that the back end isn’t populating the array of available folders. There’s a lot of reasons that could be happening.

1 Like