| 1: | <?php |
| 2: | |
| 3: | |
| 4: | |
| 5: | |
| 6: | |
| 7: | |
| 8: | |
| 9: | if (!defined('DEBUG_MODE')) { die(); } |
| 10: | |
| 11: | |
| 12: | |
| 13: | |
| 14: | |
| 15: | |
| 16: | |
| 17: | |
| 18: | |
| 19: | if (!hm_exists('imap_sources')) { |
| 20: | function imap_sources($mod, $folder = 'sent') { |
| 21: | $inbox = $mod->user_config->get('smtp_auto_bcc_setting', DEFAULT_SMTP_AUTO_BCC); |
| 22: | $sources = array(); |
| 23: | $folder = $folder == 'drafts' ? 'draft': $folder; |
| 24: | foreach (Hm_IMAP_List::dump() as $index => $vals) { |
| 25: | if (array_key_exists('hide', $vals) && $vals['hide']) { |
| 26: | continue; |
| 27: | } |
| 28: | $folders = get_special_folders($mod, $index); |
| 29: | if (array_key_exists($folder, $folders) && $folders[$folder]) { |
| 30: | $sources[] = array('folder' => bin2hex($folders[$folder]), 'folder_name' => $folders[$folder], 'type' => $vals['type'] ?? 'imap', 'name' => $vals['name'], 'id' => $index); |
| 31: | } |
| 32: | elseif ($inbox) { |
| 33: | $sources[] = array('folder' => bin2hex('INBOX'), 'folder_name' => 'INBOX', 'type' => $vals['type'] ?? 'imap', 'name' => $vals['name'], 'id' => $index); |
| 34: | } |
| 35: | elseif ($folder=="snoozed"){ |
| 36: | $sources[] = array('folder' => bin2hex('Snoozed'), 'folder_name' => 'Snoozed', 'type' => $vals['type'] ?? 'imap','name' => $vals['name'],'id' => $index); |
| 37: | } |
| 38: | else { |
| 39: | $sources[] = array('folder' => bin2hex('SPECIAL_USE_CHECK'), 'folder_name' => 'SPECIAL_USE_CHECK', 'nodisplay' => true, 'type' => $vals['type'] ?? 'imap', 'name' => $vals['name'], 'id' => $index); |
| 40: | } |
| 41: | } |
| 42: | return $sources; |
| 43: | }} |
| 44: | |
| 45: | |
| 46: | |
| 47: | |
| 48: | |
| 49: | |
| 50: | |
| 51: | if (!hm_exists('imap_data_sources')) { |
| 52: | function imap_data_sources($custom=array()) { |
| 53: | $sources = array(); |
| 54: | foreach (Hm_IMAP_List::dump() as $index => $vals) { |
| 55: | if (array_key_exists('hide', $vals) && $vals['hide']) { |
| 56: | continue; |
| 57: | } |
| 58: | if (!array_key_exists('user', $vals)) { |
| 59: | continue; |
| 60: | } |
| 61: | $mailbox = Hm_IMAP_List::get_mailbox_without_connection($vals); |
| 62: | $folder = $mailbox->get_folder_name('INBOX'); |
| 63: | $sieve = ! empty($vals['sieve_config_host']); |
| 64: | $sources[] = array('folder' => bin2hex($folder), 'folder_name' => $folder, 'type' => $vals['type'] ?? 'imap', 'name' => $vals['name'], 'id' => $index, 'sieve' => $sieve); |
| 65: | } |
| 66: | foreach ($custom as $path => $type) { |
| 67: | $parts = explode('_', $path, 3); |
| 68: | $remove_id = false; |
| 69: | |
| 70: | if ($type == 'add') { |
| 71: | $details = Hm_IMAP_List::dump($parts[1]); |
| 72: | if ($details) { |
| 73: | $folder_name = $parts[2]; |
| 74: | if (! empty($details['type']) && $details['type'] == 'ews') { |
| 75: | $mailbox = Hm_IMAP_List::get_connected_mailbox($details['id']); |
| 76: | if ($mailbox && $mailbox->authed()) { |
| 77: | $folder_name = $mailbox->get_folder_name(hex2bin($folder_name)); |
| 78: | } |
| 79: | } |
| 80: | $sources[] = array('folder' => $parts[2], 'folder_name' => $folder_name, 'type' => $details['type'] ?? 'imap', 'name' => $details['name'], 'id' => $parts[1]); |
| 81: | } |
| 82: | } |
| 83: | elseif ($type == 'remove') { |
| 84: | foreach ($sources as $index => $vals) { |
| 85: | if ($vals['folder'] == $parts[2] && $vals['id'] == $parts[1]) { |
| 86: | $remove_id = $index; |
| 87: | break; |
| 88: | } |
| 89: | } |
| 90: | if ($remove_id !== false) { |
| 91: | unset($sources[$remove_id]); |
| 92: | } |
| 93: | } |
| 94: | } |
| 95: | return $sources; |
| 96: | }} |
| 97: | |
| 98: | |
| 99: | |
| 100: | |
| 101: | |
| 102: | |
| 103: | |
| 104: | |
| 105: | if (!hm_exists('prepare_imap_message_list')) { |
| 106: | function prepare_imap_message_list($msgs, $mod, $type) { |
| 107: | $style = $mod->get('news_list_style') ? 'news' : 'email'; |
| 108: | if ($mod->get('is_mobile')) { |
| 109: | $style = 'news'; |
| 110: | } |
| 111: | $res = format_imap_message_list($msgs, $mod, $type, $style); |
| 112: | $mod->out('formatted_message_list', $res); |
| 113: | }} |
| 114: | |
| 115: | |
| 116: | |
| 117: | |
| 118: | |
| 119: | |
| 120: | |
| 121: | |
| 122: | |
| 123: | if (!hm_exists('format_imap_folder_section')) { |
| 124: | function format_imap_folder_section($folders, $id, $output_mod, $with_input = false, $can_share_folders = false) { |
| 125: | $results = '<ul class="inner_list">'; |
| 126: | $manage = $output_mod->get('imap_folder_manage_link'); |
| 127: | |
| 128: | foreach ($folders as $folder_name => $folder) { |
| 129: | $folder_name = bin2hex($folder_name); |
| 130: | $results .= '<li class="'. ($folder['children'] ? 'm-has-children ' : '') .'imap_'.$id.'_'.$output_mod->html_safe($folder_name).'" data-number-children="'.$output_mod->html_safe($folder['number_of_children']).'">'; |
| 131: | |
| 132: | if ($folder['children']) { |
| 133: | $results .= '<div class="m-has-children-wrapper"><a href="#" class="imap_folder_link expand_link d-inline-flex" data-target="imap_'.$id.'_'.$output_mod->html_safe($folder_name).'"><i class="bi bi-plus-circle-fill"></i></a>'; |
| 134: | } |
| 135: | else { |
| 136: | $results .= '<i class="bi bi-folder2-open"></i> '; |
| 137: | } |
| 138: | if (!$folder['noselect']) { |
| 139: | if (!$folder['clickable']) { |
| 140: | $attrs = 'tabindex="0"'; |
| 141: | if (!$with_input && isset($folder['subscribed']) && !$folder['subscribed']) { |
| 142: | $attrs .= ' class="folder-disabled"'; |
| 143: | } |
| 144: | } else { |
| 145: | $attrs = 'id="main-link" data-id="imap_'.$id.'_'.$output_mod->html_safe($folder_name). |
| 146: | '" href="?page=message_list&list_path='. |
| 147: | urlencode('imap_'.$id.'_'.$output_mod->html_safe($folder_name)).'"'; |
| 148: | } |
| 149: | if (mb_strlen($folder['basename'])>15) { |
| 150: | $results .= '<a ' . $attrs . |
| 151: | ' title="'.$output_mod->html_safe($folder['basename']). |
| 152: | '">'.$output_mod->html_safe(mb_substr($folder['basename'],0,15)).'...</a>'; |
| 153: | } |
| 154: | else { |
| 155: | $results .= '<a ' . $attrs. '>'.$output_mod->html_safe($folder['basename']).'</a>'; |
| 156: | } |
| 157: | } |
| 158: | else { |
| 159: | $results .= $output_mod->html_safe($folder['basename']); |
| 160: | } |
| 161: | if ($with_input) { |
| 162: | $results .= '<input type="checkbox" value="1" class="folder_subscription" id="'.$output_mod->html_safe($folder_name).'" name="'.$folder_name.'" '.($folder['subscribed']? 'checked="checked"': '').($folder['special']? ' disabled="disabled"': '').' />'; |
| 163: | } |
| 164: | $results .= '<span class="unread_count unread_imap_'.$id.'_'.$output_mod->html_safe($folder_name).'"></span>'; |
| 165: | if($folder['children']) { |
| 166: | $results .= '</div>'; |
| 167: | } |
| 168: | if($can_share_folders) { |
| 169: | $results .= '<div class="dropdown"><a href="#" class="action-link" data-bs-toggle="dropdown" aria-expanded="false"><i class="icon bi bi-three-dots-vertical"></i></a><ul class="dropdown-menu dropdown-menu"><li data-id="'.$id.'" data-folder-uid="'.$output_mod->html_safe($folder_name).'" data-folder="'.$output_mod->html_safe($folder['basename']).'"><a href="#" class="dropdown-item share"><i class="icon bi bi-share"></i> Share</a></ul></div>'; |
| 170: | } |
| 171: | $results .= '</li>'; |
| 172: | } |
| 173: | if ($manage) { |
| 174: | $results .= '<li class="manage_folders_li"><i class="bi bi-gear-wide me-1"></i><a class="manage_folder_link" href="'.$manage.'">'.$output_mod->trans('Manage Folders').'</a></li>'; |
| 175: | } |
| 176: | $f = $output_mod->get('folder', ''); |
| 177: | $quota = $output_mod->get('quota'); |
| 178: | $quota_max = $output_mod->get('quota_max'); |
| 179: | if (!$f && $quota) { |
| 180: | $results .= '<li class="quota_info"><div class="progress bg-secondary border"><div class="progress-bar bg-light" style="width:'.$quota.'%"></div></div>'.$quota.'% used on '.$quota_max.' MB</li>'; |
| 181: | } |
| 182: | |
| 183: | $results .= '</ul>'; |
| 184: | return $results; |
| 185: | }} |
| 186: | |
| 187: | |
| 188: | |
| 189: | |
| 190: | |
| 191: | |
| 192: | |
| 193: | if (!hm_exists('format_imap_from_fld')) { |
| 194: | function format_imap_from_fld($fld) { |
| 195: | $res = array(); |
| 196: | foreach (process_address_fld($fld) as $vals) { |
| 197: | if (trim($vals['label'])) { |
| 198: | $res[] = $vals['label']; |
| 199: | } |
| 200: | elseif (trim($vals['email'])) { |
| 201: | $res[] = $vals['email']; |
| 202: | } |
| 203: | } |
| 204: | return implode(', ', $res); |
| 205: | }} |
| 206: | |
| 207: | |
| 208: | |
| 209: | |
| 210: | |
| 211: | |
| 212: | |
| 213: | |
| 214: | |
| 215: | |
| 216: | if (!hm_exists('format_imap_message_list')) { |
| 217: | function format_imap_message_list($msg_list, $output_module, $parent_list=false, $style='email') { |
| 218: | $res = array(); |
| 219: | if ($msg_list === array(false)) { |
| 220: | return $msg_list; |
| 221: | } |
| 222: | $show_icons = $output_module->get('msg_list_icons'); |
| 223: | $list_page = $output_module->get('list_page', 0); |
| 224: | $list_sort = $output_module->get('list_sort', $output_module->get('default_sort_order')); |
| 225: | $list_filter = $output_module->get('list_filter'); |
| 226: | $list_keyword = $output_module->get('list_keyword'); |
| 227: | foreach($msg_list as $msg) { |
| 228: | $row_class = 'email'; |
| 229: | $icon = 'env_open'; |
| 230: | if (!$parent_list) { |
| 231: | $parent_value = sprintf('imap_%s_%s', $msg['server_id'], $msg['folder']); |
| 232: | } |
| 233: | else { |
| 234: | $parent_value = $parent_list; |
| 235: | } |
| 236: | $id = sprintf("imap_%s_%s_%s", $msg['server_id'], $msg['uid'], $msg['folder']); |
| 237: | if (!trim($msg['subject'])) { |
| 238: | $msg['subject'] = '[No Subject]'; |
| 239: | } |
| 240: | $subject = $msg['subject']; |
| 241: | $preview_msg = ""; |
| 242: | if (isset($msg['preview_msg'])) { |
| 243: | $preview_msg = $msg['preview_msg']; |
| 244: | } |
| 245: | |
| 246: | if ($parent_list == 'sent') { |
| 247: | $icon = 'sent'; |
| 248: | $from = $msg['to']; |
| 249: | } |
| 250: | else { |
| 251: | $from = $msg['from']; |
| 252: | } |
| 253: | $from = format_imap_from_fld(is_array($from) ? implode(', ', $from) : $from); |
| 254: | $nofrom = ''; |
| 255: | if (!trim($from)) { |
| 256: | $from = '[No From]'; |
| 257: | $nofrom = ' nofrom'; |
| 258: | } |
| 259: | $is_snoozed = !empty($msg['x_snoozed']) && hex2bin($msg['folder']) == 'Snoozed'; |
| 260: | $is_scheduled = !empty($msg['x_schedule']) && hex2bin($msg['folder']) == 'Scheduled'; |
| 261: | if ($is_snoozed) { |
| 262: | $snooze_header = parse_delayed_header('X-Snoozed: '.$msg['x_snoozed'], 'X-Snoozed'); |
| 263: | $date = $snooze_header['until']; |
| 264: | $timestamp = strtotime($date); |
| 265: | } elseif ($is_scheduled) { |
| 266: | $date = $msg['x_schedule']; |
| 267: | $timestamp = strtotime($date); |
| 268: | } else { |
| 269: | if ($list_sort == 'date') { |
| 270: | $date_field = 'date'; |
| 271: | } else { |
| 272: | $date_field = 'internal_date'; |
| 273: | } |
| 274: | $date = translate_time_str(human_readable_interval($msg[$date_field]), $output_module); |
| 275: | $timestamp = strtotime($msg[$date_field]); |
| 276: | } |
| 277: | |
| 278: | $flags = array(); |
| 279: | if (!mb_stristr($msg['flags'], 'seen')) { |
| 280: | $flags[] = 'unseen'; |
| 281: | if ($icon != 'sent') { |
| 282: | $icon = 'env_closed'; |
| 283: | } |
| 284: | } |
| 285: | else { |
| 286: | $row_class .= ' seen'; |
| 287: | } |
| 288: | if (trim($msg['x_auto_bcc']) === 'cypht') { |
| 289: | $from = preg_replace("/(\<.+\>)/U", '', $msg['to']); |
| 290: | $icon = 'sent'; |
| 291: | } |
| 292: | foreach (array('attachment', 'deleted', 'flagged', 'answered', 'draft') as $flag) { |
| 293: | if (mb_stristr($msg['flags'], $flag)) { |
| 294: | $flags[] = $flag; |
| 295: | } |
| 296: | } |
| 297: | $source = $msg['server_name']; |
| 298: | $row_class .= ' '.str_replace(' ', '_', $source); |
| 299: | $row_class .= ' '.implode(' ', $flags); |
| 300: | if ($msg['folder'] && strtolower(hex2bin($msg['folder'])) != 'inbox') { |
| 301: | $source .= '-'.preg_replace("/^INBOX.{1}/", '', hex2bin($msg['folder'])); |
| 302: | } |
| 303: | $url = '?page=message&uid='.$msg['uid'].'&list_path='.sprintf('imap_%s_%s', $msg['server_id'], $msg['folder']).'&list_parent='.$parent_value; |
| 304: | if ($list_page) { |
| 305: | $url .= '&list_page='.$output_module->html_safe($list_page); |
| 306: | } |
| 307: | if ($list_sort) { |
| 308: | $url .= '&sort='.$output_module->html_safe($list_sort); |
| 309: | } |
| 310: | if ($list_filter) { |
| 311: | $url .= '&filter='.$output_module->html_safe($list_filter); |
| 312: | } |
| 313: | if ($list_keyword) { |
| 314: | $url .= '&keyword='.$output_module->html_safe($list_keyword); |
| 315: | } |
| 316: | if (!$show_icons) { |
| 317: | $icon = false; |
| 318: | } |
| 319: | |
| 320: | |
| 321: | |
| 322: | |
| 323: | |
| 324: | $msgId = $msg['message_id'] ?? ''; |
| 325: | $inReplyTo = $msg['in_reply_to'] ?? ''; |
| 326: | |
| 327: | if ($msgId) { |
| 328: | $msgId = str_replace(['<', '>'], '', trim($msgId)); |
| 329: | } |
| 330: | if ($inReplyTo) { |
| 331: | $inReplyTo = str_replace(['<', '>'], '', trim($inReplyTo)); |
| 332: | } |
| 333: | |
| 334: | if ($style == 'news') { |
| 335: | $res[$id] = message_list_row(array( |
| 336: | array('checkbox_callback', $id), |
| 337: | array('icon_callback', $flags), |
| 338: | array('subject_callback', $subject, $url, $flags, $icon, $preview_msg), |
| 339: | array('safe_output_callback', 'source', $source), |
| 340: | array('safe_output_callback', 'from'.$nofrom, $from, null, str_replace(array($from, '<', '>'), '', $msg['from'])), |
| 341: | array('date_callback', $date, $timestamp, $is_snoozed || $is_scheduled), |
| 342: | array('dates_holders_callback', $msg['internal_date'], $msg['date']), |
| 343: | ), |
| 344: | $id, |
| 345: | $style, |
| 346: | $output_module, |
| 347: | $row_class, |
| 348: | $msgId, |
| 349: | $inReplyTo |
| 350: | ); |
| 351: | } |
| 352: | else { |
| 353: | $res[$id] = message_list_row(array( |
| 354: | array('checkbox_callback', $id), |
| 355: | array('safe_output_callback', 'source', $source, $icon), |
| 356: | array('safe_output_callback', 'from'.$nofrom, $from, null, str_replace(array($from, '<', '>'), '', $msg['from'])), |
| 357: | array('subject_callback', $subject, $url, $flags, null, $preview_msg), |
| 358: | array('date_callback', $date, $timestamp, $is_snoozed || $is_scheduled), |
| 359: | array('icon_callback', $flags), |
| 360: | array('dates_holders_callback', $msg['internal_date'], $msg['date']), |
| 361: | ), |
| 362: | $id, |
| 363: | $style, |
| 364: | $output_module, |
| 365: | $row_class, |
| 366: | $msgId, |
| 367: | $inReplyTo |
| 368: | ); |
| 369: | } |
| 370: | } |
| 371: | return $res; |
| 372: | }} |
| 373: | |
| 374: | |
| 375: | |
| 376: | |
| 377: | |
| 378: | |
| 379: | |
| 380: | if (!hm_exists('process_imap_message_ids')) { |
| 381: | function process_imap_message_ids($ids) { |
| 382: | $res = array(); |
| 383: | foreach (explode(',', $ids) as $id) { |
| 384: | if (preg_match("/imap_(\S+)_(\S+)_(\S+)$/", $id, $matches)) { |
| 385: | $server = $matches[1]; |
| 386: | $uid = $matches[2]; |
| 387: | $folder = $matches[3]; |
| 388: | if (!isset($res[$server])) { |
| 389: | $res[$server] = array(); |
| 390: | } |
| 391: | if (!isset($res[$server][$folder])) { |
| 392: | $res[$server][$folder] = array(); |
| 393: | } |
| 394: | $res[$server][$folder][] = $uid; |
| 395: | } |
| 396: | } |
| 397: | return $res; |
| 398: | }} |
| 399: | |
| 400: | |
| 401: | |
| 402: | |
| 403: | |
| 404: | |
| 405: | |
| 406: | |
| 407: | |
| 408: | |
| 409: | |
| 410: | |
| 411: | |
| 412: | |
| 413: | |
| 414: | if (!hm_exists('format_msg_part_row')) { |
| 415: | function format_msg_part_row($id, $vals, $output_mod, $level, $part, $dl_args, $at_args, $use_icons=false, $simple_view=false, $mobile=false) { |
| 416: | $allowed = array( |
| 417: | 'textplain', |
| 418: | 'texthtml', |
| 419: | 'messagedisposition-notification', |
| 420: | 'messagedelivery-status', |
| 421: | 'messagerfc822-headers', |
| 422: | 'textcsv', |
| 423: | 'textcss', |
| 424: | 'textunknown', |
| 425: | 'textx-vcard', |
| 426: | 'textcalendar', |
| 427: | 'textx-vcalendar', |
| 428: | 'textx-sql', |
| 429: | 'textx-comma-separated-values', |
| 430: | 'textenriched', |
| 431: | 'textrfc822-headers', |
| 432: | 'textx-diff', |
| 433: | 'textx-patch', |
| 434: | 'applicationpgp-signature', |
| 435: | 'applicationx-httpd-php', |
| 436: | 'imagepng', |
| 437: | 'imagesvg+xml', |
| 438: | 'imagejpg', |
| 439: | 'imagejpeg', |
| 440: | 'imagepjpeg', |
| 441: | 'imagegif', |
| 442: | ); |
| 443: | $icons = array( |
| 444: | 'text' => 'doc', |
| 445: | 'image' => 'camera', |
| 446: | 'application' => 'save', |
| 447: | 'multipart' => 'folder', |
| 448: | 'audio' => 'audio', |
| 449: | 'video' => 'monitor', |
| 450: | 'binary' => 'save', |
| 451: | |
| 452: | 'textx-vcard' => 'calendar', |
| 453: | 'textcalendar' => 'calendar', |
| 454: | 'textx-vcalendar' => 'calendar', |
| 455: | 'applicationics' => 'calendar', |
| 456: | 'multipartdigest' => 'spreadsheet', |
| 457: | 'applicationpgp-keys' => 'key', |
| 458: | 'applicationpgp-signature' => 'key', |
| 459: | 'multipartsigned' => 'lock', |
| 460: | 'messagerfc822' => 'env_open', |
| 461: | 'octetstream' => 'paperclip', |
| 462: | ); |
| 463: | $hidden_parts= array( |
| 464: | 'multipartdigest', |
| 465: | 'multipartsigned', |
| 466: | 'multipartmixed', |
| 467: | 'messagerfc822', |
| 468: | ); |
| 469: | $lc_type = mb_strtolower($vals['type']).mb_strtolower($vals['subtype']); |
| 470: | if ($simple_view) { |
| 471: | if (filter_message_part($vals)) { |
| 472: | return ''; |
| 473: | } |
| 474: | if (in_array($lc_type, $hidden_parts, true)) { |
| 475: | return ''; |
| 476: | } |
| 477: | } |
| 478: | if ($level > 6) { |
| 479: | $class = 'row_indent_max'; |
| 480: | } |
| 481: | else { |
| 482: | $class = 'row_indent_'.$level; |
| 483: | } |
| 484: | $desc = get_part_desc($vals, $id, $part); |
| 485: | $size = get_imap_size($vals); |
| 486: | $res = '<tr'; |
| 487: | if ($id == $part) { |
| 488: | $res .= ' class="selected_part"'; |
| 489: | } |
| 490: | $res .= '><td><div class="'.$class.'">'; |
| 491: | $icon = false; |
| 492: | if ($use_icons && array_key_exists($lc_type, $icons)) { |
| 493: | $icon = $icons[$lc_type]; |
| 494: | } |
| 495: | elseif ($use_icons && array_key_exists(mb_strtolower($vals['type']), $icons)) { |
| 496: | $icon = $icons[mb_strtolower($vals['type'])]; |
| 497: | } |
| 498: | if ($icon) { |
| 499: | $res .= '<i class="bi bi-file-plus-fill msg_part_icon"></i> '; |
| 500: | } |
| 501: | else { |
| 502: | $res .= '<i class="bi bi-file-plus-fill msg_part_icon msg_part_placeholder"></i> '; |
| 503: | } |
| 504: | if (in_array($lc_type, $allowed, true)) { |
| 505: | $res .= '<a href="#" class="msg_part_link" data-message-part="'.$output_mod->html_safe($id).'">'.$output_mod->html_safe(mb_strtolower($vals['type'])). |
| 506: | ' / '.$output_mod->html_safe(mb_strtolower($vals['subtype'])).'</a>'; |
| 507: | } |
| 508: | else { |
| 509: | $res .= $output_mod->html_safe(mb_strtolower($vals['type'])).' / '.$output_mod->html_safe(mb_strtolower($vals['subtype'])); |
| 510: | } |
| 511: | if ($mobile) { |
| 512: | $res .= '<div class="part_size">'.$output_mod->html_safe($size); |
| 513: | $res .= '</div><div class="part_desc">'.$output_mod->html_safe(decode_fld($desc)).'</div>'; |
| 514: | $res .= '<div class="download_link"><a href="#" data-src="?'.$dl_args.'&imap_msg_part='.$output_mod->html_safe($id).'">'.$output_mod->trans('Download').'</a></div></td>'; |
| 515: | } |
| 516: | else { |
| 517: | $res .= '</td><td class="part_size">'.$output_mod->html_safe($size); |
| 518: | if (!$simple_view) { |
| 519: | $res .= '</td><td class="part_encoding">'.(isset($vals['encoding']) ? $output_mod->html_safe(mb_strtolower($vals['encoding'])) : ''). |
| 520: | '</td><td class="part_charset">'.(isset($vals['attributes']['charset']) && trim($vals['attributes']['charset']) ? $output_mod->html_safe(mb_strtolower($vals['attributes']['charset'])) : ''); |
| 521: | } |
| 522: | $res .= '</td><td class="part_desc">'.$output_mod->html_safe(decode_fld($desc)).'</td>'; |
| 523: | $res .= '<td class="download_link"><a href="#" data-src="?'.$dl_args.'&imap_msg_part='.$output_mod->html_safe($id).'">'.$output_mod->trans('Download').'</a></td>'; |
| 524: | } |
| 525: | if ($output_mod->get('allow_delete_attachment') && isset($vals['file_attributes']['attachment'])) { |
| 526: | $res .= '<td><a href="#" data-src="?'.$at_args.'&imap_msg_part='.$output_mod->html_safe($id).'" class="remove_attachment">'.$output_mod->trans('Remove').'</a></td>'; |
| 527: | } |
| 528: | $res .= '</tr>'; |
| 529: | return $res; |
| 530: | }} |
| 531: | |
| 532: | |
| 533: | |
| 534: | |
| 535: | |
| 536: | |
| 537: | |
| 538: | if (!hm_exists('remove_attachment')) { |
| 539: | function remove_attachment($att_id, $msg) { |
| 540: | $message = Message::from($msg, false); |
| 541: | $message->removeAttachmentPart($att_id); |
| 542: | |
| 543: | return (string) $message; |
| 544: | } |
| 545: | } |
| 546: | |
| 547: | |
| 548: | |
| 549: | |
| 550: | |
| 551: | |
| 552: | |
| 553: | |
| 554: | if (!hm_exists('get_attachment_id_for_mail_parser')) { |
| 555: | function get_attachment_id_for_mail_parser($struct, $part_id) { |
| 556: | $count = -1; |
| 557: | $id = false; |
| 558: | foreach ($struct[0]['subs'] as $key => $sub) { |
| 559: | if (! empty($sub['file_attributes'])) { |
| 560: | $count++; |
| 561: | if ($key == $part_id && isset($sub['file_attributes']['attachment'])) { |
| 562: | $id = $count; |
| 563: | break; |
| 564: | } |
| 565: | } |
| 566: | } |
| 567: | return $id; |
| 568: | } |
| 569: | } |
| 570: | |
| 571: | |
| 572: | |
| 573: | |
| 574: | |
| 575: | |
| 576: | |
| 577: | |
| 578: | if (!hm_exists('get_part_desc')) { |
| 579: | function get_part_desc($vals, $id, $part) { |
| 580: | $desc = ''; |
| 581: | if (isset($vals['description']) && trim($vals['description'])) { |
| 582: | $desc = $vals['description']; |
| 583: | } |
| 584: | elseif (isset($vals['name']) && trim($vals['name'])) { |
| 585: | $desc = $vals['name']; |
| 586: | } |
| 587: | elseif (isset($vals['filename']) && trim($vals['filename'])) { |
| 588: | $desc = $vals['filename']; |
| 589: | } |
| 590: | elseif (isset($vals['envelope']['subject']) && trim($vals['envelope']['subject'])) { |
| 591: | $desc = $vals['envelope']['subject']; |
| 592: | } |
| 593: | $filename = get_imap_part_name($vals, $id, $part, true); |
| 594: | if (!$desc && $filename) { |
| 595: | $desc = $filename; |
| 596: | } |
| 597: | return $desc; |
| 598: | }} |
| 599: | |
| 600: | |
| 601: | |
| 602: | |
| 603: | |
| 604: | |
| 605: | if (!hm_exists('get_imap_size')) { |
| 606: | function get_imap_size($vals) { |
| 607: | if (!array_key_exists('size', $vals) || !$vals['size']) { |
| 608: | return ''; |
| 609: | } |
| 610: | $size = intval($vals['size']); |
| 611: | switch (true) { |
| 612: | case $size > 1000: |
| 613: | $size = $size/1000; |
| 614: | $label = 'KB'; |
| 615: | break; |
| 616: | case $size > 1000000: |
| 617: | $size = $size/1000000; |
| 618: | $label = 'MB'; |
| 619: | break; |
| 620: | case $size > 1000000000: |
| 621: | $size = $size/1000000000; |
| 622: | $label = 'GB'; |
| 623: | break; |
| 624: | default: |
| 625: | $label = 'B'; |
| 626: | } |
| 627: | return sprintf('%s %s', round($size, 2), $label); |
| 628: | }} |
| 629: | |
| 630: | |
| 631: | |
| 632: | |
| 633: | |
| 634: | |
| 635: | |
| 636: | |
| 637: | |
| 638: | |
| 639: | |
| 640: | if (!hm_exists('format_msg_part_section')) { |
| 641: | function format_msg_part_section($struct, $output_mod, $part, $dl_link, $at_link, $level=0) { |
| 642: | $res = ''; |
| 643: | $simple_view = $output_mod->get('simple_msg_part_view', false); |
| 644: | $use_icons = $output_mod->get('use_message_part_icons', false); |
| 645: | $mobile = $output_mod->get('is_mobile'); |
| 646: | if ($mobile) { |
| 647: | $simple_view = true; |
| 648: | } |
| 649: | |
| 650: | if(!$simple_view){ |
| 651: | foreach ($struct as $id => $vals) { |
| 652: | if (is_array($vals) && isset($vals['type'])) { |
| 653: | $row = format_msg_part_row($id, $vals, $output_mod, $level, $part, $dl_link, $at_link, $use_icons, $simple_view, $mobile); |
| 654: | if (!$row) { |
| 655: | $level--; |
| 656: | } |
| 657: | $res .= $row; |
| 658: | if (isset($vals['subs'])) { |
| 659: | $res .= format_msg_part_section($vals['subs'], $output_mod, $part, $dl_link, $at_link, ($level + 1)); |
| 660: | } |
| 661: | } |
| 662: | else { |
| 663: | if (is_array($vals) && count($vals) == 1 && isset($vals['subs'])) { |
| 664: | $res .= format_msg_part_section($vals['subs'], $output_mod, $part, $dl_link, $at_link, $level); |
| 665: | } |
| 666: | } |
| 667: | } |
| 668: | }else{ |
| 669: | $res = format_attachment($struct, $output_mod, $part, $dl_link, $at_link); |
| 670: | } |
| 671: | return $res; |
| 672: | }} |
| 673: | |
| 674: | function format_attachment($struct, $output_mod, $part, $dl_args, $at_args) { |
| 675: | $res = ''; |
| 676: | |
| 677: | foreach ($struct as $id => $vals) { |
| 678: | if(is_array($vals) && isset($vals['type']) && $vals['type'] != 'multipart' && isset($vals['file_attributes']) && !empty($vals['file_attributes'])) { |
| 679: | $size = get_imap_size($vals); |
| 680: | $desc = get_part_desc($vals, $id, $part); |
| 681: | |
| 682: | $res .= '<tr><td class="part_desc" colspan="4">'.$output_mod->html_safe(decode_fld($desc)).'</td>'; |
| 683: | $res .= '</td><td class="part_size">'.$output_mod->html_safe($size).'</td>'; |
| 684: | |
| 685: | $res .= '<td class="download_link"><a href="#" data-src="?'.$dl_args.'&imap_msg_part='.$output_mod->html_safe($id).'">'.$output_mod->trans('Download').'</a></td>'; |
| 686: | if ($output_mod->get('allow_delete_attachment') && isset($vals['file_attributes']['attachment'])) { |
| 687: | $res .= '<td><a href="?'.$at_args.'&imap_msg_part='.$output_mod->html_safe($id).'" class="remove_attachment">'.$output_mod->trans('Remove').'</a></td></tr>'; |
| 688: | } |
| 689: | } |
| 690: | |
| 691: | if(is_array($vals) && isset($vals['subs'])) { |
| 692: | $sub_res = format_attachment($vals['subs'], $output_mod, $part, $dl_args, $at_args); |
| 693: | $res =$sub_res; |
| 694: | } |
| 695: | } |
| 696: | |
| 697: | return $res; |
| 698: | } |
| 699: | |
| 700: | |
| 701: | |
| 702: | |
| 703: | |
| 704: | |
| 705: | |
| 706: | |
| 707: | |
| 708: | if (!hm_exists('format_attached_image_section')) { |
| 709: | function format_attached_image_section($struct, $output_mod, $dl_link) { |
| 710: | $res = ''; |
| 711: | $isThereAnyImg = false; |
| 712: | foreach ($struct as $id => $vals) { |
| 713: | if ($vals['type'] === 'image') { |
| 714: | $res .= '<div class="col-6 col-md-3"> |
| 715: | <img class="attached_image img-fluid" |
| 716: | src="?' . $dl_link . '&imap_msg_part=' . $output_mod->html_safe($id) . '" > |
| 717: | </div>'; |
| 718: | $isThereAnyImg = true; |
| 719: | } |
| 720: | if (isset($vals['subs'])) { |
| 721: | $res .= format_attached_image_section($vals['subs'], $output_mod, $dl_link); |
| 722: | } |
| 723: | } |
| 724: | |
| 725: | if ($isThereAnyImg) { |
| 726: | $res = '<div class="container-fluid"><div class="row text-center attached_image_box">' . $res . '</div></div>'; |
| 727: | } |
| 728: | |
| 729: | return $res; |
| 730: | }} |
| 731: | |
| 732: | |
| 733: | |
| 734: | |
| 735: | |
| 736: | |
| 737: | if (!hm_exists('filter_message_part')) { |
| 738: | function filter_message_part($vals) { |
| 739: | if (array_key_exists('disposition', $vals) && is_array($vals['disposition']) && array_key_exists('inline', $vals['disposition'])) { |
| 740: | return true; |
| 741: | } |
| 742: | if (array_key_exists('type', $vals) && $vals['type'] == 'multipart') { |
| 743: | return true; |
| 744: | } |
| 745: | return false; |
| 746: | }} |
| 747: | |
| 748: | |
| 749: | |
| 750: | |
| 751: | |
| 752: | |
| 753: | |
| 754: | |
| 755: | if (!hm_exists('sort_by_internal_date')) { |
| 756: | function sort_by_internal_date($a, $b) { |
| 757: | if ($a['internal_date'] == $b['internal_date']) return 0; |
| 758: | return (strtotime($a['internal_date']) < strtotime($b['internal_date']))? -1 : 1; |
| 759: | }} |
| 760: | |
| 761: | |
| 762: | |
| 763: | |
| 764: | |
| 765: | |
| 766: | |
| 767: | |
| 768: | |
| 769: | |
| 770: | |
| 771: | |
| 772: | |
| 773: | |
| 774: | if (!hm_exists('merge_imap_search_results')) { |
| 775: | function merge_imap_search_results($ids, $search_type, $session, $hm_cache, $folders = array('INBOX'), $limit=0, $terms=array(), $sent=false) { |
| 776: | $msg_list = array(); |
| 777: | $connection_failed = false; |
| 778: | $sent_results = array(); |
| 779: | $status = array(); |
| 780: | foreach($ids as $index => $id) { |
| 781: | $mailbox = Hm_IMAP_List::get_connected_mailbox($id, $hm_cache); |
| 782: | if ($mailbox && $mailbox->authed()) { |
| 783: | $server_details = Hm_IMAP_List::dump($id); |
| 784: | $folder = $folders[$index]; |
| 785: | if ($sent) { |
| 786: | $sent_folder = $mailbox->get_special_use_mailboxes('sent'); |
| 787: | if (array_key_exists('sent', $sent_folder)) { |
| 788: | list($sent_status, $sent_results) = merge_imap_search_results($ids, $search_type, $session, $hm_cache, array($sent_folder['sent']), $limit, $terms, false); |
| 789: | $status = array_merge($status, $sent_status); |
| 790: | } |
| 791: | if ($folder == 'SPECIAL_USE_CHECK') { |
| 792: | continue; |
| 793: | } |
| 794: | } |
| 795: | if (!empty($terms)) { |
| 796: | foreach ($terms as $term) { |
| 797: | if (preg_match('/(?:[^\x00-\x7F])/', $term[1]) === 1) { |
| 798: | $mailbox->set_search_charset('UTF-8'); |
| 799: | break; |
| 800: | } |
| 801: | } |
| 802: | if ($sent) { |
| 803: | $msgs = $mailbox->search($folder, $search_type, $terms, null, null, true, false, true); |
| 804: | } |
| 805: | else { |
| 806: | $msgs = $mailbox->search($folder, $search_type, $terms); |
| 807: | } |
| 808: | } |
| 809: | else { |
| 810: | $msgs = $mailbox->search($folder, $search_type); |
| 811: | } |
| 812: | if ($msgs) { |
| 813: | if ($limit) { |
| 814: | rsort($msgs); |
| 815: | $msgs = array_slice($msgs, 0, $limit); |
| 816: | } |
| 817: | foreach ($mailbox->get_message_list($folder, $msgs) as $msg) { |
| 818: | if (array_key_exists('content-type', $msg) && mb_stristr($msg['content-type'], 'multipart/mixed')) { |
| 819: | $msg['flags'] .= ' \Attachment'; |
| 820: | } |
| 821: | if (mb_stristr($msg['flags'], 'deleted')) { |
| 822: | continue; |
| 823: | } |
| 824: | $msg['server_id'] = $id; |
| 825: | $msg['folder'] = bin2hex($folder); |
| 826: | $msg['server_name'] = $server_details['name']; |
| 827: | $msg_list[] = $msg; |
| 828: | } |
| 829: | } |
| 830: | $status['imap_'.$id.'_'.bin2hex($folder)] = $mailbox->get_folder_state(); |
| 831: | } |
| 832: | else { |
| 833: | $connection_failed = true; |
| 834: | } |
| 835: | } |
| 836: | $session->set('imap_folder_status', $status); |
| 837: | if ($connection_failed && empty($msg_list)) { |
| 838: | return array(array(), false); |
| 839: | } |
| 840: | if (count($sent_results) > 0) { |
| 841: | $msg_list = array_merge($msg_list, $sent_results); |
| 842: | } |
| 843: | |
| 844: | usort($msg_list, function($a, $b) { |
| 845: | return strtotime($b['internal_date']) - strtotime($a['internal_date']); |
| 846: | }); |
| 847: | |
| 848: | return array($status, $msg_list); |
| 849: | }} |
| 850: | |
| 851: | |
| 852: | |
| 853: | |
| 854: | |
| 855: | |
| 856: | |
| 857: | |
| 858: | |
| 859: | if (!hm_exists('add_attached_images')) { |
| 860: | function add_attached_images($txt, $uid, $struct, $imap) { |
| 861: | if (preg_match_all("/src=('|\"|)cid:([^\s'\"]+)/", $txt, $matches)) { |
| 862: | $cids = array_pop($matches); |
| 863: | foreach ($cids as $id) { |
| 864: | $part = $imap->search_bodystructure($struct, array('id' => $id, 'type' => 'image'), true); |
| 865: | $part_ids = array_keys($part); |
| 866: | $part_id = array_pop($part_ids); |
| 867: | $img = $imap->get_message_content($uid, $part_id, false, $part[$part_id]); |
| 868: | $txt = str_replace('cid:'.$id, 'data:image/'.$part[$part_id]['subtype'].';base64,'.base64_encode($img), $txt); |
| 869: | } |
| 870: | } |
| 871: | return $txt; |
| 872: | }} |
| 873: | |
| 874: | |
| 875: | |
| 876: | |
| 877: | |
| 878: | |
| 879: | |
| 880: | |
| 881: | if (!hm_exists('imap_refresh_oauth2_token')) { |
| 882: | function imap_refresh_oauth2_token($server, $config) { |
| 883: | if ((int) $server['expiration'] <= time()) { |
| 884: | $oauth2_data = get_oauth2_data($config); |
| 885: | $details = array(); |
| 886: | if ($server['server'] == 'imap.gmail.com') { |
| 887: | $details = $oauth2_data['gmail']; |
| 888: | } |
| 889: | elseif ($server['server'] == 'imap-mail.outlook.com') { |
| 890: | $details = $oauth2_data['outlook']; |
| 891: | } |
| 892: | elseif ($server['server'] == 'imap-mail.office365.com') { |
| 893: | $details = $oauth2_data['office365']; |
| 894: | } |
| 895: | if (!empty($details)) { |
| 896: | $oauth2 = new Hm_Oauth2($details['client_id'], $details['client_secret'], $details['client_uri']); |
| 897: | $result = $oauth2->refresh_token($details['refresh_uri'], $server['refresh_token']); |
| 898: | if (array_key_exists('access_token', $result)) { |
| 899: | return array(strtotime(sprintf('+%d seconds', $result['expires_in'])), $result['access_token']); |
| 900: | } |
| 901: | } |
| 902: | } |
| 903: | return array(); |
| 904: | }} |
| 905: | |
| 906: | |
| 907: | |
| 908: | |
| 909: | |
| 910: | |
| 911: | |
| 912: | |
| 913: | |
| 914: | |
| 915: | if (!hm_exists('imap_move_same_server')) { |
| 916: | function imap_move_same_server($ids, $action, $hm_cache, $dest_path, $screen_emails=false) { |
| 917: | $moved = []; |
| 918: | $responses = []; |
| 919: | $keys = array_keys($ids); |
| 920: | $server_id = array_pop($keys); |
| 921: | $mailbox = Hm_IMAP_List::get_connected_mailbox($server_id, $hm_cache); |
| 922: | if ($mailbox && $mailbox->authed()) { |
| 923: | foreach ($ids[$server_id] as $folder => $msgs) { |
| 924: | if ($screen_emails) { |
| 925: | foreach ($msgs as $msg) { |
| 926: | $moved[] = sprintf('imap_%s_%s_%s', $server_id, $msg, $folder); |
| 927: | $email = current(array_column(process_address_fld($mailbox->get_message_headers(hex2bin($folder), $msg)['From']), "email")); |
| 928: | $uids = $mailbox->search(hex2bin($folder), 'ALL', array(array('FROM', $email))); |
| 929: | foreach ($uids as $uid) { |
| 930: | $result = $mailbox->message_action(hex2bin($folder), mb_strtoupper($action), $uid, hex2bin($dest_path[2])); |
| 931: | if ($result['status']) { |
| 932: | $response = $result['responses'][0]; |
| 933: | $responses[] = [ |
| 934: | 'oldUid' => $uid, |
| 935: | 'newUid' => $response['newUid'], |
| 936: | 'oldFolder' => hex2bin($folder), |
| 937: | 'newFolder' => hex2bin($dest_path[2]), |
| 938: | 'oldServer' => $server_id, |
| 939: | ]; |
| 940: | $moved[] = sprintf('imap_%s_%s_%s', $server_id, $uid, $folder); |
| 941: | } |
| 942: | } |
| 943: | } |
| 944: | } else { |
| 945: | $result = $mailbox->message_action(hex2bin($folder), mb_strtoupper($action), $msgs, hex2bin($dest_path[2])); |
| 946: | if ($result['status']) { |
| 947: | foreach ($msgs as $index => $msg) { |
| 948: | $response = $result['responses'][$index]; |
| 949: | $moved[] = sprintf('imap_%s_%s_%s', $server_id, $msg, $folder); |
| 950: | $responses[] = [ |
| 951: | 'oldUid' => $msg, |
| 952: | 'newUid' => $response['newUid'], |
| 953: | 'oldFolder' => hex2bin($folder), |
| 954: | 'newFolder' => hex2bin($dest_path[2]), |
| 955: | 'oldServer' => $server_id, |
| 956: | ]; |
| 957: | } |
| 958: | } |
| 959: | } |
| 960: | |
| 961: | } |
| 962: | } |
| 963: | return ['moved' => $moved, 'responses' => $responses]; |
| 964: | }} |
| 965: | |
| 966: | |
| 967: | |
| 968: | |
| 969: | |
| 970: | |
| 971: | |
| 972: | |
| 973: | |
| 974: | |
| 975: | if (!hm_exists('imap_move_different_server')) { |
| 976: | function imap_move_different_server($ids, $action, $dest_path, $hm_cache) { |
| 977: | $moved = []; |
| 978: | $responses = []; |
| 979: | $dest_mailbox = Hm_IMAP_List::get_connected_mailbox($dest_path[1], $hm_cache); |
| 980: | if ($dest_mailbox && $dest_mailbox->authed()) { |
| 981: | foreach ($ids as $server_id => $folders) { |
| 982: | $mailbox = Hm_IMAP_List::get_connected_mailbox($server_id, $hm_cache); |
| 983: | if ($mailbox && $mailbox->authed()) { |
| 984: | foreach ($folders as $folder => $msg_ids) { |
| 985: | foreach ($msg_ids as $msg_id) { |
| 986: | $detail = $mailbox->get_message_list(hex2bin($folder), array($msg_id)); |
| 987: | if (array_key_exists($msg_id, $detail)) { |
| 988: | if (mb_stristr($detail[$msg_id]['flags'], 'seen')) { |
| 989: | $seen = true; |
| 990: | } |
| 991: | else { |
| 992: | $seen = false; |
| 993: | } |
| 994: | } |
| 995: | $msg = $mailbox->get_message_content(hex2bin($folder), $msg_id); |
| 996: | $msg = str_replace("\r\n", "\n", $msg); |
| 997: | $msg = str_replace("\n", "\r\n", $msg); |
| 998: | $msg = rtrim($msg)."\r\n"; |
| 999: | if (!$seen) { |
| 1000: | $mailbox->message_action(hex2bin($folder), 'UNREAD', array($msg_id)); |
| 1001: | } |
| 1002: | if ($uid = $dest_mailbox->store_message(hex2bin($dest_path[2]), $msg, $seen)) { |
| 1003: | if ($action == 'move') { |
| 1004: | $deleteResult = $mailbox->message_action(hex2bin($folder), 'DELETE', array($msg_id)); |
| 1005: | if ($deleteResult['status']) { |
| 1006: | $mailbox->message_action(hex2bin($folder), 'EXPUNGE', array($msg_id)); |
| 1007: | } |
| 1008: | } |
| 1009: | $moved[] = sprintf('imap_%s_%s_%s', $server_id, $msg_id, $folder); |
| 1010: | $responses[] = [ |
| 1011: | 'oldUid' => $msg_id, |
| 1012: | 'newUid' => $uid, |
| 1013: | 'oldFolder' => hex2bin($folder), |
| 1014: | 'newFolder' => hex2bin($dest_path[2]), |
| 1015: | 'oldServer' => $server_id, |
| 1016: | 'newServer' => $dest_path[1], |
| 1017: | ]; |
| 1018: | } |
| 1019: | } |
| 1020: | } |
| 1021: | } |
| 1022: | } |
| 1023: | } |
| 1024: | return ['moved' => $moved, 'responses' => $responses]; |
| 1025: | }} |
| 1026: | |
| 1027: | |
| 1028: | |
| 1029: | |
| 1030: | |
| 1031: | |
| 1032: | |
| 1033: | if (!hm_exists('process_move_to_arguments')) { |
| 1034: | function process_move_to_arguments($form) { |
| 1035: | $msg_ids = explode(',', $form['imap_move_ids']); |
| 1036: | $same_server_ids = array(); |
| 1037: | $other_server_ids = array(); |
| 1038: | $dest_path = explode('_', $form['imap_move_to']); |
| 1039: | if (count($dest_path) == 3 && $dest_path[0] == 'imap' && in_array($form['imap_move_action'], array('move', 'copy'), true)) { |
| 1040: | foreach ($msg_ids as $msg_id) { |
| 1041: | $path = explode('_', $msg_id); |
| 1042: | if (count($path) == 4 && $path[0] == 'imap') { |
| 1043: | if (sprintf('%s_%s', $path[0], $path[1]) == sprintf('%s_%s', $dest_path[0], $dest_path[1])) { |
| 1044: | $same_server_ids[$path[1]][$path[3]][] = $path[2]; |
| 1045: | } |
| 1046: | else { |
| 1047: | $other_server_ids[$path[1]][$path[3]][] = $path[2]; |
| 1048: | } |
| 1049: | } |
| 1050: | } |
| 1051: | } |
| 1052: | return array($msg_ids, $dest_path, $same_server_ids, $other_server_ids); |
| 1053: | }} |
| 1054: | |
| 1055: | |
| 1056: | |
| 1057: | |
| 1058: | |
| 1059: | |
| 1060: | |
| 1061: | |
| 1062: | |
| 1063: | if (!hm_exists('get_imap_mime_extension')) { |
| 1064: | function get_imap_mime_extension($type, $subtype) { |
| 1065: | $extension = $subtype; |
| 1066: | if ($type == 'multipart' || ($type == 'message' && $subtype == 'rfc822')) { |
| 1067: | $extension = 'eml'; |
| 1068: | } |
| 1069: | if ($type == 'text') { |
| 1070: | switch ($subtype) { |
| 1071: | case 'plain': |
| 1072: | $extension = 'txt'; |
| 1073: | break; |
| 1074: | case 'richtext': |
| 1075: | $extension = 'rtf'; |
| 1076: | break; |
| 1077: | } |
| 1078: | } |
| 1079: | return '.'.$extension; |
| 1080: | }} |
| 1081: | |
| 1082: | |
| 1083: | |
| 1084: | |
| 1085: | |
| 1086: | |
| 1087: | |
| 1088: | |
| 1089: | |
| 1090: | |
| 1091: | if (!hm_exists('get_imap_part_name')) { |
| 1092: | function get_imap_part_name($struct, $uid, $part_id, $no_default=false) { |
| 1093: | $extension = get_imap_mime_extension(mb_strtolower($struct['type']), mb_strtolower($struct['subtype'])); |
| 1094: | if (array_key_exists('file_attributes', $struct) && is_array($struct['file_attributes']) && |
| 1095: | array_key_exists('attachment', $struct['file_attributes']) && is_array($struct['file_attributes']['attachment'])) { |
| 1096: | for ($i=0;$i<count($struct['file_attributes']['attachment']);$i++) { |
| 1097: | if (mb_strtolower(trim($struct['file_attributes']['attachment'][$i])) == 'filename') { |
| 1098: | if (array_key_exists(($i+1), $struct['file_attributes']['attachment'])) { |
| 1099: | return trim($struct['file_attributes']['attachment'][($i+1)]); |
| 1100: | } |
| 1101: | } |
| 1102: | } |
| 1103: | } |
| 1104: | |
| 1105: | if (array_key_exists('disposition', $struct) && is_array($struct['disposition']) && array_key_exists('attachment', $struct['disposition']) && is_array($struct['disposition']['attachment'])) { |
| 1106: | for ($i=0;$i<count($struct['disposition']['attachment']);$i++) { |
| 1107: | if (mb_strtolower(trim($struct['disposition']['attachment'][$i])) == 'filename') { |
| 1108: | if (array_key_exists(($i+1), $struct['disposition']['attachment'])) { |
| 1109: | return trim($struct['disposition']['attachment'][($i+1)]); |
| 1110: | } |
| 1111: | } |
| 1112: | } |
| 1113: | } |
| 1114: | |
| 1115: | if (array_key_exists('attributes', $struct) && is_array($struct['attributes']) && array_key_exists('name', $struct['attributes'])) { |
| 1116: | return trim($struct['attributes']['name']); |
| 1117: | } |
| 1118: | if (array_key_exists('description', $struct) && trim($struct['description'])) { |
| 1119: | return trim(str_replace(array("\n", ' '), '_', $struct['description'])).$extension; |
| 1120: | } |
| 1121: | if (array_key_exists('name', $struct) && trim($struct['name'])) { |
| 1122: | return trim($struct['name']); |
| 1123: | } |
| 1124: | if ($no_default) { |
| 1125: | return ''; |
| 1126: | } |
| 1127: | return 'message_'.$uid.'_part_'.$part_id.$extension; |
| 1128: | }} |
| 1129: | |
| 1130: | |
| 1131: | |
| 1132: | |
| 1133: | if (!hm_exists('clear_existing_reply_details')) { |
| 1134: | function clear_existing_reply_details($session) { |
| 1135: | $msgs = array(); |
| 1136: | $max = 20; |
| 1137: | foreach ($session->dump() as $name => $val) { |
| 1138: | if (mb_substr($name, 0, 19) == 'reply_details_imap_') { |
| 1139: | $msgs[$name] = $val['ts']; |
| 1140: | } |
| 1141: | } |
| 1142: | arsort($msgs, SORT_NUMERIC); |
| 1143: | if (count($msgs) <= $max) { |
| 1144: | return ; |
| 1145: | } |
| 1146: | foreach (array_slice($msgs, $max) as $name) { |
| 1147: | $session->del($name); |
| 1148: | } |
| 1149: | }} |
| 1150: | |
| 1151: | |
| 1152: | |
| 1153: | |
| 1154: | if (!hm_exists('process_sort_arg')) { |
| 1155: | function process_sort_arg($sort, $default = 'arrival') { |
| 1156: | if (!$sort) { |
| 1157: | $default = mb_strtoupper($default); |
| 1158: | return array($default, true); |
| 1159: | } |
| 1160: | $rev = false; |
| 1161: | if (mb_substr($sort, 0, 1) == '-') { |
| 1162: | $rev = true; |
| 1163: | $sort = mb_substr($sort, 1); |
| 1164: | } |
| 1165: | $sort = mb_strtoupper($sort); |
| 1166: | if ($sort == 'ARRIVAL' || $sort == 'DATE') { |
| 1167: | $rev = $rev ? false : true; |
| 1168: | } |
| 1169: | return array($sort, $rev); |
| 1170: | }} |
| 1171: | |
| 1172: | |
| 1173: | |
| 1174: | |
| 1175: | if (!hm_exists('search_since_based_on_setting')) { |
| 1176: | function search_since_based_on_setting($config) { |
| 1177: | if ($config->get('default_sort_order_setting', 'arrival') === 'arrival') { |
| 1178: | return 'SINCE'; |
| 1179: | } else { |
| 1180: | return 'SENTSINCE'; |
| 1181: | } |
| 1182: | }} |
| 1183: | |
| 1184: | |
| 1185: | |
| 1186: | |
| 1187: | |
| 1188: | if (!hm_exists('imap_server_type')) { |
| 1189: | function imap_server_type($id) { |
| 1190: | $type = 'IMAP'; |
| 1191: | $details = Hm_IMAP_List::dump($id); |
| 1192: | if (is_array($details) && array_key_exists('type', $details)) { |
| 1193: | $type = mb_strtoupper($details['type']); |
| 1194: | } |
| 1195: | return $type; |
| 1196: | }} |
| 1197: | |
| 1198: | |
| 1199: | |
| 1200: | |
| 1201: | if (!hm_exists('get_list_headers')) { |
| 1202: | function get_list_headers($headers) { |
| 1203: | $res = array(); |
| 1204: | $list_headers = array('list-archive', 'list-unsubscribe', |
| 1205: | 'list-subscribe', 'list-archive', 'list-post', 'list-help'); |
| 1206: | foreach (lc_headers($headers) as $name => $val) { |
| 1207: | if (in_array($name, $list_headers, true)) { |
| 1208: | $res[mb_substr($name, 5)] = process_list_fld($val); |
| 1209: | } |
| 1210: | } |
| 1211: | return $res; |
| 1212: | }} |
| 1213: | |
| 1214: | |
| 1215: | |
| 1216: | |
| 1217: | if (!hm_exists('process_list_fld')) { |
| 1218: | function process_list_fld($fld) { |
| 1219: | $res = array('links' => array(), 'email' => array(), 'values' => array()); |
| 1220: | $fld = is_array($fld) ? implode(" ", $fld) : $fld; |
| 1221: | foreach (explode(',', $fld) as $val) { |
| 1222: | $val = trim(str_replace(array('<', '>'), '', $val)); |
| 1223: | if (preg_match("/^http/", $val)) { |
| 1224: | $res['links'][] = $val; |
| 1225: | } |
| 1226: | elseif (preg_match("/^mailto/", $val)) { |
| 1227: | $res['email'][] = mb_substr($val, 7); |
| 1228: | } |
| 1229: | else { |
| 1230: | $res['values'][] = $val; |
| 1231: | } |
| 1232: | } |
| 1233: | return $res; |
| 1234: | }} |
| 1235: | |
| 1236: | |
| 1237: | |
| 1238: | |
| 1239: | if (!hm_exists('format_imap_envelope')) { |
| 1240: | function format_imap_envelope($env, $mod) { |
| 1241: | $env = lc_headers($env); |
| 1242: | $res = '<div class="imap_envelope d-flex flex-column border-bottom border-2 border-secondary-subtle pb-3 mb-3">'; |
| 1243: | |
| 1244: | |
| 1245: | if (array_key_exists('subject', $env) && trim($env['subject'])) { |
| 1246: | $res .= '<div class="header_subject d-flex justify-content-center"><h5 class="text-center mb-0 fw-bold">'.$mod->html_safe($env['subject']).'</h5></div>'; |
| 1247: | } |
| 1248: | |
| 1249: | |
| 1250: | foreach ($env as $name => $val) { |
| 1251: | if (in_array($name, array('date', 'from', 'to', 'message-id'), true)) { |
| 1252: | $res .= '<div class="d-flex align-items-center py-1"><span class="fw-semibold me-2 text-nowrap">'.$mod->html_safe(ucfirst($name)).':</span><span class="text-break">'.$mod->html_safe($val).'</span></div>'; |
| 1253: | } |
| 1254: | } |
| 1255: | $res .= '</div>'; |
| 1256: | return $res; |
| 1257: | }} |
| 1258: | |
| 1259: | |
| 1260: | |
| 1261: | |
| 1262: | if (!hm_exists('format_list_headers')) { |
| 1263: | function format_list_headers($mod) { |
| 1264: | $res = '<div class="row g-0 py-1 small_header">'; |
| 1265: | $res .= '<div class="col-md-2 col-12"><span class="text-muted">'.$mod->trans('List').'</span></div>'; |
| 1266: | $res .= '<div class="col-md-10 col-12">'; |
| 1267: | $sections = array(); |
| 1268: | foreach ($mod->get('list_headers') as $name => $vals) { |
| 1269: | if (count($vals['email']) > 0 || count($vals['links']) > 0) { |
| 1270: | $sources = array(); |
| 1271: | $section = '<div><p class="mb-1">'.$mod->html_safe($name).':</p>'; |
| 1272: | foreach ($vals['email'] as $v) { |
| 1273: | $sources[] = '<a href="?page=compose&compose_to='.urlencode($mod->html_safe($v)). |
| 1274: | '&compose_from='.$mod->get('msg_headers')['Delivered-To']. |
| 1275: | '" class="text-decoration-none">'.$mod->trans('email').'</a>'; |
| 1276: | } |
| 1277: | foreach ($vals['links'] as $v) { |
| 1278: | $sources[] = '<a href="'.$mod->html_safe($v).'" class="text-decoration-none">'.$mod->trans('link').'</a>'; |
| 1279: | } |
| 1280: | $section .= implode(', ', $sources).'</div>'; |
| 1281: | $sections[] = $section; |
| 1282: | } |
| 1283: | } |
| 1284: | $res .= implode(' | ', $sections).'</div></div>'; |
| 1285: | return $res; |
| 1286: | }} |
| 1287: | |
| 1288: | |
| 1289: | |
| 1290: | |
| 1291: | if (!hm_exists('decode_folder_str')) { |
| 1292: | function decode_folder_str($folder) { |
| 1293: | $folder_name = false; |
| 1294: | $parts = explode('_', $folder, 3); |
| 1295: | if (count($parts) == 3) { |
| 1296: | $folder_name = hex2bin($parts[2]); |
| 1297: | } |
| 1298: | return $folder_name; |
| 1299: | }} |
| 1300: | |
| 1301: | |
| 1302: | |
| 1303: | |
| 1304: | if (!hm_exists('prep_folder_name')) { |
| 1305: | function prep_folder_name($imap, $folder, $decode_folder=false, $parent=false) { |
| 1306: | if ($parent && $decode_folder) { |
| 1307: | $parent = decode_folder_str($parent); |
| 1308: | } |
| 1309: | if ($decode_folder) { |
| 1310: | $folder = decode_folder_str($folder); |
| 1311: | } |
| 1312: | $ns = get_personal_ns($imap); |
| 1313: | if (!$folder) { |
| 1314: | return false; |
| 1315: | } |
| 1316: | if ($parent && !$ns['delim']) { |
| 1317: | return false; |
| 1318: | } |
| 1319: | if ($parent) { |
| 1320: | $folder = sprintf('%s%s%s', $parent, $ns['delim'], $folder); |
| 1321: | } |
| 1322: | if ($folder && $ns['prefix'] && mb_substr($folder, 0, mb_strlen($ns['prefix'])) !== $ns['prefix']) { |
| 1323: | $folder = sprintf('%s%s', $ns['prefix'], $folder); |
| 1324: | } |
| 1325: | return $folder; |
| 1326: | }} |
| 1327: | |
| 1328: | |
| 1329: | |
| 1330: | |
| 1331: | if (!hm_exists('get_personal_ns')) { |
| 1332: | function get_personal_ns($imap) { |
| 1333: | $namespaces = $imap->get_namespaces(); |
| 1334: | foreach ($namespaces as $ns) { |
| 1335: | if ($ns['class'] == 'personal') { |
| 1336: | return $ns; |
| 1337: | } |
| 1338: | } |
| 1339: | return array( |
| 1340: | 'prefix' => false, |
| 1341: | 'delim'=> false |
| 1342: | ); |
| 1343: | }} |
| 1344: | |
| 1345: | |
| 1346: | |
| 1347: | |
| 1348: | if (!hm_exists('get_request_params')) { |
| 1349: | function get_request_params($request) { |
| 1350: | $server_id = NULL; |
| 1351: | $uid = NULL; |
| 1352: | $folder = NULL; |
| 1353: | $msg_id = NULL; |
| 1354: | |
| 1355: | if (array_key_exists('uid', $request) && $request['uid']) { |
| 1356: | $uid = $request['uid']; |
| 1357: | } |
| 1358: | if (array_key_exists('list_path', $request) && preg_match("/^imap_(\w+)_(.+)/", $request['list_path'], $matches)) { |
| 1359: | $server_id = $matches[1]; |
| 1360: | $folder = hex2bin($matches[2]); |
| 1361: | } |
| 1362: | if (array_key_exists('imap_msg_part', $request) && preg_match("/^[0-9\.]+$/", $request['imap_msg_part'])) { |
| 1363: | $msg_id = preg_replace("/^0.{1}/", '', $request['imap_msg_part']); |
| 1364: | } |
| 1365: | |
| 1366: | return [$server_id, $uid, $folder, $msg_id]; |
| 1367: | }} |
| 1368: | |
| 1369: | if (!hm_exists('snooze_message')) { |
| 1370: | function snooze_message($mailbox, $msg_id, $folder, $snooze_tag) { |
| 1371: | if (!$snooze_tag) { |
| 1372: | $mailbox->message_action($folder, 'UNREAD', array($msg_id)); |
| 1373: | } |
| 1374: | $msg = $mailbox->get_message_content($folder, $msg_id); |
| 1375: | preg_match("/^X-Snoozed:.*(\r?\n[ \t]+.*)*\r?\n?/im", $msg, $matches); |
| 1376: | if (count($matches)) { |
| 1377: | $msg = str_replace($matches[0], '', $msg); |
| 1378: | $old_folder = parse_delayed_header($matches[0], 'X-Snoozed')['from']; |
| 1379: | } |
| 1380: | if ($snooze_tag) { |
| 1381: | $from = $old_folder ?? $folder; |
| 1382: | $msg = "$snooze_tag;\n \tfrom $from\n".$msg; |
| 1383: | } |
| 1384: | $msg = str_replace("\r\n", "\n", $msg); |
| 1385: | $msg = str_replace("\n", "\r\n", $msg); |
| 1386: | $msg = rtrim($msg)."\r\n"; |
| 1387: | |
| 1388: | $res = false; |
| 1389: | $snooze_folder = 'Snoozed'; |
| 1390: | if ($snooze_tag) { |
| 1391: | $status = $mailbox->get_folder_status($snooze_folder); |
| 1392: | if (! count($status)) { |
| 1393: | $snooze_folder = $mailbox->create_folder($snooze_folder); |
| 1394: | } else { |
| 1395: | $snooze_folder = $status['id']; |
| 1396: | } |
| 1397: | if ($mailbox->store_message($snooze_folder, $msg)) { |
| 1398: | $deleteResult = $mailbox->message_action($folder, 'DELETE', array($msg_id)); |
| 1399: | if ($deleteResult['status']) { |
| 1400: | $mailbox->message_action($folder, 'EXPUNGE', array($msg_id)); |
| 1401: | $res = true; |
| 1402: | } |
| 1403: | } |
| 1404: | } else { |
| 1405: | $snooze_headers = parse_delayed_header($matches[0], 'X-Snoozed'); |
| 1406: | $original_folder = $snooze_headers['from']; |
| 1407: | if ($mailbox->store_message($original_folder, $msg)) { |
| 1408: | $deleteResult = $mailbox->message_action($snooze_folder, 'DELETE', array($msg_id)); |
| 1409: | if ($deleteResult['status']) { |
| 1410: | $mailbox->message_action($snooze_folder, 'EXPUNGE', array($msg_id)); |
| 1411: | $res = true; |
| 1412: | } |
| 1413: | } |
| 1414: | } |
| 1415: | return $res; |
| 1416: | }} |
| 1417: | |
| 1418: | |
| 1419: | |
| 1420: | |
| 1421: | if (!hm_exists('parse_snooze_header')) { |
| 1422: | function parse_snooze_header($snooze_header) |
| 1423: | { |
| 1424: | $snooze_header = str_replace('X-Snoozed: ', '', $snooze_header); |
| 1425: | $result = []; |
| 1426: | foreach (explode(';', $snooze_header) as $kv) |
| 1427: | { |
| 1428: | $kv = trim($kv); |
| 1429: | $spacePos = mb_strpos($kv, ' '); |
| 1430: | if ($spacePos > 0) { |
| 1431: | $result[rtrim(mb_substr($kv, 0, $spacePos), ':')] = trim(mb_substr($kv, $spacePos+1)); |
| 1432: | } else { |
| 1433: | $result[$kv] = true; |
| 1434: | } |
| 1435: | } |
| 1436: | return $result; |
| 1437: | }} |
| 1438: | |
| 1439: | |
| 1440: | |
| 1441: | |
| 1442: | if (!hm_exists('get_snooze_date')) { |
| 1443: | function get_snooze_date($format, $only_label = false) { |
| 1444: | if ($format == 'later_in_day') { |
| 1445: | $date_string = 'today 18:00'; |
| 1446: | $label = 'Later in the day'; |
| 1447: | } elseif ($format == 'tomorrow') { |
| 1448: | $date_string = '+1 day 08:00'; |
| 1449: | $label = 'Tomorrow'; |
| 1450: | } elseif ($format == 'next_weekend') { |
| 1451: | $date_string = 'next Saturday 08:00'; |
| 1452: | $label = 'Next weekend'; |
| 1453: | } elseif ($format == 'next_week') { |
| 1454: | $date_string = 'next week 08:00'; |
| 1455: | $label = 'Next week'; |
| 1456: | } elseif ($format == 'next_month') { |
| 1457: | $date_string = 'next month 08:00'; |
| 1458: | $label = 'Next month'; |
| 1459: | } else { |
| 1460: | $date_string = $format; |
| 1461: | $label = 'Certain date'; |
| 1462: | } |
| 1463: | $time = strtotime($date_string); |
| 1464: | if ($only_label) { |
| 1465: | return [$label, date('D, H:i', $time)]; |
| 1466: | } |
| 1467: | return date('D, d M Y H:i', $time); |
| 1468: | }} |
| 1469: | |
| 1470: | |
| 1471: | |
| 1472: | |
| 1473: | if (!hm_exists('snooze_formats')) { |
| 1474: | function snooze_formats() { |
| 1475: | $values = array( |
| 1476: | 'tomorrow', |
| 1477: | 'next_weekend', |
| 1478: | 'next_week', |
| 1479: | 'next_month' |
| 1480: | ); |
| 1481: | if (date('H') <= 16) { |
| 1482: | array_push($values, 'later_in_day'); |
| 1483: | } |
| 1484: | return $values; |
| 1485: | }} |
| 1486: | |
| 1487: | |
| 1488: | |
| 1489: | |
| 1490: | if (!hm_exists('snooze_dropdown')) { |
| 1491: | function snooze_dropdown($output, $unsnooze = false) { |
| 1492: | $values = nexter_formats(); |
| 1493: | |
| 1494: | $txt = '<div class="dropdown d-inline-block"> |
| 1495: | <a class="hlink text-decoration-none btn btn-sm btn-outline-secondary dropdown-toggle" id="dropdownMenuSnooze" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="true" data-bs-auto-close="outside">'.$output->trans('Snooze').'</a> |
| 1496: | <ul class="dropdown-menu" aria-labelledby="dropdownMenuSnooze">'; |
| 1497: | foreach ($values as $format) { |
| 1498: | $labels = get_scheduled_date($format, true); |
| 1499: | $txt .= '<li><a href="#" class="nexter_date_helper_snooze dropdown-item gap-5" data-value="'.$format.'"><span>'.$output->trans($labels[0]).'</span> <span class="text-end">'.$labels[1].'</span></a></li>'; |
| 1500: | } |
| 1501: | $txt .= '<li><hr class="dropdown-divider"></li>'; |
| 1502: | $txt .= '<li><label for="nexter_input_date_snooze" class="nexter_date_picker_snooze dropdown-item cursor-pointer">'.$output->trans('Pick a date').'</label>'; |
| 1503: | $txt .= '<input id="nexter_input_date_snooze" type="datetime-local" min="'.date('Y-m-d\Th:m').'" class="nexter_input_date_snooze" style="visibility: hidden; position: absolute; height: 0;">'; |
| 1504: | $txt .= '<input class="nexter_input_snooze" style="display:none;"></li>'; |
| 1505: | if ($unsnooze) { |
| 1506: | $txt .= '<a href="#" data-value="unsnooze" class="unsnooze nexter_date_helper_snooze dropdown-item"">'.$output->trans('Unsnooze').'</a>'; |
| 1507: | } |
| 1508: | $txt .= '</ul></div>'; |
| 1509: | |
| 1510: | return $txt; |
| 1511: | }} |
| 1512: | |
| 1513: | if (!hm_exists('tags_dropdown')) { |
| 1514: | function tags_dropdown($context, $headers) { |
| 1515: | $folders = $context->get('tags', array()); |
| 1516: | $txt = '<div class="dropdown d-inline-block"> |
| 1517: | <a class="hlink text-decoration-none btn btn-sm btn-outline-secondary dropdown-toggle" id="dropdownMenuTag" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="true">'.$context->trans('Tags').'</a> |
| 1518: | <ul class="dropdown-menu" aria-labelledby="dropdownMenuTag">'; |
| 1519: | |
| 1520: | $tags = !empty($headers['X-Cypht-Tags']) ? explode(',', $headers['X-Cypht-Tags']) : array(); |
| 1521: | foreach ($folders as $folder) { |
| 1522: | $tag = $folder['name']; |
| 1523: | $is_checked = in_array($folder['id'], array_map('trim', $tags)); |
| 1524: | $txt .= '<li class="d-flex dropdown-item gap-2">'; |
| 1525: | $txt .= '<input class="form-check-input me-1 label-checkbox" type="checkbox" value="" aria-label="..." data-id="'.$folder['id'].'" '.($is_checked ? 'checked' : '').'>'; |
| 1526: | $txt .= '<span>'.$context->trans($tag).'</span>'; |
| 1527: | $txt .= '</li>'; |
| 1528: | } |
| 1529: | $txt .= '</ul></div>'; |
| 1530: | |
| 1531: | return $txt; |
| 1532: | }} |
| 1533: | |
| 1534: | |
| 1535: | |
| 1536: | |
| 1537: | if (!hm_exists('forward_dropdown')) { |
| 1538: | function forward_dropdown($output,$reply_args) { |
| 1539: | $txt = '<div class="dropdown d-inline-block"> |
| 1540: | <button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" id="dropdownMenuForward" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="true">'.$output->trans('Forward').'</button> |
| 1541: | <ul class="dropdown-menu" aria-labelledby="dropdownMenuForward">'; |
| 1542: | $txt .= '<li><a href="?page=compose&forward_as_attachment=1'.$reply_args.'" class="forward_link hlink dropdown-item d-flex justify-content-between gap-5 text-decoration-none" ><span>'.$output->trans('Forward as message attachment').'</a></li>'; |
| 1543: | $txt .= '<li><a href="?page=compose&forward=1'.$reply_args.'" class="forward_link hlink dropdown-item d-flex justify-content-between gap-5 text-decoration-none"><span>'.$output->trans('Edit as new message').'</a></li>'; |
| 1544: | $txt .= '</ul></div>'; |
| 1545: | return $txt; |
| 1546: | } |
| 1547: | } |
| 1548: | |
| 1549: | if (!hm_exists('connect_to_imap_server')) { |
| 1550: | function connect_to_imap_server($address, $name, $port, $user, $pass, $tls, $imap_sieve_host, $enableSieve, $type, $context, $hidden = false, $server_id = false, $sieve_tls = false, $show_errors = true) { |
| 1551: | $imap_list = array( |
| 1552: | 'name' => $name, |
| 1553: | 'server' => $address, |
| 1554: | 'type' => $type, |
| 1555: | 'hide' => $hidden, |
| 1556: | 'port' => $port, |
| 1557: | 'user' => $user, |
| 1558: | 'tls' => $tls); |
| 1559: | |
| 1560: | if (!$server_id || ($server_id && $pass)) { |
| 1561: | $imap_list['pass'] = $pass; |
| 1562: | } |
| 1563: | |
| 1564: | if ($type === 'jmap') { |
| 1565: | $imap_list['port'] = false; |
| 1566: | $imap_list['tls'] = false; |
| 1567: | } |
| 1568: | |
| 1569: | if ($enableSieve && $imap_sieve_host) { |
| 1570: | $imap_list['sieve_config_host'] = $imap_sieve_host; |
| 1571: | $imap_list['sieve_tls'] = $sieve_tls; |
| 1572: | } |
| 1573: | if ($server_id) { |
| 1574: | if (Hm_IMAP_List::edit($server_id, $imap_list)) { |
| 1575: | $imap_server_id = $server_id; |
| 1576: | } else { |
| 1577: | return; |
| 1578: | } |
| 1579: | } else { |
| 1580: | $imap_server_id = Hm_IMAP_List::add($imap_list); |
| 1581: | if ($type != 'ews' && ! can_save_last_added_server('Hm_IMAP_List', $user)) { |
| 1582: | return; |
| 1583: | } |
| 1584: | } |
| 1585: | |
| 1586: | $server = Hm_IMAP_List::get($imap_server_id, true); |
| 1587: | |
| 1588: | if ($enableSieve && |
| 1589: | $imap_sieve_host && |
| 1590: | $context->module_is_supported('sievefilters') && |
| 1591: | $context->user_config->get('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) { |
| 1592: | try { |
| 1593: | |
| 1594: | include_once APP_PATH.'modules/sievefilters/hm-sieve.php'; |
| 1595: | $sieveClientFactory = new Hm_Sieve_Client_Factory(); |
| 1596: | $client = $sieveClientFactory->init(null, $server, $context->module_is_supported('nux')); |
| 1597: | |
| 1598: | if (!$client && $show_errors) { |
| 1599: | Hm_Msgs::add("Failed to authenticate to the Sieve host", "warning"); |
| 1600: | } |
| 1601: | } catch (Exception $e) { |
| 1602: | if ($show_errors) { |
| 1603: | Hm_Msgs::add("Failed to authenticate to the Sieve host", "warning"); |
| 1604: | } |
| 1605: | if (! $server_id) { |
| 1606: | Hm_IMAP_List::del($imap_server_id); |
| 1607: | } |
| 1608: | return; |
| 1609: | } |
| 1610: | } |
| 1611: | |
| 1612: | $mailbox = Hm_IMAP_List::connect($imap_server_id, false); |
| 1613: | |
| 1614: | if ($mailbox->authed()) { |
| 1615: | return $imap_server_id; |
| 1616: | } else { |
| 1617: | Hm_IMAP_List::del($imap_server_id); |
| 1618: | if ($show_errors) { |
| 1619: | Hm_Msgs::add('Authentication failed', 'warning'); |
| 1620: | } |
| 1621: | return null; |
| 1622: | } |
| 1623: | } |
| 1624: | } |
| 1625: | |
| 1626: | if (!hm_exists('save_sent_msg')) { |
| 1627: | function save_sent_msg($handler, $imap_id, $mailbox, $imap_details, $msg, $msg_id, $show_errors = true) { |
| 1628: | $specials = get_special_folders($handler, $imap_id); |
| 1629: | $sent_folder = false; |
| 1630: | if (array_key_exists('sent', $specials) && $specials['sent']) { |
| 1631: | $sent_folder = $specials['sent']; |
| 1632: | } |
| 1633: | |
| 1634: | if (!$sent_folder) { |
| 1635: | $auto_sent = $mailbox->get_special_use_mailboxes('sent'); |
| 1636: | if (!array_key_exists('sent', $auto_sent)) { |
| 1637: | return; |
| 1638: | } |
| 1639: | $sent_folder = $auto_sent['sent']; |
| 1640: | } |
| 1641: | if (!$sent_folder) { |
| 1642: | Hm_Debug::add(sprintf("Unable to save sent message, no sent folder for server %s %s", $mailbox->server_type(), $imap_details['server'])); |
| 1643: | } |
| 1644: | $uid = null; |
| 1645: | if ($sent_folder) { |
| 1646: | Hm_Debug::add(sprintf("Attempting to save sent message for server %s in folder %s", $mailbox->server_type(), $imap_details['server'], $sent_folder)); |
| 1647: | $uid = $mailbox->store_message($sent_folder, $msg); |
| 1648: | if (! $uid) { |
| 1649: | Hm_Msgs::add('ERRAn error occurred saving the sent message'); |
| 1650: | } |
| 1651: | } |
| 1652: | return [$uid, $sent_folder]; |
| 1653: | }} |
| 1654: | |
| 1655: | if (!hm_exists('is_imap_archive_folder')) { |
| 1656: | function is_imap_archive_folder($server_id, $user_config, $current_folder) { |
| 1657: | $special_folders = $user_config->get('special_imap_folders', array()); |
| 1658: | |
| 1659: | if (isset($special_folders[$server_id]['archive'])) { |
| 1660: | $archive_folder = $special_folders[$server_id]['archive']; |
| 1661: | if (bin2hex($archive_folder) == $current_folder) { |
| 1662: | return true; |
| 1663: | } |
| 1664: | } |
| 1665: | |
| 1666: | return false; |
| 1667: | }} |
| 1668: | |