[TikiWiki-commits] [Git][tikiwiki/tiki][master] [ENH] Tiki webmail: Enhanced calendar functionality by integrating tracker...

"Marc Laporte \(@marclaporte\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <69c7cdd98e4da_3b192b98744a8@gitlab-sidekiq-low-urgency-cpu-bound-v2-566f8746dd-4kqt7.mail>

Marc Laporte pushed to branch master at Tiki Wiki CMS Groupware / Tiki


Commits:
99650f37 by Yannick Nsenga at 2026-03-28T12:40:05+00:00
[ENH] Tiki webmail: Enhanced calendar functionality by integrating tracker email message handling for calendar invitations
---
* a lot of code fixes, resolving all review threads

* [REF] Tiki webmail: Refactor calendar invitation handling to unify IMAP and tracker message processing

* [ENH] Tiki webmail: Implement IMAP dependency checks for calendar and email functionalities

* [FIX] Tiki webmail: Include IMAP modules for email sending and streamline outbound message profile retrieval

* [ENH] Tiki webmail : Enhanced calendar functionality by integrating tracker message handling for calendar invitations

See merge request tikiwiki/tiki!8633

- - - - -


6 changed files:

- lib/cypht/modules/tiki/calendar_modules.php
- lib/cypht/modules/tiki/functions.php
- lib/cypht/modules/tiki/js_modules/DOM_events/message_content.js
- lib/cypht/modules/tiki/setup.php
- lib/cypht/modules/tiki/site.js
- lib/cypht/modules/tiki/tracker_modules.php


Changes:

=====================================
lib/cypht/modules/tiki/calendar_modules.php
=====================================
@@ -16,6 +16,7 @@ if (! defined('DEBUG_MODE')) {
 
 require_once APP_PATH . 'modules/smtp/hm-mime-message.php';
 
+
 /**
  * Parse message and check for a calendar invitation
  * @subpackage tiki/handler
@@ -24,9 +25,13 @@ class Hm_Handler_check_calendar_invitations_imap extends Hm_Handler_Module
 {
     public function process()
     {
+        $list_path = $this->get('list_path', '') ?: ($this->request->post['list_path'] ?? '');
+        $is_tracker = strpos($list_path, 'tracker_folder_') === 0;
+
         if ($this->get('msg_struct')) {
-            get_calendar_part_imap($this->get('msg_struct'), $this);
+            get_calendar_part($this->get('msg_struct'), $this, ! $is_tracker);
         }
+
         if ($this->get('calendar_event_raw')) {
             $event = Tiki\SabreDav\Utilities::getDenormalizedData($this->get('calendar_event_raw'));
             if ($this->get('formatted_calendar_event_description')) {
@@ -36,7 +41,8 @@ class Hm_Handler_check_calendar_invitations_imap extends Hm_Handler_Module
         } else {
             $event = null;
         }
-        // get recipient from TO header
+
+        // Determine recipient (same logic for both types)
         $recipient = null;
         $headers = $this->get('msg_headers', []);
         foreach ($headers as $name => $value) {
@@ -44,6 +50,7 @@ class Hm_Handler_check_calendar_invitations_imap extends Hm_Handler_Module
                 $recipient = (string)$value;
             }
         }
+
         if (! empty($event['participants'])) {
             // try to find the recipient in the participants' list
             $found = false;
@@ -155,6 +162,17 @@ class Hm_Handler_event_rsvp_action extends Hm_Handler_Module
         // use specific text body for the reply
         $event = $this->get('calendar_event');
         $comment = $this->request->post['rsvp_comment'] ?? '';
+
+        // Extract sender name from headers
+        $from_name = 'User';
+        $headers = $this->get('msg_headers', []);
+        foreach ($headers as $name => $value) {
+            if (strtolower($name) == 'from') {
+                $from_name = (string)$value;
+                break;
+            }
+        }
+
         $body = "$from_name has $action the invitation to the following event: \n\n*{$event['name']}*";
         if ($comment) {
             $body .= "\n\nNote: $comment";
@@ -510,10 +528,11 @@ class Hm_Output_add_rsvp_actions extends Hm_Output_Module
  * @subpackage tiki/functions
  * @param array $struct message structure
  * @param object $mod Hm_Handler_Module
+ * @param bool $is_imap indicates if the source is an IMAP message or a Tiki tracker message
  * @return string
  */
-if (! hm_exists('get_calendar_part_imap')) {
-    function get_calendar_part_imap($struct, $mod)
+if (! hm_exists('get_calendar_part')) {
+    function get_calendar_part($struct, $mod, $is_imap = true)
     {
         $event = $method = $html = null;
         $part = false;
@@ -528,31 +547,66 @@ if (! hm_exists('get_calendar_part_imap')) {
                     $htmlPart = $id;
                 }
                 if (isset($vals['subs'])) {
-                    return get_calendar_part_imap($vals['subs'], $mod);
+                    return get_calendar_part($vals['subs'], $mod, $is_imap);
                 }
             } else {
                 if (is_array($vals) && count($vals) == 1 && isset($vals['subs'])) {
-                    return get_calendar_part_imap($vals['subs'], $mod);
+                    return get_calendar_part($vals['subs'], $mod, $is_imap);
                 }
             }
         }
         if (! $part) {
             return;
         }
-        list($success, $form) = $mod->process_form(['imap_server_id', 'imap_msg_uid', 'folder']);
-        if ($success) {
-            $mailbox = Hm_IMAP_List::get_connected_mailbox($form['imap_server_id'], $mod->cache);
-            if ($mailbox->authed()) {
-                $event = $mailbox->get_structured_message(hex2bin($form['folder']), $form['imap_msg_uid'], $part, true)[2];
-                if ($htmlPart) {
-                    $html = $mailbox->get_structured_message(hex2bin($form['folder']), $form['imap_msg_uid'], $htmlPart, true)[2];
-                    $html = sanitize_email_html($html);
-                    $html = format_msg_html($html);
-                }
-            }
+
+        if ($is_imap) {
+            process_calendar_imap($html, $event, $mod, $part, $htmlPart);
+        } else {
+            process_calendar_tiki($html, $event, $method, $mod, $part, $htmlPart);
         }
+
         $mod->out('calendar_method', $method);
         $mod->out('calendar_event_raw', $event);
         $mod->out('formatted_calendar_event_description', $html);
     }
 }
+
+function process_calendar_imap(&$html, &$event, $mod, $part, $htmlPart)
+{
+    list($success, $form) = $mod->process_form(['imap_server_id', 'imap_msg_uid', 'folder']);
+    if ($success) {
+        $mailbox = Hm_IMAP_List::get_connected_mailbox($form['imap_server_id'], $mod->cache);
+        if ($mailbox->authed()) {
+            $event = $mailbox->get_structured_message(hex2bin($form['folder']), $form['imap_msg_uid'], $part, true)[2];
+            if ($htmlPart) {
+                $html = $mailbox->get_structured_message(hex2bin($form['folder']), $form['imap_msg_uid'], $htmlPart, true)[2];
+                $html = sanitize_email_html($html);
+                $html = format_msg_html($html);
+            }
+        }
+    }
+}
+
+function process_calendar_tiki(&$html, &$event, &$method, $mod, $part, $htmlPart)
+{
+    list($success, $form) = $mod->process_form(['imap_msg_uid', 'list_path']);
+    if ($success) {
+        $email = tiki_parse_message($form['list_path'], $form['imap_msg_uid']);
+        if ($email && ! empty($email['message_raw'])) {
+            $message = $email['message_raw'];
+            $mimePart = tiki_get_mime_part($message, $part);
+            if ($mimePart) {
+                $event = $mimePart->getContent();
+                $header = $mimePart->getHeader('Content-Type');
+                if (! $method && $header && $header->hasParameter('method')) {
+                    $method = $header->getValueFor('method');
+                }
+            }
+            $html = tiki_get_mime_part($message, $htmlPart);
+            if ($html) {
+                $html = sanitize_email_html($html->getContent());
+                $html = format_msg_html($html);
+            }
+        }
+    }
+}


=====================================
lib/cypht/modules/tiki/functions.php
=====================================
@@ -10,6 +10,7 @@ if (! defined('DEBUG_MODE')) {
     die();
 }
 
+
 /**
  * Retrive a Tiki-stored mail message and convert to a parsed mime message
  * @subpackage tiki/functions
@@ -290,6 +291,12 @@ if (! hm_exists('tiki_flag_message')) {
 if (! hm_exists('tiki_send_email_through_cypht')) {
     function tiki_send_email_through_cypht($to, $cc, $subject, $body, $in_reply_to, $file, $profiles, $hmod, $recipient = null)
     {
+        // Ensure IMAP dependency is available
+        if (! class_exists('Hm_SMTP_List')) {
+            Hm_Msgs::add('The smtp module is required to send emails. Please enable it through the configuration file.', 'danger');
+            return false;
+        }
+
         // retrieve smtp server connected with an existing imap message via profiles
         $smtp_id = 0;
         $compose_smtp_id = null;
@@ -321,7 +328,6 @@ if (! hm_exists('tiki_send_email_through_cypht')) {
 
         // profile details
         list($imap_server, $from_name, $reply_to, $from) = get_outbound_msg_profile_detail(['compose_smtp_id' => $compose_smtp_id], $profiles, $smtp_details, $hmod);
-
         // xoauth2 check
         smtp_refresh_oauth2_token_on_send($smtp_details, $hmod, $smtp_id);
 


=====================================
lib/cypht/modules/tiki/js_modules/DOM_events/message_content.js
=====================================
@@ -39,6 +39,8 @@ function RSVPButtonClick() {
                         if (action == "accept" && $('.event_calendar_select_rsvp').val()) {
                             tiki_event_calendar($('.event_calendar_select_rsvp').val());
                         }
+
+                        // Use single RSVP endpoint with source detection via list_path
                         const detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
                         $.tikiModal("Please wait...");
                         Hm_Ajax.request(
@@ -47,7 +49,8 @@ function RSVPButtonClick() {
                             {'name': 'rsvp_comment', 'value': comment},
                             {'name': 'imap_msg_uid', 'value': getMessageUidParam()},
                             {'name': 'imap_server_id', 'value': detail.server_id},
-                            {'name': 'folder', 'value': detail.folder}],
+                            {'name': 'folder', 'value': detail.folder},
+                            {'name': 'list_path', 'value': getListPathParam()}],
                             function() {
                                 Hm_Notices.show(tr("Your response has been sent."), "success");
                                 $.closeModal();


=====================================
lib/cypht/modules/tiki/setup.php
=====================================
@@ -72,15 +72,20 @@ add_output('ajax_imap_message_content', 'add_move_to_trackers', true, 'imap', 'f
 add_output('ajax_imap_message_content', 'tiki_get_create_item_trackers_output', true, 'imap', 'filter_message_headers', 'after');
 add_output('ajax_imap_message_content', 'add_restore_message', true, 'imap', 'filter_message_headers', 'after');
 
+/* message page calendar invitation hooks (Tracker-stored messages) */
+add_handler('ajax_tiki_message_content', 'check_calendar_invitations_imap', true, 'imap', 'tiki_message_content', 'after');
+add_output('ajax_tiki_message_content', 'add_rsvp_actions', true, 'tiki', 'filter_message_headers', 'after');
+
 /* message page rsvp actions to an event */
 setup_base_ajax_page('ajax_rsvp_action', 'core');
-add_handler('ajax_rsvp_action', 'check_calendar_invitations_imap', true, 'imap', 'imap_message_content', 'after');
 add_handler('ajax_rsvp_action', 'load_imap_servers_from_config', true, 'imap');
 add_handler('ajax_rsvp_action', 'load_smtp_servers_from_config', true, 'smtp', 'load_imap_servers_from_config', 'after');
 add_handler('ajax_rsvp_action', 'add_smtp_servers_to_page_data', true, 'smtp', 'load_smtp_servers_from_config', 'after');
 add_handler('ajax_rsvp_action', 'compose_profile_data', true, 'profiles', 'add_smtp_servers_to_page_data', 'after');
-add_handler('ajax_rsvp_action', 'imap_message_content', true, 'imap', 'compose_profile_data', 'after');
-add_handler('ajax_rsvp_action', 'event_rsvp_action', true, 'tiki', 'imap_message_content', 'after');
+add_handler('ajax_rsvp_action', 'tiki_message_content', true, 'tiki', 'compose_profile_data', 'after');
+add_handler('ajax_rsvp_action', 'imap_message_content', true, 'imap', 'tiki_message_content', 'after');
+add_handler('ajax_rsvp_action', 'check_calendar_invitations_imap', true, 'imap', 'imap_message_content', 'after');
+add_handler('ajax_rsvp_action', 'event_rsvp_action', true, 'tiki', 'check_calendar_invitations_imap', 'after');
 
 /* message page add to calendar function */
 setup_base_ajax_page('ajax_add_to_calendar', 'core');


=====================================
lib/cypht/modules/tiki/site.js
=====================================
@@ -65,6 +65,11 @@ var tiki_groupmail_put_back = function(btn, id) {
     );
 };
 
+// Helper function to detect if we're viewing a tracker email
+function isTrackerPath() {
+    return (getListPathParam() || '').indexOf('tracker_folder_') === 0;
+}
+
 var tiki_event_calendar = function(calendar_id) {
     var uid = getMessageUidParam();
     var detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
@@ -73,7 +78,8 @@ var tiki_event_calendar = function(calendar_id) {
         {'name': 'calendar_id', 'value': calendar_id},
         {'name': 'imap_msg_uid', 'value': uid},
         {'name': 'imap_server_id', 'value': detail.server_id},
-        {'name': 'folder', 'value': detail.folder}],
+        {'name': 'folder', 'value': detail.folder},
+        {'name': 'list_path', 'value': getListPathParam()}],
         function(res) {
             // noop
         },
@@ -89,13 +95,14 @@ var tiki_event_rsvp_actions = function() {
     });
     $(document).on("click", '.event_calendar_update', function(e) {
         var uid = getMessageUidParam();
-        var detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
         var $btn = $(this);
+        var detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
         Hm_Ajax.request(
             [{'name': 'hm_ajax_hook', 'value': 'ajax_update_in_calendar'},
             {'name': 'imap_msg_uid', 'value': uid},
             {'name': 'imap_server_id', 'value': detail.server_id},
-            {'name': 'folder', 'value': detail.folder}],
+            {'name': 'folder', 'value': detail.folder},
+            {'name': 'list_path', 'value': getListPathParam()}],
             function(res) {
                 // noop
             },
@@ -106,13 +113,14 @@ var tiki_event_rsvp_actions = function() {
     $(document).on("click", '.event_update_participant_status', function(e) {
         e.preventDefault();
         var uid = getMessageUidParam();
-        var detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
         var $btn = $(this);
+        var detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
         Hm_Ajax.request(
             [{'name': 'hm_ajax_hook', 'value': 'ajax_update_participant_status'},
             {'name': 'imap_msg_uid', 'value': uid},
             {'name': 'imap_server_id', 'value': detail.server_id},
-            {'name': 'folder', 'value': detail.folder}],
+            {'name': 'folder', 'value': detail.folder},
+            {'name': 'list_path', 'value': getListPathParam()}],
             function(res) {
                 $('.event_update_participant_status').text("Participant status updated");
                 $('.event_update_participant_status').toggleClass('event_update_participant_status event_participant_status_updated');
@@ -124,13 +132,14 @@ var tiki_event_rsvp_actions = function() {
     $(document).on("click", '.event_remove_from_calendar', function(e) {
         e.preventDefault();
         var uid = getMessageUidParam();
-        var detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
         var $btn = $(this);
+        var detail = Hm_Utils.parse_folder_path(getListPathParam(), 'imap');
         Hm_Ajax.request(
             [{'name': 'hm_ajax_hook', 'value': 'ajax_remove_from_calendar'},
             {'name': 'imap_msg_uid', 'value': uid},
             {'name': 'imap_server_id', 'value': detail.server_id},
-            {'name': 'folder', 'value': detail.folder}],
+            {'name': 'folder', 'value': detail.folder},
+            {'name': 'list_path', 'value': getListPathParam()}],
             function(res) {
                 // noop
             },


=====================================
lib/cypht/modules/tiki/tracker_modules.php
=====================================
@@ -771,11 +771,17 @@ class Hm_Handler_tiki_message_content extends Hm_Handler_Module
             return;
         }
 
+        // Only process tracker-stored messages; skip regular IMAP messages
+        $list_path = $this->request->post['list_path'] ?? '';
+        if (strpos($list_path, 'tracker_folder_') !== 0) {
+            return;
+        }
+
         $this->out('header_allow_images', $this->config->get('allow_external_image_sources'));
         $this->out('images_whitelist', explode(',', $this->user_config->get('images_whitelist_setting')));
 
         $this->out('msg_text_uid', $form['imap_msg_uid']);
-        $this->out('msg_list_path', $this->request->post['list_path']);
+        $this->out('msg_list_path', $list_path);
         $part_num = false;
         if (isset($this->request->post['imap_msg_part']) && preg_match("/[0-9\.]+/", $this->request->post['imap_msg_part'])) {
             $part_num = $this->request->post['imap_msg_part'];
@@ -785,7 +791,7 @@ class Hm_Handler_tiki_message_content extends Hm_Handler_Module
         }
         $this->out('header_allow_images', $this->config->get('allow_external_image_sources'));
 
-        $email = tiki_parse_message($this->request->post['list_path'], $form['imap_msg_uid']);
+        $email = tiki_parse_message($list_path, $form['imap_msg_uid']);
         if (! $email) {
             return;
         }



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/99650f37d03e4b566fc312e7098e8ed6e3f77a43

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/99650f37d03e4b566fc312e7098e8ed6e3f77a43
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.