Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions modules/core/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,6 @@ Hm_Modal.prototype = {
this.modalTitle.html(title);
}
};

class Hm_Alert {
constructor() {
this.container = document.querySelector('.sys_messages');
Expand Down Expand Up @@ -2588,6 +2587,39 @@ function setupActionSnooze(callback) {
$(document).on('change', '.nexter_input_snooze', callback);
}

class Hm_Filter_Modal extends Hm_Modal {
constructor(current_account) {
super({
size: "xl",
modalId: "myEditFilterModal",
});
const save_filter = Hm_Filters.save_filter;
const modalContent = document.querySelector("#edit_filter_modal");
if (modalContent) {
this.setContent(modalContent.innerHTML);
modalContent.remove();
} else {
this.setContent("<p>Could not load filter editor</p>");
}

this.addFooterBtn("Save", "btn-primary ms-auto", async () => {
let result = save_filter(current_account);
if (result) {
Hm_Notices.show("Filter saved", "success");
this.hide();
}
});

this.addFooterBtn("Convert to code", "btn-warning", async () => {
let result = save_filter(current_account, true);
if (result) {
Hm_Notices.show("Filter saved", "success");
this.hide();
}
});
}
}

document.addEventListener("show.bs.dropdown", function (event) {
const currentToggle = event.target;

Expand All @@ -2604,4 +2636,3 @@ document.addEventListener("show.bs.dropdown", function (event) {
}
});
});

6 changes: 6 additions & 0 deletions modules/imap/handler_modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,11 @@ public function process() {
$this->out('imap_accounts', $this->user_config->get('imap_servers'), array());
$this->out('show_pagination_links', $this->user_config->get('pagination_links_setting', true));
$this->out('auto_advance_email_enabled', $this->user_config->get('auto_advance_email_setting', true));

$details = Hm_IMAP_List::dump($form['imap_server_id']);
$mailbox_name = $details['name'];


$part = false;
$prefetch = false;
if (isset($this->request->post['imap_msg_part']) && preg_match("/[0-9\.]+/", $this->request->post['imap_msg_part'])) {
Expand Down Expand Up @@ -1996,6 +2001,7 @@ public function process() {
$this->session->set(sprintf('reply_details_imap_%s_%s_%s', $form['imap_server_id'], $form['folder'], $form['imap_msg_uid']),
array('ts' => time(), 'msg_struct' => $msg_struct_current, 'msg_text' => ($save_reply_text ? $msg_text : ''), 'msg_headers' => $msg_headers));
}
$this->out('mailbox_name', $mailbox_name);
}
}
}
Expand Down
54 changes: 54 additions & 0 deletions modules/imap/output_modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ protected function output() {
*/
class Hm_Output_filter_message_headers extends Hm_Output_Module {
protected function output() {

$mailbox_name = $this->get('mailbox_name');

if ($this->get('msg_headers')) {
$txt = '';
$small_headers = array('subject', 'x-snoozed', 'date', 'from', 'to', 'reply-to', 'cc', 'flags');
Expand Down Expand Up @@ -420,6 +423,57 @@ protected function output() {
$txt .= '<span class="text-decoration-none btn btn-sm btn-outline-danger" data-bs-toogle="tooltip" title="This functionality requires the email server support &quot;Sieve&quot; technology which is not provided. Contact your email provider to fix it or enable it if supported."><i class="bi bi-lock-fill"></i> <span id="filter_block_txt">'.$this->trans('Block Sender').'</span></span>';
}
}

if ($this->get('sieve_filters_enabled')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to check for this. Whenever you find yourself in the situation to check if a module is enabled, you should immediately think if you put the code in the right module. This code needs to go in sievefilters module - it can be an output module that is executed after this one here. If you need to put the content in a specific place in the middle of the headers section, add a placeholder for it or insert after an element.

$txt .= '<a class="hLink text-decoration-none btn btn-sm btn-outline-secondary dropdown-toggle me-2" '
. 'id="filter_message" href="#" data-bs-toggle="dropdown" aria-expanded="false">'
. $this->trans('Filter similar messages')
. '</a>'
. '<div class="dropdown-menu move_to_location p-3">'
. '<form id="create-filter-form" style="min-width:260px;" account="' . $mailbox_name . '">'
// From (enabled, checked by default)
. '<div class="form-check mb-1">'
. '<input class="form-check-input" type="checkbox" id="use_from" checked>'
. '<input type="hidden" name="from" value="' . htmlspecialchars($sender) . '">'
. '<label class="form-check-label small" for="use_from">'
. $this->trans('From:') . ' ' . htmlspecialchars($sender)
. '</label>'
. '</div>'

// To (disabled by default)
. '<div class="form-check mb-1">'
. '<input class="form-check-input" type="checkbox" id="use_to" >'
. '<input type="hidden" name="to" value="' . htmlspecialchars($headers['To']) . '">'
. '<label class="form-check-label small text-muted" for="use_to">'
. $this->trans('To:') . ' ' . $headers['To']
. '</label>'
. '</div>'

// Subject (disabled by default)
. '<div class="form-check mb-1">'
. '<input class="form-check-input" type="checkbox" id="use_subject" >'
. '<input type="hidden" name="subject" value="' . htmlspecialchars($headers['Subject']) . '">'
. '<label class="form-check-label small text-muted" for="use_subject">'
. $this->trans('Subject contains:') . ' ' . $headers['Subject']
. '</label>'
. '</div>'

// Reply-To (disabled by default)
. '<div class="form-check mb-2">'
. '<input class="form-check-input" type="checkbox" id="use_reply" >'
. '<input type="hidden" name="reply-to" value="' . htmlspecialchars($headers['Reply-To']) . '">'
. '<label class="form-check-label small text-muted" for="use_reply">'
. $this->trans('Reply-To:') . ' ' . $headers['Reply-To']
. '</label>'
. '</div>'

. '<button type="submit" id="create_filter" class="btn btn-primary btn-sm" >'
. $this->trans('Create filter')
. '</button>'
. '</form>'
. '</div>';
}

$txt .= '<a class="hlink text-decoration-none btn btn-sm btn-outline-secondary" id="show_message_source" href="#">' . $this->trans('Show Source') . '</a>';

$txt .= '</div><span id="extra-header-buttons"></span>';
Expand Down
1 change: 1 addition & 0 deletions modules/imap/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@
'do_not_flag_as_read_on_open' => array(FILTER_VALIDATE_BOOLEAN, false),
'ajax_imap_folders_permissions' => array(FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
'move_responses' => array(FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
'mailbox_name' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
),

'allowed_get' => array(
Expand Down
81 changes: 81 additions & 0 deletions modules/imap/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,87 @@ var imap_move_copy = function(e, action, context) {
return false;
};

$(function () {
$(document).on("submit", "#create-filter-form", function (e) {
e.preventDefault();
const current_account = $(this).attr("account");

const edit_filter_modal = new Hm_Filter_Modal(current_account);
hm_sieve_button_events(edit_filter_modal);
edit_filter_modal.setTitle("Add Filter for message like this");
const add_filter_condition = Hm_Filters.add_filter_condition;
const add_filter_action = Hm_Filters.add_filter_action;

const $form = $(this);
const $btn = $form.find("#create_filter").prop("disabled", true);
const data = {};

if ($form.find("#use_from").is(":checked"))
data["from"] = $form.find('input[name="from"]').val();
if ($form.find("#use_to").is(":checked"))
data["to"] = $form.find('input[name="to"]').val();
if ($form.find("#use_subject").is(":checked"))
data["subject"] = $form.find('input[name="subject"]').val();
if ($form.find("#use_reply").is(":checked"))
data["reply-to"] = $form.find('input[name="reply-to"]').val();

if ($.isEmptyObject(data)) {
Hm_Notices.show(
"Please check at least one condition to create a filter.",
"danger"
);
$btn.prop("disabled", false);
return;
}

edit_filter_modal.open();

const allFields = hm_sieve_condition_fields();
const availableFields = [
...allFields.Message.map((f) => f.name),
...allFields.Header.map((f) => f.name),
];

for (const [key, value] of Object.entries(data)) {
// If key is not in available fields, skip it
if (!availableFields.includes(key)) {
continue;
}

add_filter_condition();

const $lastRow = $(".sieve_list_conditions_modal tr").last();
const $selectField = $lastRow.find(
".add_condition_sieve_filters"
);
const $selectOp = $lastRow.find(".condition_options");
const $inputVal = $lastRow.find(
'input[name="sieve_selected_option_value[]"]'
);
$selectField.val(key);
$selectOp.val("Contains");
$inputVal.val(value);
}

if (data["reply-to"]) {
add_filter_action("autoreply");

const $lastRow = $(".filter_actions_modal_table tr").last();
const $select = $lastRow.find(".sieve_actions_select");
$select.val("autoreply").trigger("change");

// Focus the input field for the message
const $input = $lastRow.find(
'input[name="sieve_selected_action_value[]"]'
);
if ($input.length) {
$input.focus();
}
}

});
});

var imap_perform_move_copy = function(dest_id, context, action = null) {
if (!action) {
action = $('.move_to_type').val();
Expand Down
16 changes: 14 additions & 2 deletions modules/sievefilters/modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -1162,13 +1162,25 @@ protected function output() {
/**
* @subpackage sievefilters/output
*/
class Hm_Output_sievefilters_settings_start extends Hm_Output_Module {
class Hm_Output_sievefilters_title_start extends Hm_Output_Module {
protected function output() {
$socked_connected = $this->get('socket_connected', false);
$res = '<div class="sievefilters_settings p-0"><div class="content_title px-3">'.$this->trans('Filters').'</div>';
$res .= '<div class="p-3">';
$res .= '<div class="p-3" id="sieve_accounts"></div>';
$res .= get_classic_filter_modal_content();
return $res;
}
}

/**
* @subpackage sievefilters/output
*/
class Hm_Output_sievefilters_settings_start extends Hm_Output_Module
{
protected function output()
{

$res = get_classic_filter_modal_content();
$res .= get_script_modal_content();
return $res;
}
Expand Down
4 changes: 4 additions & 0 deletions modules/sievefilters/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
add_handler('ajax_imap_debug', 'sieve_connect', true, 'imap', 'imap_connect', 'after');

// sieve filter
add_output('sieve_filters', 'sievefilters_title_start', true, 'sievefilters', 'content_section_start', 'after');
add_output('sieve_filters', 'sievefilters_settings_start', true, 'sievefilters', 'content_section_start', 'after');
add_output('message', 'sievefilters_settings_start', true, 'sievefilters', 'content_section_start', 'after');
add_output('ajax_hm_folders', 'sievefilters_settings_link', true, 'sievefilters', 'settings_menu_end', 'before');
add_output('message', 'sievefilters_settings_link', true, 'sievefilters', 'settings_menu_end', 'before');
setup_base_ajax_page('ajax_account_sieve_filters', 'core');
add_handler('ajax_account_sieve_filters', 'settings_load_imap', true, 'sievefilters', 'load_user_data', 'after');
add_handler('ajax_account_sieve_filters', 'load_account_sieve_filters', true, 'sievefilters', 'settings_load_imap', 'after');
Expand Down Expand Up @@ -145,6 +148,7 @@
'ajax_sieve_toggle_script_state',
'ajax_list_block_sieve',
'message_list',
'message',
'ajax_account_sieve_filters',
'ajax_block_account_sieve_filters',
),
Expand Down
Loading
Loading