diff --git a/language/az.php b/language/az.php index 5e1c54a187..e3f91e1ced 100755 --- a/language/az.php +++ b/language/az.php @@ -621,6 +621,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/de.php b/language/de.php index 7150e9c182..8bd66b1a43 100755 --- a/language/de.php +++ b/language/de.php @@ -618,6 +618,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/en.php b/language/en.php index f630f6a2d3..5cd8c300ef 100755 --- a/language/en.php +++ b/language/en.php @@ -636,6 +636,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/es.php b/language/es.php index fa551b1ea9..c253b1f363 100755 --- a/language/es.php +++ b/language/es.php @@ -618,6 +618,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/et.php b/language/et.php index 61b7b6addb..53e6207a9f 100755 --- a/language/et.php +++ b/language/et.php @@ -626,6 +626,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/fa.php b/language/fa.php index b2ad0e2221..9431100de7 100755 --- a/language/fa.php +++ b/language/fa.php @@ -670,6 +670,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/fr.php b/language/fr.php index b60c7c3592..8e0550fc0e 100755 --- a/language/fr.php +++ b/language/fr.php @@ -617,6 +617,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => 'Vous avez %d messages programmés qui ne seront pas exécutés si vous quittez', 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/hu.php b/language/hu.php index e91cd6a66d..7e9b587059 100755 --- a/language/hu.php +++ b/language/hu.php @@ -618,6 +618,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/id.php b/language/id.php index 07b205ab8b..95c4ac6a5f 100755 --- a/language/id.php +++ b/language/id.php @@ -625,6 +625,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/it.php b/language/it.php index 5147b4e8ad..d720e4214a 100755 --- a/language/it.php +++ b/language/it.php @@ -618,6 +618,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/ja.php b/language/ja.php index 30596c066d..7c7d601ac5 100755 --- a/language/ja.php +++ b/language/ja.php @@ -618,6 +618,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/nl.php b/language/nl.php index 1d1db295cc..82e94158d6 100755 --- a/language/nl.php +++ b/language/nl.php @@ -618,6 +618,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/pt-BR.php b/language/pt-BR.php index 1fcf9142ec..7ad23625b8 100755 --- a/language/pt-BR.php +++ b/language/pt-BR.php @@ -617,6 +617,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/ro.php b/language/ro.php index 5a52506d25..c019b88263 100755 --- a/language/ro.php +++ b/language/ro.php @@ -617,6 +617,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/ru.php b/language/ru.php index 60813edac2..70cd16aa1c 100755 --- a/language/ru.php +++ b/language/ru.php @@ -619,6 +619,7 @@ 'You must provide a name for your script' => false, 'Empty script' => false, 'Please create a profile for saving sent messages option' => false, + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => false, 'Your subject is empty!' => false, 'Your body is empty!' => false, diff --git a/language/zh-Hans.php b/language/zh-Hans.php index 8baf2310ff..526e932c4a 100644 --- a/language/zh-Hans.php +++ b/language/zh-Hans.php @@ -639,6 +639,7 @@ 'You must provide a name for your script' => '请提供脚本名称', 'Empty script' => '空脚本', 'Please create a profile for saving sent messages option' => '请创建用于保存已发送信息选项的配置文件', + 'You have %d scheduled messages that won\'t be executed if you quit' => false, 'Attachment storage unavailable, please contact your site administrator' => '附件存储不可用,请联系您的网站管理员', 'Your subject is empty!' => '主题为空!', 'Your body is empty!' => '内容为空!', diff --git a/modules/core/functions.php b/modules/core/functions.php index 1e224fff70..a422a0858b 100644 --- a/modules/core/functions.php +++ b/modules/core/functions.php @@ -637,3 +637,99 @@ function privacy_setting_callback($val, $key, $mod) { } return $val; } + +if (!hm_exists('get_scheduled_date')) { +function get_scheduled_date($format, $only_label = false) { + if ($format == 'later_in_day') { + $date_string = 'today 18:00'; + $label = 'Later in the day'; + } elseif ($format == 'tomorrow') { + $date_string = '+1 day 08:00'; + $label = 'Tomorrow'; + } elseif ($format == 'next_weekend') { + $date_string = 'next Saturday 08:00'; + $label = 'Next weekend'; + } elseif ($format == 'next_week') { + $date_string = 'next week 08:00'; + $label = 'Next week'; + } elseif ($format == 'next_month') { + $date_string = 'next month 08:00'; + $label = 'Next month'; + } else { + $date_string = $format; + $label = 'Certain date'; + } + $time = strtotime($date_string); + if ($only_label) { + return [$label, date('D, H:i', $time)]; + } + return date('D, d M Y H:i', $time); +}} + +/** + * @subpackage imap/functions + */ +if (!hm_exists('nexter_formats')) { +function nexter_formats() { + $values = array( + 'tomorrow', + 'next_weekend', + 'next_week', + 'next_month' + ); + if (date('H') <= 16) { + array_push($values, 'later_in_day'); + } + return $values; +}} + +if (!hm_exists('schedule_dropdown')) { +function schedule_dropdown($output, $send_now = false) { + $values = nexter_formats(); + + $txt = ''; + if ($send_now) { + $txt .= ''; + } + + return $txt; +}} + +/** + * @subpackage imap/functions + */ +if (!hm_exists('parse_nexter_header')) { + function parse_nexter_header($header, $name) + { + $header = str_replace("$name: ", '', $header); + $result = []; + foreach (explode(';', $header) as $kv) + { + $kv = trim($kv); + $spacePos = strpos($kv, ' '); + if ($spacePos > 0) { + $result[rtrim(substr($kv, 0, $spacePos), ':')] = trim(substr($kv, $spacePos+1)); + } else { + $result[$kv] = true; + } + } + return $result; + }} diff --git a/modules/core/message_list_functions.php b/modules/core/message_list_functions.php index 02c2d61dea..36bf2788fa 100644 --- a/modules/core/message_list_functions.php +++ b/modules/core/message_list_functions.php @@ -322,11 +322,11 @@ function subject_callback($vals, $style, $output_mod) { */ if (!hm_exists('date_callback')) { function date_callback($vals, $style, $output_mod) { - $snooze_class = isset($vals[2]) && $vals[2]? ' snoozed_date': ''; + $nexter_class = isset($vals[2]) && $vals[2]? ' nexter_date': ''; if ($style == 'news') { - return sprintf('
%s
', $snooze_class, $output_mod->html_safe($vals[0]), $output_mod->html_safe($vals[1])); + return sprintf('
%s
', $nexter_class, $output_mod->html_safe($vals[0]), $output_mod->html_safe($vals[1])); } - return sprintf('%s', $snooze_class, $output_mod->html_safe(date('r', $vals[1])), $output_mod->html_safe($vals[0]), $output_mod->html_safe($vals[1])); + return sprintf('%s', $nexter_class, $output_mod->html_safe(date('r', $vals[1])), $output_mod->html_safe($vals[0]), $output_mod->html_safe($vals[1])); }} /** diff --git a/modules/core/site.css b/modules/core/site.css index 95e98e0f8a..1609ae3636 100644 --- a/modules/core/site.css +++ b/modules/core/site.css @@ -1276,7 +1276,7 @@ div.unseen, .mobile .imap_sort { width: 100%; } -.snoozed_date { +.nexter_date { color: var(--bs-primary) !important; } diff --git a/modules/core/site.js b/modules/core/site.js index 58cd6e638a..ff806d2328 100644 --- a/modules/core/site.js +++ b/modules/core/site.js @@ -47,7 +47,7 @@ var Hm_Ajax = { active_reqs: 0, icon_loading_id: false, - get_ajax_hook_name: function(args) { + get_ajax_hook_name: function (args) { var index; for (index in args) { if (args[index]['name'] == 'hm_ajax_hook') { @@ -57,7 +57,7 @@ var Hm_Ajax = { return; }, - request: function(args, callback, extra, no_icon, batch_callback, on_failure, signal) { + request: function (args, callback, extra, no_icon, batch_callback, on_failure, signal) { var bcb = false; if (typeof batch_callback != 'undefined' && $.inArray(batch_callback, this.batch_callbacks) === -1) { bcb = batch_callback.toString(); @@ -79,27 +79,27 @@ var Hm_Ajax = { return ajax.make_request(args, callback, extra, name, on_failure, batch_callback, signal); }, - show_loading_icon: function() { + show_loading_icon: function () { if (Hm_Ajax.icon_loading_id !== false) { return; } - var hm_loading_pos = $('.loading_icon').width()/40; + var hm_loading_pos = $('.loading_icon').width() / 40; $('.loading_icon').show(); function move_background_image() { hm_loading_pos = hm_loading_pos + 50; - $('.loading_icon').css('background-position', hm_loading_pos+'px 0'); + $('.loading_icon').css('background-position', hm_loading_pos + 'px 0'); Hm_Ajax.icon_loading_id = setTimeout(move_background_image, 100); } move_background_image(); }, - stop_loading_icon : function(loading_id) { + stop_loading_icon: function (loading_id) { clearTimeout(loading_id); $('.loading_icon').hide(); Hm_Ajax.icon_loading_id = false; }, - process_callback_hooks: function(name, res) { + process_callback_hooks: function (name, res) { var hook; var func; for (var i in Hm_Ajax.callback_hooks) { @@ -116,180 +116,182 @@ var Hm_Ajax = { } }, - add_callback_hook: function(request_name, hook_function) { + add_callback_hook: function (request_name, hook_function) { Hm_Ajax.callback_hooks.push([request_name, hook_function]); } }; /* ajax request wrapper */ -var Hm_Ajax_Request = function() { return { - callback: false, - name: false, - batch_callback: false, - index: 0, - on_failure: false, - start_time: 0, - - xhr_fetch: function(config) { - var xhr = new XMLHttpRequest(); - var data = ''; - if (config.data) { - data = this.format_xhr_data(config.data); - } - const url = window.location.next ?? window.location.href; - xhr.open('POST', url) - if (config.signal) { - config.signal.addEventListener('abort', function() { - xhr.abort(); +var Hm_Ajax_Request = function () { + return { + callback: false, + name: false, + batch_callback: false, + index: 0, + on_failure: false, + start_time: 0, + + xhr_fetch: function (config) { + var xhr = new XMLHttpRequest(); + var data = ''; + if (config.data) { + data = this.format_xhr_data(config.data); + } + const url = window.location.next ?? window.location.href; + xhr.open('POST', url) + if (config.signal) { + config.signal.addEventListener('abort', function () { + xhr.abort(); + }); + } + xhr.addEventListener('load', function () { + config.callback.done(Hm_Utils.json_decode(xhr.response, true), xhr); + config.callback.always(Hm_Utils.json_decode(xhr.response, true)); }); - } - xhr.addEventListener('load', function() { - config.callback.done(Hm_Utils.json_decode(xhr.response, true), xhr); - config.callback.always(Hm_Utils.json_decode(xhr.response, true)); - }); - xhr.addEventListener('error', function() { - Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); - config.callback.fail(xhr); - config.callback.always(Hm_Utils.json_decode(xhr.response, true)); - }); - xhr.addEventListener('abort', function() { - Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); - config.callback.always(Hm_Utils.json_decode(xhr.response, true)); + xhr.addEventListener('error', function () { + Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); + config.callback.fail(xhr); + config.callback.always(Hm_Utils.json_decode(xhr.response, true)); + }); + xhr.addEventListener('abort', function () { + Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); + config.callback.always(Hm_Utils.json_decode(xhr.response, true)); - }); - xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); - xhr.setRequestHeader('X-Requested-with', 'xmlhttprequest'); - xhr.send(data); - }, + }); + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xhr.setRequestHeader('X-Requested-with', 'xmlhttprequest'); + xhr.send(data); + }, - format_xhr_data: function(data) { - var res = [] - for (var i in data) { - res.push(encodeURIComponent(data[i]['name']) + '=' + encodeURIComponent(data[i]['value'])); - } - return res.join('&'); - }, + format_xhr_data: function (data) { + var res = [] + for (var i in data) { + res.push(encodeURIComponent(data[i]['name']) + '=' + encodeURIComponent(data[i]['value'])); + } + return res.join('&'); + }, - make_request: function(args, callback, extra, request_name, on_failure, batch_callback, signal) { - var name; - var arg; - this.batch_callback = batch_callback; - this.name = request_name; - this.callback = callback; - if (on_failure) { - this.on_failure = true; - } - if (extra) { - for (name in extra) { - args.push({'name': name, 'value': extra[name]}); + make_request: function (args, callback, extra, request_name, on_failure, batch_callback, signal) { + var name; + var arg; + this.batch_callback = batch_callback; + this.name = request_name; + this.callback = callback; + if (on_failure) { + this.on_failure = true; + } + if (extra) { + for (name in extra) { + args.push({ 'name': name, 'value': extra[name] }); + } } - } - var key_found = false; - for (arg in args) { - if (args[arg].name == 'hm_page_key') { - key_found = true; - break; + var key_found = false; + for (arg in args) { + if (args[arg].name == 'hm_page_key') { + key_found = true; + break; + } } - } - if (!key_found) { - args.push({'name': 'hm_page_key', 'value': $('#hm_page_key').val()}); - } - var dt = new Date(); - this.start_time = dt.getTime(); - this.xhr_fetch({url: '', data: args, callback: this, signal}); - return false; - }, + if (!key_found) { + args.push({ 'name': 'hm_page_key', 'value': $('#hm_page_key').val() }); + } + var dt = new Date(); + this.start_time = dt.getTime(); + this.xhr_fetch({ url: '', data: args, callback: this, signal }); + return false; + }, - done: function(res, xhr) { - if (Hm_Ajax.aborted) { - return; - } - else if (!res || typeof res == 'string' && (res == 'null' || res.indexOf('<') === 0 || res == '{}')) { - this.fail(xhr); - return; - } - else { - $('.offline').hide(); - if (hm_encrypt_ajax_requests()) { - res = Hm_Utils.json_decode(Hm_Crypt.decrypt(res.payload)); + done: function (res, xhr) { + if (Hm_Ajax.aborted) { + return; } - if ((res.state && res.state == 'not callable') || !res.router_login_state) { - this.fail(xhr, true); + else if (!res || typeof res == 'string' && (res == 'null' || res.indexOf('<') === 0 || res == '{}')) { + this.fail(xhr); return; } - if (Hm_Ajax.err_condition) { - Hm_Ajax.err_condition = false; - Hm_Notices.hide(true); - } - if (res.router_user_msgs && !$.isEmptyObject(res.router_user_msgs)) { - Hm_Notices.show(res.router_user_msgs); - } - if (res.folder_status) { - for (const name in res.folder_status) { - if (name === getListPathParam()) { - Hm_Folders.unread_counts[name] = res.folder_status[name]['unseen']; - Hm_Folders.update_unread_counts(); - const messages = new Hm_MessagesStore(name, Hm_Utils.get_url_page_number()); - messages.load().then(() => { - if (messages.count != res.folder_status[name].messages) { - messages.load(true).then(() => { - display_imap_mailbox(messages.rows, messages.links); - }) - } - }); + else { + $('.offline').hide(); + if (hm_encrypt_ajax_requests()) { + res = Hm_Utils.json_decode(Hm_Crypt.decrypt(res.payload)); + } + if ((res.state && res.state == 'not callable') || !res.router_login_state) { + this.fail(xhr, true); + return; + } + if (Hm_Ajax.err_condition) { + Hm_Ajax.err_condition = false; + Hm_Notices.hide(true); + } + if (res.router_user_msgs && !$.isEmptyObject(res.router_user_msgs)) { + Hm_Notices.show(res.router_user_msgs); + } + if (res.folder_status) { + for (const name in res.folder_status) { + if (name === getListPathParam()) { + Hm_Folders.unread_counts[name] = res.folder_status[name]['unseen']; + Hm_Folders.update_unread_counts(); + const messages = new Hm_MessagesStore(name, Hm_Utils.get_url_page_number()); + messages.load().then(() => { + if (messages.count != res.folder_status[name].messages) { + messages.load(true).then(() => { + display_imap_mailbox(messages.rows, messages.links); + }) + } + }); + } } } + if (this.callback) { + this.callback(res); + } + Hm_Ajax.process_callback_hooks(this.name, res); } - if (this.callback) { - this.callback(res); - } - Hm_Ajax.process_callback_hooks(this.name, res); - } - }, + }, - run_on_failure: function() { - if (this.on_failure && this.callback) { - this.callback(false); - } - return false; - }, + run_on_failure: function () { + if (this.on_failure && this.callback) { + this.callback(false); + } + return false; + }, - fail: function(xhr, not_callable) { - if (not_callable === true || (xhr.status && xhr.status == 500)) { - Hm_Notices.show([err_msg('Server Error')]); - } - else { - $('.offline').show(); + fail: function (xhr, not_callable) { + if (not_callable === true || (xhr.status && xhr.status == 500)) { + Hm_Notices.show([err_msg('Server Error')]); + } + else { + $('.offline').show(); + } + Hm_Ajax.err_condition = true; + this.run_on_failure(); + }, + + always: function (res) { + Hm_Ajax.active_reqs--; + var batch_count = 1; + if (this.batch_callback) { + if (typeof Hm_Ajax.batch_callbacks[this.batch_callback.toString()] != 'undefined') { + batch_count = --Hm_Ajax.batch_callbacks[this.batch_callback.toString()]; + } + } + Hm_Message_List.set_row_events(); + if (batch_count === 0) { + Hm_Ajax.batch_callbacks[this.batch_callback.toString()] = 0; + Hm_Ajax.aborted = false; + Hm_Ajax.p_callbacks = []; + this.batch_callback(res); + this.batch_callback = false; + Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); + $('body').removeClass('wait'); + } + if (Hm_Ajax.active_reqs == 0) { + Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); + $('body').removeClass('wait'); + } + res = null; } - Hm_Ajax.err_condition = true; - this.run_on_failure(); - }, - - always: function(res) { - Hm_Ajax.active_reqs--; - var batch_count = 1; - if (this.batch_callback) { - if (typeof Hm_Ajax.batch_callbacks[this.batch_callback.toString()] != 'undefined') { - batch_count = --Hm_Ajax.batch_callbacks[this.batch_callback.toString()]; - } - } - Hm_Message_List.set_row_events(); - if (batch_count === 0) { - Hm_Ajax.batch_callbacks[this.batch_callback.toString()] = 0; - Hm_Ajax.aborted = false; - Hm_Ajax.p_callbacks = []; - this.batch_callback(res); - this.batch_callback = false; - Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); - $('body').removeClass('wait'); - } - if (Hm_Ajax.active_reqs == 0) { - Hm_Ajax.stop_loading_icon(Hm_Ajax.icon_loading_id); - $('body').removeClass('wait'); - } - res = null; } -}}; +}; /** * Show a modal dialog with a title, content and buttons. @@ -326,7 +328,7 @@ function Hm_Modal(options) { @@ -380,7 +382,7 @@ function Hm_Modal(options) { var Hm_Notices = { hide_id: false, - show: function(msgs) { + show: function (msgs) { var message = ''; var type = ''; for (var i in msgs) { @@ -397,7 +399,7 @@ var Hm_Notices = { } }, - hide: function(now) { + hide: function (now) { if (Hm_Notices.hide_id) { clearTimeout(Hm_Notices.hide_id); } @@ -406,7 +408,7 @@ var Hm_Notices = { Hm_Utils.clear_sys_messages(); } else { - Hm_Notices.hide_id = setTimeout(function() { + Hm_Notices.hide_id = setTimeout(function () { $('.sys_messages').addClass('d-none'); Hm_Utils.clear_sys_messages(); }, 5000); @@ -419,7 +421,7 @@ var Hm_Timer = { jobs: [], interval: 1000, - add_job: function(job, interval, defer, custom_defer) { + add_job: function (job, interval, defer, custom_defer) { if (custom_defer) { Hm_Timer.jobs.push([job, interval, custom_defer]); } @@ -427,11 +429,11 @@ var Hm_Timer = { Hm_Timer.jobs.push([job, interval, interval]); } if (!defer) { - try { job(); } catch(e) { console.log(e); } + try { job(); } catch (e) { console.log(e); } } }, - cancel: function(job) { + cancel: function (job) { for (var index in Hm_Timer.jobs) { if (Hm_Timer.jobs[index][0] == job) { Hm_Timer.jobs.splice(index, 1); @@ -441,7 +443,7 @@ var Hm_Timer = { return false; }, - fire: function() { + fire: function () { var job; var index; for (index in Hm_Timer.jobs) { @@ -450,7 +452,7 @@ var Hm_Timer = { if (job[2] === 0) { job[2] = job[1]; Hm_Timer.jobs[index] = job; - try { job[0](); } catch(e) { console.log(e); } + try { job[0](); } catch (e) { console.log(e); } } } setTimeout(Hm_Timer.fire, Hm_Timer.interval); @@ -489,13 +491,13 @@ function Message_List() { if (completed) { for (index in this.callbacks) { func = this.callbacks[index]; - try { func(); } catch(e) { console.log(e); } + try { func(); } catch (e) { console.log(e); } } } fixLtrInRtl(); }; - this.update = function(msgs) { + this.update = function (msgs) { Hm_Utils.tbody().html(''); for (const index in msgs) { const row = msgs[index][0]; @@ -503,20 +505,20 @@ function Message_List() { } }; - this.set_tab_index = function() { + this.set_tab_index = function () { var msg_rows = Hm_Utils.rows(); var count = 1; - msg_rows.each(function() { + msg_rows.each(function () { $(this).attr('tabindex', count); count++; }); }; - this.sort = function(fld) { + this.sort = function (fld) { var listitems = Hm_Utils.rows(); var aval; var bval; - var sort_result = listitems.sort(function(a, b) { + var sort_result = listitems.sort(function (a, b) { switch (Math.abs(fld)) { case 1: case 2: @@ -545,13 +547,13 @@ function Message_List() { }); this.sort_fld = fld; Hm_Utils.tbody().html(''); - for (var i = 0, len=sort_result.length; i < len; i++) { + for (var i = 0, len = sort_result.length; i < len; i++) { Hm_Utils.tbody().append(sort_result[i]); } this.save_updated_list(); }; - this.insert_into_message_list = function(row, msg_rows) { + this.insert_into_message_list = function (row, msg_rows) { var sort_fld = this.sort_fld; if (typeof sort_fld == 'undefined' || sort_fld == null) { sort_fld = 4; @@ -560,10 +562,10 @@ function Message_List() { if (sort_fld == 4 || sort_fld == -4) { var timestr2; var timestr = $('.msg_timestamp', $(row)).val(); - $('tr', msg_rows).each(function() { + $('tr', msg_rows).each(function () { timestr2 = $('.msg_timestamp', $(this)).val(); - if ((sort_fld == -4 && (timestr2*1) >= (timestr*1)) || - (sort_fld == 4 && (timestr*1) >= (timestr2*1))) { + if ((sort_fld == -4 && (timestr2 * 1) >= (timestr * 1)) || + (sort_fld == 4 && (timestr * 1) >= (timestr2 * 1))) { element = $(this); return false; } @@ -572,10 +574,10 @@ function Message_List() { else { var bval; var aval = $($('td', $(row))[Math.abs(sort_fld)]).text().replace(/^\s+/g, ''); - $('tr', msg_rows).each(function() { + $('tr', msg_rows).each(function () { bval = $($('td', $(this))[Math.abs(sort_fld)]).text().replace(/^\s+/g, ''); if ((sort_fld < 0 && aval.toUpperCase().localeCompare(bval.toUpperCase()) > 0) || - (sort_fld > 0 && bval.toUpperCase().localeCompare(aval.toUpperCase()) > 0)) { + (sort_fld > 0 && bval.toUpperCase().localeCompare(aval.toUpperCase()) > 0)) { element = $(this); return false; } @@ -588,16 +590,16 @@ function Message_List() { else { msg_rows.append(row); } - self.just_inserted.push($('.from', $(row)).text()+' - '+$('.subject', $(row)).text()); + self.just_inserted.push($('.from', $(row)).text() + ' - ' + $('.subject', $(row)).text()); }; - this.reset_checkboxes = function() { + this.reset_checkboxes = function () { this.toggle_msg_controls(); this.set_row_events(); }; - this.toggle_msg_controls = function() { - if ($('input[type=checkbox]', $('.message_table')).filter(function() {return this.checked; }).length > 0) { + this.toggle_msg_controls = function () { + if ($('input[type=checkbox]', $('.message_table')).filter(function () { return this.checked; }).length > 0) { $('.msg_controls').addClass('d-flex'); $('.msg_controls').removeClass('d-none'); $('.mailbox_list_title').addClass('hide'); @@ -609,7 +611,7 @@ function Message_List() { } }; - this.update_after_action = function(action_type, selected) { + this.update_after_action = function (action_type, selected) { var remove = false; if (action_type == 'read' && getListPathParam() == 'unread') { remove = true; @@ -635,20 +637,20 @@ function Message_List() { this.reset_checkboxes(); }; - this.save_updated_list = function() { + this.save_updated_list = function () { if (this.page_caches.hasOwnProperty(getListPathParam())) { this.set_message_list_state(this.page_caches[getListPathParam()]); - Hm_Utils.save_to_local_storage('sort_'+getListPathParam(), this.sort_fld); + Hm_Utils.save_to_local_storage('sort_' + getListPathParam(), this.sort_fld); } }; - this.remove_after_action = function(action_type, selected) { + this.remove_after_action = function (action_type, selected) { var removed = 0; var class_name = false; var index; for (index in selected) { class_name = selected[index]; - $('.'+Hm_Utils.clean_selector(class_name)).remove(); + $('.' + Hm_Utils.clean_selector(class_name)).remove(); if (action_type == 'delete') { this.deleted.push(class_name); } @@ -657,14 +659,14 @@ function Message_List() { return removed; }; - this.read_after_action = function(action_type, selected) { + this.read_after_action = function (action_type, selected) { var read = 0; var row; var index; var class_name = false; for (index in selected) { class_name = selected[index]; - row = $('.'+Hm_Utils.clean_selector(class_name)); + row = $('.' + Hm_Utils.clean_selector(class_name)); if (action_type == 'read') { $('.subject > div', row).removeClass('unseen'); row.removeClass('unseen'); @@ -678,14 +680,14 @@ function Message_List() { return read; }; - this.flag_after_action = function(action_type, selected) { + this.flag_after_action = function (action_type, selected) { var flagged = 0; var class_name; var row; var index; for (index in selected) { class_name = selected[index]; - row = $('.'+Hm_Utils.clean_selector(class_name)); + row = $('.' + Hm_Utils.clean_selector(class_name)); if (action_type == 'flag') { $('.icon', row).html(hm_flag_image_src()); } @@ -697,7 +699,7 @@ function Message_List() { return flagged; }; - this.load_sources = function() { + this.load_sources = function () { var index; var source; if (!self.background) { @@ -710,7 +712,7 @@ function Message_List() { return false; }; - this.select_combined_view = function() { + this.select_combined_view = function () { if (self.page_caches.hasOwnProperty(getListPathParam())) { self.setup_combined_view(self.page_caches[getListPathParam()]); } @@ -722,23 +724,24 @@ function Message_List() { self.setup_combined_view(false); } } - var sort_type = Hm_Utils.get_from_local_storage('sort_'+getListPathParam()); + var sort_type = Hm_Utils.get_from_local_storage('sort_' + getListPathParam()); if (sort_type != null) { this.sort_fld = sort_type; $('.combined_sort').val(sort_type); } - $('.core_msg_control').on("click", function(e) { + $('.core_msg_control').on("click", function (e) { e.preventDefault(); - return self.message_action($(this).data('action')); }); - $('.toggle_link').on("click", function() { return self.toggle_rows(); }); - $('.refresh_link').on("click", function() { return self.load_sources(); }); + return self.message_action($(this).data('action')); + }); + $('.toggle_link').on("click", function () { return self.toggle_rows(); }); + $('.refresh_link').on("click", function () { return self.load_sources(); }); }; - this.add_sources = function(sources) { + this.add_sources = function (sources) { self.sources = sources; }; - this.setup_combined_view = function(cache_name) { + this.setup_combined_view = function (cache_name) { self.add_sources(hm_data_sources()); var data = Hm_Utils.get_from_local_storage(cache_name); var interval = Hm_Utils.get_from_global('combined_view_refresh_interval', 60); @@ -758,53 +761,53 @@ function Message_List() { } }; - this.clear_read_messages = function() { + this.clear_read_messages = function () { var class_name; var list = Hm_Utils.get_from_local_storage('read_message_list'); if (list && list.length) { list = Hm_Utils.json_decode(list); for (class_name in list) { - $('.'+Hm_Utils.clean_selector(class_name)).remove(); + $('.' + Hm_Utils.clean_selector(class_name)).remove(); } Hm_Utils.save_to_local_storage('read_message_list', ''); } }; /* TODO: remove module specific refs */ - this.update_title = function(list_path = getListPathParam()) { + this.update_title = function (list_path = getListPathParam()) { var count = 0; var rows = Hm_Utils.rows(); var tbody = Hm_Utils.tbody(); if (list_path == 'unread') { count = rows.length; - document.title = count+' '+hm_trans('Unread'); + document.title = count + ' ' + hm_trans('Unread'); } else if (list_path == 'flagged') { count = rows.length; - document.title = count+' '+hm_trans('Flagged'); + document.title = count + ' ' + hm_trans('Flagged'); } else if (list_path == 'combined_inbox') { count = $('tr .unseen', tbody).length; - document.title = count+' '+hm_trans('Unread in Everything'); + document.title = count + ' ' + hm_trans('Unread in Everything'); } else if (list_path == 'email') { count = $('tr .unseen', tbody).length; - document.title = count+' '+hm_trans('Unread in Email'); + document.title = count + ' ' + hm_trans('Unread in Email'); } else if (list_path == 'feeds') { count = $('tr .unseen', tbody).length; - document.title = count+' '+hm_trans('Unread in Feeds'); + document.title = count + ' ' + hm_trans('Unread in Feeds'); } }; - this.message_action = function(action_type) { + this.message_action = function (action_type) { if (action_type == 'delete' && !hm_delete_prompt()) { return false; } var msg_list = $('.message_table'); var selected = []; var current_list = self.filter_list(); - $('input[type=checkbox]', msg_list).each(function() { + $('input[type=checkbox]', msg_list).each(function () { if (this.checked) { selected.push($(this).val()); } @@ -812,10 +815,10 @@ function Message_List() { if (selected.length > 0) { var updated = false; Hm_Ajax.request( - [{'name': 'hm_ajax_hook', 'value': 'ajax_message_action'}, - {'name': 'action_type', 'value': action_type}, - {'name': 'message_ids', 'value': selected}], - function(res) { + [{ 'name': 'hm_ajax_hook', 'value': 'ajax_message_action' }, + { 'name': 'action_type', 'value': action_type }, + { 'name': 'message_ids', 'value': selected }], + function (res) { if (!res) { $('.message_table_body').replaceWith(current_list); self.save_updated_list(); @@ -840,7 +843,7 @@ function Message_List() { } }; - this.prev_next_links = function(msgUid, lisPath = getListPathParam()) { + this.prev_next_links = function (msgUid, lisPath = getListPathParam()) { let phref; let nhref; const target = $('.msg_headers tr').last(); @@ -852,30 +855,30 @@ function Message_List() { const prevSubject = $(prev['0']).find('.subject a'); phref = prevSubject.prop('href'); const subject = prevSubject.text(); - const plink = ' '+subject+''; - $(''+plink+'').insertBefore(target); + const plink = ' ' + subject + ''; + $('' + plink + '').insertBefore(target); } if (next) { const nextSubject = $(next['0']).find('.subject a'); nhref = nextSubject.prop('href'); const subject = nextSubject.text(); - - const nlink = ' '+subject+''; - $(''+nlink+'').insertBefore(target); + + const nlink = ' ' + subject + ''; + $('' + nlink + '').insertBefore(target); } return [phref, nhref]; }; - this.check_empty_list = function() { + this.check_empty_list = function () { var count = Hm_Utils.rows().length; if (!count) { if (!$('.empty_list').length) { if (getPageNameParam() == 'search') { - $('.search_content').append('
'+hm_empty_folder()+'
'); + $('.search_content').append('
' + hm_empty_folder() + '
'); } else { - $('.message_list').append('
'+hm_empty_folder()+'
'); + $('.message_list').append('
' + hm_empty_folder() + '
'); } $(".page_links").css("display", "none");// Hide page links as message list is empty } @@ -887,7 +890,7 @@ function Message_List() { return count === 0; }; - this.track_read_messages = function(class_name) { + this.track_read_messages = function (class_name) { var read_messages = Hm_Utils.get_from_local_storage('read_message_list'); if (read_messages && read_messages.length) { read_messages = Hm_Utils.json_decode(read_messages); @@ -904,9 +907,9 @@ function Message_List() { return added; }; - this.adjust_unread_total = function(amount, replace) { + this.adjust_unread_total = function (amount, replace) { var missing = $('.total_unread_count').text() === '' ? true : false; - var current = $('.total_unread_count').text()*1; + var current = $('.total_unread_count').text() * 1; var new_total; if (replace && amount == current && amount != 0) { return; @@ -924,7 +927,7 @@ function Message_List() { new_total = 0; } if (new_total != current || missing) { - $('.total_unread_count').html(' '+new_total+' '); + $('.total_unread_count').html(' ' + new_total + ' '); } if (new_total > current && getPageNameParam() != 'message_list' && getListPathParam() != 'unread') { $('.menu_unread > a').css('font-weight', 'bold'); @@ -936,14 +939,14 @@ function Message_List() { self.past_total = current; }; - this.toggle_rows = function() { + this.toggle_rows = function () { $('input[type=checkbox]', $('.message_table')).each(function () { this.checked = !this.checked; }); self.toggle_msg_controls(); return false; }; - this.filter_list = function() { - var data = Hm_Utils.rows().clone().filter(function() { + this.filter_list = function () { + var data = Hm_Utils.rows().clone().filter(function () { if (this.className == 'inline_msg') { return false; } @@ -954,7 +957,7 @@ function Message_List() { return res; }; - this.set_message_list_state = function(list_type) { + this.set_message_list_state = function (list_type) { var data = this.filter_list(); data.find('*[style]').attr('style', ''); data.find('input[type=checkbox]').removeAttr('checked'); @@ -970,10 +973,10 @@ function Message_List() { } }; - this.select_range = function(a, b) { + this.select_range = function (a, b) { var start = false; var end = false; - $('input[type=checkbox]', $('.message_table')).each(function() { + $('input[type=checkbox]', $('.message_table')).each(function () { if (end) { return false; } @@ -992,7 +995,7 @@ function Message_List() { }); }; - this.process_shift_click = function(el) { + this.process_shift_click = function (el) { var id = el.prop('id'); if (id == self.last_click) { return; @@ -1000,12 +1003,12 @@ function Message_List() { self.select_range(id, self.last_click); }; - this.set_row_events = function() { + this.set_row_events = function () { Hm_Utils.rows().off('click'); - Hm_Utils.rows().on('click', function(e) { self.process_row_click(e); }); + Hm_Utils.rows().on('click', function (e) { self.process_row_click(e); }); } - this.process_row_click = function(e) { + this.process_row_click = function (e) { if (e.target.tagName === 'A') { return; } @@ -1031,47 +1034,47 @@ function Message_List() { return false; } - this.select_on_row_click = function(shift, ctrl, el, target) { + this.select_on_row_click = function (shift, ctrl, el, target) { if (shift) { if (self.last_click) { self.process_shift_click(el); } - $('#'+el.prop('id')).prop('checked', 'checked'); + $('#' + el.prop('id')).prop('checked', 'checked'); self.last_click = el.prop('id'); } else if (ctrl) { if (el.prop('checked')) { - $('#'+el.prop('id')).prop('checked', false); + $('#' + el.prop('id')).prop('checked', false); } else { - $('#'+el.prop('id')).prop('checked', 'checked'); + $('#' + el.prop('id')).prop('checked', 'checked'); self.last_click = el.prop('id'); } } } - this.set_all_mail_state = function() { self.set_message_list_state('formatted_all_mail'); }; - this.set_combined_inbox_state = function() { self.set_message_list_state('formatted_combined_inbox'); }; - this.set_flagged_state = function() { self.set_message_list_state('formatted_flagged_data'); }; - this.set_unread_state = function() { self.set_message_list_state('formatted_unread_data'); }; - this.set_search_state = function() { self.set_message_list_state('formatted_search_data'); }; - this.set_junk_state = function() { self.set_message_list_state('formatted_junk_data'); }; - this.set_trash_state = function() { self.set_message_list_state('formatted_trash_data'); }; - this.set_draft_state = function() { self.set_message_list_state('formatted_drafts_data'); }; - this.set_tag_state = function() { self.set_message_list_state('formatted_tag_data'); }; + this.set_all_mail_state = function () { self.set_message_list_state('formatted_all_mail'); }; + this.set_combined_inbox_state = function () { self.set_message_list_state('formatted_combined_inbox'); }; + this.set_flagged_state = function () { self.set_message_list_state('formatted_flagged_data'); }; + this.set_unread_state = function () { self.set_message_list_state('formatted_unread_data'); }; + this.set_search_state = function () { self.set_message_list_state('formatted_search_data'); }; + this.set_junk_state = function () { self.set_message_list_state('formatted_junk_data'); }; + this.set_trash_state = function () { self.set_message_list_state('formatted_trash_data'); }; + this.set_draft_state = function () { self.set_message_list_state('formatted_drafts_data'); }; + this.set_tag_state = function () { self.set_message_list_state('formatted_tag_data'); }; }; /* folder list */ var Hm_Folders = { expand_after_update: false, unread_counts: {}, - observer : false, + observer: false, - save_folder_list: function() { + save_folder_list: function () { Hm_Utils.save_to_local_storage('formatted_folder_list', $('.folder_list').html()); }, - load_unread_counts: function() { + load_unread_counts: function () { var res = Hm_Utils.json_decode(Hm_Utils.get_from_local_storage('unread_counts')); if (!res) { Hm_Folders.unread_counts = {}; @@ -1081,9 +1084,9 @@ var Hm_Folders = { } }, - update_unread_counts: function(folder) { + update_unread_counts: function (folder) { if (folder) { - $('.unread_'+folder).html(' '+Hm_Folders.unread_counts[folder]+' '); + $('.unread_' + folder).html(' ' + Hm_Folders.unread_counts[folder] + ' '); } else { var name; @@ -1095,17 +1098,17 @@ var Hm_Folders = { if (count) { if (getListPathParam() == name && getPageNameParam() == 'message_list') { var title = document.title.replace(/^\[\d+\]/, ''); - document.title = '['+count+'] '+title; + document.title = '[' + count + '] ' + title; /* HERE */ } - $('.unread_'+name).html(' '+count+' '); + $('.unread_' + name).html(' ' + count + ' '); } } } Hm_Utils.save_to_local_storage('unread_counts', Hm_Utils.json_encode(Hm_Folders.unread_counts)); }, - open_folder_list: function() { + open_folder_list: function () { $('.folder_list').show(); $('.folder_toggle').toggle(); if (hm_mobile()) { @@ -1118,7 +1121,7 @@ var Hm_Folders = { return false; }, - toggle_folder_list: function() { + toggle_folder_list: function () { if ($('.folder_list').css('display') == 'none') { Hm_Folders.open_folder_list(); } @@ -1127,7 +1130,7 @@ var Hm_Folders = { } }, - hide_folder_list: function(forget) { + hide_folder_list: function (forget) { $('.folder_list').hide(); $('.folder_toggle').show(); if (!forget) { @@ -1138,7 +1141,7 @@ var Hm_Folders = { return false; }, - reload_folders: function(force, expand_after_update) { + reload_folders: function (force, expand_after_update) { if (document.cookie.indexOf('hm_reload_folders=1') > -1 || force) { Hm_Folders.expand_after_update = expand_after_update; var ui_state = Hm_Utils.preserve_local_settings(); @@ -1150,28 +1153,28 @@ var Hm_Folders = { return false; }, - sort_list: function(class_name, exclude_name, last_name) { - var folder = $('.'+class_name+' ul'); + sort_list: function (class_name, exclude_name, last_name) { + var folder = $('.' + class_name + ' ul'); var listitems; if (exclude_name) { - listitems = $('li:not(.'+exclude_name+')', folder); + listitems = $('li:not(.' + exclude_name + ')', folder); } else { listitems = $('li', folder); } - listitems = listitems.sort(function(a, b) { + listitems = listitems.sort(function (a, b) { if (last_name && ($(a).attr('class') == last_name || $(b).attr('class') == last_name)) { return false; } if ($(b).text().toUpperCase() == 'ALL') { return true; } - return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase()); + return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase()); }); - $.each(listitems, function(_, itm) { folder.append(itm); }); + $.each(listitems, function (_, itm) { folder.append(itm); }); }, - update_folder_list_display: function(res) { + update_folder_list_display: function (res) { $('.folder_list').html(res.formatted_folder_list); Hm_Folders.sort_list('email_folders', 'menu_email'); Hm_Folders.sort_list('feeds_folders', 'menu_feeds', 'feeds_add_new'); @@ -1187,9 +1190,9 @@ var Hm_Folders = { hl_save_link(); }, - update_folder_list: function() { + update_folder_list: function () { Hm_Ajax.request( - [{'name': 'hm_ajax_hook', 'value': 'ajax_hm_folders'}], + [{ 'name': 'hm_ajax_hook', 'value': 'ajax_hm_folders' }], Hm_Folders.update_folder_list_display, [], true @@ -1197,72 +1200,72 @@ var Hm_Folders = { return false; }, - folder_list_events: function() { - $('.imap_folder_link').on("click", function() { return expand_imap_folders($(this)); }); - $('.src_name').on('click', function() { + folder_list_events: function () { + $('.imap_folder_link').on("click", function () { return expand_imap_folders($(this)); }); + $('.src_name').on('click', function () { let transformValue = ''; if ($(this).attr('aria-expanded') == 'true') { transformValue = 'rotate(180deg)'; - + } else { transformValue = 'rotate(0deg)'; } - + $(this).find('i').css('transform', transformValue); }); - $('.update_message_list').on("click", function(e) { + $('.update_message_list').on("click", function (e) { var text = e.target.innerHTML; e.target.innerHTML = '
Loading...
'; Hm_Folders.update_folder_list(); - Hm_Ajax.add_callback_hook('hm_reload_folders', function() { + Hm_Ajax.add_callback_hook('hm_reload_folders', function () { e.target.innerHTML = text; }); return false; }); - $('.hide_folders').on("click", function() { return Hm_Folders.hide_folder_list(); }); - $('.logout_link').on("click", function(e) { return Hm_Utils.confirm_logout(); }); + $('.hide_folders').on("click", function () { return Hm_Folders.hide_folder_list(); }); + $('.logout_link').on("click", function (e) { return Hm_Utils.confirm_logout(); }); if (hm_search_terms()) { $('.search_terms').val(hm_search_terms()); } - $('.search_terms').on('search', function() { - Hm_Ajax.request([{'name': 'hm_ajax_hook', 'value': 'ajax_reset_search'}]); + $('.search_terms').on('search', function () { + Hm_Ajax.request([{ 'name': 'hm_ajax_hook', 'value': 'ajax_reset_search' }]); }); }, - hl_selected_menu: function() { + hl_selected_menu: function () { const page = getPageNameParam(); const path = getListPathParam(); - + $('.folder_list').find('*').removeClass('selected_menu'); if (path) { if (page == 'message_list' || page == 'message') { - $("[data-id='"+Hm_Utils.clean_selector(path)+"']").closest('li').addClass('selected_menu'); - $('.menu_'+Hm_Utils.clean_selector(path)).addClass('selected_menu'); + $("[data-id='" + Hm_Utils.clean_selector(path) + "']").closest('li').addClass('selected_menu'); + $('.menu_' + Hm_Utils.clean_selector(path)).addClass('selected_menu'); } else { - $('.menu_'+path).addClass('selected_menu'); + $('.menu_' + path).addClass('selected_menu'); } } else { - $('.menu_'+page).addClass('selected_menu'); + $('.menu_' + page).addClass('selected_menu'); } }, - listen_for_new_messages: function() { + listen_for_new_messages: function () { var target = $('.total_unread_count').get(0); if (!Hm_Folders.observer) { - Hm_Folders.observer = new MutationObserver(function(mutations) { + Hm_Folders.observer = new MutationObserver(function (mutations) { $('body').trigger('new_message'); }); } else { Hm_Folders.observer.disconnect(); } - Hm_Folders.observer.observe(target, {attributes: true, childList: true, characterData: true}); + Hm_Folders.observer.observe(target, { attributes: true, childList: true, characterData: true }); }, - load_from_local_storage: function() { + load_from_local_storage: function () { var folder_list = Hm_Utils.get_from_local_storage('formatted_folder_list'); if (folder_list) { $('.folder_list').html(folder_list); @@ -1281,21 +1284,21 @@ var Hm_Folders = { return false; }, - toggle_folders_event: function() { - $('.folder_toggle').on("click", function() { return Hm_Folders.open_folder_list(); }); + toggle_folders_event: function () { + $('.folder_toggle').on("click", function () { return Hm_Folders.open_folder_list(); }); } }; /* misc */ var Hm_Utils = { - get_url_page_number: function() { + get_url_page_number: function () { var index; var match_result; var page_number = 1; var params = location.search.substr(1).split('&'); var param_len = params.length; - for (index=0; index < param_len; index++) { + for (index = 0; index < param_len; index++) { match_result = params[index].match(/list_page=(\d+)/); if (match_result) { page_number = match_result[1]; @@ -1305,14 +1308,14 @@ var Hm_Utils = { return page_number; }, - get_from_global: function(name, def) { + get_from_global: function (name, def) { if (globals[name]) { return globals[name]; } return def; }, - preserve_local_settings: function() { + preserve_local_settings: function () { var i; var result = {}; var prefix = window.location.pathname.length; @@ -1325,33 +1328,33 @@ var Hm_Utils = { return result; }, - restore_local_settings: function(settings) { + restore_local_settings: function (settings) { var i; for (i in settings) { Hm_Utils.save_to_local_storage(i, settings[i]); } }, - reset_search_form: function() { + reset_search_form: function () { Hm_Utils.save_to_local_storage('formatted_search_data', ''); - Hm_Ajax.request([{'name': 'hm_ajax_hook', 'value': 'ajax_reset_search'}], - function(res) { window.location = '?page=search'; }, false, true); + Hm_Ajax.request([{ 'name': 'hm_ajax_hook', 'value': 'ajax_reset_search' }], + function (res) { window.location = '?page=search'; }, false, true); return false; }, - confirm_logout: function() { - if (! $('#unsaved_changes').length || $('#unsaved_changes').val() == 0) { + confirm_logout: function () { + if (!$('#unsaved_changes').length || $('#unsaved_changes').val() == 0) { document.getElementById('logout_without_saving').click(); } else { - var confirmLogoutModal = new bootstrap.Modal(document.getElementById('confirmLogoutModal'), {keyboard: true}) + var confirmLogoutModal = new bootstrap.Modal(document.getElementById('confirmLogoutModal'), { keyboard: true }) confirmLogoutModal.show(); $('.confirm_logout').show(); } return false; }, - get_path_type: function(path) { + get_path_type: function (path) { if (path.indexOf('_') != -1) { var path_parts = path.split('_'); return path_parts[0]; @@ -1359,7 +1362,7 @@ var Hm_Utils = { return false; }, - parse_folder_path: function(path, path_type) { + parse_folder_path: function (path, path_type) { if (!path_type) { path_type = Hm_Utils.get_path_type(path); } @@ -1390,7 +1393,7 @@ var Hm_Utils = { folder = parts[3]; } if (type && server_id) { - return {'type': type, 'server_id' : server_id, 'folder' : folder, 'uid': uid}; + return { 'type': type, 'server_id': server_id, 'folder': folder, 'uid': uid }; } } else if (path_type == 'feeds') { @@ -1403,13 +1406,13 @@ var Hm_Utils = { uid = parts[2]; } if (type && server_id) { - return {'type': type, 'server_id' : server_id, 'uid': uid}; + return { 'type': type, 'server_id': server_id, 'uid': uid }; } } return false; }, - toggle_section: function(class_name, force_on, force_off) { + toggle_section: function (class_name, force_on, force_off) { if ($(class_name).length) { if (force_off) { $(class_name).css('display', 'block'); @@ -1423,7 +1426,7 @@ var Hm_Utils = { return false; }, - toggle_page_section: function(class_name) { + toggle_page_section: function (class_name) { if ($(class_name).length) { $(class_name).toggle(); Hm_Utils.save_to_local_storage(class_name, $(class_name).css('display')); @@ -1431,12 +1434,12 @@ var Hm_Utils = { return false; }, - get_from_local_storage: function(key) { + get_from_local_storage: function (key) { var prefix = window.location.pathname; - key = prefix+key; + key = prefix + key; var res = false; if (hm_encrypt_local_storage()) { - res = Hm_Crypt.decrypt(sessionStorage.getItem(key)); + res = Hm_Crypt.decrypt(sessionStorage.getItem(key)); } else { res = sessionStorage.getItem(key); @@ -1444,7 +1447,7 @@ var Hm_Utils = { return res; }, - search_from_local_storage: function(pattern) { + search_from_local_storage: function (pattern) { const results = []; const key_pattern = new RegExp(pattern); for (let i = 0; i < sessionStorage.length; i++) { @@ -1457,14 +1460,14 @@ var Hm_Utils = { return results; }, - save_to_local_storage: function(key, val) { + save_to_local_storage: function (key, val) { var prefix = window.location.pathname; - key = prefix+key; + key = prefix + key; if (hm_encrypt_local_storage()) { val = Hm_Crypt.encrypt(val); } - if (Storage !== void(0)) { - try { sessionStorage.setItem(key, val); } catch(e) { + if (Storage !== void (0)) { + try { sessionStorage.setItem(key, val); } catch (e) { sessionStorage.clear(); sessionStorage.setItem(key, val); } @@ -1476,25 +1479,25 @@ var Hm_Utils = { return false; }, - clean_selector: function(str) { + clean_selector: function (str) { return str.replace(/(:|\.|\[|\]|\/)/g, "\\$1"); }, - toggle_long_headers: function() { + toggle_long_headers: function () { $('.long_header').toggle(); $('.all_headers').toggle(); $('.small_headers').toggle(); return false; }, - set_unsaved_changes: function(state) { + set_unsaved_changes: function (state) { $('#unsaved_changes').val(state); }, /** * Shows pending messages added with the add_sys_message method */ - show_sys_messages: function() { + show_sys_messages: function () { $('.sys_messages').removeClass('d-none'); }, @@ -1503,12 +1506,12 @@ var Hm_Utils = { * @param {*} msg : The alert message to display * @param {*} type : The type of message to display, depending on the type of boostrap5 alert (primary, secondary, success, danger, warning, info, light, dark ) */ - add_sys_message: function(msg, type = 'info') { + add_sys_message: function (msg, type = 'info') { if (!msg) { return; } const icon = type == 'success' ? 'bi-check-circle' : 'bi-exclamation-circle'; - $('.sys_messages').append(''); + $('.sys_messages').append(''); this.show_sys_messages(); }, @@ -1516,11 +1519,11 @@ var Hm_Utils = { $('.sys_messages').html(''); }, - cancel_logout_event: function() { - $('.cancel_logout').on("click", function() { $('.confirm_logout').hide(); return false; }); + cancel_logout_event: function () { + $('.cancel_logout').on("click", function () { $('.confirm_logout').hide(); return false; }); }, - json_encode: function(val) { + json_encode: function (val) { try { return JSON.stringify(val); } @@ -1529,7 +1532,7 @@ var Hm_Utils = { } }, - json_decode: function(val, original) { + json_decode: function (val, original) { try { return JSON.parse(val); } @@ -1541,22 +1544,22 @@ var Hm_Utils = { } }, - rows: function() { + rows: function () { return $('.message_table_body > tr').not('.inline_msg'); }, - tbody: function() { + tbody: function () { return $('.message_table_body'); }, - html_entities: function(str) { + html_entities: function (str) { return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); }, - test_connection: function() { + test_connection: function () { $('.offline').hide(); Hm_Ajax.request( - [{'name': 'hm_ajax_hook', 'value': 'ajax_test'}], + [{ 'name': 'hm_ajax_hook', 'value': 'ajax_test' }], false, [], false, false, false); }, @@ -1567,7 +1570,7 @@ var Hm_Utils = { }, redirect: function (path) { - if (! path) { + if (!path) { path = window.location.href; } window.location.href = path; @@ -1579,7 +1582,7 @@ var Hm_Utils = { }; var Hm_Crypt = { - decrypt: function(ciphertext) { + decrypt: function (ciphertext) { try { ciphertext = atob(ciphertext); if (!ciphertext || ciphertext.length < 200) { @@ -1601,16 +1604,16 @@ var Hm_Crypt = { } var iv = forge.pkcs5.pbkdf2(secret, salt, 100, 16, digest); var decipher = forge.cipher.createDecipher('AES-CBC', key); - decipher.start({iv: iv}); + decipher.start({ iv: iv }); decipher.update(forge.util.createBuffer(payload, 'raw')); decipher.finish(); return forge.util.decodeUtf8(decipher.output.data); - } catch(e) { + } catch (e) { return false; } }, - encrypt: function(plaintext) { + encrypt: function (plaintext) { try { var secret = $('#hm_page_key').val(); var salt = forge.random.getBytesSync(128); @@ -1620,28 +1623,28 @@ var Hm_Crypt = { var iv = forge.pkcs5.pbkdf2(secret, salt, 100, 16, digest); var hmac = forge.hmac.create(); var cipher = forge.cipher.createCipher('AES-CBC', key); - cipher.start({iv: iv}); + cipher.start({ iv: iv }); cipher.update(forge.util.createBuffer(plaintext, 'utf8')); cipher.finish(); hmac.start(digest, hmac_key); hmac.update(cipher.output.data); - return btoa(salt+hmac.digest().data+cipher.output.data); - } catch(e) { + return btoa(salt + hmac.digest().data + cipher.output.data); + } catch (e) { return false; } }, } -var update_password = function(id) { - var pass = $('#update_pw_'+id).val(); +var update_password = function (id) { + var pass = $('#update_pw_' + id).val(); if (pass && pass.length) { Hm_Ajax.request( - [{'name': 'hm_ajax_hook', 'value': 'ajax_update_server_pw'}, - {'name': 'password', 'value': pass}, - {'name': 'server_pw_id', 'value': id}], - function(res) { + [{ 'name': 'hm_ajax_hook', 'value': 'ajax_update_server_pw' }, + { 'name': 'password', 'value': pass }, + { 'name': 'server_pw_id', 'value': id }], + function (res) { if (res.connect_status) { - $('.div_'+id).remove(); + $('.div_' + id).remove(); if ($('.home_password_dialogs div').length == 1) { $('.home_password_dialogs').remove(); } @@ -1651,13 +1654,13 @@ var update_password = function(id) { } } -var elog = function(val) { +var elog = function (val) { if (hm_debug()) { console.log(val); } }; -var hl_save_link = function() { +var hl_save_link = function () { if ($('.save_reminder').length) { $('.menu_save a').css('font-weight', 'bold'); } @@ -1666,7 +1669,7 @@ var hl_save_link = function() { } }; -var reset_default_value_checkbox = function() { +var reset_default_value_checkbox = function () { var checkbox = $(this).closest('.tooltip_restore').prev('input[type="checkbox"]'); var default_value = checkbox.data('default-value'); default_value = (default_value === 'true'); @@ -1674,27 +1677,27 @@ var reset_default_value_checkbox = function() { checkbox.prop('disabled', true); }; -var reset_default_timezone = function() { +var reset_default_timezone = function () { var hm_default_timezone = window.hm_default_timezone; $('#timezone').val(hm_default_timezone); } -var reset_default_value_select = function() { +var reset_default_value_select = function () { var dropdown = $(this).closest('.tooltip_restore').prev('select'); var default_value = dropdown.data('default-value'); dropdown.val(default_value); } -var reset_default_value_input = function() { +var reset_default_value_input = function () { var inputField = $(this).closest('.tooltip_restore').prev('input'); var default_value = inputField.data('default-value'); inputField.val(default_value); } -var decrease_servers = function(section) { +var decrease_servers = function (section) { const element = document.querySelector(`.server_count .${section}_server_count`); const value = parseInt(element.textContent); if (value > 0) { - element.innerHTML = value - 1; + element.innerHTML = value - 1; } if (value === 1) { @@ -1704,11 +1707,11 @@ var decrease_servers = function(section) { } }; -var err_msg = function(msg) { - return "ERR"+hm_trans(msg); +var err_msg = function (msg) { + return "ERR" + hm_trans(msg); }; -var hm_spinner = function(type = 'border', size = '') { +var hm_spinner = function (type = 'border', size = '') { return `
Loading... @@ -1716,7 +1719,7 @@ var hm_spinner = function(type = 'border', size = '') {
` }; -var fillImapData = function(details) { +var fillImapData = function (details) { $('#srv_setup_stepper_imap_address').val(details.server); $('#srv_setup_stepper_imap_port').val(details.port); $('#srv_setup_stepper_imap_server_id').val(details.id); @@ -1725,31 +1728,31 @@ var fillImapData = function(details) { $('#srv_setup_stepper_imap_sieve_host').val(details.sieve_config_host); $("#srv_setup_stepper_enable_sieve").trigger("click", false); $('#srv_setup_stepper_imap_sieve_mode_tls') - .prop('checked', details.tls) - .trigger('change'); + .prop('checked', details.tls) + .trigger('change'); } - if(details.tls) { + if (details.tls) { $("input[name='srv_setup_stepper_imap_tls'][value='true']").prop("checked", true); } else { $("input[name='srv_setup_stepper_imap_tls'][value='false']").prop("checked", true); } }; -var fillSmtpData = function(details) { +var fillSmtpData = function (details) { $('#srv_setup_stepper_smtp_server_id').val(details.id); $('#srv_setup_stepper_smtp_address').val(details.server); $('#srv_setup_stepper_smtp_port').val(details.port); }; -var fillJmapData = function(details) { +var fillJmapData = function (details) { $('#srv_setup_stepper_imap_server_id').val(details.id); $('#srv_setup_stepper_only_jmap').trigger('click'); $('#srv_setup_stepper_jmap_address').val(details.server); $('#srv_setup_stepper_imap_hide_from_c_page').prop("checked", details.hide); }; -var imap_smtp_edit_action = function(event) { +var imap_smtp_edit_action = function (event) { resetQuickSetupForm(); event.preventDefault(); Hm_Notices.hide(true); @@ -1767,7 +1770,7 @@ var imap_smtp_edit_action = function(event) { fillJmapData(details); } else if ($(this).data('type') == 'imap') { fillImapData(details); - var smtpDetails = $('[data-type="smtp"][data-id="'+details.name+'"]'); + var smtpDetails = $('[data-type="smtp"][data-id="' + details.name + '"]'); if (smtpDetails.length) { fillSmtpData(smtpDetails.data('server-details')); } else { @@ -1775,7 +1778,7 @@ var imap_smtp_edit_action = function(event) { } } else { fillSmtpData(details); - var imapDetails = $('[data-type="imap"][data-id="'+details.name+'"]'); + var imapDetails = $('[data-type="imap"][data-id="' + details.name + '"]'); if (imapDetails.length) { fillImapData(imapDetails.data('server-details')); } else { @@ -1784,7 +1787,8 @@ var imap_smtp_edit_action = function(event) { } }; -var hasLeadingOrTrailingSpaces = function(str) { + +var hasLeadingOrTrailingSpaces = function (str) { return str !== str.trim(); }; @@ -1792,8 +1796,8 @@ var hasLeadingOrTrailingSpaces = function(str) { var Hm_Message_List = new Message_List(); function sortHandlerForMessageListAndSearchPage() { - $('.combined_sort').on("change", function() { Hm_Message_List.sort($(this).val()); }); - $('.source_link').on("click", function() { $('.list_sources').toggle(); $('#list_controls_menu').hide(); return false; }); + $('.combined_sort').on("change", function () { Hm_Message_List.sort($(this).val()); }); + $('.source_link').on("click", function () { $('.list_sources').toggle(); $('#list_controls_menu').hide(); return false; }); if (getListPathParam() == 'unread' && $('.menu_unread > a').css('font-weight') == 'bold') { $('.menu_unread > a').css('font-weight', 'normal'); Hm_Folders.save_folder_list(); @@ -1801,7 +1805,7 @@ function sortHandlerForMessageListAndSearchPage() { } /* executes on onload, has access to other module code */ -$(function() { +$(function () { /* Remove disabled attribute to send checkbox */ $('.save_settings').on("click", function (e) { $('.general_setting input[type=checkbox]').each(function () { @@ -1810,7 +1814,7 @@ $(function() { } }); }) - $('.reset_factory_button').on('click', function() { return hm_delete_prompt(); }); + $('.reset_factory_button').on('click', function () { return hm_delete_prompt(); }); /* check for folder reload */ var reloaded = Hm_Folders.reload_folders(); @@ -1821,7 +1825,7 @@ $(function() { /* fire up the job scheduler */ Hm_Timer.fire(); - + /* show any pending notices */ Hm_Utils.show_sys_messages(); @@ -1832,18 +1836,18 @@ $(function() { hl_save_link(); if (hm_mailto()) { - try { navigator.registerProtocolHandler("mailto", "?page=compose&compose_to=%s", "Cypht"); } catch(e) {} + try { navigator.registerProtocolHandler("mailto", "?page=compose&compose_to=%s", "Cypht"); } catch (e) { } } if (hm_mobile()) { - swipe_event(document.body, function() { Hm_Folders.open_folder_list(); }, 'right'); - swipe_event(document.body, function() { Hm_Folders.hide_folder_list(); }, 'left'); + swipe_event(document.body, function () { Hm_Folders.open_folder_list(); }, 'right'); + swipe_event(document.body, function () { Hm_Folders.hide_folder_list(); }, 'left'); $('.list_controls.on_mobile').show(); $('.list_controls.no_mobile').hide(); } else { $('.list_controls.on_mobile').hide(); } - $('.offline').on("click", function() { Hm_Utils.test_connection(); }); + $('.offline').on("click", function () { Hm_Utils.test_connection(); }); if (hm_check_dirty_flag()) { $('form:not(.search_terms)').areYouSure(); @@ -1893,7 +1897,7 @@ function fixLtrInRtl() { return [] } - setTimeout(function(){ + setTimeout(function () { var elements = getElements() for (var index = 0; index < elements.length; index++) { if (isTextEnglish(elements[index].textContent)) { @@ -1911,7 +1915,7 @@ function listControlsMenu() { $('.list_sources').hide(); } -var resetStepperButtons = function() { +var resetStepperButtons = function () { $('.step_config-actions button').removeAttr('disabled'); $('#stepper-action-finish').text($('#stepper-action-finish').text().slice(0, -3)); }; @@ -1948,14 +1952,14 @@ function submitSmtpImapServer() { { name: 'srv_setup_stepper_smtp_server_id', value: $('#srv_setup_stepper_smtp_server_id').val() } ]; - Hm_Ajax.request(requestData, function(res) { + Hm_Ajax.request(requestData, function (res) { resetStepperButtons(); if (res.just_saved_credentials) { if (res.imap_server_id) { Hm_Ajax.request( - [{'name': 'hm_ajax_hook', 'value': 'ajax_imap_accept_special_folders'}, - {'name': 'imap_server_id', value: res.imap_server_id}, - {'name': 'imap_service_name', value: res.imap_service_name}], + [{ 'name': 'hm_ajax_hook', 'value': 'ajax_imap_accept_special_folders' }, + { 'name': 'imap_server_id', value: res.imap_server_id }, + { 'name': 'imap_service_name', value: res.imap_service_name }], function () { resetQuickSetupForm(); Hm_Utils.redirect(); @@ -2000,23 +2004,23 @@ function resetQuickSetupForm() { } function handleCreateProfileCheckboxChange(checkbox) { - if(checkbox.checked) { - $(checkbox).closest('.form-check').next().show(); - }else{ - $(checkbox).closest('.form-check').next().hide(); + if (checkbox.checked) { + $('#srv_setup_stepper_profile_bloc').show(); + } else { + $('#srv_setup_stepper_profile_bloc').hide(); } } -function handleSieveStatusChange (checkbox) { - if(checkbox.checked) { +function handleSieveStatusChange(checkbox) { + if (checkbox.checked) { $('#srv_setup_stepper_imap_sieve_host_bloc').show(); - }else{ + } else { $('#srv_setup_stepper_imap_sieve_host_bloc').hide(); } } function handleSmtpImapCheckboxChange(checkbox) { if (checkbox.id === 'srv_setup_stepper_is_receiver') { - if(checkbox.checked) { + if (checkbox.checked) { $('#step_config-imap_bloc').show(); $('#step_config_combined_view').show(); $('#srv_setup_stepper_jmap_select_box').show(); @@ -2031,15 +2035,15 @@ function handleSmtpImapCheckboxChange(checkbox) { if (checkbox.id === 'srv_setup_stepper_is_sender') { console.log("checkbox.checked", checkbox.checked) - if(checkbox.checked) $('#step_config-smtp_bloc').show(); + if (checkbox.checked) $('#step_config-smtp_bloc').show(); else $('#step_config-smtp_bloc').hide(); } if ($('#srv_setup_stepper_is_sender').prop('checked') && $('#srv_setup_stepper_is_receiver').prop('checked')) { $('#srv_setup_stepper_profile_bloc').show(); $('#srv_setup_stepper_profile_checkbox_bloc').show(); - - } else if(! $('#srv_setup_stepper_is_sender').prop('checked') || ! $('#srv_setup_stepper_is_receiver').prop('checked')) { + + } else if (!$('#srv_setup_stepper_is_sender').prop('checked') || !$('#srv_setup_stepper_is_receiver').prop('checked')) { $('#srv_setup_stepper_profile_bloc').hide(); $('#srv_setup_stepper_profile_checkbox_bloc').hide(); } @@ -2049,7 +2053,7 @@ function handleJmapCheckboxChange(checkbox) { if (checkbox.checked) { $('#step_config-jmap_bloc').show(); $('#step_config-imap_bloc').hide(); - if (! $('#srv_setup_stepper_enable_sieve').prop('checked')) { + if (!$('#srv_setup_stepper_enable_sieve').prop('checked')) { $('#srv_setup_stepper_imap_sieve_host_bloc').hide(); } } else { @@ -2060,9 +2064,9 @@ function handleJmapCheckboxChange(checkbox) { function handleProviderChange(select) { let providerKey = select.value; - if(providerKey) { + if (providerKey) { getServiceDetails(providerKey); - }else{ + } else { $("#srv_setup_stepper_smtp_address").val(''); $("#srv_setup_stepper_smtp_port").val(465); $("#srv_setup_stepper_imap_address").val(''); @@ -2076,13 +2080,13 @@ function setDefaultReplyTo(val) { } } function display_config_step(stepNumber) { - if(stepNumber === 2) { + if (stepNumber === 2) { var isValid = true; - [ {key: 'srv_setup_stepper_profile_name', value: $('#srv_setup_stepper_profile_name').val()}, - {key: 'srv_setup_stepper_email', value: $('#srv_setup_stepper_email').val()}, - {key: 'srv_setup_stepper_password', value: $('#srv_setup_stepper_password').val()}].forEach((item) => { + [{ key: 'srv_setup_stepper_profile_name', value: $('#srv_setup_stepper_profile_name').val() }, + { key: 'srv_setup_stepper_email', value: $('#srv_setup_stepper_email').val() }, + { key: 'srv_setup_stepper_password', value: $('#srv_setup_stepper_password').val() }].forEach((item) => { if (!item.value) { if (item.key == 'srv_setup_stepper_password' && ($('#srv_setup_stepper_imap_server_id').val() || $('#srv_setup_stepper_smtp_server_id').val())) { $(`#${item.key}-error`).text(''); @@ -2090,7 +2094,7 @@ function display_config_step(stepNumber) { $(`#${item.key}-error`).text('Required'); isValid = false; } - + } else { $(`#${item.key}-error`).text(''); } @@ -2105,46 +2109,46 @@ function display_config_step(stepNumber) { setDefaultReplyTo($('#srv_setup_stepper_email').val()); } - if(stepNumber === 3) { + if (stepNumber === 3) { var requiredFields = []; var isValid = true; - if(!$('#srv_setup_stepper_is_sender').is(':checked') && !$('#srv_setup_stepper_is_receiver').is(':checked')){ + if (!$('#srv_setup_stepper_is_sender').is(':checked') && !$('#srv_setup_stepper_is_receiver').is(':checked')) { $('#srv_setup_stepper_serve_type-error').text('Required'); return; } - if($('#srv_setup_stepper_is_sender').is(':checked') && + if ($('#srv_setup_stepper_is_sender').is(':checked') && $('#srv_setup_stepper_is_receiver').is(':checked') && - $('#srv_setup_stepper_only_jmap').is(':checked')){ + $('#srv_setup_stepper_only_jmap').is(':checked')) { requiredFields.push( - {key: 'srv_setup_stepper_jmap_address', value: $('#srv_setup_stepper_jmap_address').val()}, + { key: 'srv_setup_stepper_jmap_address', value: $('#srv_setup_stepper_jmap_address').val() }, ) - }else { - if($('#srv_setup_stepper_is_sender').is(':checked')){ + } else { + if ($('#srv_setup_stepper_is_sender').is(':checked')) { requiredFields.push( - {key: 'srv_setup_stepper_smtp_address', value: $('#srv_setup_stepper_smtp_address').val()}, - {key: 'srv_setup_stepper_smtp_port', value: $('#srv_setup_stepper_smtp_port').val()}, + { key: 'srv_setup_stepper_smtp_address', value: $('#srv_setup_stepper_smtp_address').val() }, + { key: 'srv_setup_stepper_smtp_port', value: $('#srv_setup_stepper_smtp_port').val() }, ) } - if($('#srv_setup_stepper_is_receiver').is(':checked')) { + if ($('#srv_setup_stepper_is_receiver').is(':checked')) { requiredFields.push( - {key: 'srv_setup_stepper_imap_address', value: $('#srv_setup_stepper_imap_address').val()}, - {key: 'srv_setup_stepper_imap_port', value: $('#srv_setup_stepper_imap_port').val()}, + { key: 'srv_setup_stepper_imap_address', value: $('#srv_setup_stepper_imap_address').val() }, + { key: 'srv_setup_stepper_imap_port', value: $('#srv_setup_stepper_imap_port').val() }, ) } } - if($('#srv_setup_stepper_enable_sieve').is(':checked')) { + if ($('#srv_setup_stepper_enable_sieve').is(':checked')) { requiredFields.push( - {key: 'srv_setup_stepper_imap_sieve_host', value: $('#srv_setup_stepper_imap_sieve_host').val()}, - {key: 'srv_setup_stepper_imap_sieve_mode_tls', value: $('#srv_setup_stepper_imap_sieve_mode_tls').val()}, + { key: 'srv_setup_stepper_imap_sieve_host', value: $('#srv_setup_stepper_imap_sieve_host').val() }, + { key: 'srv_setup_stepper_imap_sieve_mode_tls', value: $('#srv_setup_stepper_imap_sieve_mode_tls').val() }, ) } requiredFields.forEach((item) => { - if(!item.value) { + if (!item.value) { $(`#${item.key}-error`).text('Required'); isValid = false; } @@ -2152,7 +2156,7 @@ function display_config_step(stepNumber) { }) - if(!isValid) return + if (!isValid) return submitSmtpImapServer(); return @@ -2168,32 +2172,32 @@ function display_config_step(stepNumber) { if (selectedStep) { selectedStep.style.display = 'block'; - if(stepNumber === 0) $('.srv_setup_stepper_btn').show(); + if (stepNumber === 0) $('.srv_setup_stepper_btn').show(); } } -function getServiceDetails(providerKey){ - if(providerKey) { +function getServiceDetails(providerKey) { + if (providerKey) { $("#srv_setup_stepper_provider").val(providerKey); Hm_Ajax.request( [ - {'name': 'hm_ajax_hook', 'value': 'ajax_get_nux_service_details'}, - {'name': 'nux_service', 'value': providerKey},], - function(res) { - if(res.service_details){ + { 'name': 'hm_ajax_hook', 'value': 'ajax_get_nux_service_details' }, + { 'name': 'nux_service', 'value': providerKey },], + function (res) { + if (res.service_details) { let serverConfig = JSON.parse(res.service_details) $("#srv_setup_stepper_smtp_address").val(serverConfig.smtp.server); $("#srv_setup_stepper_smtp_port").val(serverConfig.smtp.port); - if(serverConfig.smtp.tls)$("input[name='srv_setup_stepper_smtp_tls'][value='true']").prop("checked", true); + if (serverConfig.smtp.tls) $("input[name='srv_setup_stepper_smtp_tls'][value='true']").prop("checked", true); else $("input[name='srv_setup_stepper_smtp_tls'][value='false']").prop("checked", true); $("#srv_setup_stepper_imap_address").val(serverConfig.server); $("#srv_setup_stepper_imap_port").val(serverConfig.port); - if(serverConfig.tls)$("input[name='srv_setup_stepper_imap_tls'][value='true']").prop("checked", true); + if (serverConfig.tls) $("input[name='srv_setup_stepper_imap_tls'][value='true']").prop("checked", true); else $("input[name='srv_setup_stepper_imap_tls'][value='false']").prop("checked", true); if (serverConfig.hasOwnProperty('sieve')) { @@ -2245,7 +2249,7 @@ function getEmailProviderKey(email) { const emailParts = email.split("@"); - if(emailParts.length !== 2) return ""; + if (emailParts.length !== 2) return ""; const provider = emailParts[1].toLowerCase(); @@ -2374,14 +2378,14 @@ const handleExternalResources = (inline) => { }; const observeMessageTextMutationAndHandleExternalResources = (inline) => { - const message = document.querySelector('.msg_text'); + const message = document.querySelector('.msg_text'); if (message) { new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(function (node) { if (node.classList.contains('msg_text_inner')) { - handleExternalResources(inline); + handleExternalResources(inline); } }); } @@ -2391,3 +2395,55 @@ const observeMessageTextMutationAndHandleExternalResources = (inline) => { }); } }; + +function setupActionSchedule(callback) { + $(document).on('click', '.nexter_date_picker', function (e) { + document.querySelector('.nexter_input_date').showPicker(); + }); + $(document).on('click', '.nexter_date_helper', function (e) { + e.preventDefault(); + $('.nexter_input').val($(this).attr('data-value')).trigger('change'); + }); + $(document).on('input', '.nexter_input_date', function (e) { + var now = new Date(); + now.setMinutes(now.getMinutes() + 1); + $(this).attr('min', now.toJSON().slice(0, 16)); + if (new Date($(this).val()).getTime() <= now.getTime()) { + $('.nexter_date_picker').css('border', '1px solid red'); + } else { + $('.nexter_date_picker').css({ 'border': 'unset', 'border-top': '1px solid #ddd' }); + } + }); + $(document).on('change', '.nexter_input_date', function (e) { + if ($(this).val() && new Date().getTime() < new Date($(this).val()).getTime()) { + $('.nexter_input').val($(this).val()).trigger('change'); + } + }); + $(document).on('change', '.nexter_input', callback); +} + +function setupActionSnooze(callback) { + $(document).on('click', '.nexter_date_picker_snooze', function (e) { + document.querySelector('.nexter_input_date_snooze').showPicker(); + }); + $(document).on('click', '.nexter_date_helper_snooze', function (e) { + e.preventDefault(); + $('.nexter_input_snooze').val($(this).attr('data-value')).trigger('change'); + }); + $(document).on('input', '.nexter_input_date_snooze', function (e) { + var now = new Date(); + now.setMinutes(now.getMinutes() + 1); + $(this).attr('min', now.toJSON().slice(0, 16)); + if (new Date($(this).val()).getTime() <= now.getTime()) { + $('.nexter_date_picker_snooze').css('border', '1px solid red'); + } else { + $('.nexter_date_picker_snooze').css({ 'border': 'unset', 'border-top': '1px solid #ddd' }); + } + }); + $(document).on('change', '.nexter_input_date_snooze', function (e) { + if ($(this).val() && new Date().getTime() < new Date($(this).val()).getTime()) { + $('.nexter_input_snooze').val($(this).val()).trigger('change'); + } + }); + $(document).on('change', '.nexter_input_snooze', callback); +} diff --git a/modules/imap/functions.php b/modules/imap/functions.php index 524a585016..c6d2d60098 100644 --- a/modules/imap/functions.php +++ b/modules/imap/functions.php @@ -248,10 +248,14 @@ function format_imap_message_list($msg_list, $output_module, $parent_list=false, $nofrom = ' nofrom'; } $is_snoozed = !empty($msg['x_snoozed']) && hex2bin($msg['folder']) == 'Snoozed'; + $is_scheduled = !empty($msg['x_schedule']) && hex2bin($msg['folder']) == 'Scheduled'; if ($is_snoozed) { - $snooze_header = parse_snooze_header('X-Snoozed: '.$msg['x_snoozed']); + $snooze_header = parse_nexter_header('X-Snoozed: '.$msg['x_snoozed'], 'X-Snoozed'); $date = $snooze_header['until']; $timestamp = strtotime($date); + } elseif ($is_scheduled) { + $date = $msg['x_schedule']; + $timestamp = strtotime($date); } else { if ($list_sort == 'date') { $date_field = 'date'; @@ -326,7 +330,7 @@ function format_imap_message_list($msg_list, $output_module, $parent_list=false, array('safe_output_callback', 'source', $source, $icon), array('safe_output_callback', 'from'.$nofrom, $from, null, str_replace(array($from, '<', '>'), '', $msg['from'])), array('subject_callback', $subject, $url, $flags, null, $preview_msg), - array('date_callback', $date, $timestamp, $is_snoozed), + array('date_callback', $date, $timestamp, $is_snoozed || $is_scheduled), array('icon_callback', $flags) ), $id, @@ -1324,7 +1328,7 @@ function snooze_message($mailbox, $msg_id, $folder, $snooze_tag) { preg_match("/^X-Snoozed:.*(\r?\n[ \t]+.*)*\r?\n?/im", $msg, $matches); if (count($matches)) { $msg = str_replace($matches[0], '', $msg); - $old_folder = parse_snooze_header($matches[0])['from']; + $old_folder = parse_nexter_header($matches[0], 'X-Snoozed')['from']; } if ($snooze_tag) { $from = $old_folder ?? $folder; @@ -1351,7 +1355,7 @@ function snooze_message($mailbox, $msg_id, $folder, $snooze_tag) { } } } else { - $snooze_headers = parse_snooze_header($matches[0]); + $snooze_headers = parse_nexter_header($matches[0], 'X-Snoozed'); $original_folder = $snooze_headers['from']; if ($mailbox->store_message($original_folder, $msg)) { $deleteResult = $mailbox->message_action($snooze_folder, 'DELETE', array($msg_id)); @@ -1438,21 +1442,21 @@ function snooze_formats() { */ if (!hm_exists('snooze_dropdown')) { function snooze_dropdown($output, $unsnooze = false) { - $values = snooze_formats(); + $values = nexter_formats(); $txt = ''; @@ -1585,3 +1589,42 @@ function connect_to_imap_server($address, $name, $port, $user, $pass, $tls, $ima } } } + +if (!hm_exists('save_sent_msg')) { +function save_sent_msg($handler, $imap_id, $imap, $imap_details, $msg, $msg_id, $show_errors = true) { + $specials = get_special_folders($handler, $imap_id); + if (array_key_exists('sent', $specials) && $specials['sent']) { + $sent_folder = $specials['sent']; + } + + if (!$sent_folder) { + $auto_sent = $imap->get_special_use_mailboxes('sent'); + if (!array_key_exists('sent', $auto_sent)) { + return; + } + $sent_folder = $auto_sent['sent']; + } + if (!$sent_folder) { + Hm_Debug::add(sprintf("Unable to save sent message, no sent folder for IMAP %s", $imap_details['server'])); + } + $uid = null; + if ($sent_folder) { + Hm_Debug::add(sprintf("Attempting to save sent message for IMAP server %s in folder %s", $imap_details['server'], $sent_folder)); + if ($imap->append_start($sent_folder, strlen($msg), true)) { + $imap->append_feed($msg."\r\n"); + if (!$imap->append_end() && $show_errors) { + Hm_Msgs::add('ERRAn error occurred saving the sent message'); + } + } + + $mailbox_page = $imap->get_mailbox_page($sent_folder, 'ARRIVAL', true, 'ALL', 0, 10); + foreach ($mailbox_page[1] as $mail) { + $msg_header = $imap->get_message_headers($mail['uid']); + if ($msg_header['Message-Id'] === $msg_id) { + $uid = $mail['uid']; + break; + } + } + } + return $uid; +}} diff --git a/modules/imap/handler_modules.php b/modules/imap/handler_modules.php index a44ebfd461..c27fce69a5 100644 --- a/modules/imap/handler_modules.php +++ b/modules/imap/handler_modules.php @@ -361,7 +361,10 @@ public function process() { break; } } - if ($uid && $this->user_config->get('review_sent_email_setting', true)) { + } + $uid = save_sent_msg($this, $imap_id, $imap, $imap_details, $msg, $mime->get_headers()['Message-Id']); + if ($uid) { + if ($uid && $this->user_config->get('review_sent_email_setting', false)) { $this->out('redirect_url', '?page=message&uid='.$uid.'&list_path=imap_'.$imap_id.'_'.bin2hex($sent_folder)); } } @@ -1042,7 +1045,7 @@ public function process() { $snooze_tag = null; if ($form['imap_snooze_until'] != 'unsnooze') { $at = date('D, d M Y H:i:s O'); - $until = get_snooze_date($form['imap_snooze_until']); + $until = get_scheduled_date($form['imap_snooze_until']); $snooze_tag = "X-Snoozed: at $at; until $until"; } $ids = explode(',', $form['imap_snooze_ids']); @@ -1093,7 +1096,7 @@ public function process() { $msg_headers = $mailbox->get_message_headers($folder, $msg['uid']); if (isset($msg_headers['X-Snoozed'])) { try { - $snooze_headers = parse_snooze_header($msg_headers['X-Snoozed']); + $snooze_headers = parse_nexter_header($msg_headers['X-Snoozed'], 'X-Snoozed'); if (new DateTime($snooze_headers['until']) <= new DateTime()) { snooze_message($mailbox, $msg['uid'], $folder, null); } diff --git a/modules/imap/hm-imap.php b/modules/imap/hm-imap.php index 3e8759c32b..3574666aba 100644 --- a/modules/imap/hm-imap.php +++ b/modules/imap/hm-imap.php @@ -899,7 +899,7 @@ public function get_message_list($uids, $raw=false, $include_content_body = fals if ($this->is_supported( 'X-GM-EXT-1' )) { $command .= 'X-GM-MSGID X-GM-THRID X-GM-LABELS '; } - $command .= "BODY.PEEK[HEADER.FIELDS (SUBJECT X-AUTO-BCC FROM DATE CONTENT-TYPE X-PRIORITY TO LIST-ARCHIVE REFERENCES MESSAGE-ID X-SNOOZED)]"; + $command .= "BODY.PEEK[HEADER.FIELDS (SUBJECT X-AUTO-BCC FROM DATE CONTENT-TYPE X-PRIORITY TO LIST-ARCHIVE REFERENCES MESSAGE-ID X-SNOOZED X-SCHEDULE X-PROFILE-ID X-DELIVERY)])"; if ($include_content_body) { $command .= " BODY.PEEK[0.1]"; } @@ -913,8 +913,8 @@ public function get_message_list($uids, $raw=false, $include_content_body = fals $res = $this->get_response(false, true); $status = $this->check_response($res, true); $tags = array('X-GM-MSGID' => 'google_msg_id', 'X-GM-THRID' => 'google_thread_id', 'X-GM-LABELS' => 'google_labels', 'UID' => 'uid', 'FLAGS' => 'flags', 'RFC822.SIZE' => 'size', 'INTERNALDATE' => 'internal_date'); - $junk = array('X-AUTO-BCC', 'MESSAGE-ID', 'REFERENCES', 'X-SNOOZED', 'LIST-ARCHIVE', 'SUBJECT', 'FROM', 'CONTENT-TYPE', 'TO', '(', ')', ']', 'X-PRIORITY', 'DATE'); - $flds = array('x-auto-bcc' => 'x_auto_bcc', 'message-id' => 'message_id', 'references' => 'references', 'x-snoozed' => 'x_snoozed', 'list-archive' => 'list_archive', 'date' => 'date', 'from' => 'from', 'to' => 'to', 'subject' => 'subject', 'content-type' => 'content_type', 'x-priority' => 'x_priority', 'body' => 'content_body'); + $junk = array('X-AUTO-BCC', 'MESSAGE-ID', 'REFERENCES', 'X-SNOOZED', 'X-SCHEDULE', 'X-PROFILE-ID', 'X-DELIVERY', 'LIST-ARCHIVE', 'SUBJECT', 'FROM', 'CONTENT-TYPE', 'TO', '(', ')', ']', 'X-PRIORITY', 'DATE'); + $flds = array('x-auto-bcc' => 'x_auto_bcc', 'message-id' => 'message_id', 'references' => 'references', 'x-snoozed' => 'x_snoozed', 'x-schedule' => 'x_schedule', 'x-profile-id' => 'x_profile_id', 'x-delivery' => 'x_delivery', 'list-archive' => 'list_archive', 'date' => 'date', 'from' => 'from', 'to' => 'to', 'subject' => 'subject', 'content-type' => 'content_type', 'x-priority' => 'x_priority'); $headers = array(); foreach ($res as $n => $vals) { @@ -937,6 +937,9 @@ public function get_message_list($uids, $raw=false, $include_content_body = fals $google_labels = ''; $x_auto_bcc = ''; $x_snoozed = ''; + $x_schedule = ''; + $x_profile_id = ''; + $x_delivery = ''; $count = count($vals); for ($i=0;$i<$count;$i++) { if ($vals[$i] == 'BODY[HEADER.FIELDS') { @@ -999,8 +1002,7 @@ public function get_message_list($uids, $raw=false, $include_content_body = fals 'timestamp' => time(), 'charset' => $cset, 'x-priority' => $x_priority, 'google_msg_id' => $google_msg_id, 'google_thread_id' => $google_thread_id, 'google_labels' => $google_labels, 'list_archive' => $list_archive, 'references' => $references, 'message_id' => $message_id, 'x_auto_bcc' => $x_auto_bcc, - 'x_snoozed' => $x_snoozed); - $headers[$uid]['preview_msg'] = $flds['body'] != "content_body" ? $flds['body'] : ""; + 'x_snoozed' => $x_snoozed, 'x_schedule' => $x_schedule, 'x_profile_id' => $x_profile_id, 'x_delivery' => $x_delivery); if ($raw) { $headers[$uid] = array_map('trim', $headers[$uid]); diff --git a/modules/imap/js_modules/route_handlers.js b/modules/imap/js_modules/route_handlers.js index 6b98603913..2d2f7bd4f3 100644 --- a/modules/imap/js_modules/route_handlers.js +++ b/modules/imap/js_modules/route_handlers.js @@ -4,10 +4,14 @@ function applyImapMessageListPageHandlers(routeParams) { imap_setup_snooze(); imap_setup_tags(); + Hm_Message_List.set_row_events(); + + processNextActionDate(); + if (window.inlineMessageMessageListAndSearchPageHandler) inlineMessageMessageListAndSearchPageHandler(routeParams); if (window.wpMessageListPageHandler) wpMessageListPageHandler(routeParams); - return async function() { + return async function () { const [refreshIntervalId, abortController] = await setupPageResult; abortController.abort(); clearInterval(refreshIntervalId); @@ -33,4 +37,4 @@ function applyImapMessageContentPageHandlers(routeParams) { if (window.pgpMessageContentPageHandler) pgpMessageContentPageHandler(); if (window.wpMessageContentPageHandler) wpMessageContentPageHandler(routeParams); -} \ No newline at end of file +} diff --git a/modules/imap/js_modules/utils/handleNexterDateAction.js b/modules/imap/js_modules/utils/handleNexterDateAction.js new file mode 100644 index 0000000000..02c303a9fc --- /dev/null +++ b/modules/imap/js_modules/utils/handleNexterDateAction.js @@ -0,0 +1,71 @@ +function processNextActionDate(e) { + let isReloading = false; + + let reload_and_redirect = async function () { + if (isReloading) { + return; + } + isReloading = true; + + showRoutingToast(); + + try { + Hm_Folders.reload_folders(true); + let path = getListPathParam(); + await navigate(`?page=message_list&list_path=${path}`); + } finally { + hideRoutingToast(); + isReloading = false; + } + }; + + + + let collectCheckedIds = function () { + let ids = []; + $('input[type=checkbox]').each(function () { + if (this.checked && this.id.search('imap') !== -1) { + let parts = this.id.split('_'); + ids.push(parts[1] + '_' + parts[2] + '_' + parts[3]); + } + }); + if (ids.length === 0) { + return; + } + return ids; + }; + + setupActionSchedule(function () { + let ids = collectCheckedIds(); + + Hm_Ajax.request( + [ + { 'name': 'hm_ajax_hook', 'value': 'ajax_re_schedule_message_sending' }, + { 'name': 'scheduled_msg_ids', 'value': ids }, + { 'name': 'schedule_date', 'value': $(this).val() } + ], + function (res) { + if (res.scheduled_msg_count > 0) { + reload_and_redirect(); + } + } + ); + }); + + setupActionSnooze(function () { + let ids = collectCheckedIds(); + + Hm_Ajax.request( + [ + { 'name': 'hm_ajax_hook', 'value': 'ajax_imap_snooze' }, + { 'name': 'imap_snooze_ids', 'value': ids }, + { 'name': 'imap_snooze_until', 'value': $(this).val() } + ], + function (res) { + if (res.snoozed_messages > 0) { + reload_and_redirect(); + } + } + ); + }); +} \ No newline at end of file diff --git a/modules/imap/output_modules.php b/modules/imap/output_modules.php index c72420fc6c..538f05fc04 100644 --- a/modules/imap/output_modules.php +++ b/modules/imap/output_modules.php @@ -206,9 +206,9 @@ protected function output() { $txt .= $this->html_safe($value).''; } elseif ($fld == 'x-snoozed') { - $snooze_header = parse_snooze_header($value); + $snooze_header = parse_nexter_header($value, 'X-Snoozed'); $txt .= ''; - $txt .= $this->trans('Snoozed').''.$this->trans('Until').' '.$this->html_safe($snooze_header['until']).' Unsnooze'; + $txt .= $this->trans('Snoozed').''.$this->trans('Until').' '.$this->html_safe($snooze_header['until']).' Unsnooze'; } elseif ($fld == 'date') { try { @@ -390,6 +390,9 @@ protected function output() { if($this->get('tags')){ $txt .= ' | '. tags_dropdown($this, $headers); } + if (isset($headers['X-Schedule'])) { + $txt .= ' | ' . schedule_dropdown($this, true); + } $is_draft = isset($headers['Flags']) && mb_stristr($headers['Flags'], 'draft'); if ($this->get('sieve_filters_enabled') && !$is_draft) { diff --git a/modules/imap/site.css b/modules/imap/site.css index f291345bab..db8576ec53 100644 --- a/modules/imap/site.css +++ b/modules/imap/site.css @@ -126,7 +126,7 @@ .header_links { padding-top: 10px !important; } -.header_links #dropdownMenuSnooze { +.header_links #dropdownMenuNexterDate { padding: 0; border: unset; font-variant: inherit; @@ -134,7 +134,7 @@ font-size: inherit; vertical-align: baseline; } -.header_links #dropdownMenuSnooze:hover { +.header_links #dropdownMenuNexterDate:hover { background-color: inherit; color: inherit; } diff --git a/modules/imap/site.js b/modules/imap/site.js index c751439a6b..dc6a9e7169 100644 --- a/modules/imap/site.js +++ b/modules/imap/site.js @@ -1221,6 +1221,7 @@ $(function() { setTimeout(search_selected_for_imap, 100); }); + if (hm_is_logged()) { imap_unsnooze_messages(); setInterval(imap_unsnooze_messages, 60000); diff --git a/modules/profiles/functions.php b/modules/profiles/functions.php index dcfc100056..d75922ab6a 100644 --- a/modules/profiles/functions.php +++ b/modules/profiles/functions.php @@ -12,8 +12,8 @@ function add_profile($name, $signature, $reply_to, $is_default, $email, $server, 'replyto' => $reply_to, 'default' => $is_default, 'address' => $email, - 'server' => $server, - 'user' => $user, + 'server' => $imap_server_id, + 'user' => $email, 'type' => 'imap' ); $id = Hm_Profiles::add($profile); diff --git a/modules/profiles/hm-profiles.php b/modules/profiles/hm-profiles.php index 16997e0582..046d6e6648 100644 --- a/modules/profiles/hm-profiles.php +++ b/modules/profiles/hm-profiles.php @@ -109,4 +109,19 @@ public static function loadLegacy($hmod) { } } } + + /** + * @param string $field The name of the field to search within. + * @param mixed $value The value to search for within the specified field. + * @return array An array containing profiles that match the search criteria. + */ + public static function search($field, $value) { + $res = array(); + foreach (self::getAll() as $profile) { + if (!empty($profile[$field]) && $profile[$field] == $value) { + $res[] = $profile; + } + } + return $res; + } } diff --git a/modules/smtp/functions.php b/modules/smtp/functions.php index 68a8db3b16..742068cc49 100644 --- a/modules/smtp/functions.php +++ b/modules/smtp/functions.php @@ -61,3 +61,109 @@ function get_reply_type($request) { return false; } } + +/** + * @subpackage smtp/functions + */ +if (!hm_exists('send_scheduled_message')) { +function send_scheduled_message($handler, $imap, $msg_id, $server_id, $send_now = false) { + $msg_headers = $imap->get_message_headers($msg_id); + $imap_details = Hm_IMAP_List::dump($server_id); + if (empty($imap_details)) { + return false; + } + + try { + if (empty($msg_headers['X-Schedule'])) { + return false; + } + + if (new DateTime($msg_headers['X-Schedule']) <= new DateTime() || $send_now) { + $profile = Hm_Profiles::get($msg_headers['X-Profile-ID']); + if (!$profile) { + $profiles = Hm_Profiles::search('server', $imap_details['server']); + + if (!$profiles) { + Hm_Debug::add(sprintf('ERRCannot find profiles corresponding with IMAP server: %s', $imap_details['server'])); + return false; + } + $profile = $profiles[0]; + } + + $smtp = Hm_SMTP_List::connect($profile['smtp_id'], false); + + if (smtp_authed($smtp)) { + if (isset($msg_headers['X-Delivery'])) { + $from_params = 'RET=HDRS'; + $recipients_params = 'NOTIFY=SUCCESS,FAILURE'; + } else { + $from_params = ''; + $recipients_params = ''; + } + + $recipients = []; + foreach (['To', 'Cc', 'Bcc'] as $fld) { + if (array_key_exists($fld, $msg_headers)) { + $recipients = array_merge($recipients, Hm_MIME_Msg::find_addresses($msg_headers[$fld])); + } + } + + $msg_content = $imap->get_message_content($msg_id, 0); + $from = process_address_fld($msg_headers['From']); + + $err_msg = $smtp->send_message($from[0]['email'], $recipients, $msg_content, $from_params, $recipients_params); + + if (!$err_msg) { + if ($imap->message_action('DELETE', [$msg_id])) { + $imap->message_action('EXPUNGE', [$msg_id]); + } + save_sent_msg($handler, $server_id, $imap, $imap_details, $msg_content, $msg_id, false); + return true; + } + } + } + } catch (Exception $e) { + Hm_Debug::add(sprintf('ERRCannot send message: %s', $msg_headers['subject'])); + } + return false; +}} + +/** + * @subpackage smtp/functions + */ +if (!hm_exists('reschedule_message_sending')) { +function reschedule_message_sending($handler, $imap, $msg_id, $folder, $new_date, $server_id) { + if (!$imap->select_mailbox($folder)) { + return; + } + if ($new_date == 'now') { + return send_scheduled_message($handler, $imap, $msg_id, $server_id, true); + } + $msg = $imap->get_message_content($msg_id, 0); + $new_date = get_scheduled_date($new_date); + preg_match("/^X-Schedule:.*(\r?\n[ \t]+.*)*\r?\n?/im", $msg, $matches); + if (count($matches)) { + $msg = str_replace($matches[0], "X-Schedule: {$new_date}\n", $msg); + } else { + return; + } + $msg = str_replace("\r\n", "\n", $msg); + $msg = str_replace("\n", "\r\n", $msg); + $msg = rtrim($msg)."\r\n"; + + $schedule_folder = 'Scheduled'; + if (!count($imap->get_mailbox_status($schedule_folder))) { + return; + } + $res = false; + if ($imap->select_mailbox($schedule_folder) && $imap->append_start($schedule_folder, strlen($msg))) { + $imap->append_feed($msg."\r\n"); + if ($imap->append_end()) { + if ($imap->select_mailbox($folder) && $imap->message_action('DELETE', array($msg_id))) { + $imap->message_action('EXPUNGE', array($msg_id)); + $res = true; + } + } + } + return $res; +}} diff --git a/modules/smtp/hm-mime-message.php b/modules/smtp/hm-mime-message.php index 1b775e0941..64cfe7b9dc 100644 --- a/modules/smtp/hm-mime-message.php +++ b/modules/smtp/hm-mime-message.php @@ -21,10 +21,15 @@ class Hm_MIME_Msg { private $final_msg = ''; /* build mime message data */ - function __construct($to, $subject, $body, $from, $html=false, $cc='', $bcc='', $in_reply_to_id='', $from_name='', $reply_to='') { + function __construct($to, $subject, $body, $from, $html=false, $cc='', $bcc='', $in_reply_to_id='', $from_name='', $reply_to='', $delivery_receipt='', $schedule='', $profile_id = '') { if ($cc) { $this->headers['Cc'] = $cc; } + if ($schedule) { + $this->headers['X-Schedule'] = $schedule; + $this->headers['X-Profile-ID'] = $profile_id; + } + if ($in_reply_to_id) { $this->headers['In-Reply-To'] = $in_reply_to_id; } @@ -41,6 +46,9 @@ function __construct($to, $subject, $body, $from, $html=false, $cc='', $bcc='', else { $this->headers['Reply-To'] = $from; } + if ($delivery_receipt) { + $this->headers['X-Delivery'] = $delivery_receipt; + } $this->headers['To'] = $to; $this->headers['Subject'] = html_entity_decode($subject, ENT_QUOTES); $this->headers['Date'] = date('r'); @@ -190,7 +198,7 @@ function prep_fld($val, $name) { return $this->encode_fld($val); } - function find_addresses($str) { + static function find_addresses($str) { $res = array(); foreach (process_address_fld($str) as $vals) { $res[] = $vals['email']; @@ -210,7 +218,7 @@ function get_recipient_addresses() { else { continue; } - $res = array_merge($res, $this->find_addresses($v)); + $res = array_merge($res, self::find_addresses($v)); } return $res; } diff --git a/modules/smtp/js_modules/route_handlers.js b/modules/smtp/js_modules/route_handlers.js index 7849599571..1f6a5692b5 100644 --- a/modules/smtp/js_modules/route_handlers.js +++ b/modules/smtp/js_modules/route_handlers.js @@ -2,18 +2,28 @@ function applyComposePageHandlers() { init_resumable_upload() + let isScheduledMode = null; + + setupActionSchedule(function () { + let schedule = $('.nexter_input').val(); + $('.smtp_send_placeholder').trigger('click'); + + save_compose_state(false, true, schedule); + isScheduledMode = schedule; + }); + if (window.HTMLEditor) { useKindEditor(); } var interval = Hm_Utils.get_from_global('compose_save_interval', 30); - Hm_Timer.add_job(function() { save_compose_state(); }, interval, true); - $('.draft_title').on("click", function() { $('.draft_list').toggle(); }); - $('.toggle_recipients').on("click", function() { return toggle_recip_flds(); }); + Hm_Timer.add_job(function () { save_compose_state(); }, interval, true); + $('.draft_title').on("click", function () { $('.draft_list').toggle(); }); + $('.toggle_recipients').on("click", function () { return toggle_recip_flds(); }); $('.smtp_reset').on("click", reset_smtp_form); - $('.delete_draft').on("click", function() { smtp_delete_draft($(this).data('id')); }); - $('.smtp_save').on("click", function() { save_compose_state(false, true); }); - $('.smtp_send_archive').on("click", function() { send_archive(false, true); }); + $('.delete_draft').on("click", function () { smtp_delete_draft($(this).data('id')); }); + $('.smtp_save').on("click", function () { save_compose_state(false, true); }); + $('.smtp_send_archive').on("click", function () { send_archive(false, true); }); const modal = new Hm_Modal({ modalId: 'emptySubjectBodyModal', @@ -85,7 +95,7 @@ function applyComposePageHandlers() { ======================================== */ function showModal() { - if (! modal.modalContent.html()) { + if (!modal.modalContent.html()) { modal.addFooterBtn(hm_trans('Send anyway'), 'btn-warning', handleSendAnyway); if (showBtnSendAnywayDontWarnFuture) { modal.addFooterBtn(hm_trans("Send anyway and don't warn in the future"), 'btn-warning', handleSendAnywayAndDontWarnMe); @@ -99,26 +109,26 @@ function applyComposePageHandlers() { return new Promise((resolve) => { const checkValue = () => { if ($(selector).val() !== targetValue) { - resolve(); + resolve(); } else { - setTimeout(checkValue, 100); + setTimeout(checkValue, 100); } }; - checkValue(); + checkValue(); }); } async function handleSendAnyway() { if ($('.compose_draft_id').val() == '0') { - Hm_Notices.show([hm_trans('Please wait, sending message...')]); - await waitForValueChange('.compose_draft_id', '0'); + Hm_Notices.show([hm_trans('Please wait, sending message...')]); + await waitForValueChange('.compose_draft_id', '0'); } - - if (handleMissingAttachment()) { - document.getElementsByClassName("smtp_send")[0].click(); + if (isScheduledMode == null) { + document.getElementsByClassName("smtp_send")[0].click(); + } } else { e.preventDefault(); } @@ -162,53 +172,53 @@ function applyComposePageHandlers() { return true; } }); - $('.compose_form').on('submit', function() { + $('.compose_form').on('submit', function () { process_compose_form(); }); if ($('.compose_cc').val() || $('.compose_bcc').val()) { toggle_recip_flds(); } if (window.location.href.search('&reply=1') !== -1 || window.location.href.search('&reply_all=1') !== -1) { - replace_cursor_positon ($('textarea[name="compose_body"]')); + replace_cursor_positon($('textarea[name="compose_body"]')); } if (window.location.href.search('&forward=1') !== -1) { - setTimeout(function() { + setTimeout(function () { save_compose_state(); }, 100); } if ($('.sys_messages').text() != 'Message Sent') { get_smtp_profile($('.compose_server').val()); } - $('.compose_server').on('change', function() { + $('.compose_server').on('change', function () { get_smtp_profile($('.compose_server').val()); }); - if($('.compose_attach_button').attr('disabled') == 'disabled'){ + if ($('.compose_attach_button').attr('disabled') == 'disabled') { check_attachment_dir_access(); }; $('.compose_container').attr('ondrop', 'move_recipient_to_section(event)').attr('ondragover', 'allow_drop(event)'); - $('.compose_to, .compose_cc, .compose_bcc').on('keypress', function(e) { - if(e.which == 13) { + $('.compose_to, .compose_cc, .compose_bcc').on('keypress', function (e) { + if (e.which == 13) { e.preventDefault(); text_to_bubbles(this); } }); - $('.compose_to, .compose_cc, .compose_bcc').on('blur', function(e) { + $('.compose_to, .compose_cc, .compose_bcc').on('blur', function (e) { e.preventDefault(); text_to_bubbles(this); }); - $('.compose_subject, .compose_body, .compose_server, .smtp_send_placeholder, .smtp_send_archive').on('focus', function(e) { - $('.compose_to, .compose_cc, .compose_bcc').each(function() { + $('.compose_subject, .compose_body, .compose_server, .smtp_send_placeholder, .smtp_send_archive').on('focus', function (e) { + $('.compose_to, .compose_cc, .compose_bcc').each(function () { bubbles_to_text(this); }); }); - $('.compose_to, .compose_cc, .compose_bcc').on('focus', function(e) { + $('.compose_to, .compose_cc, .compose_bcc').on('focus', function (e) { text_to_bubbles(this); }); - $('.compose_container').on('click', function() { + $('.compose_container').on('click', function () { $(this).find('input').focus(); }); - $(document).on('click', '.bubble_close', function(e) { + $(document).on('click', '.bubble_close', function (e) { e.stopPropagation(); $(".bubble_dropdown-content").remove(); $(this).parent().remove(); @@ -222,7 +232,7 @@ function applyComposePageHandlers() { var excludedEmail = null; const excludeEmail = function () { - var newRecipients = recipientsInput.val().split(',').filter(function(email) { + var newRecipients = recipientsInput.val().split(',').filter(function (email) { if (email.includes(selectedEmail)) { excludedEmail = email; return false; @@ -234,7 +244,7 @@ function applyComposePageHandlers() { if (recipientsInput.val().includes(selectedEmail)) { excludeEmail(); - $(document).on('change', '#compose_smtp_id', function() { + $(document).on('change', '#compose_smtp_id', function () { if ($(this).val() !== selectedVal) { if (!recipientsInput.val().includes(selectedEmail)) { recipientsInput.val(recipientsInput.val() + ', ' + excludedEmail); @@ -245,9 +255,10 @@ function applyComposePageHandlers() { }); } - $('.compose_to').on('keyup', function(e) { autocomplete_contact(e, '.compose_to', '#to_contacts'); }); - $('.compose_cc').on('keyup', function(e) { autocomplete_contact(e, '.compose_cc', '#cc_contacts'); }); - $('.compose_bcc').on('keyup', function(e) { autocomplete_contact(e, '.compose_bcc', '#bcc_contacts'); }); + + $('.compose_to').on('keyup', function (e) { autocomplete_contact(e, '.compose_to', '#to_contacts'); }); + $('.compose_cc').on('keyup', function (e) { autocomplete_contact(e, '.compose_cc', '#cc_contacts'); }); + $('.compose_bcc').on('keyup', function (e) { autocomplete_contact(e, '.compose_bcc', '#bcc_contacts'); }); $('.compose_to').focus(); if (window.pgpComposePageHandler) pgpComposePageHandler(); diff --git a/modules/smtp/modules.php b/modules/smtp/modules.php index 5142ce3e3e..f79e2d5b50 100644 --- a/modules/smtp/modules.php +++ b/modules/smtp/modules.php @@ -113,6 +113,8 @@ public function process() { } } + + /** * @subpackage smtp/handler */ @@ -208,6 +210,7 @@ public function process() { } } + /** * @subpackage smtp/handler */ @@ -317,6 +320,8 @@ public function process() { $draft_id = array_key_exists('draft_id', $this->request->post) ? $this->request->post['draft_id'] : false; $draft_notice = array_key_exists('draft_notice', $this->request->post) ? $this->request->post['draft_notice'] : false; $uploaded_files = array_key_exists('uploaded_files', $this->request->post) ? $this->request->post['uploaded_files'] : false; + $delivery_receipt = array_key_exists('compose_delivery_receipt', $this->request->post) ? $this->request->post['compose_delivery_receipt'] : false; + $schedule = array_key_exists('schedule', $this->request->post) ? $this->request->post['schedule'] : ''; if (array_key_exists('delete_uploaded_files', $this->request->post) && $this->request->post['delete_uploaded_files']) { delete_uploaded_files($this->session, $draft_id); @@ -333,7 +338,7 @@ public function process() { if ($this->get('save_draft_to_imap') === false) { $from = isset($profile) ? $profile['replyto'] : ''; $name = isset($profile) ? $profile['name'] : ''; - $mime = prepare_draft_mime($msg_attrs, $uploaded_files, $from, $name); + $mime = prepare_draft_mime($msg_attrs, $uploaded_files, $from, $name, $profile['id']); $this->out('draft_mime', $mime); return; } @@ -343,15 +348,20 @@ public function process() { foreach($uploaded_files as $key => $file) { $uploaded_files[$key] = $this->config->get('attachment_dir').DIRECTORY_SEPARATOR.$userpath.DIRECTORY_SEPARATOR.$file; } - $new_draft_id = save_imap_draft($msg_attrs, $draft_id, $this->session, $this, $this->cache, $uploaded_files, $profile); + $new_draft_id = save_imap_draft(array('draft_smtp' => $smtp, 'draft_to' => $to, 'draft_body' => $body, + 'draft_subject' => $subject, 'draft_cc' => $cc, 'draft_bcc' => $bcc, + 'draft_in_reply_to' => $inreplyto, 'delivery_receipt' => $delivery_receipt, 'schedule' => $schedule), $draft_id, $this->session, + $this, $this->cache, $uploaded_files, $profile); if ($new_draft_id >= 0) { if ($draft_notice) { - Hm_Msgs::add('Draft saved'); + $msg = $schedule ? 'Message scheduled to be sent later' : 'Draft saved'; + Hm_Msgs::add($msg); } $this->out('draft_id', $new_draft_id); } elseif ($draft_notice) { - Hm_Msgs::add('ERRUnable to save draft'); + $msg = $schedule ? 'Something went wrong when scheduling draft' : 'Unable to save draft'; + Hm_Msgs::add('ERR' . $msg); } return; } @@ -662,6 +672,9 @@ public function process() { 'draft_subject' => $form['compose_subject'], 'draft_smtp' => $smtp_id ); + $delivery_receipt = !empty($this->request->post['compose_delivery_receipt']); + $from_params = ''; + $recipients_params = ''; /* parse attachments */ $uploaded_files = []; @@ -706,7 +719,7 @@ public function process() { } /* build message */ - $mime = new Hm_MIME_Msg($to, $subject, $body, $from, $body_type, $cc, $bcc, $in_reply_to, $from_name, $reply_to); + $mime = new Hm_MIME_Msg($to, $subject, $body, $from, $body_type, $cc, $bcc, $in_reply_to, $from_name, $reply_to, $delivery_receipt); /* add attachments */ $mime->add_attachments($uploaded_files); @@ -875,6 +888,97 @@ protected function output() { } } +/** + * Send scheduled messages + * @subpackage smtp/handler + */ +class Hm_Handler_send_scheduled_messages extends Hm_Handler_Module { + /** + * Send delayed messages + * This should use cron + */ + public function process() { + if (!($this->module_is_supported('imap') || $this->module_is_supported('profiles'))) { + return; + } + + $servers = Hm_IMAP_List::dump(); + $scheduled_msg_count = 0; + + foreach (array_keys($servers) as $server_id) { + $cache = Hm_IMAP_List::get_cache($this->cache, $server_id); + $imap = Hm_IMAP_List::connect($server_id, $cache); + + if (imap_authed($imap)) { + $folder = 'Scheduled'; + $ret = $imap->get_mailbox_page($folder, 'DATE', false, 'ALL'); + + foreach ($ret[1] as $msg) { + $msg_headers = $imap->get_message_headers($msg['uid']); + + try { + if (!empty($msg_headers['X-Schedule'])) { + $scheduled_msg_count++; + } else { + continue; + } + + if (send_scheduled_message($this, $imap, $msg, $server_id)) { + $scheduled_msg_count--; + } + } catch (Exception $e) { + Hm_Debug::add(sprintf('ERRCannot send message: %s', $msg_headers['subject'])); + } + } + } + } + + $this->out('scheduled_msg_count', $scheduled_msg_count); +}} + +/** + * Changes the schedule of the message + * @subpackage smtp/handler + */ +class Hm_Handler_re_schedule_message_sending extends Hm_Handler_Module { + public function process() { + if (!($this->module_is_supported('imap') || $this->module_is_supported('profiles'))) { + return; + } + list($success, $form) = $this->process_form(array('schedule_date', 'scheduled_msg_ids')); + if (!$success) { + return; + } + $scheduled_msg_count = 0; + $new_schedule_date = $form['schedule_date']; + if ($form['schedule_date'] != 'now') { + $new_schedule_date = get_scheduled_date($form['schedule_date']); + } + $ids = explode(',', $form['scheduled_msg_ids']); + foreach ($ids as $msg_part) { + list($imap_server_id, $msg_id, $folder) = explode('_', $msg_part); + $cache = Hm_IMAP_List::get_cache($this->cache, $imap_server_id); + $imap = Hm_IMAP_List::connect($imap_server_id, $cache); + if (imap_authed($imap)) { + $folder = hex2bin($folder); + if (reschedule_message_sending($this, $imap, $msg_id, $folder, $new_schedule_date, $imap_server_id)) { + $scheduled_msg_count++; + } + } + } + $this->out('scheduled_msg_count', $scheduled_msg_count); + if ($scheduled_msg_count == count($ids)) { + $msg = 'Operation successful'; + } elseif ($scheduled_msg_count > 0) { + $msg = 'Some messages have been scheduled for sending'; + } else { + $msg = 'ERRFailed to schedule sending for messages'; + } + Hm_Msgs::add($msg); + $this->save_hm_msgs(); + } +} + /** * @subpackage keyboard_shortcuts/output */ @@ -1226,11 +1330,15 @@ protected function output() { } } } - $res .= ''. smtp_server_dropdown($this->module_output(), $this, $recip, $selected_id). - ''; - + '
+ + '. + schedule_dropdown($this). + '
'; if ($this->get('list_path') && ($reply_type == 'reply' || $reply_type == 'reply_all')) { $res .= ''; } @@ -1527,6 +1635,20 @@ protected function output() { } } +/** + * Add scheduled send to the message list controls + * @subpackage imap/output + */ +class Hm_Output_scheduled_send_msg_control extends Hm_Output_Module { + protected function output() { + $parts = explode('_', $this->get('list_path')); + if ($parts[0] == 'imap' && hex2bin($parts[2]) == 'Scheduled') { + $res = schedule_dropdown($this, true); + $this->concat('msg_controls_extra', $res); + } + } +} + /** * @subpackage smtp/functions */ @@ -1853,10 +1975,8 @@ function get_uploaded_files_from_array($uploaded_files) { } } -function prepare_draft_mime($atts, $uploaded_files, $from = false, $name = '') { - if (! empty($uploaded_files) && ! is_array($uploaded_files[0])) { - $uploaded_files = get_uploaded_files_from_array($uploaded_files); - } +function prepare_draft_mime($atts, $uploaded_files, $from = false, $name = '', $profile_id = null) { + $uploaded_files = get_uploaded_files_from_array($uploaded_files); $mime = new Hm_MIME_Msg( $atts['draft_to'], $atts['draft_subject'], @@ -1867,7 +1987,10 @@ function prepare_draft_mime($atts, $uploaded_files, $from = false, $name = '') { $atts['draft_bcc'], '', $name, - $atts['draft_in_reply_to'] + $atts['draft_in_reply_to'], + $atts['delivery_receipt'], + $atts['schedule'], + $profile_id ); $mime->add_attachments($uploaded_files); @@ -1906,28 +2029,40 @@ function save_imap_draft($atts, $id, $session, $mod, $mod_cache, $uploaded_files $specials = get_special_folders($mod, $imap_profile['id']); - if (!array_key_exists('draft', $specials) || !$specials['draft']) { + if ((!array_key_exists('draft', $specials) || !$specials['draft']) && !array_key_exists('schedule', $atts)) { Hm_Msgs::add('ERRThere is no draft directory configured for this account.'); return -1; } - $mailbox = Hm_IMAP_List::get_connected_mailbox($imap_profile['id'], $mod_cache); - if (! $mailbox || ! $mailbox->authed()) { - return -1; + $cache = Hm_IMAP_List::get_cache($mod_cache, $imap_profile['id']); + $imap = Hm_IMAP_List::connect($imap_profile['id'], $cache); + + if (!empty($atts['schedule'])) { + $folder ='Scheduled'; + if (!count($imap->get_mailbox_status($folder))) { + $imap->create_mailbox($folder); + } + $atts['schedule'] = get_scheduled_date($atts['schedule']); + } else { + $folder = $specials['draft']; } + $imap->select_mailbox($folder); - $mime = prepare_draft_mime($atts, $uploaded_files, $from, $name); + $mime = prepare_draft_mime($atts, $uploaded_files, $from, $name, $profile['id']); $res = $mime->process_attachments(); - + $msg = str_replace("\r\n", "\n", $mime->get_mime_msg()); $msg = str_replace("\n", "\r\n", $msg); $msg = rtrim($msg)."\r\n"; - if (! $mailbox->store_message($specials['draft'], $msg, false, true)) { - Hm_Msgs::add('ERRAn error occurred saving the draft message'); - return -1; + if ($imap->append_start($folder, mb_strlen($msg), false, true)) { + $imap->append_feed($msg."\r\n"); + if (!$imap->append_end()) { + Hm_Msgs::add('ERRAn error occurred saving the draft message'); + return -1; + } } - $messages = $mailbox->get_messages($specials['draft'], 'ARRIVAL', true, 'DRAFT', 0, 10); + $mailbox_page = $imap->get_mailbox_page($folder, 'ARRIVAL', true, 'DRAFT', 0, 10); // Remove old version from the mailbox if ($id) { @@ -2208,4 +2343,4 @@ function recip_count_check($headers, $omod) { if ($recip_count > MAX_RECIPIENT_WARNING) { Hm_Msgs::add('ERRMessage contains more than the maximum number of recipients, proceed with caution'); } -}} +}} \ No newline at end of file diff --git a/modules/smtp/setup.php b/modules/smtp/setup.php index 916bf9e613..c16fddecb5 100644 --- a/modules/smtp/setup.php +++ b/modules/smtp/setup.php @@ -21,6 +21,7 @@ add_handler('compose', 'load_smtp_is_imap_forward_as_attachment', true, 'smtp', 'load_user_data', 'after'); add_handler('compose', 'load_smtp_is_imap_forward', true, 'smtp', 'load_smtp_is_imap_forward_as_attachment', 'after'); + add_handler('functional_api', 'default_smtp_server', true, 'smtp'); add_handler('profiles', 'load_smtp_servers_from_config', true, 'smtp', 'load_user_data', 'after'); @@ -102,6 +103,20 @@ add_handler('settings', 'process_enable_compose_delivery_receipt_setting', true, 'core', 'save_user_settings', 'before'); add_output('settings', 'enable_compose_delivery_receipt_setting', true, 'core', 'start_general_settings', 'after'); +/* send delayed emails */ +setup_base_ajax_page('ajax_send_scheduled_messages', 'core'); +add_handler('ajax_send_scheduled_messages', 'load_imap_servers_from_config', true, 'imap', 'load_user_data', 'after'); +add_handler('ajax_send_scheduled_messages', 'load_smtp_servers_from_config', true, 'smtp', 'load_user_data', 'after'); +add_handler('ajax_send_scheduled_messages', 'compose_profile_data', true, 'profiles'); +add_handler('ajax_send_scheduled_messages', 'send_scheduled_messages', true, 'smtp'); + +setup_base_ajax_page('ajax_re_schedule_message_sending', 'core'); +add_handler('ajax_re_schedule_message_sending', 'load_imap_servers_from_config', true, 'imap', 'load_user_data', 'after'); +add_handler('ajax_re_schedule_message_sending', 'load_smtp_servers_from_config', true, 'smtp', 'load_user_data', 'after'); +add_handler('ajax_re_schedule_message_sending', 'compose_profile_data', true, 'profiles'); +add_handler('ajax_re_schedule_message_sending', 're_schedule_message_sending', true, 'smtp'); + +add_output('message_list', 'scheduled_send_msg_control', true, 'smtp', 'imap_custom_controls', 'after'); return array( 'allowed_pages' => array( @@ -112,7 +127,9 @@ 'ajax_profiles_status', 'ajax_attachment_reminder_check', 'ajax_get_test_chunk', - 'ajax_upload_chunk' + 'ajax_upload_chunk', + 'ajax_send_scheduled_messages', + 'ajax_re_schedule_message_sending' ), 'allowed_get' => array( 'imap_draft' => FILTER_VALIDATE_INT, @@ -144,9 +161,13 @@ 'msg_sent_and_archived' => array(FILTER_VALIDATE_BOOLEAN, false), 'sent_msg_id' => array(FILTER_VALIDATE_BOOLEAN, false), 'enable_attachment_reminder' => array(FILTER_VALIDATE_BOOLEAN, false), + 'scheduled_msg_count' => array(FILTER_VALIDATE_INT, false), ), 'allowed_post' => array( 'post_archive' => FILTER_VALIDATE_INT, + 'send_tomorrow_morning' => FILTER_DEFAULT, + 'send_today_afternoon' => FILTER_DEFAULT, + 'schedule_sending' => FILTER_DEFAULT, 'attachment_id' => FILTER_DEFAULT, 'smtp_compose_type' => FILTER_VALIDATE_INT, 'new_smtp_name' => FILTER_DEFAULT, @@ -185,6 +206,9 @@ 'uploaded_files' => FILTER_DEFAULT, 'send_uploaded_files' => FILTER_DEFAULT, 'next_email_post' => FILTER_DEFAULT, - 'enable_attachment_reminder' => FILTER_VALIDATE_INT + 'enable_attachment_reminder' => FILTER_VALIDATE_INT, + 'schedule' => FILTER_DEFAULT, + 'schedule_date' => FILTER_DEFAULT, + 'scheduled_msg_ids' => FILTER_DEFAULT, ) ); diff --git a/modules/smtp/site.js b/modules/smtp/site.js index 30a6bce694..2c60c8b688 100644 --- a/modules/smtp/site.js +++ b/modules/smtp/site.js @@ -28,7 +28,7 @@ var smtp_test_action = function(event) { false, {'smtp_connect': 1} ); -}; +}; var smtp_delete_action = function(event) { if (!hm_delete_prompt()) { @@ -69,7 +69,7 @@ var send_archive = function() { document.getElementsByClassName("smtp_send_placeholder")[0].click(); } -var save_compose_state = function(no_files, notice) { +var save_compose_state = function(no_files, notice, schedule, callback) { var no_icon = true; if (notice) { no_icon = false; @@ -82,6 +82,7 @@ var save_compose_state = function(no_files, notice) { var cc = $('.compose_cc').val(); var bcc = $('.compose_bcc').val(); var inreplyto = $('.compose_in_reply_to').val(); + var delivery_receipt = $('#compose_delivery_receipt').prop('checked'); var draft_id = $('.compose_draft_id').val(); if (globals.draft_state == body+subject+to+smtp+cc+bcc+uploaded_files) { @@ -105,6 +106,8 @@ var save_compose_state = function(no_files, notice) { {'name': 'draft_in_reply_to', 'value': inreplyto}, {'name': 'delete_uploaded_files', 'value': no_files}, {'name': 'draft_to', 'value': to}, + {'name': 'schedule', 'value': schedule}, + {'name': 'compose_delivery_receipt', 'value': delivery_receipt}, {'name': 'uploaded_files', 'value': uploaded_files}], function(res) { if (res.draft_id) { @@ -113,6 +116,15 @@ var save_compose_state = function(no_files, notice) { if (res.draft_subject) { $('.draft_list .draft_'+draft_id+' a').text(res.draft_subject); } + + if (schedule) { + $(".compose_form")[0].reset(); + return; + } + + if (callback) { + callback(res); + } }, [], no_icon @@ -138,7 +150,7 @@ function smtpServersPageHandler() { } } -var reset_smtp_form = function() { +var reset_smtp_form = function(save = true) { $('.compose_body').val(''); $('.compose_subject').val(''); $('.compose_to').val(''); @@ -146,7 +158,10 @@ var reset_smtp_form = function() { $('.compose_bcc').val(''); $('.ke-content', $('iframe').contents()).html(''); $('.uploaded_files').html(''); - save_compose_state(true); + $('#compose_delivery_receipt').prop('checked', false); + if (save) { + save_compose_state(true); + } }; var replace_cursor_positon = function (txtElement) { @@ -382,4 +397,4 @@ function smtpSettingsPageHandler() { [] ); }); -} +} \ No newline at end of file