Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix for the default email in the SMTP list when using the mailing and base IMAP draft implementation #464

Merged
merged 10 commits into from
May 5, 2021
4 changes: 4 additions & 0 deletions modules/core/message_list_functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ function icon_callback($vals, $style, $output_mod) {
$icons .= $show_icons ? '<img src="'.Hm_Image_Sources::$star.'" width="16" height="16" alt="'.$output_mod->trans('Flagged').'" />' : ' F';
$title[] = $output_mod->trans('Flagged');
}
if (in_array('draft', $vals[0])) {
$icons .= $show_icons ? '<img src="'.Hm_Image_Sources::$star.'" width="16" height="16" alt="'.$output_mod->trans('Draft').'" />' : ' D';
$title[] = $output_mod->trans('Draft');
}
if (in_array('answered', $vals[0])) {
$icons .= $show_icons ? '<img src="'.Hm_Image_Sources::$circle_check.'" width="16" height="16" alt="'.$output_mod->trans('Answered').'" />' : ' A';
$title[] = $output_mod->trans('Answered');
Expand Down
7 changes: 6 additions & 1 deletion modules/imap/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ function format_imap_message_list($msg_list, $output_module, $parent_list=false,
$from = preg_replace("/(\<.+\>)/U", '', $msg['to']);
$icon = 'sent';
}
foreach (array('attachment', 'deleted', 'flagged', 'answered') as $flag) {
foreach (array('attachment', 'deleted', 'flagged', 'answered', 'draft') as $flag) {
if (stristr($msg['flags'], $flag)) {
$flags[] = $flag;
}
Expand All @@ -244,6 +244,11 @@ function format_imap_message_list($msg_list, $output_module, $parent_list=false,
if (!$show_icons) {
$icon = false;
}

if (in_array('draft', $flags)) {
$url = '?page=compose&list_path='.sprintf('imap_%s_%s', $msg['server_id'], $msg['folder']).'&uid='.$msg['uid'].'&imap_draft=1';
}

if ($style == 'news') {
$res[$id] = message_list_row(array(
array('checkbox_callback', $id),
Expand Down
6 changes: 4 additions & 2 deletions modules/imap/hm-imap.php
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,6 @@ private function parse_bodystructure_response($result) {
* get content for a message part
* @param int $uid a single IMAP message UID
* @param string $message_part the IMAP message part number
* @param bool $raw flag to enabled fetching the entire message as text
* @param int $max maximum read length to allow.
* @param mixed $struct a message part structure array for decoding and
* charset conversion. bool true for auto discovery
Expand Down Expand Up @@ -1595,7 +1594,7 @@ public function message_action($action, $uids, $mailbox=false, $keyword=false) {
* @param bool $seen flag to mark the message seen
* $return bool true on success
*/
public function append_start($mailbox, $size, $seen=true) {
public function append_start($mailbox, $size, $seen=true, $draft=false) {
if (!$this->is_clean($mailbox, 'mailbox') || !$this->is_clean($size, 'uid')) {
return false;
}
Expand All @@ -1605,6 +1604,9 @@ public function append_start($mailbox, $size, $seen=true) {
else {
$command = 'APPEND "'.$this->utf7_encode($mailbox).'" () {'.$size."}\r\n";
}
if ($draft) {
$command = 'APPEND "'.$this->utf7_encode($mailbox).'" (\Draft) {'.$size."}\r\n";
}
$this->send_command($command);
$result = $this->fgets();
if (substr($result, 0, 1) == '+') {
Expand Down
2 changes: 1 addition & 1 deletion modules/imap_folders/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
add_output('folders', 'folders_trash_dialog', true, 'imap_folders', 'folders_delete_dialog', 'after');
add_output('folders', 'folders_sent_dialog', true, 'imap_folders', 'folders_trash_dialog', 'after');
add_output('folders', 'folders_archive_dialog', true, 'imap_folders', 'folders_sent_dialog', 'after');
//add_output('folders', 'folders_draft_dialog', true, 'imap_folders', 'folders_sent_dialog', 'after');
add_output('folders', 'folders_draft_dialog', true, 'imap_folders', 'folders_sent_dialog', 'after');

add_handler('compose', 'special_folders', true, 'imap_folders', 'load_user_data', 'after');

Expand Down
6 changes: 5 additions & 1 deletion modules/smtp/hm-mime-message.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ function __construct($to, $subject, $body, $from, $html=false, $cc='', $bcc='',
$this->body = $body;
}

/* return headers array */
function get_headers() {
return $this->headers;
}

/* add attachments */
function add_attachments($files) {
$this->attachments = $files;
Expand Down Expand Up @@ -267,4 +272,3 @@ function qp_encode($string) {
return str_replace('.', '=2E', quoted_printable_encode($string));
}
}

180 changes: 174 additions & 6 deletions modules/smtp/modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,50 @@ public function process() {
}
}

/**
* @subpackage smtp/handler
*/
class Hm_Handler_load_smtp_is_imap_draft extends Hm_Handler_Module {
public function process() {
if (!$this->module_is_supported('imap')) {
Hm_Msgs::add('ERRIMAP module unavailable.');
return;
}
if (array_key_exists('imap_draft', $this->request->get)
&& array_key_exists('list_path', $this->request->get)
&& array_key_exists('uid', $this->request->get)) {
$path = explode('_', $this->request->get['list_path']);

$imap = Hm_IMAP_List::connect($path[1]);
if ($imap->select_mailbox(hex2bin($path[2]))) {
$msg_struct = $imap->get_message_structure($this->request->get['uid']);
list($part, $msg_text) = $imap->get_first_message_part($this->request->get['uid'], 'text', 'plain', $msg_struct);
$msg_header = $imap->get_message_headers($this->request->get['uid']);

$imap_draft = array(
'From' => $msg_header['From'],
'To' => $msg_header['To'],
'Subject' => $msg_header['Subject'],
'Message-Id' => $msg_header['Message-Id'],
'Content-Type' => $msg_header['Content-Type'],
'Body' => $msg_text
);

if (array_key_exists('Cc', $msg_header)) {
$imap_draft['Cc'] = $msg_header['Cc'];
}

if ($imap_draft) {
$this->out('draft_id', $this->request->get['uid']);
$this->out('imap_draft', $imap_draft);
}
return;
}
Hm_Msgs::add('ERRCould not load the IMAP mailbox.');
}
}
}

/**
* @subpackage smtp/handler
*/
Expand Down Expand Up @@ -106,7 +150,7 @@ public function process() {
if (!is_readable($file['tmp_name'])) {
if($file['error'] == 1) {
$upload_max_filesize = ini_get('upload_max_filesize');
Hm_Msgs::add('ERRYour upload failed because you reached the limit of ' . $upload_max_filesize . '.');
Hm_Msgs::add('ERRYour upload failed because you reached the limit of ' . $upload_max_filesize . '.');
return;
}
Hm_Msgs::add('ERRAn error occurred saving the uploaded file.');
Expand Down Expand Up @@ -166,6 +210,20 @@ public function process() {
delete_draft($draft_id, $this->session);
}
else {
if ($this->module_is_supported('imap')) {
$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), $draft_id, $this->session,
$this, $this->cache);
if ($new_draft_id) {
Hm_Msgs::add('Draft saved');
$this->out('draft_id', $new_draft_id);
} elseif ($draft_notice) {
Hm_Msgs::add('ERRYou must enter a subject to save a draft');
}
return;
}

if (save_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), $draft_id, $this->session) !== false) {
Expand Down Expand Up @@ -619,6 +677,7 @@ protected function output() {

$draft = $this->get('compose_draft', array());
$reply = $this->get('reply_details', array());
$imap_draft = $this->get('imap_draft', array());
$reply_type = $this->get('reply_type', '');
$html = $this->get('smtp_compose_type', 0);
$msg_path = $this->get('list_path', '');
Expand All @@ -633,14 +692,16 @@ protected function output() {
}
$smtp_id = false;
$draft_id = $this->get('compose_draft_id', 0);

if (!empty($reply)) {
list($to, $cc, $subject, $body, $in_reply_to) = format_reply_fields(
$reply['msg_text'], $reply['msg_headers'], $reply['msg_struct'], $html, $this, $reply_type);

$recip = get_primary_recipient($this->get('compose_profiles', array()), $reply['msg_headers'],
$this->get('smtp_servers', array()));
}
elseif (!empty($draft)) {

if (!empty($draft)) {
if (array_key_exists('draft_to', $draft)) {
$to = $draft['draft_to'];
}
Expand All @@ -663,6 +724,23 @@ protected function output() {
$bcc = $draft['draft_bcc'];
}
}

if ($imap_draft) {
if (array_key_exists('Body', $imap_draft)) {
$body= $imap_draft['Body'];
}
if (array_key_exists('To', $imap_draft)) {
$to= $imap_draft['To'];
}
if (array_key_exists('Subject', $imap_draft)) {
$subject= $imap_draft['Subject'];
}
if (array_key_exists('Cc', $imap_draft)) {
$cc= $imap_draft['Cc'];
}
$draft_id = $msg_uid;
}

$send_disabled = '';
if (count($this->get('smtp_servers', array())) == 0) {
$send_disabled = 'disabled="disabled" ';
Expand Down Expand Up @@ -708,10 +786,28 @@ protected function output() {
$res .= format_attachment_row($file, $this);
}

// If compose_from GET parameter is set, force $recip replacement.
// This ensures any module can force the selected dropdown SMTP server
// If compose_from GET parameter is set, search for the correct smtp_id
// within the SMTP profiles.
//
// Added latency reduction 'break' for big smtp profile lists
if ($from) {
$recip = $from;
$profiles = $this->module_output()['smtp_servers'];
foreach ($profiles as $id => $profile) {
if ($profile['user'] == $from) {
$smtp_id = $id;
}
// Profile users without the domain
if ($profile['user'] == explode('@', $from)[0]) {
$smtp_id = $id;
}
// Some users might use the profile name as the full email
if ($profile['name'] == $from) {
$smtp_id = $id;
}
if ($smtp_id) {
break;
}
}
}

$res .= '</table>'.
Expand Down Expand Up @@ -856,7 +952,7 @@ protected function output() {
$res .= '<div class="configured_server">';
$res .= sprintf('<div class="server_title">%s</div><div class="server_subtitle">%s/%d %s</div>',
$this->html_safe($vals['name']), $this->html_safe($vals['server']), $this->html_safe($vals['port']), $vals['tls'] ? 'TLS' : '' );
$res .=
$res .=
'<form class="smtp_connect" method="POST">'.
'<input type="hidden" name="hm_page_key" value="'.$this->html_safe(Hm_Request_Key::generate()).'" />'.
'<input type="hidden" name="smtp_server_id" value="'.$this->html_safe($index).'" /><span> '.
Expand Down Expand Up @@ -1130,6 +1226,78 @@ function save_draft($atts, $id, $session) {
return $id;
}}

/**
* @subpackage smtp/functions
*/
if (!hm_exists('find_imap_by_smtp')) {
function find_imap_by_smtp($imap_profiles, $smtp_profile)
{
foreach ($imap_profiles as $id => $profile) {
if ($smtp_profile['user'] == $profile['user']) {
return array_merge(['id' => $id], $profile);
}
if (explode('@', $smtp_profile['user'])[0]
== explode('@', $profile['user'])[0]) {
return array_merge(['id' => $id], $profile);
}
if ($smtp_profile['user'] == $profile['name']) {
return array_merge(['id' => $id], $profile);
}
}
}}

/**
* @subpackage smtp/functions
*/
if (!hm_exists('save_imap_draft')) {
function save_imap_draft($atts, $id, $session, $mod, $mod_cache) {
$imap_profile = find_imap_by_smtp($mod->user_config->get('imap_servers'),
$mod->user_config->get('smtp_servers')[$atts['draft_smtp']]);

$specials = $mod->user_config->get('special_imap_folders');

if (array_key_exists($imap_profile['id'], $specials) &&
$specials[$imap_profile['id']]['draft']) {
$cache = Hm_IMAP_List::get_cache($mod_cache, $imap_profile['id']);
$imap = Hm_IMAP_List::connect($imap_profile['id'], $cache);
$draft_folder = $imap->select_mailbox($specials[$imap_profile['id']]['draft']);

$mime = new Hm_MIME_Msg($atts['draft_to'], $atts['draft_subject'], $atts['draft_body'],
$mod->user_config->get('smtp_servers')[$atts['draft_smtp']]['user'],
0, $atts['draft_cc'], $atts['draft_bcc'], $atts['draft_bcc'], $atts['draft_in_reply_to']);

$msg = str_replace("\r\n", "\n", $mime->get_mime_msg());
$msg = str_replace("\n", "\r\n", $msg);
$msg = rtrim($msg)."\r\n";

if ($imap->append_start($specials[$imap_profile['id']]['draft'], 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 0;
}
}

$mailbox_page = $imap->get_mailbox_page($specials[$imap_profile['id']]['draft'], 'ARRIVAL', true, 'DRAFT', 0, 10);

// Remove old version from the mailbox
if ($id) {
$imap->message_action('DELETE', array($id));
}

foreach ($mailbox_page[1] as $mail) {
$msg_header = $imap->get_message_headers($mail['uid']);
if ($msg_header['Message-Id'] === $mime->get_headers()['Message-Id'])
{
return $mail['uid'];
}
}

return 0;
}
return save_draft($atts, $id, $session);
}}

/**
* @subpackage smtp/functions
*/
Expand Down
5 changes: 4 additions & 1 deletion modules/smtp/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

add_module_to_all_pages('handler', 'smtp_default_server', true, 'smtp', 'load_user_data', 'after');
add_handler('compose', 'load_smtp_reply_to_details', true, 'smtp', 'load_user_data', 'after');
add_handler('compose', 'load_smtp_is_imap_draft', true, 'smtp', 'load_user_data', 'after');
add_handler('compose', 'smtp_from_replace', true, 'smtp', 'load_user_data', 'after');
add_handler('compose', 'load_smtp_servers_from_config', true, 'smtp', 'load_smtp_reply_to_details', 'after');
add_handler('compose', 'add_smtp_servers_to_page_data', true, 'smtp', 'load_smtp_servers_from_config', 'after');
Expand Down Expand Up @@ -50,6 +51,7 @@
add_handler('ajax_smtp_debug', 'http_headers', true, 'core');

/* save draft ajax request */
add_handler('ajax_smtp_save_draft', 'load_imap_servers_from_config', true, 'imap', 'load_user_data', 'after');
add_handler('ajax_smtp_save_draft', 'login', false, 'core');
add_handler('ajax_smtp_save_draft', 'load_user_data', true, 'core');
add_handler('ajax_smtp_save_draft', 'smtp_save_draft', true);
Expand Down Expand Up @@ -92,6 +94,7 @@
'ajax_smtp_delete_draft'
),
'allowed_get' => array(
'imap_draft' => FILTER_VALIDATE_INT,
'reply' => FILTER_VALIDATE_INT,
'reply_all' => FILTER_VALIDATE_INT,
'forward' => FILTER_VALIDATE_INT,
Expand Down Expand Up @@ -134,7 +137,7 @@
'draft_body' => FILTER_UNSAFE_RAW,
'draft_subject' => FILTER_UNSAFE_RAW,
'draft_to' => FILTER_UNSAFE_RAW,
'draft_smtp' => FILTER_VALIDATE_FLOAT,
'draft_smtp' => FILTER_SANITIZE_STRING,
'draft_cc' => FILTER_UNSAFE_RAW,
'draft_bcc' => FILTER_UNSAFE_RAW,
'draft_in_reply_to' => FILTER_UNSAFE_RAW,
Expand Down
Loading