True, 'get_info_msg' => True, 'get_info_msgs' => True, 'get_folders_list' => True, 'import_msgs' => True, 'report_mail_error' => True, 'msgs_to_archive' => True ); var $ldap; var $mbox; var $mboxFolder; var $imap_port; var $has_cid; var $imap_options = ''; var $functions; var $prefs; var $foldersLimit; var $imap_sentfolder; var $rawMessage; var $folders; var $cache = false; var $useCache = false; var $expirationCache = false; function imap_functions (){ $this->init(); } function init(){ $this->foldersLimit = $_SESSION['phpgw_info']['user']['preferences']['expressoMail']['imap_max_folders'] ? $_SESSION['phpgw_info']['user']['preferences']['expressoMail']['imap_max_folders'] : 20000; //Limit of folders (mailboxes) user can see $this->username = $_SESSION['phpgw_info']['expressomail']['user']['userid']; $this->password = $_SESSION['phpgw_info']['expressomail']['user']['passwd']; $this->imap_server = $_SESSION['phpgw_info']['expressomail']['email_server']['imapServer']; $this->imap_port = $_SESSION['phpgw_info']['expressomail']['email_server']['imapPort']; $this->imap_delimiter = $_SESSION['phpgw_info']['expressomail']['email_server']['imapDelimiter']; $this->functions = new functions(); $this->imap_sentfolder = $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSentFolder'] ? $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSentFolder'] : str_replace("*","", $this->functions->getLang("Sent")); $this->has_cid = false; $this->prefs = $_SESSION['phpgw_info']['user']['preferences']['expressoMail']; //armazena os caminhos das pastas ( sent, spam, drafts, trash ) $this->folders['sent'] = empty($_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSentFolder']) ? 'Sent' : $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSentFolder']; //Variavel folders armazena o caminho /sent $this->folders['spam'] = empty($_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSpamFolder']) ? 'Spam' : $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSpamFolder']; $this->folders['drafts'] = empty($_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultDraftsFolder']) ? 'Drafts' : $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultDraftsFolder']; $this->folders['trash'] = empty($_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultTrashFolder']) ? 'Trash' : $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultTrashFolder']; if(isset($_SESSION['phpgw_info']['expresso']['expressoMail']['expressoMail_enable_memcache']) && $_SESSION['phpgw_info']['expresso']['expressoMail']['expressoMail_enable_memcache'] === 'true') $this->useCache = true; if(isset($_SESSION['phpgw_info']['expresso']['expressoMail']['expressoMail_time_memcache']) && trim($_SESSION['phpgw_info']['expresso']['expressoMail']['expressoMail_time_memcache']) != '') $this->expirationCache = $_SESSION['phpgw_info']['expresso']['expressoMail']['expressoMail_time_memcache']; if ($_SESSION['phpgw_info']['expressomail']['email_server']['imapTLSEncryption'] == 'yes') $this->imap_options = '/tls/novalidate-cert'; else $this->imap_options = '/notls/novalidate-cert'; } function mount_url_folder($folders){ return implode($this->imap_delimiter,$folders); } // BEGIN of functions. function open_mbox( $folder = false, $force_die = true) { $newFolder = mb_convert_encoding($folder, 'UTF7-IMAP','UTF-8, ISO-8859-1, UTF7-IMAP'); if($newFolder === $this->mboxFolder && is_resource( $this->mbox )) return $this->mbox; $this->mboxFolder = $newFolder; $url = '{'.$this->imap_server.":".$this->imap_port.$this->imap_options.'}'.$this->mboxFolder; if (is_resource($this->mbox)) if ($force_die) imap_reopen($this->mbox, $url ) or die(serialize(array('imap_error' => $this->parse_error(imap_last_error())))); else imap_reopen($this->mbox, $url ); else if($force_die) $this->mbox = imap_open( $url , $this->username, $this->password) or die(serialize(array('imap_error' => $this->parse_error(imap_last_error())))); else $this->mbox = imap_open( $url , $this->username, $this->password); return $this->mbox; } /** * Move as pastas que vieram do resultado de um Drag & Drop da arvore de pastas do Expresso Mail * * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Gustavo Pereira dos Santos Stabelini * @param array $params Contem dois indices : um contem o caminho atual da pasta, e o outro contem o caminho futuro da pasta * @return boolean * @access public */ function move_folder($params){ //preg_match( '/[a-zA-Z0-9]+$/',$params['folder_to_move'], $new_folder); $old_folder = mb_convert_encoding($params['folder_to_move'], 'UTF7-IMAP','UTF-8, ISO-8859-1, UTF7-IMAP'); $new_folder = explode($this->imap_delimiter, $old_folder ); $to_folder = mb_convert_encoding($params['folder_to'], 'UTF7-IMAP','UTF-8, ISO-8859-1, UTF7-IMAP'); $mbox = imap_open('{'.$this->imap_server.":".$this->imap_port.$this->imap_options.'}'.$new_folder[0], $this->username, $this->password); $result = true; if(!imap_renamemailbox($mbox, '{'.$this->imap_server.":".$this->imap_port.$this->imap_options.'}'.$old_folder, '{'.$this->imap_server.":".$this->imap_port.$this->imap_options.'}'.$to_folder.$this->imap_delimiter.$new_folder[count($new_folder)-1])){ $result = false; } imap_close($mbox); return $result; } function parse_error($error, $field = ''){ // This error is returned from Imap. if(strstr($error,'Connection refused')) { return str_replace("%1", $this->functions->getLang("Mail"), $this->functions->getLang("Connection failed with %1 Server. Try later.")); } else if(strstr($error,'virus')) { return str_replace("%1", $this->functions->getLang("Mail"), $this->functions->getLang("Your message was rejected by antivirus. Perhaps your attachment has been infected.")); } else if(strstr($error,'Failed to add recipient:')) { preg_match_all('/:\s([\s\.";@!a-z0-9]+)\s\[SMTP:/', $error, $res); return str_replace("%1", $res['1']['0'], $this->functions->getLang("SMTP Error: The following recipient addresses failed: %1")); } else if(strstr($error,'Recipient address rejected')) { return str_replace("%1", $this->functions->getLang("Mail"), $this->functions->getLang("Invalid recipients in the message").'.'); } else if(strstr($error,'Invalid Mail:')) { return str_replace("%1", $field, $this->functions->getLang("The recipients addresses failed %1")); } else if(strstr($error,'Message file too big')) { return ($this->functions->getLang("Message file too big.")); } // This condition verifies if SESSION is expired. else if(!count($_SESSION)) return "nosession"; return $error; } function get_range_msgs3($params){ $return = $this->get_range_msgs2($params); $return['folder'] = mb_convert_encoding( $return['folder'], 'ISO-8859-1', 'UTF-8' ); return $return; } function get_range_msgs2($params) { include_once dirname(__FILE__).'/../../prototype/api/controller.php'; // Free others requests session_write_close(); $folder = $params['folder']; $msg_range_begin = $params['msg_range_begin']; $msg_range_end = $params['msg_range_end']; $sort_box_type = isset($params['sort_box_type']) ? $params['sort_box_type'] : ''; $sort_box_reverse = isset($params['sort_box_reverse']) ? $params['sort_box_reverse'] : ''; $search_box_type = (isset($params['search_box_type']) && $params['search_box_type'] != 'ALL' && $params['search_box_type'] != '' )? $params['search_box_type'] : false; if( !$this->mbox || !is_resource( $this->mbox ) ) $this->mbox = $this->open_mbox($folder); $return = array(); $return['folder'] = $folder; //Para enviar o offset entre o timezone definido pelo usuário e GMT $return['offsetToGMT'] = $this->functions->CalculateDateOffset(); if(!$search_box_type || $search_box_type == 'UNSEEN' || $search_box_type == 'SEEN') { $msgs_info = imap_status($this->mbox,"{".$this->imap_server.":".$this->imap_port.$this->imap_options."}".mb_convert_encoding( $folder, 'UTF7-IMAP', 'UTF-8, ISO-8859-1' ) ,SA_ALL); $return['tot_unseen'] = ($search_box_type == 'SEEN') ? 0 : $msgs_info->unseen; $sort_array_msg = $this->get_msgs($folder, $sort_box_type, $search_box_type, $sort_box_reverse,$msg_range_begin,$msg_range_end); $num_msgs = ($search_box_type=="UNSEEN") ? $msgs_info->unseen : (($search_box_type=="SEEN") ? ($msgs_info->messages - $msgs_info->unseen) : $msgs_info->messages); $i = 0; if(is_array($sort_array_msg)){ foreach($sort_array_msg as $msg_number => $value) { $sample = false; if( (isset($this->prefs['preview_msg_subject']) && ($this->prefs['preview_msg_subject'] === '1')) || (isset($this->prefs['preview_msg_tip'] ) && ($this->prefs['preview_msg_tip'] === '1')) ) $sample = true; $return[$i] = $this->get_info_head_msg( $msg_number , $sample ); $i++; } $filter = array('AND', array('=', 'folderName', $folder), array('IN','messageNumber', $sort_array_msg)); $followupflagged = Controller::find( array('concept' => 'followupflagged'), false, array('filter' => $filter, 'criteria' => array('deepness' => '2')) ); $labeleds = Controller::find( array('concept' => 'labeled'), false, array('filter' => $filter, 'criteria' => array('deepness' => '2')) ); for($i=0; $i 'followupflag', 'id' => $followupflagged[$ii]['followupflagId'] )); $return[$i]['followupflagged'] = $followupflagged[$ii]; $return[$i]['followupflagged']['followupflag'] = $followupflag; break; } } $numLabels = count($labeleds); for($ii=0; $ii<$numLabels; $ii++){ if($return[$i]['msg_number'] == $labeleds[$ii]['messageNumber']){ $labels = Controller::read( array( 'concept' => 'label', 'id' => $labeleds[$ii]['labelId'])); $return[$i]['labels'][$labeleds[$ii]['labelId']] = $labels; } } } } $return['num_msgs'] = $num_msgs; } else { $num_msgs = imap_num_msg($this->mbox); $sort_array_msg = $this-> get_msgs($folder, $sort_box_type, $search_box_type, $sort_box_reverse,$msg_range_begin,$num_msgs); $return['tot_unseen'] = 0; $i = 0; if(is_array($sort_array_msg)){ foreach($sort_array_msg as $msg_number => $value) { $temp = $this->get_info_head_msg($msg_number); if(!$temp) return false; if($temp['Unseen'] == 'U' || $temp['Recent'] == 'N'){ $return['tot_unseen']++; } if($i <= ($msg_range_end-$msg_range_begin)) $return[$i] = $temp; $i++; } } $return['num_msgs'] = count($sort_array_msg)+($msg_range_begin-1); } return $return; } function getMessages($params) { $result = array(); $exporteml = new ExportEml(); $unseen_msgs = array(); foreach($params['messages'] as $folder => $messages) { foreach($messages as $msg_number) { $this->mbox = $this->open_mbox($folder); if (isset($params['details']) && $params['details'] == 'all') { $message = $this->get_info_msg(array('msg_number' => $msg_number, 'msg_folder' =>urlencode($folder))); } else { $message['headers'] = $this->get_info_head_msg($msg_number, true); //$message['attachments'] = $exporteml->get_attachments_in_array(array("num_msg" => $msg_number)); } imap_close($this->mbox); $this->mbox = false; if($msg_info['Unseen'] == "U" || $msg_info['Recent'] == "N") { array_push($unseen_msgs,$msg_number); } $result[$folder][] = $message; } if($unseen_msgs){ $msgs_list = implode(",",$unseen_msgs); $array_msgs = array('folder' => $folder, "msgs_to_set" => $msgs_list, "flag" => "unseen"); $this->set_messages_flag($array_msgs); } } return $result; } /** * Decodifica uma string no formato mime RFC2047 * * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Cristiano Corrêa Schmidt * @param string $string string no formato mime RFC2047 * @return string * @access public */ static function decodeMimeString( $string ) { $string = preg_replace('/\?\=(\s)*\=\?/', '?==?', $string); return preg_replace_callback( '/\=\?([^\?]*)\?([qb])\?([^\?]*)\?=/i' ,array( 'self' , 'decodeMimeStringCallback'), $string); } /** * Decodifica os tokens encontrados na função decodeMimeString * * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Cristiano Corrêa Schmidt * @param array $mathes array retornado pelo preg_replace_callback da função decodeMimeString * @return string * @access public */ static function decodeMimeStringCallback( $mathes ) { $str = (strtolower($mathes[2]) == 'q') ? quoted_printable_decode(str_replace('_','=20',$mathes[3])) : base64_decode( $mathes[3]) ; return ( strtoupper($mathes[1]) == 'UTF-8' ) ? mb_convert_encoding( $str , 'ISO-8859-1' , 'UTF-8') : $str; } /** * Formata um mailObject para um array com name e email * * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Cristiano Corrêa Schmidt * @return bool * @access public */ static function formatMailObject( $obj ) { $return = array(); $return['email'] = self::decodeMimeString($obj->mailbox) . ((isset( $obj->host) && ($obj->host != 'unspecified-domain' || $obj->host != '.SYNTAX-ERROR.') )? '@'. $obj->host : ''); $return['name'] = ( isset( $obj->personal ) && trim($obj->personal) !== '' ) ? self::decodeMimeString($obj->personal) : $return['email']; return $return; } /** * Retorna informações do cabeçario da mensagem e um preview caso appendSample = true * Utiliza memCache caso esta preferencia esteja ativada. * * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Cristiano Corrêa Schmidt * @return bool * @access public */ function get_info_head_msg( $msg_number , $appendSample = false ) { $return = false; $cached = false; if( $this->useCache === true ) { if( $this->cache === false ) { $this->cache = ServiceLocator::getService( 'memCache' ); //Serviço Cache $this->cache->connect( $_SESSION['phpgw_info']['expressomail']['server']['server_memcache'] , $_SESSION['phpgw_info']['expressomail']['server']['port_server_memcache'] ); } if( $return = $this->cache->get( 'infoHead://'.$this->username.'://'.$this->mboxFolder.'://'.$msg_number )) $cached = true; } $header = imap_headerinfo($this->mbox, imap_msgno( $this->mbox , $msg_number )); //Resgata o objeto Header da mensagem , nescessario mesmo com o cache pois as flags podem ser atualizadas por outro cliente de email $return['Recent'] = $header->Recent; $return['Unseen'] = $header->Unseen; $return['Deleted'] = $header->Deleted; $return['Flagged'] = $header->Flagged; if($header->Answered =='A' && $header->Draft == 'X') $return['Forwarded'] = 'F'; else { $return['Answered'] = $header->Answered; $return['Draft'] = $header->Draft; } if( $cached === true ) //Caso a mensagem ja tenha vindo do cache da o return { if($appendSample !== false && !isset($return['msg_sample'])) //verifica o msg_sample caso seja alterada a preferencia e não esteja em cache carregar { $return['msg_sample'] = $this->get_msg_sample($msg_number); $this->cache->set( 'infoHead://'.$this->username.'://'.$this->mboxFolder.'://'.$msg_number , $return , $this->expirationCache); } return $return; } $importance = array(); $mimeHeader = imap_fetchheader( $this->mbox, $msg_number , FT_UID ); //Resgata o Mime Header da mensagem $mimeBody = imap_body( $this->mbox, $msg_number , FT_UID|FT_PEEK ); //Resgata o Mime Body da mensagem sem marcar como lida $offsetToGMT = $this->functions->CalculateDateOffset(); $return['ContentType'] = $this->getMessageType( $msg_number , $mimeHeader , $mimeBody ); $return['Importance'] = ( preg_match('/importance *: *(.*)\r/i', $mimeHeader , $importance) === 0 ) ? 'Normal' : $importance[1]; $return['msg_number'] = $msg_number; $return['udate'] = $header->udate; $return['offsetToGMT'] = $offsetToGMT; $return['timestamp'] = $header->udate + $return['offsetToGMT']; $return['smalldate'] = (date('d/m/Y') == gmdate( 'd/m/Y', $return['timestamp'] )) ? gmdate("H:i", $return['timestamp'] ) : gmdate("d/m/Y", $return['timestamp'] ); $return['Size'] = $header->Size; $return['from'] = (isset( $header->from[0] )) ? self::formatMailObject( $header->from[0] ) : array( 'name' => '' , 'email' => ''); $return['subject'] = ( isset($header->subject) && trim($header->subject) !== '' ) ? self::decodeMimeString($header->subject) : $this->functions->getLang('(no subject) '); $return['attachment'] = ( preg_match('/((Content-Disposition:(.)*([\r\n\s]*filename))|(Content-Type:(.)*([\r\n\s]*name)))/i', $mimeBody) ) ? '1' : '0'; //Verifica se a anexos na mensagem $return['reply_toaddress'] = isset($header->reply_toaddress) ? self::decodeMimeString($header->reply_toaddress) : ''; $return['flag'] = $header->Unseen.$header->Recent.$header->Flagged.$header->Draft.$header->Answered.$header->Deleted.( $return['attachment'] === '1' ? 'T': '' ); if (!empty($header->to)){ foreach ($header->to as $i => $v){ $return['to'][$i] = self::formatMailObject( $v ); } } else if (!empty($header->cc)){ foreach ($header->cc as $i => $v){ $return['to'][$i] = self::formatMailObject( $v ); } } else if (!empty($header->bcc)){ foreach ($header->bcc as $i => $v){ $return['to'][$i] = self::formatMailObject( $v ); } } else $return['to'] = array( 'name' => '' , 'email' => ''); if (!empty($return['to'])){ foreach ($return['to'] as $i => $v){ if($v['name'] == 'undisclosed-recipients@' || $v['name'] == '@') $return['to'][$i] = $return['from']; } } if($appendSample !== false) $return['msg_sample'] = $this->get_msg_sample($msg_number); if( $this->useCache === true ) $this->cache->set( 'infoHead://'.$this->username.'://'.$this->mboxFolder.'://'.$msg_number , $return , $this->expirationCache); return $return; } /** * * @license http://www.gnu.org/copyleft/gpl.html GPL * @param string $string String a ser decodificada * @return string * @todo Verificar a possibilidade de se utilizar a função iconv_mime_decode, que é capaz de identificar a codificação por si só, mas que pode ser interpretada de forma diversa dependendo da implementação do sistema * @todo Executar testes suficientes para validar a funçao iconv_mime_decode em substituição à este método decode_string */ function decode_string($string) { $return = ''; $decoded = ''; if ((strpos(strtolower($string), '=?iso-8859-1') !== false) || (strpos(strtolower($string), '=?windows-1252') !== false)) { $tmp = imap_mime_header_decode($string); foreach ($tmp as $tmp1) { $return .= $this->htmlspecialchars_encode($tmp1->text); } return str_replace("\t", "", $return); } else if (strpos(strtolower($string), '=?utf-8') !== false) { $elements = imap_mime_header_decode($string); for($i = 0;$i < count($elements);$i++) { $charset = strtolower($elements[$i]->charset); $text = $elements[$i]->text; if(!strcasecmp($charset, "utf-8") || !strcasecmp($charset, "utf-7")) $decoded .= $this->functions->utf8_to_ncr($text); else { if( strcasecmp($charset,"default") ) $decoded .= $this->htmlspecialchars_encode(iconv($charset, "iso-8859-1", $text)); else $decoded .= $this->htmlspecialchars_encode($text); } } return str_replace("\t", "", $decoded); } else if(strpos(strtolower($string), '=?us-ascii') !== false) { $retun = ''; $tmp = imap_mime_header_decode($string); foreach ($tmp as $tmp1) $return .= $this->htmlspecialchars_encode(quoted_printable_decode($tmp1->text)); return str_replace("\t", "", $return); } else if( strpos( $string , '=?' ) !== false ) return $this->htmlspecialchars_encode(iconv_mime_decode( $string )); return $this->htmlspecialchars_encode($string); } /** * Função que importa arquivos .eml exportados pelo expresso para a caixa do usuário. Testado apenas * com .emls gerados pelo expresso, e o arquivo pode ser um zip contendo vários emls ou um .eml. */ function import_msgs($params) { if(!$this->mbox) $this->mbox = $this->open_mbox(); if( preg_match('/local_/',$params["folder"]) ){ // PLEASE, BE CAREFULL!!! YOU SHOULD USE EMAIL CONFIGURATION VALUES (EMAILADMIN MODULE) //$tmp_box = mb_convert_encoding('INBOX'.$this->folders['trash'].$this->imap_delimiter.'tmpMoveToLocal', "UTF7-IMAP", "UTF-8"); $tmp_box = mb_convert_encoding($this->mount_url_folder(array("INBOX",$this->folders['trash'],"tmpMoveToLocal")), "UTF7-IMAP", "UTF-8"); if ( ! imap_createmailbox( $this->mbox,"{".$this -> imap_server."}$tmp_box" ) ) return $this->functions->getLang( 'Import to Local : fail...' ); imap_reopen($this->mbox, "{".$this->imap_server.":".$this->imap_port.$this->imap_options."}".$tmp_box); $params["folder"] = $tmp_box; } $errors = array(); $invalid_format = false; $filename = $params['FILES'][0]['name']; $params["folder"] = mb_convert_encoding($params["folder"], "UTF7-IMAP","ISO-8859-1, UTF-8"); $quota = imap_get_quotaroot($this->mbox, $params["folder"]); if((($quota['limit'] - $quota['usage'])*1024) <= $params['FILES'][0]['size']){ return array( 'error' => $this->functions->getLang("fail in import:"). " ".$this->functions->getLang("Over quota")); } if(substr($filename,strlen($filename)-4)==".zip") { $zip = zip_open($params['FILES'][0]['tmp_name']); if ($zip) { while ($zip_entry = zip_read($zip)) { if (zip_entry_open($zip, $zip_entry, "r")) { $email = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); $status = @imap_append($this->mbox, "{".$this->imap_server.":".$this->imap_port.$this->imap_options."}".$params["folder"], $email ); if(!$status) array_push($errors,zip_entry_name($zip_entry)); zip_entry_close($zip_entry); } } zip_close($zip); } if (isset( $tmp_box ) && ! sizeof( $errors )){ $mc = imap_check($this->mbox); $result = imap_fetch_overview( $this -> mbox, "1:{$mc -> Nmsgs}", 0 ); $ids = array( ); foreach ($result as $overview) $ids[ ] = $overview -> uid; return implode( ',', $ids ); } }else if(substr($filename,strlen($filename)-4)==".eml") { $email = implode("",file($params['FILES'][0]['tmp_name'])); $status = imap_append($this->mbox,"{".$this->imap_server.":".$this->imap_port.$this->imap_options."}".$params["folder"],$email); if(!$status) return "Error importing"; if ( isset( $tmp_box ) && ! sizeof( $errors ) ) { $mc = imap_check($this->mbox); $result = imap_fetch_overview( $this -> mbox, "1:{$mc -> Nmsgs}", 0 ); $ids = array( ); foreach ($result as $overview) $ids[ ] = $overview -> uid; return implode( ',', $ids ); } } else{ if ( isset( $tmp_box ) ) imap_deletemailbox( $this->mbox,"{".$this -> imap_server."}$tmp_box" ); return array("error" => $this->functions->getLang("wrong file format")); $invalid_format = true; } if(!$invalid_format) { if(count($errors)>0) { $message = $this->functions->getLang("fail in import:")."\n"; foreach($errors as $arquivo) { $message.=$arquivo."\n"; } return array("error" => $message); } else return $this->functions->getLang("The import was executed successfully."); } } /* Remove os anexos de uma mensagem. A estratégia para isso é criar uma mensagem nova sem os anexos, mantendo apenas a primeira parte do e-mail, que é o texto, sem anexos. O método considera que o email é multpart. */ function remove_attachments($params) { include_once("class.message_components.inc.php"); if(!$this->mbox || !is_resource($this->mbox)) $this->mbox = $this->open_mbox($params["folder"]); $return["status"] = true; $header = ""; $headertemp = explode("\n",imap_fetchheader($this->mbox, imap_msgno($this->mbox, $params["msg_num"]))); foreach($headertemp as $head) {//Se eu colocar todo o header do email dá pau no append, então procuro apenas o que interessa. $head1 = explode(":",$head); if ( (strtoupper($head1[0]) == "TO") || (strtoupper($head1[0]) == "FROM") || (strtoupper($head1[0]) == "SUBJECT") || (strtoupper($head1[0]) == "DATE") ) $header .= $head."\r\n"; } $msg = new message_components($this->mbox); $msg->fetch_structure($params["msg_num"]);/* O fetchbody tava trazendo o email com problemas na acentuação. Então uso essa classe para verificar a codificação e o charset, para que o método decodeBody do expresso possa trazer tudo certinho*/ $all_body_type = strtolower($msg->file_type[$params["msg_num"]][0]); $all_body_encoding = $msg->encoding[$params["msg_num"]][0]; $all_body_charset = $msg->charset[$params["msg_num"]][0]; if($all_body_type=='multipart/alternative') { if(strtolower($msg->file_type[$params["msg_num"]][2]=='text/html') && $msg->pid[$params["msg_num"]][2] == '1.2') { $body_part_to_show = '1.2'; $all_body_type = strtolower($msg->file_type[$params["msg_num"]][2]); $all_body_encoding = $msg->encoding[$params["msg_num"]][2]; $all_body_charset = $msg->charset[$params["msg_num"]][2]; } else { $body_part_to_show = '1.1'; $all_body_type = strtolower($msg->file_type[$params["msg_num"]][1]); $all_body_encoding = $msg->encoding[$params["msg_num"]][1]; $all_body_charset = $msg->charset[$params["msg_num"]][1]; } } else $body_part_to_show = '1'; $status = imap_append($this->mbox, "{".$this->imap_server.":".$this->imap_port.$this->imap_options."}".$params["folder"], $header. "Content-Type: ".$all_body_type."; charset = \"".$all_body_charset."\"". "\r\n". "Content-Transfer-Encoding: ".$all_body_encoding. "\r\n". "\r\n". str_replace("\n","\r\n",preg_replace("/]+\>/i", " ", $this->decodeBody( imap_fetchbody($this->mbox,imap_msgno($this->mbox, $params["msg_num"]),$body_part_to_show), $all_body_encoding, $all_body_charset )) ), "\\Seen"); //Append do novo email, só com header e conteúdo sem anexos. //Remove imagens do corpo, pois estas estão na lista de anexo e serão removidas. if(!$status) { $return["status"] = false; $return["msg"] = lang("error appending mail on delete attachments"); } else { $status = imap_status($this->mbox, "{".$this->imap_server.":".$this->imap_port."}".$params['folder'], SA_UIDNEXT); $return['msg_no'] = $status->uidnext - 1; imap_delete($this->mbox, imap_msgno($this->mbox, $params["msg_num"])); imap_expunge($this->mbox); } return $return; } function msgs_to_archive($params) { $folder = $params['folder']; $all_ids = $this-> get_msgs($folder, 'SORTARRIVAL', false, 0,-1,-1); $messages_not_to_copy = explode(",",$params['mails']); $ids = array(); $cont = 0; foreach($all_ids as $each_id=>$value) { if(!in_array($each_id,$messages_not_to_copy)) { array_push($ids,$each_id); $cont++; } if($cont>=100) break; } if (empty($ids)) return array(); $params = array("folder"=>$folder,"msgs_number"=>implode(",",$ids)); return $this->get_info_msgs($params); } /** * * @return * @param $params Object */ function get_info_msgs($params) { include_once("class.exporteml.inc.php"); if(array_key_exists('messages', $params)){ $sel_msgs = explode(",", $params['messages']); @reset($sel_msgs); $sorted_msgs = array(); foreach($sel_msgs as $idx => $sel_msg) { $sel_msg = explode(";", $sel_msg); if(array_key_exists($sel_msg[0], $sorted_msgs)){ $sorted_msgs[$sel_msg[0]] .= ",".$sel_msg[1]; } else { $sorted_msgs[$sel_msg[0]] = $sel_msg[1]; } } unset($sorted_msgs['']); $return = array(); $array_names_keys = array_keys($sorted_msgs); for($i = 0; $i < count($sorted_msgs); $i++){ $new_params = array(); $attach_params = array(); $new_params["msg_folder"]= $array_names_keys[$i]; $attach_params["folder"] = $params["folder"]; $msgs = explode(",",$sorted_msgs[$array_names_keys[$i]]); $exporteml = new ExportEml(); $unseen_msgs = array(); foreach($msgs as $msg_number) { $new_params["msg_number"] = $msg_number; //ini_set("display_errors","1"); $msg_info = $this->get_info_msg($new_params); $this->mbox = $this->open_mbox($array_names_keys[$i]); //Não sei porque, mas se não abrir de novo a caixa dá erro. $msg_info['header'] = $this->get_info_head_msg($msg_number); $attach_params["num_msg"] = $msg_number; $msg_info['array_attach'] = $exporteml->get_attachments_in_array($attach_params); imap_close($this->mbox); $this->mbox=false; array_push($return,serialize($msg_info)); if($msg_info['Unseen'] == "U" || $msg_info['Recent'] == "N"){ array_push($unseen_msgs,$msg_number); } } } if($unseen_msgs){ $msgs_list = implode(",",$unseen_msgs); $array_msgs = array('folder' => $new_params["msg_folder"], "msgs_to_set" => $msgs_list, "flag" => "unseen"); $this->set_messages_flag($array_msgs); } return $return; }else{ $return = array(); $new_params = array(); $attach_params = array(); $new_params["msg_folder"]=$params["folder"]; $attach_params["folder"] = $params["folder"]; $msgs = explode(",",$params["msgs_number"]); $exporteml = new ExportEml(); $unseen_msgs = array(); foreach($msgs as $msg_number) { $new_params["msg_number"] = $msg_number; //ini_set("display_errors","1"); $msg_info = $this->get_info_msg($new_params); $this->mbox = $this->open_mbox($params['folder']); //Não sei porque, mas se não abrir de novo a caixa dá erro. $msg_info['header'] = $this->get_info_head_msg($msg_number); $attach_params["num_msg"] = $msg_number; $msg_info['array_attach'] = $exporteml->get_attachments_in_array($attach_params); imap_close($this->mbox); $this->mbox=false; array_push($return,serialize($msg_info)); if($msg_info['Unseen'] == "U" || $msg_info['Recent'] == "N"){ array_push($unseen_msgs,$msg_number); } } if($unseen_msgs){ $msgs_list = implode(",",$unseen_msgs); $array_msgs = array('folder' => $new_params["msg_folder"], "msgs_to_set" => $msgs_list, "flag" => "unseen"); $this->set_messages_flag($array_msgs); } return $return; } } /** * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @param $msg_number numero da mensagem */ function getRawHeader($msg_number) { return imap_fetchheader($this->mbox, $msg_number, FT_UID); } /** * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @param $msg_number numero da mensagem */ function getRawBody($msg_number) { return imap_body($this->mbox, $msg_number, FT_UID); } /** * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @param $msg mensagem */ function builderMsgHeader($msg) { $fromMail = str_replace('<','', str_replace('>','',$msg->headers['from'])); $tosMails = str_replace('<','', str_replace('>','',$msg->headers['to'])); $tos = explode(',',$tosMails); $to = ''; foreach ($tos as $value) { $to .= ''.$value.', '; } $header = '
'.$this->functions->getLang('Subject').':'.$msg->headers['subject'].'
'.$this->functions->getLang('From').':'.$fromMail.'
'.$this->functions->getLang('Date').':'.$msg->headers['date'].'
'.$this->functions->getLang('To').':'.$to.'

' ; return $header; } /** * Constroe o corpo da msg direto na variavel de conteudo * @param Mail_mimeDecode $structure * @param $content Ponteiro para Variavel de conteudo da msg */ function builderMsgBody($structure , &$content , $printHeader = false) { if(strtolower($structure->ctype_primary) == 'multipart' && strtolower($structure->ctype_secondary) == 'alternative') { $numParts = count($structure->parts) - 1; for($i = $numParts; $i >= 0; $i--) { $part = $structure->parts[$i]; switch (strtolower($part->ctype_primary)) { case 'text': $disposition = isset($part->disposition) ? strtolower($part->disposition) : ''; if($disposition != 'attachment') { if(strtolower($part->ctype_secondary) == 'html') { if($printHeader) $content .= $this->builderMsgHeader($part); $content .= $this->decodeMailPart($part->body,$part->ctype_parameters['charset']); } if(strtolower($part->ctype_secondary) == 'plain' ) { if($printHeader) $content .= $this->builderMsgHeader($part); $content .= '
'. htmlentities($this->decodeMailPart($part->body,$part->ctype_parameters['charset'],false)).'
'; } if(strtolower($part->ctype_secondary) == 'calendar') $content.= $this->builderMsgCalendar($this->decodeMailPart($part->body, $part->ctype_parameters['charset'])); } $i = -1; break; case 'multipart': if($printHeader) $content .= $this->builderMsgHeader($part); $this->builderMsgBody($part,$content); $i = -1; break; case 'message': if(!is_array($part->parts)) { $content .= "
"; $content .= '
'. htmlentities($this->decodeMailPart($part->body, $structure->ctype_parameters['charset'],false)).'
'; $content .= "
"; } else $this->builderMsgBody($part,$content,true); $i = -1; break; } } } else { foreach ($structure->parts as $index => $part) { switch (strtolower($part->ctype_primary)) { case 'text': $disposition = ''; if(isset($part->disposition)) $disposition = isset($part->disposition) ? strtolower($part->disposition) : ''; if($disposition != 'attachment') { if(strtolower($part->ctype_secondary) == 'html') { if($printHeader) $content .= $this->builderMsgHeader($part); $content .= $this->decodeMailPart($part->body,$part->ctype_parameters['charset']); } if(strtolower($part->ctype_secondary) == 'plain') { if($printHeader) $content .= $this->builderMsgHeader($part); $content .= '
'. htmlentities($this->decodeMailPart($part->body,$part->ctype_parameters['charset'],false)).'
'; } if(strtolower($part->ctype_secondary) == 'calendar') $content .= $this->builderMsgCalendar($part->body); } break; case 'multipart': if($printHeader) $content .= $this->builderMsgHeader($part); $this->builderMsgBody($part,$content); break; case 'message': if($_SESSION['phpgw_info']['user']['preferences']['expressoMail']['nested_messages_are_shown'] != '1') { if(!is_array($part->parts)) { $content .= "
"; $content .= '
'.  htmlentities($this->decodeMailPart($part->body, $structure->ctype_parameters['charset'],false)).'
'; $content .= "
"; } else $this->builderMsgBody($part,$content,true); break; } } } } } /** * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @param $msg_number numero da mensagem */ function get_msg_sample($msg_number) { $content = ''; $return = array(); include_once('class.message_components.inc.php'); $msg = new message_components($this->mbox); $msg->fetch_structure($msg_number); if(!isset($msg->structure[$msg_number]->parts)) { $content = ''; if (strtolower($msg->structure[$msg_number]->subtype) == "plain" || strtolower($msg->structure[$msg_number]->subtype) == "html") $content = $this->decodeBody(imap_body($this->mbox, $msg_number, FT_UID|FT_PEEK), $msg->encoding[$msg_number][0], $msg->charset[$msg_number][0]); } else { foreach($msg->pid[$msg_number] as $values => $msg_part) { $file_type = strtolower($msg->file_type[$msg_number][$values]); if($file_type == "text/plain" || $file_type == "text/html") { $content = $this->decodeBody(imap_fetchbody($this->mbox, $msg_number, $msg_part, FT_UID|FT_PEEK), $msg->encoding[$msg_number][$values], $msg->charset[$msg_number][$values]); break; } } } $tags_replace = array("
","
","
"); $content = str_replace($tags_replace," ", nl2br($content)); $content = $this->html2txt($content); $content != "" ? $return['body'] = " - " . $content: $return['body'] = ""; $return['body'] = base64_encode(mb_convert_encoding(substr($return['body'], 0, 305),'UTF-8' , 'UTF-8,ISO-8859-1')); return $return; } function html2txt($document){ $search = array('@]*?>.*?@si', // Strip out javascript '@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags '@]*?>.*?@siU', // Strip style tags properly '@@si' // Strip multi-line comments including CDATA ); $text = preg_replace($search, '', $document); return html_entity_decode($text); } function ope_msg_part($params) { $return = array(); require_once dirname(__FILE__).'/class.attachment.inc.php'; $atObj = new attachment(); $atObj->setStructureFromMail($params['msg_folder'],$params['msg_number']); $mbox_stream = $this->open_mbox($params['save_folder']); $return['append'] = imap_append($mbox_stream, "{".$this->imap_server.":".$this->imap_port."}".$params['save_folder'], $atObj->getAttachment($params['msg_part']), "\\Seen \\Draft"); $status = imap_status($mbox_stream, "{".$this->imap_server.":".$this->imap_port."}".$params['save_folder'], SA_UIDNEXT); $return['msg_folder'] = $params['save_folder']; $return['msg_number'] = $status->uidnext - 1; return $return; } function get_info_msg($params) { if(isset($params['alarm'])){ $alarm = $params['alarm']; }else{ $alarm = false; } $return = array(); $msg_number = $params['msg_number']; $msg_folder = isset($params['decoded']) ? $params['msg_folder'] : urldecode($params['msg_folder']); if(preg_match('/(.+)(_[a-zA-Z0-9]+)/',$msg_number,$matches)) { //Verifies if it comes from a tab diferent of the main one. $msg_number = $matches[1]; $plus_id = $matches[2]; } else { $plus_id = ''; } $this->mbox = $this->open_mbox($msg_folder); $header = $this->get_header($msg_number); if (!$header) { $return['status_get_msg_info'] = "false"; return $return; } $header_ = imap_fetchheader($this->mbox, $msg_number, FT_UID); $return_get_body = $this->get_body_msg($msg_number, $msg_folder); $body = $return_get_body['body']; if($return_get_body['body']=='isCripted'){ $exporteml = new ExportEml(); $return['source']=$exporteml->export_msg_data($msg_number,$msg_folder); $return['body'] = ""; $return['attachments'] = ""; $return['thumbs'] = ""; $return['signature'] = ""; //return $return; }else{ $return['body'] = $body; $return['attachments'] = $return_get_body['attachments']; $return['thumbs'] = $return_get_body['thumbs']; //$return['signature'] = $return_get_body['signature']; } $pattern = '/^[ \t]*Disposition-Notification-To:.*/mi'; if (preg_match($pattern, $header_, $fields)) $return['DispositionNotificationTo'] = base64_encode(trim(str_ireplace('Disposition-Notification-To:', '', $fields[0]))); $return['Recent'] = $header->Recent; $return['Unseen'] = $header->Unseen; $return['Deleted'] = $header->Deleted; $return['Flagged'] = $header->Flagged; if($header->Answered =='A' && $header->Draft == 'X'){ $return['Forwarded'] = 'F'; } else { $return['Answered'] = $header->Answered; $return['Draft'] = $header->Draft; } $return['msg_number'] = $msg_number.$plus_id; $return['msg_folder'] = isset($params['decoded']) ? mb_convert_encoding( $msg_folder, "ISO-8859-1", "UTF-8" ) : $msg_folder; $msgTimesTamp = $header->udate + $this->functions->CalculateDateOffset(); //Aplica offset do usuario $date_msg = gmdate("d/m/Y",$msgTimesTamp); // Removido codigo pois a o método send_nofication precisa da data completa. // if (date("d/m/Y") == $date_msg) // $return['udate'] = gmdate("H:i",$header->udate); // else // Passa o a data completa para mensagem. $return['udate'] = $header->udate; $return['msg_day'] = $date_msg; $return['msg_hour'] = gmdate("H:i",$msgTimesTamp); if (date("d/m/Y") == $date_msg) //no dia { $return['fulldate'] = gmdate("d/m/Y H:i",$msgTimesTamp); $return['smalldate'] = gmdate("H:i",$msgTimesTamp); $timestamp_now = strtotime("now"); // removido offset nao esta sendo parametrizado // $timestamp_now = strtotime("now") + $offset; $timestamp_msg_time = $msgTimesTamp; // $timestamp_now is GMT and $timestamp_msg_time is MailDate TZ. // The variable $timestamp_diff is calculated without MailDate TZ. $pdate = date_parse($header->MailDate); $timestamp_diff = $timestamp_now - $timestamp_msg_time + ($pdate['zone']*(-60)); if (gmdate("H",$timestamp_diff) > 0) { $return['fulldate'] .= " (" . gmdate("H:i", $timestamp_diff) . ' ' . $this->functions->getLang('hours ago') . ')'; } else { if (gmdate("i",$timestamp_diff) == 0){ $return['fulldate'] .= ' ('. $this->functions->getLang('now').')'; } elseif (gmdate("i",$timestamp_diff) == 1){ $return['fulldate'] .= ' (1 '. $this->functions->getLang('minute ago').')'; } else{ $return['fulldate'] .= " (" . gmdate("i",$timestamp_diff) .' '. $this->functions->getLang('minutes ago') . ')'; } } } else{ $return['fulldate'] = gmdate("d/m/Y H:i",$msgTimesTamp); $return['smalldate'] = gmdate("d/m/Y",$msgTimesTamp); } $from = $header->from; $return['from'] = array(); $return['from']['name'] = isset($sender[0]->personal) ? $this->decode_string($from[0]->personal) : ''; $return['from']['email'] = $this->decode_string($from[0]->mailbox . "@" . $from[0]->host); if ($return['from']['name']) { if (substr($return['from']['name'], 0, 1) == '"') $return['from']['full'] = $return['from']['name'] . ' ' . '<' . $return['from']['email'] . '>'; else $return['from']['full'] = '"' . $return['from']['name'] . '" ' . '<' . $return['from']['email'] . '>'; } else $return['from']['full'] = $return['from']['email']; // Sender attribute $sender = $header->sender; $return['sender'] = array(); $return['sender']['name'] = isset($sender[0]->personal) ? $this->decode_string($sender[0]->personal): ''; $return['sender']['email'] = $this->decode_string($sender[0]->mailbox . "@" . $sender[0]->host); if ($return['sender']['name']) { if (substr($return['sender']['name'], 0, 1) == '"') $return['sender']['full'] = $return['sender']['name'] . ' ' . '<' . $return['sender']['email'] . '>'; else $return['sender']['full'] = '"' . $return['sender']['name'] . '" ' . '<' . $return['sender']['email'] . '>'; } else $return['sender']['full'] = $return['sender']['email']; if($return['from']['full'] == $return['sender']['full']) $return['sender'] = null; $to = $header->to; $return['toaddress2'] = ""; if (!empty($to)) { foreach ($to as $tmp) { if (!empty($tmp->personal)) { $personal_tmp = $this->formatMailObject($tmp); $return['toaddress2'] .= '"' . $personal_tmp['name'] . '"'; $return['toaddress2'] .= " "; $return['toaddress2'] .= "<"; $return['toaddress2'] .= $personal_tmp['email']; $return['toaddress2'] .= ">"; $return['toaddress2'] .= ", "; } else { if (isset($tmp->host) && $tmp->host != 'unspecified-domain') $return['toaddress2'] .= $tmp->mailbox . "@" . $tmp->host; else $return['toaddress2'] .= $tmp->mailbox; $return['toaddress2'] .= ", "; } } $return['toaddress2'] = $this->del_last_two_caracters($return['toaddress2']); } else { $return['toaddress2'] = ""; } if(isset($header->cc)) $cc = $header->cc; $return['cc'] = ""; if (!empty($cc)) { foreach ($cc as $tmp_cc) { if (!empty($tmp_cc->personal)) { $personal_tmp_cc = $this->formatMailObject($tmp_cc); $return['cc'] .= '"' . $personal_tmp_cc['name']. '"'; $return['cc'] .= " "; $return['cc'] .= "<"; $return['cc'] .= $personal_tmp_cc['email']; $return['cc'] .= ">"; $return['cc'] .= ", "; } else { if ($tmp_cc->host != 'unspecified-domain') $return['cc'] .= $tmp_cc->mailbox . "@" . $tmp_cc->host; else $return['cc'] .= $tmp_cc->mailbox; //$return['cc'] .= $tmp_cc->mailbox . "@" . $tmp_cc->host; $return['cc'] .= ", "; } } $return['cc'] = $this->del_last_two_caracters($return['cc']); } else { $return['cc'] = ""; } ## # @AUTHOR Rodrigo Souza dos Santos # @DATE 2008/09/12 # @BRIEF Adding the BCC field. ## if(isset($header->bcc)){ $bcc = $header->bcc; } $return['bcc'] = ""; if (!empty($bcc)) { foreach ($bcc as $tmp_bcc) { if (!empty($tmp_bcc->personal)) { $personal_tmp_bcc = $this->formatMailObject($tmp_bcc); $return['bcc'] .= '"' . $personal_tmp_bcc['name'] . '"'; $return['bcc'] .= " "; $return['bcc'] .= "<"; $return['bcc'] .= $personal_tmp_bcc['email']; $return['bcc'] .= ">"; $return['bcc'] .= ", "; } else { if ($tmp_bcc->host != 'unspecified-domain') $return['bcc'] .= $tmp_bcc->mailbox . "@" . $tmp_bcc->host; else $return['bcc'] .= $tmp_bcc->mailbox; //$return['bcc'] .= $tmp_bcc->mailbox . "@" . $tmp_bcc->host; $return['bcc'] .= ", "; } } $return['bcc'] = $this->del_last_two_caracters($return['bcc']); } else { $return['bcc'] = ""; } $reply_to = $header->reply_to; $return['reply_to'] = ""; if (is_object($reply_to[0])) { if ($return['from']['email'] != ($reply_to[0]->mailbox."@".$reply_to[0]->host)) { if (!empty($reply_to[0]->personal)) { $personal_reply_to = $this->formatMailObject($tmp_reply_to); if(!empty($personal_reply_to[0]->text)) { $return['reply_to'] .= '"' . $personal_reply_to['name']. '"'; $return['reply_to'] .= " "; $return['reply_to'] .= "<"; $return['reply_to'] .= $personal_reply_to['email']; $return['reply_to'] .= ">"; } else { $return['reply_to'] .= $reply_to[0]->mailbox . "@" . $reply_to[0]->host; } } else { $return['reply_to'] .= $reply_to[0]->mailbox . "@" . $reply_to[0]->host; } } } $return['reply_to'] = $this->decode_string($return['reply_to']); $return['subject'] = ( isset($header->subject) && trim($header->subject) !== '' ) ? self::decodeMimeString($header->subject) : $this->functions->getLang('(no subject) '); $return['Size'] = $header->Size; $return['reply_toaddress'] = $header->reply_toaddress; //All this is to help in local messages $return['timestamp'] = $header->udate; $return['login'] = $_SESSION['phpgw_info']['expressomail']['user']['account_id'];//$GLOBALS['phpgw_info']['user']['account_id']; $return['reply_toaddress'] = $header->reply_toaddress; if(($return['from']['email'] == '@unspecified-domain' || $return['sender']['email'] == null) && $return['msg_folder'] == 'INBOX/Drafts'){ $return['from']['email'] = "Rascunho"; } if(strpos($return['toaddress2'], 'undisclosed-recipients') !== false){ $return['toaddress2'] = $this->functions->getLang('without destination'); } $return['alarm'] = $alarm; return $return; } /* * Converte textos utf8 para o padrão html. * Modificado por Cristiano Corrêa Schmidt * @link http://php.net/manual/en/function.utf8-decode.php * @author luka8088 */ static function utf8_to_html ($data) { return preg_replace("/([\\xC0-\\xF7]{1,1}[\\x80-\\xBF]+)/e", 'self::_utf8_to_html("\\1")', $data); } static function _utf8_to_html ($data) { $ret = 0; foreach((str_split(strrev(chr((ord($data{0}) % 252 % 248 % 240 % 224 % 192) + 128) . substr($data, 1)))) as $k => $v) $ret += (ord($v) % 128) * pow(64, $k); return html_entity_decode("&#$ret;" , ENT_QUOTES); } //------------------------------------------------------------------------------// /** * Decodifica uma part da mensagem para iso-8859-1 * @param $part parte do email * @param $encode codificação da parte * @return string decodificada */ function decodeMailPart($part, $encode, $html = true) { switch (strtolower($encode)) { case 'iso-8859-1': return $part; break; case 'utf-8': if ($html) return self::utf8_to_html($part); else return utf8_decode ($part); break; default: return mb_convert_encoding($part, 'iso-8859-1'); break; } } function get_body_msg($msg_number, $msg_folder) { /* * Requires of librarys */ require_once dirname(__FILE__).'/../../library/mime/mimePart.php'; require_once dirname(__FILE__).'/../../library/mime/mimeDecode.php'; require_once dirname(__FILE__).'/class.attachment.inc.php'; //include_once("class.message_components.inc.php"); //--------------------------------------------------------------------// $return = array(); // $msg = new message_components($this->mbox); // $msg->fetch_structure($msg_number); $content = ''; /* * Chamada original $this->getRawHeader($msg_number)."\r\n".$this->getRawBody($msg_number); * Inserido replace para corrigir um bug que acontece raramente em mensagens vindas do outlook com muitos destinatarios */ $rawMessageData = str_replace("\r\n\t", '', $this->getRawHeader($msg_number))."\r\n".$this->getRawBody($msg_number); $decoder = new Mail_mimeDecode($rawMessageData); $params['include_bodies'] = true; $params['decode_bodies'] = true; $params['decode_headers'] = true; if(array_key_exists('nested_messages_are_shown', $_SESSION['phpgw_info']['user']['preferences']['expressoMail']) && ($_SESSION['phpgw_info']['user']['preferences']['expressoMail']['nested_messages_are_shown'] == '1')) $params['rfc_822bodies'] = true; $structure = $decoder->decode($params); /* * Inicia Gerenciador de Anexos */ $attachmentManager = new attachment(); $attachmentManager->setStructure($structure); //----------------------------------------------// /* * Monta informações dos anexos para o cabecalhos */ $attachments = $attachmentManager->getAttachmentsInfo(); $return['attachments'] = $attachments; //----------------------------------------------// /* * Monta informações das imagens */ $images = $attachmentManager->getEmbeddedImagesInfo(); //----------------------------------------------// if(!$this->has_cid) { $return['thumbs'] = $this->get_thumbs($images,$msg_number,$msg_folder); // $return['signature'] = $this->get_signature($msg,$msg_number,$msg_folder); } switch (strtolower($structure->ctype_primary)) { case 'text': if(strtolower($structure->ctype_secondary) == 'x-pkcs7-mime') { $return['body']='isCripted'; return $return; } $attachment = array(); $msg_subtype = strtolower($structure->ctype_secondary); if(isset($structure->disposition)) $disposition = strtolower($structure->disposition); else $disposition = ''; if(($msg_subtype == "html" || $msg_subtype == 'plain') && ($disposition != 'attachment')) { if(strtolower($msg_subtype) == 'plain') { if(isset($structure->ctype_parameters['charset'])) $content = $this->decodeMailPart($structure->body, $structure->ctype_parameters['charset'],false); else $content = $this->decodeMailPart($structure->body, null,false); $content = str_replace( array( '<', '>' ), array( ' #$<$# ', ' #$>$# ' ), $content ); $content = htmlentities( $content ); $this->replace_links($content); $content = str_replace( array( ' #$<$# ', ' #$>$# ' ), array( '<', '>' ), $content ); $content = '
' . $content . '
'; $return[ 'body' ] = $content; return $return; } $content = $this->decodeMailPart($structure->body, $structure->ctype_parameters['charset']); } if(strtolower($structure->ctype_secondary) == 'calendar') $content .= $this->builderMsgCalendar($structure->body); break; case 'multipart': $this->builderMsgBody($structure , $content); break; case 'message': if($_SESSION['phpgw_info']['user']['preferences']['expressoMail']['nested_messages_are_shown'] != 1) { if(!is_array($structure->parts)) { $content .= "
"; $content .= '
'.htmlentities($this->decodeMailPart($structure->body, $structure->ctype_parameters['charset'],false)).'
'; $content .= "
"; } else $this->builderMsgBody($structure , $content,true); } break; case 'application': if(strtolower($structure->ctype_secondary) == 'x-pkcs7-mime') { // $return['body']='isCripted'; // return $return; //TODO: Descartar código após atualização do módulo de segurança da SERPRO $rawMessageData2 = $this->extractSignedContents($rawMessageData); if($rawMessageData2 === false){ $return['body']='isCripted'; return $return; } $decoder2 = new Mail_mimeDecode($rawMessageData2); $structure2 = $decoder2->decode($params); $this-> builderMsgBody($structure2 , $content); $attachmentManager->setStructure($structure2); /* * Monta informações dos anexos para o cabecarios */ $attachments = $attachmentManager->getAttachmentsInfo(); $return['attachments'] = $attachments; //----------------------------------------------// /* * Monta informações das imagens */ $images = $attachmentManager->getEmbeddedImagesInfo(); //----------------------------------------------// if(!$this->has_cid){ $return['thumbs'] = $this->get_thumbs($images,$msg_number,$msg_folder); $return['signature'] = $this->get_signature($msg,$msg_number,$msg_folder); } } /////////////////////////////////////////////////////////////////////////////////////////// default: if(count($attachments) > 0) $content .= ''; break; } $params = array('folder' => $msg_folder, "msgs_to_set" => $msg_number, "flag" => "seen"); $this->set_messages_flag($params); $content = $this->process_embedded_images($images,$msg_number,$content, $msg_folder); $content = $this->replace_special_characters($content); $this->replace_links($content); $return['body'] = &$content; return $return; } //TODO: Descartar código após atualização do módulo de segurança da SERPRO function extractSignedContents( $data ) { $pipes_desc = array( 0 => array('pipe', 'r'), 1 => array('pipe', 'w') ); $fp = proc_open( 'openssl smime -verify -noverify -nochain', $pipes_desc, $pipes); if (!is_resource($fp)) { return false; } $output = ''; /* $pipes[0] => writeable handle connected to child stdin $pipes[1] => readable handle connected to child stdout */ fwrite($pipes[0], $data); fclose($pipes[0]); while (!feof($pipes[1])) { $output .= fgets($pipes[1], 1024); } fclose($pipes[1]); proc_close($fp); return $output; } /////////////////////////////////////////////////////////////////////////////////////// function builderMsgCalendar($calendar) { $icalService = ServiceLocator::getService('ical'); $codificao = mb_detect_encoding($calendar.'x', 'UTF-8, ISO-8859-1'); if($codificao == 'UTF-8') $calendar = utf8_decode($calendar); if($icalService->setIcal($calendar)) { $content = ''; switch ($icalService->getMethod()) { case 'REPLY': break; case 'CANCEL': $ical = $icalService->getComponent('vevent'); $content.= ''.$this->functions->getLang('Event Calendar').'

'; $content.= ''; $content.= ''.$this->functions->getLang('Your event has been canceled').''; if($ical['description']['value']) $content.= '

'.str_replace('\n','
',nl2br($ical['description']['value'])); $content.= '
* '.$this->functions->getLang('To remove the event from your calendar to import the iCal file attached').'.'; $content.= '


'; break; case 'REQUEST': $ical = $icalService->getComponent('vevent'); if($ical['dtstart']['value']['tz'] == 'Z') { $tz = $_SESSION['phpgw_info']['user']['preferences']['common']['tz_offset']; $ical['dtstart']['value']['hour'] += $tz; $ical['dtend']['value']['hour'] += $tz; } $content.= ''.$this->functions->getLang('Event Calendar').'
'. '
'.$this->functions->getLang('Title').': '.$ical['summary']['value']. '
'.$this->functions->getLang('Location').': '.$ical['location']['value']. '
'.$this->functions->getLang('Details').': '. str_ireplace('\n','
',nl2br($ical['description']['value'])); $content.= '
'.$this->functions->getLang('Start') . ': ' . $ical['dtstart']['value']['day'] . "/" . $ical['dtstart']['value']['month'] . "/" . $ical['dtstart']['value']['year'] . " - " . $ical['dtstart']['value']['hour'] . ":" . $ical['dtstart']['value']['min'] ; $content.= '
'.$this->functions->getLang('End') . ': ' . $ical['dtend']['value']['day'] . "/" . $ical['dtend']['value']['month'] . "/" . $ical['dtend']['value']['year'] . " - " . $ical['dtend']['value']['hour'] . ":" . $ical['dtend']['value']['min'] ; if($ical['organizer']['params']['CN']) $content.= '
'.$this->functions->getLang('Organizer').': '.$ical['organizer']['params']['CN'].' - '.$ical['organizer']['value'].'' ; else $content.= '
'.$this->functions->getLang('Organizer').': '.$ical['organizer']['value'].'' ; if($ical['attendee']) { $att = '
'.$this->functions->getLang('Participants').': '; $att .= '
' ; } $content.= $att; break; default: break; } } return $content; } function htmlfilter($body) { require_once('htmlfilter.inc'); $tag_list = Array( false, 'blink', 'object', 'meta', 'html', 'link', 'frame', 'iframe', 'layer', 'ilayer', 'plaintext' ); /** * A very exclusive set: */ // $tag_list = Array(true, "b", "a", "i", "img", "strong", "em", "p"); $rm_tags_with_content = Array( 'script', 'style', 'applet', 'embed', 'head', 'frameset', 'xml', 'xmp' ); $self_closing_tags = Array( 'img', 'br', 'hr', 'input' ); $force_tag_closing = true; $rm_attnames = Array( '/.*/' => Array( '/target/i', //'/^on.*/i', -> onClick, dos compromissos da agenda. '/^dynsrc/i', '/^datasrc/i', '/^data.*/i', '/^lowsrc/i' ) ); /** * Yeah-yeah, so this looks horrible. Check out htmlfilter.inc for * some idea of what's going on here. :) */ $bad_attvals = Array( '/.*/' => Array( '/.*/' => Array( Array( '/^([\'\"])\s*\S+\s*script\s*:*(.*)([\'\"])/si', //'/^([\'\"])\s*https*\s*:(.*)([\'\"])/si', -> doclinks notes '/^([\'\"])\s*mocha\s*:*(.*)([\'\"])/si', '/^([\'\"])\s*about\s*:(.*)([\'\"])/si' ), Array( '\\1oddjob:\\2\\1', //'\\1uucp:\\2\\1', -> doclinks notes '\\1amaretto:\\2\\1', '\\1round:\\2\\1' ) ), '/^style/i' => Array( Array( '/expression/i', '/behaviou*r/i', '/binding/i', '/include-source/i', '/url\s*\(\s*([\'\"]*)\s*https*:.*([\'\"]*)\s*\)/si', '/url\s*\(\s*([\'\"]*)\s*\S+\s*script:.*([\'\"]*)\s*\)/si' ), Array( 'idiocy', 'idiocy', 'idiocy', 'idiocy', 'url(\\1http://securityfocus.com/\\1)', 'url(\\1http://securityfocus.com/\\1)' ) ) ) ); $add_attr_to_tag = Array( '/^a$/i' => Array('target' => '"_new"') ); $trusted_body = sanitize($body, $tag_list, $rm_tags_with_content, $self_closing_tags, $force_tag_closing, $rm_attnames, $bad_attvals, $add_attr_to_tag ); return $trusted_body; } function decodeBody($body, $encoding, $charset=null) { if ($encoding == 'quoted-printable') { $body = quoted_printable_decode($body); } else if ($encoding == 'base64') { $body = base64_decode($body); } // All other encodings are returned raw. if (strtolower($charset) == "utf-8") return utf8_decode($body); else return $body; } /** * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @param $images * @param $msgno * @param $body * @param $msg_folder */ function process_embedded_images($images, $msgno, $body, $msg_folder) { foreach ($images as $image) { $image['cid'] = preg_replace('//i', '', $image['cid']); $body = str_replace("src=\"cid:".$image['cid']."\"", " src=\"./inc/get_archive.php?msgFolder=$msg_folder&msgNumber=$msgno&indexPart=".$image['pid']."\" ", $body); $body = str_replace("src='cid:".$image['cid']."'", " src=\"./inc/get_archive.php?msgFolder=$msg_folder&msgNumber=$msgno&indexPart=".$image['pid']."\"", $body); $body = str_replace("src=cid:".$image['cid'], " src=\"./inc/get_archive.php?msgFolder=$msg_folder&msgNumber=$msgno&indexPart=".$image['pid']."\"", $body); } return $body; } function replace_special_characters($body) { if(trim($body) === '') return; $body = str_ireplace('POSITION: ABSOLUTE;','', $body); $body = str_ireplace(' ','
', $body);//Qubra de linha do MSO $body = preg_replace('/<(meta|base|link|html|\/html)[^>]*>/i', '', $body); require_once(dirname(__FILE__).'/../../library/CssToInlineStyles/css_to_inline_styles.php'); $cssToInlineStyles = new CSSToInlineStyles($body); $cssToInlineStyles->setUseInlineStylesBlock(true); $cssToInlineStyles->setCleanup(TRUE); $body = $cssToInlineStyles->convert(); //Converte as tag style em inline styles ///--------------------------------// // tags to be removed doe to security reasons $tag_list = Array( 'blink', 'object', 'frame', 'iframe', 'layer', 'ilayer', 'plaintext', 'script', 'applet', 'embed', 'frameset', 'xml', 'xmp','style','head' ); foreach ($tag_list as $index => $tag) $body = @mb_eregi_replace("<$tag\\b[^>]*>(.*?)", '', $body); // Malicious Code Remove $dirtyCodePattern = "/(<([\w]+[\w0-9]*)(.*)on(mouse(move|over|down|up)|load|blur|change|error|click|dblclick|focus|key(down|up|press)|select)([\n\ ]*)=([\n\ ]*)[\"'][^>\"']*[\"']([^>]*)>)(.*)(<\/\\2>)?/misU"; preg_match_all($dirtyCodePattern, $body, $rest, PREG_PATTERN_ORDER); foreach ($rest[0] as $i => $val) { if (!(preg_match("/javascript:window\.open\(\"([^'\"]*)\/index\.php\?menuaction=calendar\.uicalendar\.set_action\&cal_id=([^;'\"]+);?['\"]/i", $rest[1][$i]) && strtoupper($rest[4][$i]) == "CLICK" )) //Calendar events $body = str_replace($rest[1][$i], "<" . $rest[2][$i] . $rest[3][$i] . $rest[7][$i] . ">", $body); } /* * Remove deslocamento a esquerda colocado pelo Outlook. * Este delocamento faz com que algumas palavras fiquem escondidas atras da barra lateral do expresso. */ $body = mb_ereg_replace("(]*)(text-indent:[^>;]*-[^>;]*;)([^>]*>)", "\\1\\3", $body); $body = mb_ereg_replace("(]*)(margin-right:[^>;]*-[^>;]*;)([^>]*>)", "\\1\\3", $body); $body = mb_ereg_replace("(]*)(margin-left:[^>;]*-[^>;]*;)([^>]*>)", "\\1\\3", $body); //--------------------------------------------------------------------------------------------// //Remoção de tags para correção de erro no firefox //Comentado pois estes replaces geram erros no html da msg, não se pode garantir que o os sejam realmente os fechamentos dos . //Caso realmente haja a nescessidade de remover estes spans deve ser repensado a forma de como faze-lo. // $body = mb_eregi_replace("","",$body); // $body = mb_eregi_replace("","",$body); //Correção para compatibilização com Outlook, ao visualizar a mensagem $body = mb_ereg_replace('', $body); $body = preg_replace("/]*>([\s]?)*<\/p[^>]*>/", '', $body); //Remove paragrafos vazios (evita duplo espaçamento em emails do MSO) return $body ; } function replace_links_callback($matches) { if($matches[3]) $pref = $matches[3]; else $pref = $matches[3] = 'http'; return ''.$matches[0].''; } /** * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @param $body corpo da mensagem */ function replace_links(&$body) { // Trata urls do tipo aaaa.bbb.empresa // Usadas na intranet. $pattern = '/(?<=[\s|(
)|\n|\r|;])(((http|https|ftp|ftps)?:\/\/((?:[\w]\.?)+(?::[\d]+)?[:\/.\-~&=?%;@#,+\w]*))|((?:www?\.)(?:\w\.?)*(?::\d+)?[\:\/\w.\-~&=?%;@+]*))/i'; $body = preg_replace_callback($pattern,array( &$this, 'replace_links_callback'), $body); } function get_signature($msg, $msg_number, $msg_folder) { include_once(dirname( __FILE__ ) ."/../../security/classes/CertificadoB.php"); include_once("class.db_functions.inc.php"); foreach ($msg->file_type[$msg_number] as $index => $file_type) { $sign = array(); $temp = $this->get_info_head_msg($msg_number); if($temp['ContentType'] =='normal') return $sign; $file_type = strtolower($file_type); if(strtolower($msg->encoding[$msg_number][$index]) == 'base64') { if ($temp['ContentType'] == 'signature') { if(!$this->mbox || !is_resource($this->mbox)) $this->mbox = $this->open_mbox($msg_folder); $header = @imap_headerinfo($this->mbox, imap_msgno($this->mbox, $msg_number), 80, 255); $imap_msg = @imap_fetchheader($this->mbox, $msg_number, FT_UID); $imap_msg .= @imap_body($this->mbox, $msg_number, FT_UID); $certificado = new certificadoB(); $validade = $certificado->verificar($imap_msg); $sign[] = $certificado->msg_sem_assinatura; if ($certificado->apresentado) { $from = $header->from; foreach ($from as $id => $object) { $fromname = $object->personal; $fromaddress = $object->mailbox . "@" . $object->host; } foreach ($certificado->erros_ssl as $item) { $sign[] = $item . "#@#"; } if (count($certificado->erros_ssl) < 1) { $check_msg = 'Message untouched'; if(strtoupper($fromaddress) == strtoupper($certificado->dados['EMAIL'])) { $check_msg .= ' and authentic###'; } else { $check_msg .= ' with signer different from sender#@#'; } $sign[] = $check_msg; } $sign[] = 'Message signed by: ###' . $certificado->dados['NOME']; $sign[] = 'Certificate email: ###' . $certificado->dados['EMAIL']; $sign[] = 'Mail from: ###' . $fromaddress; $sign[] = 'Certificate Authority: ###' . $certificado->dados['EMISSOR']; $sign[] = 'Validity of certificate: ###' . gmdate('r',openssl_to_timestamp($certificado->dados['FIM_VALIDADE'])); $sign[] = 'Message date: ###' . $header->Date; $cert = openssl_x509_parse($certificado->cert_assinante); $sign_alert = array(); $sign_alert[] = 'Certificate Owner###:\n'; $sign_alert[] = 'Common Name (CN)### ' . $cert[subject]['CN'] . '\n'; $X = substr($certificado->dados['NASCIMENTO'] ,0,2) . '-' . substr($certificado->dados['NASCIMENTO'] ,2,2) . '-' . substr($certificado->dados['NASCIMENTO'] ,4,4); $sign_alert[]= 'Organization (O)### ' . $cert[subject]['O'] . '\n'; $sign_alert[]= 'Organizational Unit (OU)### ' . $cert[subject]['OU'][0] . '\n'; //$sign_alert[] = 'Serial Number### ' . $cert['serialNumber'] . '\n'; $sign_alert[] = 'Personal Data###:' . '\n'; $sign_alert[] = 'Birthday### ' . $X . '\n'; $sign_alert[]= 'Fiscal Id### ' . $certificado->dados['CPF'] . '\n'; $sign_alert[]= 'Identification### ' . $certificado->dados['RG'] . '\n\n'; $sign_alert[]= 'Certificate Issuer###:\n'; $sign_alert[]= 'Common Name (CN)### ' . $cert[issuer]['CN'] . '\n'; $sign_alert[]= 'Organization (O)### ' . $cert[issuer]['O'] . '\n'; $sign_alert[]= 'Organizational Unit (OU)### ' . $cert[issuer]['OU'][0] . '\n\n'; $sign_alert[]= 'Validity###:\n'; $H = data_hora($cert[validFrom]); $X = substr($H,6,2) . '-' . substr($H,4,2) . '-' . substr($H,0,4); $sign_alert[]= 'Valid From### ' . $X . '\n'; $H = data_hora($cert[validTo]); $X = substr($H,6,2) . '-' . substr($H,4,2) . '-' . substr($H,0,4); $sign_alert[]= 'Valid Until### ' . $X; $sign[] = $sign_alert; $this->db = new db_functions(); // TODO: testar se existe um certificado no banco e verificar qual � o mais atual. if(!$certificado->dados['EXPIRADO'] && !$certificado->dados['REVOGADO'] && count($certificado->erros_ssl) < 1) $this->db->insert_certificate(strtolower($certificado->dados['EMAIL']), $certificado->cert_assinante, $certificado->dados['SERIALNUMBER'], $certificado->dados['AUTHORITYKEYIDENTIFIER']); } else { $sign[] = "" . $this->functions->getLang('Invalid signature') . ""; foreach($certificado->erros_ssl as $item) $sign[] = "" . $this->functions->getLang($item) . ""; } } } } return $sign; } /** * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @param $images * @param $msg_number * @param $msg_folder */ function get_thumbs($images, $msg_number, $msg_folder) { if (!count($images)) return ''; foreach ($images as $key => $value) { $images[$key]['width'] = 160; $images[$key]['height'] = 120; $images[$key]['url'] = "inc/get_archive.php?msgFolder=".$msg_folder."&msgNumber=".$msg_number."&indexPart=".$value['pid']."&image=true"; } return json_encode($images); } /*function delete_msg($params) { $folder = $params['folder']; $msgs_to_delete = explode(",",$params['msgs_to_delete']); $mbox_stream = $this->open_mbox($folder); foreach ($msgs_to_delete as $msg_number){ imap_delete($mbox_stream, $msg_number, FT_UID); } imap_close($mbox_stream, CL_EXPUNGE); return $params['msgs_to_delete']; }*/ // Novo function delete_msgs($params) { $folder = $params['folder']; $folder = mb_convert_encoding($folder, "UTF7-IMAP","ISO-8859-1"); $msgs_number = explode(",",$params['msgs_number']); if(array_key_exists('border_ID' ,$params)) $border_ID = $params['border_ID']; else $border_ID = ''; $return = array(); if (array_key_exists('get_previous_msg' , $params) && $params['get_previous_msg']){ $return['previous_msg'] = $this->get_info_previous_msg($params); // Fix problem in unserialize function JS. $return['previous_msg']['body'] = str_replace(array('{','}'), array('{','}'), $return['previous_msg']['body']); } //$mbox_stream = $this->open_mbox($folder); $mbox_stream = @imap_open("{".$this->imap_server.":".$this->imap_port.$this->imap_options."}".$folder, $this->username, $this->password) or die(serialize(array('imap_error' => $this->parse_error(imap_last_error())))); foreach ($msgs_number as $msg_number) { if (imap_delete($mbox_stream, $msg_number, FT_UID)); $return['msgs_number'][] = $msg_number; } $return['folder'] = $folder; $return['border_ID'] = $border_ID; if($mbox_stream) imap_close($mbox_stream, CL_EXPUNGE); $return['status'] = true; return $return; } function refresh($params) { $return = array(); $return['new_msgs'] = 0; $folder = $params['folder']; $msg_range_begin = $params['msg_range_begin']; $msg_range_end = $params['msg_range_end']; $msgs_existent = $params['msgs_existent']; $sort_box_type = $params['sort_box_type']; $sort_box_reverse = $params['sort_box_reverse']; $msgs_in_the_server = array(); $search_box_type = $params['search_box_type'] != "ALL" && $params['search_box_type'] != "" ? $params['search_box_type'] : false; $msgs_in_the_server = $this->get_msgs($folder, $sort_box_type, $search_box_type, $sort_box_reverse,$msg_range_begin,$msg_range_end); $msgs_in_the_server = array_keys($msgs_in_the_server); $num_msgs = (count($msgs_in_the_server) - imap_num_recent($this->mbox)); $dif = ($params['msg_range_end'] - $params['msg_range_begin']) +1; if(!count($msgs_in_the_server)){ $msg_range_begin -= $dif; $msg_range_end -= $dif; $msgs_in_the_server = $this->get_msgs($folder, $sort_box_type, $search_box_type, $sort_box_reverse,$msg_range_begin,$msg_range_end); $msgs_in_the_server = array_keys($msgs_in_the_server); $num_msgs = NULL; $return['msg_range_begin'] = $msg_range_begin; $return['msg_range_end'] = $msg_range_end; } $return['new_msgs'] = imap_num_recent($this->mbox); $msgs_in_the_client = explode(",", $msgs_existent); $msg_to_insert = array_diff($msgs_in_the_server, $msgs_in_the_client); if(count($msg_to_insert) > 0 && $return['new_msgs'] == 0 && $msgs_in_the_client[0] != ""){ $aux = 0; while(array_key_exists($aux, $msg_to_insert)){ if($msg_to_insert[$aux] > $msgs_in_the_client[0]){ $return['new_msgs'] += 1; } $aux++; } }else if(count($msg_to_insert) > 0 && $msgs_in_the_server && $msgs_in_the_client[0] != "" && $return['new_msgs'] == 0){ $aux = 0; while(array_key_exists($aux, $msg_to_insert)){ if($msg_to_insert[$aux] == $msgs_in_the_server[$aux]){ $return['new_msgs'] += 1; } $aux++; } }else if($num_msgs < $msg_range_end && $return['new_msgs'] == 0 && count($msg_to_insert) > 0 && $msg_range_end == $dif){ $return['tot_msgs'] = $num_msgs; } if(!count($msgs_in_the_server)){ return Array(); } $msg_to_delete = array_diff($msgs_in_the_client, $msgs_in_the_server); $msgs_to_exec = array(); foreach($msg_to_insert as $msg_number) $msgs_to_exec[] = $msg_number; //sort($msgs_to_exec); $i = 0; foreach($msgs_to_exec as $msg_number) { $sample = false; if( (isset($this->prefs['preview_msg_subject']) || ($this->prefs['preview_msg_subject'] === '1')) && (isset($this->prefs['preview_msg_tip'] ) || ($this->prefs['preview_msg_tip'] === '1')) ) $sample = true; $return[$i] = $this->get_info_head_msg($msg_number , $sample ); //get the next msg number to append this msg in the view in a correct place $msg_key_position = array_search($msg_number, $msgs_in_the_server); $return[$i]['msg_key_position'] = $msg_key_position; if($msg_key_position !== false && array_key_exists($msg_key_position + 1,$msgs_in_the_server) !== false) $return[$i]['next_msg_number'] = $msgs_in_the_server[$msg_key_position + 1]; else $return[$i]['next_msg_number'] = $msgs_in_the_server[$msg_key_position]; $return[$i]['msg_folder'] = $folder; $i++; } $return['quota'] = $this->get_quota(array('folder_id' => $folder)); $return['sort_box_type'] = $params['sort_box_type']; if(!$this->mbox || !is_resource($this->mbox)) $this->open_mbox($folder); $return['msgs_to_delete'] = $msg_to_delete; $return['offsetToGMT'] = $this->functions->CalculateDateOffset(); if($this->mbox && is_resource($this->mbox)) imap_close($this->mbox); return $return; } /** * Método que faz a verificação do Content-Type do e-mail e verifica se é um e-mail normal, * assinado ou cifrado. * @author Mário César Kolling * @param $headers Uma String contendo os Headers do e-mail retornados pela função imap_imap_fetchheader * @param $msg_number O número da mesagem * @return Retorna o tipo da mensagem (normal, signature, cipher). */ function getMessageType($msg_number, $headers = false , &$body = false){ include_once(dirname( __FILE__ ) ."/../../security/classes/CertificadoB.php"); $contentType = "normal"; if (!$headers) $headers = imap_fetchheader($this->mbox, $msg_number, FT_UID); if (preg_match("/pkcs7-signature/i", $headers) == 1) $contentType = "signature"; else if (preg_match("/pkcs7-mime/i", $headers) == 1) $contentType = testa_p7m( $body ? $body : imap_body($this->mbox, $msg_number , FT_UID )) ; return $contentType; } /** * Retorna a posição que a pasta esta dentro do array de pastas * * @license www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Cristiano Corrêa Schmidt * @access public */ function getFolderPos(&$array , $find) { foreach($array as $i => $v) if($v['id'] === $find) return $i; return false; } /** * Ordenas as pastas padrões do usuario na ordem INBOX > SENT > DRAFTS > SPAM > TRASH > OTHERS * * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Cristiano Corrêa Schmidt * @access public */ function orderDefaultFolders( &$folders , $user) { $principals = array(); for($x = 0; $x < 5 ; $x++) { switch ($x) { case 0: if( ($p = $this->getFolderPos($folders , $user )) || $p === 0 ) $principals[] = $folders[$p]; break; case 1: if( ($p = $this->getFolderPos($folders , $this->mount_url_folder(array($user , $this->folders['drafts'])) )) || $p === 0 ) $principals[] = $folders[$p]; break; case 2: if( ($p = $this->getFolderPos($folders , $this->mount_url_folder(array($user , $this->folders['sent'])) )) || $p === 0 ) $principals[] = $folders[$p]; break; case 3: if( ($p = $this->getFolderPos($folders , $this->mount_url_folder(array($user , $this->folders['spam'])) )) || $p === 0 ) $principals[] = $folders[$p]; break; case 4: if( ($p = $this->getFolderPos($folders , $this->mount_url_folder(array($user , $this->folders['trash'])) )) || $p === 0 ) $principals[] = $folders[$p]; break; } if($p !== false) unset($folders[$p]); } $folders = array_merge($principals, $folders); } /** * Retorna lista de pastas do usuario no padrão que a lib javascript espera. * * @license http://www.gnu.org/copyleft/gpl.html GPL * @author Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) * @sponsor Caixa Econômica Federal * @author Cristiano Corrêa Schmidt * @access public */ function get_folders_list($params = null) { $return = $this->getFolders( $params ); foreach ($return as $i => &$vv) { if(!is_array($vv)) continue; $vv['folder_id'] = mb_convert_encoding($vv['folder_id'],'ISO-8859-1','UTF7-IMAP');//DECODIFICA ID DAS PASTAS COM ACENTOS $vv['folder_name'] = mb_convert_encoding($vv['folder_name'],'ISO-8859-1','UTF7-IMAP');//DECODIFICA NOME DAS PASTAS COM ACENTOS $vv['folder_parent'] = mb_convert_encoding($vv['folder_parent'],'ISO-8859-1','UTF7-IMAP');//DECODIFICA NOME DAS PASTAS COM ACENTOS } return ( $return ); } function getFolders($params = null) { ///Define Variaveis $prefixShared = 'user'; //Prefixo das pastas compartilhadas $uid2cn = (isset($_SESSION['phpgw_info']['user']['preferences']['expressoMail']['uid2cn'])) ? $_SESSION['phpgw_info']['user']['preferences']['expressoMail']['uid2cn'] : false; $mboxStream = $this->open_mbox(); //abre conexão imap $currentFolder = isset($params['folder']) ? $params['folder'] : 'INBOX'; $folders = array(); $return = array(); /////////////////////////////////////////////////////////////// if( isset($params['onload']) && $_SESSION['phpgw_info']['expressomail']['server']['certificado']) $this->delete_mailbox(array('del_past' => 'INBOX'.$this->imap_delimiter.'decifradas')); //Deleta Pasta decifradas session_write_close(); // Free others requests $serverString = "{".$this->imap_server.":".$this->imap_port.$this->imap_options."}"; if ( isset($params['noSharedFolders']) ) $folders_list = array_merge(imap_getmailboxes($mboxStream, $serverString, 'INBOX' ), imap_getmailboxes($mboxStream, $serverString, 'INBOX/*' ) ); else $folders_list = imap_getmailboxes($mboxStream, $serverString, '*' ); $folders_list = array_slice($folders_list,0,$this->foldersLimit); if (!is_array($folders_list)) return false; if($uid2cn) $this->ldap = new ldap_functions(); foreach ($folders_list as $i => $v ) //Separando Pastas e informações { $folderId = substr($v->name,(strpos($v->name , '}') + 1)); $nameArray = explode($this->imap_delimiter, $folderId); $nameCount = count($nameArray); $decifrada = mb_convert_encoding('INBOX'.$this->imap_delimiter.'decifradas','UTF7-IMAP','ISO-8859-1'); //Ignorar esta pasta decifrada $parent = ($nameCount > 1 && $nameArray[($nameCount - 2)] !== 'INBOX') ? implode($this->imap_delimiter, array_slice($nameArray, 0, ($nameCount - 1))): ''; //Pega folder pai if($nameArray[0] === 'user') $folders[$prefixShared.$this->imap_delimiter.$nameArray[1]][] = array('id' => $folderId , 'stream' => $v->name , 'attributes' => $v->attributes , 'name' => $nameArray[($nameCount-1)] , 'user' => $nameArray[1] ,'parent' => $parent); else if( $folderId !== $decifrada) //Escapa pasta decifrada $folders['INBOX'][strtolower($folderId)] = array('id' => $folderId , 'stream' => $v->name , 'attributes' => $v->attributes ,'name' => $nameArray[($nameCount-1)] , 'parent' => $parent); } unset($folders_list); //destroy array de objetos desnecessarios ksort($folders['INBOX']); foreach($folders as $i => $v) //Ordenando e resgatando novas informações { $this->orderDefaultFolders($folders[$i] , $i); //Ordenando Pastas Padrões foreach ($folders[$i] as $ii => $vv) { $append = array(); $append['folder_id'] = $vv['id']; $append['folder_name'] = (($uid2cn && isset($vv['user'])) && ($cn = $this->ldap->uid2cn($vv['user']))) ? $cn : $vv['name']; $status = imap_status($mboxStream, $vv['stream'], SA_UNSEEN); //Resgata Numero de mensagens não lidas $append['folder_unseen'] = isset($status->unseen) ? $status->unseen : 0 ; $append['folder_hasChildren'] = (($vv['attributes'] == 32) && ($vv['name'] != 'INBOX')) ? 1 : 0; $append['folder_parent'] = $vv['parent']; $return[] = $append; } } $quotaInfo = (!isset($params['noQuotaInfo'])) ? $this->get_quota( array('folder_id' => $currentFolder)) : false; //VERIFICA SE O USUARIO TEM COTA return ( ( is_array($quotaInfo) ) ? array_merge($return, $quotaInfo) : $return ); } function create_mailbox($arr) { $namebox = $arr['newp']; $base_path = $arr['base_path']; $mbox_stream = $this->open_mbox(); $imap_server = $_SESSION['phpgw_info']['expressomail']['email_server']['imapServer']; $test = explode("/", $namebox); if(count($test) < 1 || $base_path == null || $base_path == "" || $base_path == 'undefined'){ if($base_path != null || $base_path != "" || $base_path != 'undefined'){ $namebox = $base_path.$namebox; } $namebox = mb_convert_encoding($namebox, "UTF7-IMAP", "UTF-8"); $result = "Ok"; if(!imap_createmailbox($mbox_stream,"{".$imap_server."}".$namebox)) { $result = implode("
\n", imap_errors()); } }else{ $child = $base_path.$this->imap_delimiter; for($i =0; $i < count($test); $i++){ $child .= ($test[$i] ? $test[$i] : $this->functions->getLang("New Folder")); $namebox = mb_convert_encoding($child, "UTF7-IMAP", "UTF-8"); $result = "Ok"; if(!imap_createmailbox($mbox_stream,"{".$imap_server."}$namebox")) { $result = implode("
\n", imap_errors()); } $child .=$this->imap_delimiter; } } if($mbox_stream) imap_close($mbox_stream); return $result; } function create_extra_mailbox($arr) { $nameboxs = explode(";",$arr['nw_folders']); $result = ""; $mbox_stream = $this->open_mbox(); $imap_server = $_SESSION['phpgw_info']['expressomail']['email_server']['imapServer']; foreach($nameboxs as $key=>$tmp){ if($tmp != ""){ if(!imap_createmailbox($mbox_stream,imap_utf7_encode("{".$imap_server."}$tmp"))){ $result = implode("
\n", imap_errors()); if($mbox_stream) imap_close($mbox_stream); return $result; } } } if($mbox_stream) imap_close($mbox_stream); return true; } function delete_mailbox($arr) { $namebox = $arr['del_past']; $imap_server = $_SESSION['phpgw_info']['expressomail']['email_server']['imapServer']; $mbox_stream = $this->mbox ? $this->mbox : $this->open_mbox(); //$del_folder = imap_deletemailbox($mbox_stream,"{".$imap_server."}INBOX.$namebox"); $result = "Ok"; $namebox = mb_convert_encoding($namebox, "UTF7-IMAP","UTF-8"); if(!imap_deletemailbox($mbox_stream,"{".$imap_server."}$namebox")) { $result = implode("
\n", imap_errors()); } /* if($mbox_stream) imap_close($mbox_stream); */ return $result; } function ren_mailbox($arr) { $namebox = $arr['current']; $new_box = $arr['rename']; $imap_server = $_SESSION['phpgw_info']['expressomail']['email_server']['imapServer']; $mbox_stream = $this->open_mbox(); //$ren_folder = imap_renamemailbox($mbox_stream,"{".$imap_server."}INBOX.$namebox","{".$imap_server."}INBOX.$new_box"); $result = "Ok"; $namebox = mb_convert_encoding($namebox, "UTF7-IMAP","UTF-8"); $new_box = mb_convert_encoding($new_box, "UTF7-IMAP","UTF-8"); if(!imap_renamemailbox($mbox_stream,"{".$imap_server."}$namebox","{".$imap_server."}$new_box")) { $result = imap_errors(); } if($mbox_stream) imap_close($mbox_stream); return $result; } function get_num_msgs($params) { $folder = $params['folder']; if(!$this->mbox || !is_resource($this->mbox)) { $this->mbox = $this->open_mbox($folder); if(!$this->mbox || !is_resource($this->mbox)) return imap_last_error(); } $num_msgs = imap_num_msg($this->mbox); if($this->mbox && is_resource($this->mbox)) imap_close($this->mbox); return $num_msgs; } function folder_exists($folder){ $mbox = $this->open_mbox(); $serverString = "{".$this->imap_server.":".$this->imap_port.$this->imap_options."}"; $list = imap_getmailboxes($mbox,$serverString, $folder); $return = is_array($list); imap_close($mbox); return $return; } function send_mail($params) { require_once dirname(__FILE__) . '/../../services/class.servicelocator.php'; require_once dirname(__FILE__) . '/../../prototype/api/controller.php'; $mailService = ServiceLocator::getService('mail'); include_once("class.db_functions.inc.php"); $db = new db_functions(); $fromaddress = $params['input_from'] ? explode(';', $params['input_from']) : ""; $message_attachments_contents = (isset($params['message_attachments_content'])) ? $params['message_attachments_content'] : false; ## # @AUTHOR Rodrigo Souza dos Santos # @DATE 2008/09/17$fileName # @BRIEF Checks if the user has permission to send an email with the email address used. ## if (is_array($fromaddress) && ($fromaddress[1] != $_SESSION['phpgw_info']['expressomail']['user']['email'])) { $deny = true; foreach ($_SESSION['phpgw_info']['expressomail']['user']['shared_mailboxes'] as $key => $val) if (array_key_exists('mail', $val) && $val['mail'][0] == $fromaddress[1]) $deny = false and end($_SESSION['phpgw_info']['expressomail']['user']['shared_mailboxes']); if ($deny) return "The server denied your request to send a mail, you cannot use this mail address."; } /*Wraps the text dividing the emails as from ">,"*/ $toaddress = $db->getAddrs(preg_split('/>,/',preg_replace('/>,/', '>>,', $params['input_to']))); $ccaddress = $db->getAddrs(preg_split('/>,/',preg_replace('/>,/', '>>,', $params['input_cc']))); $ccoaddress = $db->getAddrs(preg_split('/>,/',preg_replace('/>,/', '>>,', $params['input_cco']))); if ($toaddress["False"] || $ccaddress["False"] || $ccoaddress["False"]) { return $this->parse_error("Invalid Mail:", ($toaddress["False"] ? $toaddress["False"] : ($ccaddress["False"] ? $ccaddress["False"] : $ccoaddress["False"]))); } $toaddress = implode(',', $toaddress); $ccaddress = implode(',', $ccaddress); $ccoaddress = implode(',', $ccoaddress); if ($toaddress == "" && $ccaddress == "" && $ccoaddress == "") { return $this->parse_error("Invalid Mail:", ($params['input_to'] ? $params['input_to'] : ($params['input_cc'] ? $params['input_cc'] : $params['input_cco']))); } $toaddress = preg_replace('/<\s+/', '<', $toaddress); $toaddress = preg_replace('/\s+>/', '>', $toaddress); $ccaddress = preg_replace('/<\s+/', '<', $ccaddress); $ccaddress = preg_replace('/\s+>/', '>', $ccaddress); $ccoaddress = preg_replace('/<\s+/', '<', $ccoaddress); $ccoaddress = preg_replace('/\s+>/', '>', $ccoaddress); $replytoaddress = $params['input_replyto']; $subject = $params['input_subject']; $return_receipt = $params['input_return_receipt']; $is_important = $params['input_important_message']; $encrypt = $params['input_return_cripto']; $signed = $params['input_return_digital']; $params['attachments'] = mb_convert_encoding($params['attachments'], "UTF7-IMAP","UTF-8, ISO-8859-1, UTF7-IMAP"); $message_attachments = $params['message_attachments']; if (substr($params['input_to'], -1) == ',') $params['input_to'] = substr($params['input_to'], 0, -1); if (substr($params['input_cc'], -1) == ',') $params['input_cc'] = substr($params['input_cc'], 0, -1); if (substr($params['input_cco'], -1) == ',') $params['input_cco'] = substr($params['input_cco'], 0, -1); // Valida numero Maximo de Destinatarios if ($_SESSION['phpgw_info']['expresso']['expressoMail']['expressoAdmin_maximum_recipients'] > 0) { $sendersNumber = count(explode(',', $params['input_to'])); if ($params['input_cc']) $sendersNumber += count(explode(',', $params['input_cc'])); if ($params['input_cco']) $sendersNumber += count(explode(',', $params['input_cco'])); $userMaxmimumSenders = $db->getMaximumRecipientsUser($this->username); if ($userMaxmimumSenders) { if ($sendersNumber > $userMaxmimumSenders) return $this->functions->getLang('Number of recipients greater than allowed'); } else { $ldap = new ldap_functions(); $groupsToUser = $ldap->get_user_groups($this->username); $groupMaxmimumSenders = $db->getMaximumRecipientsGroup($groupsToUser); if ($groupMaxmimumSenders > 0) { if ($sendersNumber > $groupMaxmimumSenders) return $this->functions->getLang('Number of recipients greater than allowed'); } else { if ($sendersNumber > $_SESSION['phpgw_info']['expresso']['expressoMail']['expressoAdmin_maximum_recipients']) return $this->functions->getLang('Number of recipients greater than allowed'); } } } //Fim Valida numero maximo de destinatarios //Valida envio de email para shared accounts if ($_SESSION['phpgw_info']['expresso']['expressoMail']['expressoMail_block_institutional_comunication'] == 'true') { $ldap = new ldap_functions(); $arrayF = explode(';', $params['input_from']); /* * Verifica se o remetente n?o ? uma conta compartilhada */ if (!$ldap->isSharedAccountByMail($arrayF[1])) { $groupsToUser = $ldap->get_user_groups($this->username); $sharedAccounts = $ldap->returnSharedsAccounts($toaddress, $ccaddress, $ccoaddress); /* * Pega o UID do remetente */ $uidFrom = $ldap->mail2uid($arrayF[1]); /* * Remove a conta compartilhada caso o uid do remetente exista na conta compartilhada */ foreach ($sharedAccounts as $key => $value) { if ($value) $acl = $this->getaclfrombox($value); if (array_key_exists($uidFrom, $acl)) unset($sharedAccounts[$key]); } /* * Caso ainda exista contas compartilhadas, verifica se existe alguma exce??o para estas contas */ if (count($sharedAccounts) > 0) $accountsBlockeds = $db->validadeSharedAccounts($this->username, $groupsToUser, $sharedAccounts); /* * Retorna as contas compartilhadas bloqueadas */ if (count($accountsBlockeds) > 0) { $return = ''; foreach ($accountsBlockeds as $accountBlocked) $return.= $accountBlocked . ', '; $return = substr($return, 0, -2); return $this->functions->getLang('you are blocked from sending mail to the following addresses') . ': ' . $return; } } } // Fim Valida envio de email para shared accounts // TODO - implementar tratamento SMIME no novo serviço de envio de emails e retirar o AND false abaixo if ($params['smime'] AND false) { $body = $params['smime']; $mail->SMIME = true; // A MSG assinada deve ser testada neste ponto. // Testar o certificado e a integridade da msg.... include_once(dirname(__FILE__) . "/../../security/classes/CertificadoB.php"); $erros_acumulados = ''; $certificado = new certificadoB(); $validade = $certificado->verificar($body); if (!$validade) { foreach ($certificado->erros_ssl as $linha_erro) { $erros_acumulados .= $linha_erro; } } else { // Testa o CERTIFICADO: se o CPF he o do usuario logado, se pode assinar msgs e se nao esta expirado... if ($certificado->apresentado) { if ($certificado->dados['EXPIRADO']) $erros_acumulados .='Certificado expirado.'; $this->cpf = isset($GLOBALS['phpgw_info']['server']['certificado_atributo_cpf']) && $GLOBALS['phpgw_info']['server']['certificado_atributo_cpf'] != '' ? $_SESSION['phpgw_info']['expressomail']['user'][$GLOBALS['phpgw_info']['server']['certificado_atributo_cpf']] : $this->username; if ($certificado->dados['CPF'] != $this->cpf) $erros_acumulados .=' CPF no certificado diferente do logado no expresso.'; if (!($certificado->dados['KEYUSAGE']['digitalSignature'] && $certificado->dados['EXTKEYUSAGE']['emailProtection'])) $erros_acumulados .=' Certificado nao permite assinar mensagens.'; } else { $$erros_acumulados .= 'Nao foi possivel usar o certificado para assinar a msg'; } } if (!$erros_acumulados == '') { return $erros_acumulados; } } else { //Compatibilização com Outlook, ao encaminhar a mensagem $body = mb_ereg_replace('