/** * Reads an email object from MAPI * * @param mixed $mapimessage * @param ContentParameters $contentparameters * * @access private * @return SyncEmail */ private function getEmail($mapimessage, $contentparameters) { $message = new SyncMail(); $this->getPropsFromMAPI($message, $mapimessage, MAPIMapping::GetEmailMapping()); $emailproperties = MAPIMapping::GetEmailProperties(); $messageprops = $this->getProps($mapimessage, $emailproperties); if (isset($messageprops[PR_SOURCE_KEY])) { $sourcekey = $messageprops[PR_SOURCE_KEY]; } else { return false; } //set the body according to contentparameters and supported AS version $this->setMessageBody($mapimessage, $contentparameters, $message); $fromname = $fromaddr = ""; if (isset($messageprops[$emailproperties["representingname"]])) { // remove encapsulating double quotes from the representingname $fromname = preg_replace('/^\\"(.*)\\"$/', "\${1}", $messageprops[$emailproperties["representingname"]]); } if (isset($messageprops[$emailproperties["representingentryid"]])) { $fromaddr = $this->getSMTPAddressFromEntryID($messageprops[$emailproperties["representingentryid"]]); } if ($fromname == $fromaddr) { $fromname = ""; } if ($fromname) { $from = "\"" . w2u($fromname) . "\" <" . w2u($fromaddr) . ">"; } else { //START CHANGED dw2412 HTC shows "error" if sender name is unknown $from = "\"" . w2u($fromaddr) . "\" <" . w2u($fromaddr) . ">"; } //END CHANGED dw2412 HTC shows "error" if sender name is unknown $message->from = $from; // process Meeting Requests if (isset($message->messageclass) && strpos($message->messageclass, "IPM.Schedule.Meeting") === 0) { $message->meetingrequest = new SyncMeetingRequest(); $this->getPropsFromMAPI($message->meetingrequest, $mapimessage, MAPIMapping::GetMeetingRequestMapping()); $meetingrequestproperties = MAPIMapping::GetMeetingRequestProperties(); $props = $this->getProps($mapimessage, $meetingrequestproperties); // Get the GOID if (isset($props[$meetingrequestproperties["goidtag"]])) { $message->meetingrequest->globalobjid = base64_encode($props[$meetingrequestproperties["goidtag"]]); } // Set Timezone if (isset($props[$meetingrequestproperties["timezonetag"]])) { $tz = $this->getTZFromMAPIBlob($props[$meetingrequestproperties["timezonetag"]]); } else { $tz = $this->getGMTTZ(); } $message->meetingrequest->timezone = base64_encode($this->getSyncBlobFromTZ($tz)); // send basedate if exception if (isset($props[$meetingrequestproperties["recReplTime"]]) || isset($props[$meetingrequestproperties["lidIsException"]]) && $props[$meetingrequestproperties["lidIsException"]] == true) { if (isset($props[$meetingrequestproperties["recReplTime"]])) { $basedate = $props[$meetingrequestproperties["recReplTime"]]; $message->meetingrequest->recurrenceid = $this->getGMTTimeByTZ($basedate, $this->getGMTTZ()); } else { if (!isset($props[$meetingrequestproperties["goidtag"]]) || !isset($props[$meetingrequestproperties["recurStartTime"]]) || !isset($props[$meetingrequestproperties["timezonetag"]])) { ZLog::Write(LOGLEVEL_WARN, "Missing property to set correct basedate for exception"); } else { $basedate = Utils::ExtractBaseDate($props[$meetingrequestproperties["goidtag"]], $props[$meetingrequestproperties["recurStartTime"]]); $message->meetingrequest->recurrenceid = $this->getGMTTimeByTZ($basedate, $tz); } } } // Organizer is the sender $message->meetingrequest->organizer = $message->from; // Process recurrence if (isset($props[$meetingrequestproperties["isrecurringtag"]]) && $props[$meetingrequestproperties["isrecurringtag"]]) { $myrec = new SyncMeetingRequestRecurrence(); // get recurrence -> put $message->meetingrequest as message so the 'alldayevent' is set correctly $this->getRecurrence($mapimessage, $props, $message->meetingrequest, $myrec, $tz); $message->meetingrequest->recurrences = array($myrec); } // Force the 'alldayevent' in the object at all times. (non-existent == 0) if (!isset($message->meetingrequest->alldayevent) || $message->meetingrequest->alldayevent == "") { $message->meetingrequest->alldayevent = 0; } // Instancetype // 0 = single appointment // 1 = master recurring appointment // 2 = single instance of recurring appointment // 3 = exception of recurring appointment $message->meetingrequest->instancetype = 0; if (isset($props[$meetingrequestproperties["isrecurringtag"]]) && $props[$meetingrequestproperties["isrecurringtag"]] == 1) { $message->meetingrequest->instancetype = 1; } else { if ((!isset($props[$meetingrequestproperties["isrecurringtag"]]) || $props[$meetingrequestproperties["isrecurringtag"]] == 0) && isset($message->meetingrequest->recurrenceid)) { if (isset($props[$meetingrequestproperties["appSeqNr"]]) && $props[$meetingrequestproperties["appSeqNr"]] == 0) { $message->meetingrequest->instancetype = 2; } else { $message->meetingrequest->instancetype = 3; } } } // Disable reminder if it is off if (!isset($props[$meetingrequestproperties["reminderset"]]) || $props[$meetingrequestproperties["reminderset"]] == false) { $message->meetingrequest->reminder = ""; } else { ///set the default reminder time to seconds if ($props[$meetingrequestproperties["remindertime"]] == 0x5ae980e1) { $message->meetingrequest->reminder = 900; } else { $message->meetingrequest->reminder = $props[$meetingrequestproperties["remindertime"]] * 60; } } // Set sensitivity to 0 if missing if (!isset($message->meetingrequest->sensitivity)) { $message->meetingrequest->sensitivity = 0; } // if a meeting request response hasn't been processed yet, // do it so that the attendee status is updated on the mobile if (!isset($messageprops[$emailproperties["processed"]])) { $req = new Meetingrequest($this->store, $mapimessage, $this->session); if ($req->isMeetingRequestResponse()) { $req->processMeetingRequestResponse(); } if ($req->isMeetingCancellation()) { $req->processMeetingCancellation(); } } } // Add attachments $attachtable = mapi_message_getattachmenttable($mapimessage); $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM)); $entryid = bin2hex($messageprops[$emailproperties["entryid"]]); foreach ($rows as $row) { if (isset($row[PR_ATTACH_NUM])) { $mapiattach = mapi_message_openattach($mapimessage, $row[PR_ATTACH_NUM]); $attachprops = mapi_getprops($mapiattach, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME, PR_ATTACHMENT_HIDDEN, PR_ATTACH_CONTENT_ID, PR_ATTACH_CONTENT_ID_W, PR_ATTACH_MIME_TAG, PR_ATTACH_MIME_TAG_W)); $stream = mapi_openpropertytostream($mapiattach, PR_ATTACH_DATA_BIN); if ($stream) { $stat = mapi_stream_stat($stream); if (Request::GetProtocolVersion() >= 12.0) { $attach = new SyncBaseAttachment(); } else { $attach = new SyncAttachment(); } // the displayname is handled equal for all AS versions $attach->displayname = w2u(isset($attachprops[PR_ATTACH_LONG_FILENAME]) ? $attachprops[PR_ATTACH_LONG_FILENAME] : (isset($attachprops[PR_ATTACH_FILENAME]) ? $attachprops[PR_ATTACH_FILENAME] : "attachment.bin")); // fix attachment name in case of inline images if ($attach->displayname == "inline.txt" && (isset($attachprops[PR_ATTACH_MIME_TAG]) || $attachprops[PR_ATTACH_MIME_TAG_W])) { $mimetype = isset($attachprops[PR_ATTACH_MIME_TAG]) ? $attachprops[PR_ATTACH_MIME_TAG] : $attachprops[PR_ATTACH_MIME_TAG_W]; $mime = explode("/", $mimetype); if (count($mime) == 2 && $mime[0] == "image") { $attach->displayname = "inline." . $mime[1]; } } // set AS version specific parameters if (Request::GetProtocolVersion() >= 12.0) { $attach->filereference = $entryid . ":" . $row[PR_ATTACH_NUM]; $attach->method = 1; $attach->estimatedDataSize = $stat["cb"]; if (isset($attachprops[PR_ATTACH_CONTENT_ID]) && $attachprops[PR_ATTACH_CONTENT_ID]) { $attach->contentid = $attachprops[PR_ATTACH_CONTENT_ID]; } if (!isset($attach->contentid) && isset($attachprops[PR_ATTACH_CONTENT_ID_W]) && $attachprops[PR_ATTACH_CONTENT_ID_W]) { $attach->contentid = $attachprops[PR_ATTACH_CONTENT_ID_W]; } if (isset($attachprops[PR_ATTACHMENT_HIDDEN]) && $attachprops[PR_ATTACHMENT_HIDDEN]) { $attach->isinline = 1; } if (!isset($message->asattachments)) { $message->asattachments = array(); } array_push($message->asattachments, $attach); } else { $attach->attsize = $stat["cb"]; $attach->attname = $entryid . ":" . $row[PR_ATTACH_NUM]; if (!isset($message->attachments)) { $message->attachments = array(); } array_push($message->attachments, $attach); } } } } // Get To/Cc as SMTP addresses (this is different from displayto and displaycc because we are putting // in the SMTP addresses as well, while displayto and displaycc could just contain the display names $message->to = array(); $message->cc = array(); $reciptable = mapi_message_getrecipienttable($mapimessage); $rows = mapi_table_queryallrows($reciptable, array(PR_RECIPIENT_TYPE, PR_DISPLAY_NAME, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS, PR_ENTRYID)); foreach ($rows as $row) { $address = ""; $fulladdr = ""; $addrtype = isset($row[PR_ADDRTYPE]) ? $row[PR_ADDRTYPE] : ""; if (isset($row[PR_SMTP_ADDRESS])) { $address = $row[PR_SMTP_ADDRESS]; } elseif ($addrtype == "SMTP" && isset($row[PR_EMAIL_ADDRESS])) { $address = $row[PR_EMAIL_ADDRESS]; } elseif ($addrtype == "ZARAFA" && isset($row[PR_ENTRYID])) { $address = $this->getSMTPAddressFromEntryID($row[PR_ENTRYID]); } $name = isset($row[PR_DISPLAY_NAME]) ? $row[PR_DISPLAY_NAME] : ""; if ($name == "" || $name == $address) { $fulladdr = w2u($address); } else { if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') { $fulladdr = "\"" . w2u($name) . "\" <" . w2u($address) . ">"; } else { $fulladdr = w2u($name) . "<" . w2u($address) . ">"; } } if ($row[PR_RECIPIENT_TYPE] == MAPI_TO) { array_push($message->to, $fulladdr); } else { if ($row[PR_RECIPIENT_TYPE] == MAPI_CC) { array_push($message->cc, $fulladdr); } } } if (is_array($message->to) && !empty($message->to)) { $message->to = implode(", ", $message->to); } if (is_array($message->cc) && !empty($message->cc)) { $message->cc = implode(", ", $message->cc); } // without importance some mobiles assume "0" (low) - Mantis #439 if (!isset($message->importance)) { $message->importance = IMPORTANCE_NORMAL; } //TODO contentclass and nativebodytype and internetcpid if (!isset($message->internetcpid)) { $message->internetcpid = defined('STORE_INTERNET_CPID') ? constant('STORE_INTERNET_CPID') : INTERNET_CPID_WINDOWS1252; } $this->setFlag($mapimessage, $message); $message->contentclass = DEFAULT_EMAIL_CONTENTCLASS; if (!isset($message->nativebodytype)) { $message->nativebodytype = $this->getNativeBodyType($messageprops); } return $message; }
function parse_messages($store, $entryid) { global $total_deleted; $folder = mapi_msgstore_openentry($store, $entryid); if (!$folder) { print "Unable to open folder."; return false; } $table = mapi_folder_getcontentstable($folder); if (!$table) { print "Unable to open table."; return false; } $org_hash = null; $dup_messages = array(); $dup_count = 0; $result = mapi_table_sort($table, array(PR_CLIENT_SUBMIT_TIME => TABLE_SORT_DESCEND)); if ($result == false) { echo "Could not sort table\n"; return; } while (1) { // query messages from folders content table $filters = array(PR_MESSAGE_SIZE, PR_CLIENT_SUBMIT_TIME, PR_MESSAGE_RECIPIENTS, PR_EMAIL_ADDRESS, PR_BODY, PR_HTML, PR_ENTRYID, PR_SUBJECT, PR_SMTP_ADDRESS); $rows = mapi_table_queryrows($table, $filters, 0, 50); if (count($rows) == 0) { break; } // we got the messages foreach ($rows as $row) { // hash message body (plaintext + html + subject) $md5_subject = md5($row[PR_SUBJECT]); $md5_body = md5($row[PR_BODY]); $md5_html = md5($row[PR_HTML]); $md5_eid = $row[PR_ENTRYID]; $PR_EMAIL_ADDRESS = $row[PR_EMAIL_ADDRESS]; $PR_SMTP_ADDRESS = $row[PR_SMTP_ADDRESS]; } $message = mapi_msgstore_openentry($store, $md5_eid); $recipTable = mapi_message_getrecipienttable($message); $oldRecipients = mapi_table_queryallrows($recipTable, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TYPE, PR_SEND_INTERNET_ENCODING, PR_SEND_RICH_INFO, PR_RECIPIENT_DISPLAY_NAME, PR_ADDRTYPE, PR_DISPLAY_TYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_FLAGS, PR_ROWID)); print_r($oldRecipients); } }
/** * Clear responses of all attendees who have replied in past. * @param MAPI_MESSAGE $message on which responses should be cleared */ function clearRecipientResponse($message) { $recipTable = mapi_message_getrecipienttable($message); $recipsRows = mapi_table_queryallrows($recipTable, $this->recipprops); foreach ($recipsRows as $recipient) { if (($recipient[PR_RECIPIENT_FLAGS] & recipOrganizer) != recipOrganizer) { // Recipient is attendee, set the trackstatus to "Not Responded" $recipient[PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusNone; } else { // Recipient is organizer, this is not possible, but for safety // it is best to clear the trackstatus for him as well by setting // the trackstatus to "Organized". $recipient[PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusNone; } mapi_message_modifyrecipients($message, MODRECIP_MODIFY, array($recipient)); } }
/** * Function which applies the provided recipients to the exception, also checks for deleted recipients. * * The $exception_recips should be an array containing all recipients which must be applied * to the exception. This will copy all recipients from the original message and then start filter * out all recipients which are not provided by the $exception_recips list. * * @param resource $message exception attachment of recurring item * @param array $exception_recips list of recipients */ function setAllExceptionRecipients($message, $exception_recips) { $deletedRecipients = array(); $useMessageRecipients = false; $recipientTable = mapi_message_getrecipienttable($message); $recipientRows = mapi_table_queryallrows($recipientTable, $this->recipprops); if (empty($recipientRows)) { $useMessageRecipients = true; $recipientTable = mapi_message_getrecipienttable($this->message); $recipientRows = mapi_table_queryallrows($recipientTable, $this->recipprops); } // Add organizer to meeting only if it is not organized. $msgprops = mapi_getprops($message, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ADDRTYPE, $this->proptags['responsestatus'])); if (isset($msgprops[$this->proptags['responsestatus']]) && $msgprops[$this->proptags['responsestatus']] != olResponseOrganized) { $this->addOrganizer($msgprops, $exception_recips); } if (!empty($exception_recips)) { foreach ($recipientRows as $key => $recipient) { $found = false; foreach ($exception_recips as $excep_recip) { if (isset($recipient[PR_SEARCH_KEY]) && isset($excep_recip[PR_SEARCH_KEY]) && $recipient[PR_SEARCH_KEY] == $excep_recip[PR_SEARCH_KEY]) { $found = true; } } if (!$found) { $foundInDeletedRecipients = false; // Look if the $recipient is in the list of deleted recipients if (!empty($deletedRecipients)) { foreach ($deletedRecipients as $recip) { if ($recip[PR_SEARCH_KEY] == $recipient[PR_SEARCH_KEY]) { $foundInDeletedRecipients = true; break; } } } // If recipient is not in list of deleted recipient, add him if (!$foundInDeletedRecipients) { if (!isset($recipient[PR_RECIPIENT_FLAGS]) || $recipient[PR_RECIPIENT_FLAGS] != (recipReserved | recipExceptionalDeleted | recipSendable)) { $recipient[PR_RECIPIENT_FLAGS] = recipSendable | recipExceptionalDeleted; } else { $recipient[PR_RECIPIENT_FLAGS] = recipReserved | recipExceptionalDeleted | recipSendable; } $recipient[PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusNone; // No Response required $deletedRecipients[] = $recipient; } } // When $message contains a non-empty recipienttable, we must delete the recipients // before re-adding them. However, when $message is doesn't contain any recipients, // we are using the recipient table of the original message ($this->message) // rather then $message. In that case, we don't need to remove the recipients // from the $message, as the recipient table is already empty, and // mapi_message_modifyrecipients() will throw an error. if ($useMessageRecipients === false) { mapi_message_modifyrecipients($message, MODRECIP_REMOVE, array($recipient)); } } $exception_recips = array_merge($exception_recips, $deletedRecipients); } else { $exception_recips = $recipientRows; } if (!empty($exception_recips)) { // Set the new list of recipients on the exception message, this also removes the existing recipients mapi_message_modifyrecipients($message, 0, $exception_recips); } }
/** * Function which clones current occurrence and sets appropriate properties. * The original recurring item is moved to next occurrence. *@param boolean $markComplete true if existing occurrence has to be mark complete else false. */ function regenerateTask($markComplete) { // Get all properties $taskItemProps = mapi_getprops($this->message); if (isset($this->action["subject"])) { $taskItemProps[$this->proptags["subject"]] = $this->action["subject"]; } if (isset($this->action["importance"])) { $taskItemProps[$this->proptags["importance"]] = $this->action["importance"]; } if (isset($this->action["startdate"])) { $taskItemProps[$this->proptags["startdate"]] = $this->action["startdate"]; $taskItemProps[$this->proptags["commonstart"]] = $this->action["startdate"]; } if (isset($this->action["duedate"])) { $taskItemProps[$this->proptags["duedate"]] = $this->action["duedate"]; $taskItemProps[$this->proptags["commonend"]] = $this->action["duedate"]; } $folder = mapi_msgstore_openentry($this->store, $taskItemProps[PR_PARENT_ENTRYID]); $newMessage = mapi_folder_createmessage($folder); $taskItemProps[$this->proptags["status"]] = $markComplete ? olTaskComplete : olTaskNotStarted; $taskItemProps[$this->proptags["complete"]] = $markComplete; $taskItemProps[$this->proptags["percent_complete"]] = $markComplete ? 1 : 0; // This occurrence has been marked as 'Complete' so disable reminder if ($markComplete) { $taskItemProps[$this->proptags["reset_reminder"]] = false; $taskItemProps[$this->proptags["reminder"]] = false; $taskItemProps[$this->proptags["datecompleted"]] = $this->action["datecompleted"]; unset($this->action[$this->proptags['datecompleted']]); } // Recurrence ends for this item $taskItemProps[$this->proptags["dead_occurrence"]] = true; $taskItemProps[$this->proptags["task_f_creator"]] = true; //OL props $taskItemProps[$this->proptags["side_effects"]] = 1296; $taskItemProps[$this->proptags["icon_index"]] = 1280; // Copy recipients $recipienttable = mapi_message_getrecipienttable($this->message); $recipients = mapi_table_queryallrows($recipienttable, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TYPE, PR_SEND_INTERNET_ENCODING, PR_SEND_RICH_INFO, PR_RECIPIENT_DISPLAY_NAME, PR_ADDRTYPE, PR_DISPLAY_TYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_TRACKSTATUS_TIME, PR_RECIPIENT_FLAGS, PR_ROWID)); $copy_to_recipientTable = mapi_message_getrecipienttable($newMessage); $copy_to_recipientRows = mapi_table_queryallrows($copy_to_recipientTable, array(PR_ROWID)); foreach ($copy_to_recipientRows as $recipient) { mapi_message_modifyrecipients($newMessage, MODRECIP_REMOVE, array($recipient)); } mapi_message_modifyrecipients($newMessage, MODRECIP_ADD, $recipients); // Copy attachments $attachmentTable = mapi_message_getattachmenttable($this->message); if ($attachmentTable) { $attachments = mapi_table_queryallrows($attachmentTable, array(PR_ATTACH_NUM, PR_ATTACH_SIZE, PR_ATTACH_LONG_FILENAME, PR_ATTACHMENT_HIDDEN, PR_DISPLAY_NAME, PR_ATTACH_METHOD)); foreach ($attachments as $attach_props) { $attach_old = mapi_message_openattach($this->message, (int) $attach_props[PR_ATTACH_NUM]); $attach_newResourceMsg = mapi_message_createattach($newMessage); mapi_copyto($attach_old, array(), array(), $attach_newResourceMsg, 0); mapi_savechanges($attach_newResourceMsg); } } mapi_setprops($newMessage, $taskItemProps); mapi_savechanges($newMessage); // Update body of original message $msgbody = mapi_message_openproperty($this->message, PR_BODY); $msgbody = trim($this->windows1252_to_utf8($msgbody), ""); $separator = "------------\r\n"; if (!empty($msgbody) && strrpos($msgbody, $separator) === false) { $msgbody = $separator . $msgbody; $stream = mapi_openpropertytostream($this->message, PR_BODY, MAPI_CREATE | MAPI_MODIFY); mapi_stream_setsize($stream, strlen($msgbody)); mapi_stream_write($stream, $msgbody); mapi_stream_commit($stream); } // We need these properties to notify client return mapi_getprops($newMessage, array(PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID)); }
function buildEMLAttachment($attach) { $msgembedded = mapi_attach_openobj($attach); $msgprops = mapi_getprops($msgembedded, array(PR_MESSAGE_CLASS, PR_CLIENT_SUBMIT_TIME, PR_DISPLAY_TO, PR_SUBJECT, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_EMAIL_ADDRESS)); $msgembeddedrcpttable = mapi_message_getrecipienttable($msgembedded); $msgto = $msgprops[PR_DISPLAY_TO]; if ($msgembeddedrcpttable) { $msgembeddedrecipients = mapi_table_queryrows($msgembeddedrcpttable, array(PR_ADDRTYPE, PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS, PR_RECIPIENT_TYPE, PR_RECIPIENT_FLAGS, PR_PROPOSEDNEWTIME, PR_PROPOSENEWTIME_START, PR_PROPOSENEWTIME_END, PR_RECIPIENT_TRACKSTATUS), 0, 99999999); foreach ($msgembeddedrecipients as $rcpt) { if ($rcpt[PR_DISPLAY_NAME] == $msgprops[PR_DISPLAY_TO]) { $msgto = $rcpt[PR_DISPLAY_NAME]; if (isset($rcpt[PR_EMAIL_ADDRESS]) && $rcpt[PR_EMAIL_ADDRESS] != $msgprops[PR_DISPLAY_TO]) { $msgto .= " <" . $rcpt[PR_EMAIL_ADDRESS] . ">"; } break; } } } $msgsubject = $msgprops[PR_SUBJECT]; $msgfrom = $msgprops[PR_SENT_REPRESENTING_NAME]; if (isset($msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS]) && $msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS] != $msgprops[PR_SENT_REPRESENTING_NAME]) { $msgfrom .= " <" . $msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS] . ">"; } $msgtime = $msgprops[PR_CLIENT_SUBMIT_TIME]; $msgembeddedbody = eml_ReadMessage($msgembedded); $msgembeddedattachtable = mapi_message_getattachmenttable($msgembedded); $msgembeddedattachtablerows = mapi_table_queryallrows($msgembeddedattachtable, array(PR_ATTACH_NUM, PR_ATTACH_METHOD)); if ($msgembeddedattachtablerows) { $boundary = '=_zpush_static'; $headercontenttype = "multipart/mixed"; $msgembeddedbody['body'] = "Unfortunately your mobile is not able to handle MIME Messages\n" . "--" . $boundary . "\n" . "Content-Type: " . $msgembeddedbody['content'] . "; charset=utf-8\n" . "Content-Transfer-Encoding: quoted-printable\n\n" . $msgembeddedbody['body'] . "\n"; foreach ($msgembeddedattachtablerows as $msgembeddedattachtablerow) { $msgembeddedattach = mapi_message_openattach($msgembedded, $msgembeddedattachtablerow[PR_ATTACH_NUM]); if (!$msgembeddedattach) { debugLog("Unable to open attachment number {$attachnum}"); } else { $msgembeddedattachprops = mapi_getprops($msgembeddedattach, array(PR_ATTACH_MIME_TAG, PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME, PR_DISPLAY_NAME)); if (isset($msgembeddedattachprops[PR_ATTACH_LONG_FILENAME])) { $attachfilename = w2u($msgembeddedattachprops[PR_ATTACH_LONG_FILENAME]); } else { if (isset($msgembeddedattachprops[PR_ATTACH_FILENAME])) { $attachfilename = w2u($msgembeddedattachprops[PR_ATTACH_FILENAME]); } else { if (isset($msgembeddedattachprops[PR_DISPLAY_NAME])) { $attachfilename = w2u($msgembeddedattachprops[PR_DISPLAY_NAME]); } else { $attachfilename = w2u("untitled"); } } } if ($msgembeddedattachtablerow[PR_ATTACH_METHOD] == ATTACH_EMBEDDED_MSG) { $attachfilename .= w2u(".eml"); } $msgembeddedbody['body'] .= "--" . $boundary . "\n" . "Content-Type: " . $msgembeddedattachprops[PR_ATTACH_MIME_TAG] . ";\n" . " name=\"" . $attachfilename . "\"\n" . "Content-Transfer-Encoding: base64\n" . "Content-Disposition: attachment;\n" . " filename=\"" . $attachfilename . "\"\n\n"; $msgembeddedattachstream = mapi_openpropertytostream($msgembeddedattach, PR_ATTACH_DATA_BIN); $msgembeddedattachment = ""; while (1) { $msgembeddedattachdata = mapi_stream_read($msgembeddedattachstream, 4096); if (byte_strlen($msgembeddedattachdata) == 0) { break; } $msgembeddedattachment .= $msgembeddedattachdata; } $msgembeddedbody['body'] .= chunk_split(base64_encode($msgembeddedattachment)) . "\n"; unset($msgembeddedattachment); } } $msgembeddedbody['body'] .= "--" . $boundary . "--\n"; } else { $headercontenttype = $msgembeddedbody['content'] . "; charset=utf-8"; $boundary = ''; } $msgembeddedheader = "Subject: " . $msgsubject . "\n" . "From: " . $msgfrom . "\n" . "To: " . $msgto . "\n" . "Date: " . gmstrftime("%a, %d %b %Y %T +0000", $msgprops[PR_CLIENT_SUBMIT_TIME]) . "\n" . "MIME-Version: 1.0\n" . "Content-Type: " . $headercontenttype . ";\n" . ($boundary ? " boundary=\"" . $boundary . "\"\n" : "") . "\n"; $stream = mapi_stream_create(); mapi_stream_setsize($stream, byte_strlen($msgembeddedheader . $msgembeddedbody['body'])); mapi_stream_write($stream, $msgembeddedheader . $msgembeddedbody['body']); mapi_stream_seek($stream, 0, STREAM_SEEK_SET); return $stream; }
function _getEmail($mapimessage, $truncsize, $mimesupport = 0) { $message = new SyncMail(); $this->_getPropsFromMAPI($message, $mapimessage, $this->_emailmapping); // Override 'From' to show "Full Name <*****@*****.**>" $messageprops = mapi_getprops($mapimessage, array(PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ENTRYID, PR_SOURCE_KEY)); // Override 'body' for truncation $body = mapi_openproperty($mapimessage, PR_BODY); $message->bodysize = strlen($body); if ($message->bodysize > $truncsize) { $body = utf8_truncate($body, $truncsize); $message->bodytruncated = 1; } else { $message->bodytruncated = 0; } $message->body = str_replace("\n", "\r\n", w2u(str_replace("\r", "", $body))); if (isset($messageprops[PR_SOURCE_KEY])) { $sourcekey = $messageprops[PR_SOURCE_KEY]; } else { return false; } $fromname = $fromaddr = ""; if (isset($messageprops[PR_SENT_REPRESENTING_NAME])) { $fromname = $messageprops[PR_SENT_REPRESENTING_NAME]; } if (isset($messageprops[PR_SENT_REPRESENTING_ENTRYID])) { $fromaddr = $this->_getSMTPAddressFromEntryID($messageprops[PR_SENT_REPRESENTING_ENTRYID]); } if ($fromname == $fromaddr) { $fromname = ""; } if ($fromname) { $from = "\"" . w2u($fromname) . "\" <" . w2u($fromaddr) . ">"; } else { //START CHANGED dw2412 HTC shows "error" if sender name is unknown $from = "\"" . w2u($fromaddr) . "\" <" . w2u($fromaddr) . ">"; } //END CHANGED dw2412 HTC shows "error" if sender name is unknown $message->from = $from; // process Meeting Requests if (isset($message->messageclass) && strpos($message->messageclass, "IPM.Schedule.Meeting") === 0) { $message->meetingrequest = new SyncMeetingRequest(); $this->_getPropsFromMAPI($message->meetingrequest, $mapimessage, $this->_meetingrequestmapping); $goidtag = $this->_getPropIdFromString("PT_BINARY:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0x3"); $timezonetag = $this->_getPropIDFromString("PT_BINARY:{00062002-0000-0000-C000-000000000046}:0x8233"); $recReplTime = $this->_getPropIDFromString("PT_SYSTIME:{00062002-0000-0000-C000-000000000046}:0x8228"); $isrecurringtag = $this->_getPropIDFromString("PT_BOOLEAN:{00062002-0000-0000-C000-000000000046}:0x8223"); $recurringstate = $this->_getPropIDFromString("PT_BINARY:{00062002-0000-0000-C000-000000000046}:0x8216"); $appSeqNr = $this->_getPropIDFromString("PT_LONG:{00062002-0000-0000-C000-000000000046}:0x8201"); $lidIsException = $this->_getPropIDFromString("PT_BOOLEAN:{00062002-0000-0000-C000-000000000046}:0xA"); $recurStartTime = $this->_getPropIDFromString("PT_LONG:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0xE"); $recurrenceend = $this->_getPropIDFromString("PT_SYSTIME:{00062002-0000-0000-C000-000000000046}:0x8236"); $props = mapi_getprops($mapimessage, array($goidtag, $timezonetag, $recReplTime, $isrecurringtag, $recurringstate, $appSeqNr, $lidIsException, $recurStartTime, $recurrenceend)); // Get the GOID if (isset($props[$goidtag])) { $message->meetingrequest->globalobjid = base64_encode($props[$goidtag]); } // Set Timezone if (isset($props[$timezonetag])) { $tz = $this->_getTZFromMAPIBlob($props[$timezonetag]); } else { $tz = $this->_getGMTTZ(); } $message->meetingrequest->timezone = base64_encode($this->_getSyncBlobFromTZ($tz)); // send basedate if exception if (isset($props[$recReplTime]) || isset($props[$lidIsException]) && $props[$lidIsException] == true) { if (isset($props[$recReplTime])) { $basedate = $props[$recReplTime]; $message->meetingrequest->recurrenceid = $this->_getGMTTimeByTZ($basedate, $this->_getGMTTZ()); } else { if (!isset($props[$goidtag]) || !isset($props[$recurStartTime]) || !isset($props[$timezonetag])) { debugLog("Missing property to set correct basedate for exception"); } else { $basedate = extractBaseDate($props[$goidtag], $props[$recurStartTime]); $message->meetingrequest->recurrenceid = $this->_getGMTTimeByTZ($basedate, $tz); } } } // Organizer is the sender $message->meetingrequest->organizer = $message->from; // Process recurrence if (isset($props[$isrecurringtag]) && $props[$isrecurringtag]) { $myrec = new SyncMeetingRequestRecurrence(); // get recurrence -> put $message->meetingrequest as message so the 'alldayevent' is set correctly $this->_getRecurrence($mapimessage, $props, $message->meetingrequest, $myrec, $tz); $message->meetingrequest->recurrences = array($myrec); } // Force the 'alldayevent' in the object at all times. (non-existent == 0) if (!isset($message->meetingrequest->alldayevent) || $message->meetingrequest->alldayevent == "") { $message->meetingrequest->alldayevent = 0; } // Instancetype // 0 = single appointment // 1 = master recurring appointment // 2 = single instance of recurring appointment // 3 = exception of recurring appointment $message->meetingrequest->instancetype = 0; if (isset($props[$isrecurringtag]) && $props[$isrecurringtag] == 1) { $message->meetingrequest->instancetype = 1; } else { if ((!isset($props[$isrecurringtag]) || $props[$isrecurringtag] == 0) && isset($message->meetingrequest->recurrenceid)) { if (isset($props[$appSeqNr]) && $props[$appSeqNr] == 0) { $message->meetingrequest->instancetype = 2; } else { $message->meetingrequest->instancetype = 3; } } } // Disable reminder if it is off $reminderset = $this->_getPropIDFromString("PT_BOOLEAN:{00062008-0000-0000-C000-000000000046}:0x8503"); $remindertime = $this->_getPropIDFromString("PT_LONG:{00062008-0000-0000-C000-000000000046}:0x8501"); $messageprops = mapi_getprops($mapimessage, array($reminderset, $remindertime)); if (!isset($messageprops[$reminderset]) || $messageprops[$reminderset] == false) { $message->meetingrequest->reminder = ""; } else { ///set the default reminder time to seconds if ($messageprops[$remindertime] == 0x5ae980e1) { $message->meetingrequest->reminder = 900; } else { $message->meetingrequest->reminder = $messageprops[$remindertime] * 60; } } // Set sensitivity to 0 if missing if (!isset($message->meetingrequest->sensitivity)) { $message->meetingrequest->sensitivity = 0; } } // Add attachments $attachtable = mapi_message_getattachmenttable($mapimessage); $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM)); foreach ($rows as $row) { if (isset($row[PR_ATTACH_NUM])) { $mapiattach = mapi_message_openattach($mapimessage, $row[PR_ATTACH_NUM]); $attachprops = mapi_getprops($mapiattach, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME)); $attach = new SyncAttachment(); $stream = mapi_openpropertytostream($mapiattach, PR_ATTACH_DATA_BIN); if ($stream) { $stat = mapi_stream_stat($stream); $attach->attsize = $stat["cb"]; $attach->displayname = w2u(isset($attachprops[PR_ATTACH_LONG_FILENAME]) ? $attachprops[PR_ATTACH_LONG_FILENAME] : (isset($attachprops[PR_ATTACH_FILENAME]) ? $attachprops[PR_ATTACH_FILENAME] : "attachment.bin")); $attach->attname = bin2hex($this->_folderid) . ":" . bin2hex($sourcekey) . ":" . $row[PR_ATTACH_NUM]; if (!isset($message->attachments)) { $message->attachments = array(); } array_push($message->attachments, $attach); } } } // Get To/Cc as SMTP addresses (this is different from displayto and displaycc because we are putting // in the SMTP addresses as well, while displayto and displaycc could just contain the display names $to = array(); $cc = array(); $reciptable = mapi_message_getrecipienttable($mapimessage); $rows = mapi_table_queryallrows($reciptable, array(PR_RECIPIENT_TYPE, PR_DISPLAY_NAME, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS)); foreach ($rows as $row) { $address = ""; $fulladdr = ""; $addrtype = isset($row[PR_ADDRTYPE]) ? $row[PR_ADDRTYPE] : ""; if (isset($row[PR_SMTP_ADDRESS])) { $address = $row[PR_SMTP_ADDRESS]; } else { if ($addrtype == "SMTP" && isset($row[PR_EMAIL_ADDRESS])) { $address = $row[PR_EMAIL_ADDRESS]; } } $name = isset($row[PR_DISPLAY_NAME]) ? $row[PR_DISPLAY_NAME] : ""; if ($name == "" || $name == $address) { $fulladdr = w2u($address); } else { if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') { $fulladdr = "\"" . w2u($name) . "\" <" . w2u($address) . ">"; } else { $fulladdr = w2u($name) . "<" . w2u($address) . ">"; } } if ($row[PR_RECIPIENT_TYPE] == MAPI_TO) { array_push($to, $fulladdr); } else { if ($row[PR_RECIPIENT_TYPE] == MAPI_CC) { array_push($cc, $fulladdr); } } } $message->to = implode(", ", $to); $message->cc = implode(", ", $cc); if (!isset($message->body) || strlen($message->body) == 0) { $message->body = " "; } if ($mimesupport == 2 && function_exists("mapi_inetmapi_imtoinet")) { $addrBook = mapi_openaddressbook($this->_session); $mstream = mapi_inetmapi_imtoinet($this->_session, $addrBook, $mapimessage, array()); $mstreamstat = mapi_stream_stat($mstream); if ($mstreamstat['cb'] < MAX_EMBEDDED_SIZE) { $message->mimetruncated = 0; $mstreamcontent = mapi_stream_read($mstream, MAX_EMBEDDED_SIZE); $message->mimedata = $mstreamcontent; $message->mimesize = $mstreamstat["cb"]; unset($message->body, $message->bodytruncated); } } // without importance some mobiles assume "0" (low) - Mantis #439 if (!isset($message->importance)) { $message->importance = 1; } return $message; }
/** Deletes all recipients from given message object * *@param $message MAPI message from which recipients are to be removed. */ function deleteAllRecipients($message) { $recipTable = mapi_message_getrecipienttable($message); $recipRows = mapi_table_queryallrows($recipTable, array(PR_ROWID)); foreach ($recipRows as $recipient) { mapi_message_modifyrecipients($message, MODRECIP_REMOVE, array($recipient)); } }
function _getEmail($mapimessage, $truncsize) { $message = new SyncMail(); $this->_getPropsFromMAPI($message, $mapimessage, $this->_emailmapping); // Override 'From' to show "Full Name <*****@*****.**>" $messageprops = mapi_getprops($mapimessage, array(PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ENTRYID, PR_SOURCE_KEY)); // Override 'body' for truncation $body = mapi_openproperty($mapimessage, PR_BODY); if (strlen($body) > $truncsize) { $body = substr($body, 0, $truncsize); $message->bodytruncated = 1; } else { $message->bodytruncated = 0; } $message->body = str_replace("\n", "\r\n", w2u(str_replace("\r", "", $body))); if (isset($messageprops[PR_SOURCE_KEY])) { $sourcekey = $messageprops[PR_SOURCE_KEY]; } else { return false; } $fromname = $fromaddr = ""; if (isset($messageprops[PR_SENT_REPRESENTING_NAME])) { $fromname = $messageprops[PR_SENT_REPRESENTING_NAME]; } if (isset($messageprops[PR_SENT_REPRESENTING_ENTRYID])) { $fromaddr = $this->_getSMTPAddressFromEntryID($messageprops[PR_SENT_REPRESENTING_ENTRYID]); } if ($fromname == $fromaddr) { $fromname = ""; } if ($fromname) { $from = "\"" . w2u($fromname) . "\" <" . $fromaddr . ">"; } else { $from = $fromaddr; } $message->from = $from; if (isset($message->messageclass) && strpos($message->messageclass, "IPM.Schedule.Meeting.Request") === 0) { $message->meetingrequest = new SyncMeetingRequest(); $this->_getPropsFromMAPI($message->meetingrequest, $mapimessage, $this->_meetingrequestmapping); $goidtag = $this->_getPropIdFromString("PT_BINARY:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0x3"); $timezonetag = $this->_getPropIDFromString("PT_BINARY:{00062002-0000-0000-C000-000000000046}:0x8233"); // Organizer is the sender $message->meetingrequest->organizer = $message->from; // Get the GOID $props = mapi_getprops($mapimessage, array($goidtag)); if (isset($props[$goidtag])) { $message->meetingrequest->globalobjid = base64_encode($props[$goidtag]); } // Force the 'alldayevent' in the object at all times. (non-existent == 0) if (!isset($message->meetingrequest->alldayevent) || $message->meetingrequest->alldayevent == "") { $message->meetingrequest->alldayevent = 0; } // Set Timezone if (isset($recurprops[$timezonetag])) { $tz = $this->_getTZFromMAPIBlob($recurprops[$timezonetag]); } else { $tz = $this->_getGMTTZ(); } if ($tz) { $message->meetingrequest->timezone = base64_encode($this->_getSyncBlobFromTZ($tz)); } // 'Instance' is always 0 (?) $message->meetingrequest->instancetype = 0; // Disable reminder if it is off $reminderset = $this->_getPropIDFromString("PT_BOOLEAN:{00062008-0000-0000-C000-000000000046}:0x8503"); $remindertime = $this->_getPropIDFromString("PT_LONG:{00062008-0000-0000-C000-000000000046}:0x8501"); $messageprops = mapi_getprops($mapimessage, array($reminderset, $remindertime)); if (!isset($messageprops[$reminderset]) || $messageprops[$reminderset] == false) { $message->meetingrequest->reminder = ""; } else { ///set the default reminder time to seconds if ($messageprops[$remindertime] == 0x5ae980e1) { $message->meetingrequest->reminder = 900; } else { $message->meetingrequest->reminder = $messageprops[$remindertime] * 60; } } // Set sensitivity to 0 if missing if (!isset($message->meetingrequest->sensitivity)) { $message->meetingrequest->sensitivity = 0; } } // Add attachments $attachtable = mapi_message_getattachmenttable($mapimessage); $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM)); foreach ($rows as $row) { if (isset($row[PR_ATTACH_NUM])) { $mapiattach = mapi_message_openattach($mapimessage, $row[PR_ATTACH_NUM]); $attachprops = mapi_getprops($mapiattach, array(PR_ATTACH_LONG_FILENAME)); $attach = new SyncAttachment(); $stream = mapi_openpropertytostream($mapiattach, PR_ATTACH_DATA_BIN); if ($stream) { $stat = mapi_stream_stat($stream); $attach->attsize = $stat["cb"]; $attach->displayname = w2u($attachprops[PR_ATTACH_LONG_FILENAME]); $attach->attname = bin2hex($this->_folderid) . ":" . bin2hex($sourcekey) . ":" . $row[PR_ATTACH_NUM]; if (!isset($message->attachments)) { $message->attachments = array(); } array_push($message->attachments, $attach); } } } // Get To/Cc as SMTP addresses (this is different from displayto and displaycc because we are putting // in the SMTP addresses as well, while displayto and displaycc could just contain the display names $to = array(); $cc = array(); $reciptable = mapi_message_getrecipienttable($mapimessage); $rows = mapi_table_queryallrows($reciptable, array(PR_RECIPIENT_TYPE, PR_DISPLAY_NAME, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS)); foreach ($rows as $row) { $address = ""; $fulladdr = ""; $addrtype = isset($row[PR_ADDRTYPE]) ? $row[PR_ADDRTYPE] : ""; if (isset($row[PR_SMTP_ADDRESS])) { $address = $row[PR_SMTP_ADDRESS]; } else { if ($addrtype == "SMTP" && isset($row[PR_EMAIL_ADDRESS])) { $address = $row[PR_EMAIL_ADDRESS]; } } $name = isset($row[PR_DISPLAY_NAME]) ? $row[PR_DISPLAY_NAME] : ""; if ($name == "" || $name == $address) { $fulladdr = $address; } else { $fulladdr = "\"" . w2u($name) . "\" <" . $address . ">"; } if ($row[PR_RECIPIENT_TYPE] == MAPI_TO) { array_push($to, $fulladdr); } else { if ($row[PR_RECIPIENT_TYPE] == MAPI_CC) { array_push($cc, $fulladdr); } } } $message->to = implode(", ", $to); $message->cc = implode(", ", $cc); if (!isset($message->body) || strlen($message->body) == 0) { $message->body = " "; } return $message; }
function _getEmail($mapimessage, $truncsize, $bodypreference, $optionbodypreference, $mimesupport = 0) { $messageprops = mapi_getprops($mapimessage, array(PR_MESSAGE_CLASS, PR_LAST_VERB_EXECUTED, PR_LAST_VERB_EXECUTION_TIME, PR_CONVERSATION_INDEX)); // Destinguish between SMS and eMail Messages. In case we have an SMS to sync // we need a SyncSMS Object that is in real a very much castrated SyncMail Object... // We even could create a separate _get function BUT since its Folderclass is email it // makes things easier to work just with one function. Except the Address Handling and // less fields everything else remains the same if (strtolower($messageprops[PR_MESSAGE_CLASS]) == 'ipm.note.mobile.sms') { $message = new SyncSMS(); if (isset($optionbodypreference) && $optionbodypreference != false) { $bodypreference = $optionbodypreference; } } else { $message = new SyncMail(); } if (isset($messageprops[PR_LAST_VERB_EXECUTED])) { switch ($messageprops[PR_LAST_VERB_EXECUTED]) { case 0x66: $message->lastverbexecuted = 1; break; case 0x67: $message->lastverbexecuted = 2; break; case 0x68: $message->lastverbexecuted = 3; break; default: $message->lastverbexecuted = 0; } $message->lastverbexecutiontime = $messageprops[PR_LAST_VERB_EXECUTION_TIME]; } else { $message->lastverbexecuted = 0; } $this->_getPropsFromMAPI($message, $mapimessage, $this->_emailmapping); // start added dw2412 AS V12.0 Flag support // should not break anything since in proto AS12 Fields get excluded in case a lower protocol is in use $message->poommailflag = new SyncPoommailFlag(); $this->_getPropsFromMAPI($message->poommailflag, $mapimessage, $this->_emailflagmapping); if (!isset($message->poommailflag->flagstatus)) { $message->poommailflag->flagstatus = 0; } // end added dw2412 AS V12.0 Flag Support // dw2412 According to docs... if (!isset($message->contentclass) || $message->contentclass == "") { $message->contentclass = "urn:content-classes:message"; } // Override 'body' for truncation // START CHANGED dw2412 Support Protocol Version 12 (added bodypreference compare) // We never the less transfer always UTF-8 so it should not matter to hardcode the internet cpid... // Other possible values are // // Name Character Set Code Page // Arabic (ISO) iso-8859-6 28596 // Arabic (Windows) windows-1256 1256 // Baltic (ISO) iso-8859-4 28594 // Baltic (Windows) windows-1257 1257 // Central European (ISO) iso-8859-2 28592 // Central European (Windows) windows-1250 1250 // Chinese Simplified (GB2312) gb2312 936 // Chinese Simplified (HZ) hz-gb-2312 52936 // Chinese Traditional (Big5) big5 950 // Cyrillic (ISO) iso-8859-5 28595 // Cyrillic (KOI8-R) koi8-r 20866 // Cyrillic (KOI8-U) koi8-u 21866 // Cyrillic (Windows) windows-1251 1251 // Greek (ISO) iso-8859-7 28597 // Greek (Windows) windows-1253 1253 // Hebrew (ISO-Logical) iso-8859-8-i 38598 // Hebrew (Windows) windows-1255 1255 // Japanese (EUC) euc-jp 51932 // Japanese (JIS) iso-2022-jp 50220 // Japanese (JIS-Allow 1 byte Kana) csISO2022JP 50221 // Japanese (Shift-JIS) iso-2022-jp 932 // Korean ks_c_5601-1987 949 // Korean (EUC) euc-kr 51949 // Latin 3 (ISO) iso-8859-3 28593 // Latin 9 (ISO) iso-8859-15 28605 // Thai (Windows) windows-874 874 // Turkish (ISO) iso-8859-9 28599 // Turkish (Windows) windows-1254 1254 // Unicode (UTF-7) utf-7 65000 // Unicode (UTF-8) utf-8 65001 // US-ASCII us-ascii 20127 // Vietnamese (Windows) windows-1258 1258 // Western European (ISO) iso-8859-1 28591 // Western European (Windows) Windows-1252 1252 // // For Compatibility with older Mailsystems // // Name Character Set Code Page // Arabic (Windows) windows-1256 1256 // Baltic (ISO) iso-8859-4 28594 // Central European (ISO) iso-8859-2 28592 // Chinese Simplified (GB2312) gb2312 936 // Chinese Traditional (Big5) big5 950 // Cyrillic (KOI8-R) koi8-r 20866 // Cyrillic (Windows) windows-1251 1251 // Greek (ISO) iso-8859-7 28597 // Hebrew (Windows) windows-1255 1255 // Japanese (JIS) iso-2022-jp 50220 // Korean ks_c_5601-1987 949 // Thai (Windows) windows-874 874 // Turkish (ISO) iso-8859-9 28599 // Unicode (UTF-8) utf-8 65001 // US-ASCII us-ascii 20127 // Vietnamese (Windows) windows-1258 1258 // Western European (ISO) iso-8859-1 28591 if (!isset($message->internetcpid) || $message->internetcpid == "") { $message->internetcpid = 65001; } debugLog("_getemail: MimeSupport is " . $mimesupport); if ($bodypreference == false) { $body = mapi_openproperty($mapimessage, PR_BODY); $bodysize = strlen($body); if ($bodysize > $truncsize) { $body = substr($body, 0, $truncsize); $message->bodysize = $bodysize; $message->bodytruncated = 1; } else { $message->bodytruncated = 0; } $message->body = str_replace("\n", "\r\n", w2u(str_replace("\r", "", $body))); if (!isset($message->body) || strlen($message->body) == 0) { $message->body = " "; } } else { $rtf = mapi_message_openproperty($mapimessage, PR_RTF_COMPRESSED); if (!$rtf) { $message->airsyncbasenativebodytype = 1; } else { $rtf = preg_replace("/(\n.*)/m", "", mapi_decompressrtf($rtf)); if (strpos($rtf, "\\fromtext") != false) { $message->airsyncbasenativebodytype = 1; } else { $message->airsyncbasenativebodytype = 2; } } if (!isset($bodypreference[1]["TruncationSize"])) { $bodypreference[1]["TruncationSize"] = 1024 * 1024; } if (isset($bodypreference[4]) && function_exists("mapi_inetmapi_imtoinet") && (!defined('ICS_IMTOINET_SEGFAULT') || ICS_IMTOINET_SEGFAULT === false)) { $addrBook = mapi_openaddressbook($this->_session); $mstream = mapi_inetmapi_imtoinet($this->_session, $addrBook, $mapimessage, array()); $mstreamstat = mapi_stream_stat($mstream); } $message->airsyncbasebody = new SyncAirSyncBaseBody(); debugLog("airsyncbasebody!"); if (isset($bodypreference[4]) && isset($mstream) && ($mimesupport == 2 || $mimesupport == 1 && strtolower(substr($messageprops[PR_MESSAGE_CLASS], 0, 14)) == 'ipm.note.smime')) { $mstreamcontent = mapi_stream_read($mstream, MAX_EMBEDDED_SIZE); $message->airsyncbasebody->type = 4; if (isset($bodypreference[4]["TruncationSize"])) { $hdrend = strpos("\r\n\r\n", $mstreamcontent); $message->airsyncbasebody->data = substr($mstreamcontent, 0, $hdrend + $bodypreference[4]["TruncationSize"]); } else { $message->airsyncbasebody->data = $mstreamcontent; } if (strlen($message->airsyncbasebody->data) < $mstreamstat["cb"]) { $message->airsyncbasebody->truncated = 1; } $message->airsyncbasebody->estimateddatasize = strlen($mstreamcontent); } elseif (isset($bodypreference[3]) && $message->airsyncbasenativebodytype == 3) { $message->airsyncbasebody->type = 3; $rtf = mapi_openproperty($mapimessage, PR_RTF_COMPRESSED); $message->airsyncbasebody->data = base64_encode($rtf); $message->airsyncbasebody->estimateddatasize = strlen($rtf); debugLog("RTF Body!"); } elseif (isset($bodypreference[2])) { $message->airsyncbasebody->type = 2; $html = mapi_openproperty($mapimessage, PR_HTML); if (strpos(strtoupper($html), "<HTML>") == 0 && strpos(strtoupper($html), "<HEAD>") == 0 && strpos(strtoupper($html), "<BODY>") == 0) { debugLog("Malformed html message, (HTML, HEAD, BODY missing"); $html = '<HTML>' . '<HEAD>' . '<META NAME="Generator" CONTENT="Z-Push">' . '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">' . '</HEAD>' . '<BODY>' . iconv(getCodepageCharset($message->internetcpid), "utf-8", $html) . '</BODY></HTML>'; $message->internetcpid = 65001; } else { if ($message->internetcpid != 65001) { $html = iconv(getCodepageCharset($message->internetcpid), "utf-8", $html); } } /* This should be removed 110422 if ($message->airsyncbasenativebodytype==2) { $html = mapi_openproperty($mapimessage, PR_HTML); } else { $html = '<html>'. '<head>'. '<meta name="Generator" content="Z-Push">'. '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'. '</head>'. '<body>'. str_replace("\n","<BR>",str_replace("\r","<BR>", str_replace("\r\n","<BR>",mapi_openproperty($mapimessage, PR_BODY)))). '</body>'. '</html>'; } */ $message->airsyncbasebody->estimateddatasize = strlen($html); if (isset($bodypreference[2]["TruncationSize"]) && strlen($html) > $bodypreference[2]["TruncationSize"]) { $html = substr($html, 0, $bodypreference[2]["TruncationSize"]); $message->airsyncbasebody->truncated = 1; } $message->airsyncbasebody->data = w2u($html); debugLog("HTML Body!"); } else { $body = mapi_openproperty($mapimessage, PR_BODY); $message->airsyncbasebody->estimateddatasize = strlen($body); $message->airsyncbasebody->type = 1; if (isset($bodypreference[1]["TruncationSize"]) && strlen($body) > $bodypreference[1]["TruncationSize"]) { $body = substr($body, 0, $bodypreference[1]["TruncationSize"]); $message->airsyncbasebody->truncated = 1; } $message->airsyncbasebody->data = str_replace("\n", "\r\n", w2u(str_replace("\r", "", $body))); debugLog("Plain Body!"); } if (isset($bodypreference[1]["Preview"])) { $body = mapi_openproperty($mapimessage, PR_BODY); $body = substr($body, 0, $bodypreference[1]["Preview"]); // $message->airsyncbasebody->preview = 1; $message->airsyncbasebody->preview = str_replace("\n", "\r\n", w2u(str_replace("\r", "", $body))); // unset($message->airsyncbasebody->data); } $message->md5body = md5(mapi_openproperty($mapimessage, PR_BODY)); if (!isset($message->airsyncbasebody->data) || strlen($message->airsyncbasebody->data) == 0) { $message->airsyncbasebody->data = " "; } } // END CHANGED dw2412 Support Protocol Version 12 (added bodypreference compare) // Override 'From' to show "Full Name <*****@*****.**>" // CHANGED dw2412 to honor the Reply-To Information in messages // setlocale(LC_CTYPE,'en_US.utf-8'); $messageprops = mapi_getprops($mapimessage, array(PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ENTRYID, PR_SOURCE_KEY, PR_REPLY_RECIPIENT_ENTRIES, PR_SENDER_NAME, PR_SENDER_ENTRYID, PR_RECEIVED_BY_NAME, PR_DISPLAY_TO, PR_DISPLAY_CC)); if (isset($messageprops[PR_SOURCE_KEY])) { $sourcekey = $messageprops[PR_SOURCE_KEY]; } else { return false; } $fromname = $fromaddr = ""; if ($message->messageclass == "IPM.Note.Mobile.SMS") { if (isset($messageprops[PR_SENT_REPRESENTING_NAME])) { $fromname = $messageprops[PR_SENT_REPRESENTING_NAME]; } if (isset($messageprops[PR_SENT_REPRESENTING_ENTRYID])) { $fromaddr = $this->_getMobileAddressFromEntryID($messageprops[PR_SENT_REPRESENTING_ENTRYID]); } if ($fromname == $fromaddr) { $fromname = ""; } if ($fromname) { $from = "\"" . w2u($fromname) . "\" [MOBILE:" . w2u($fromaddr) . "]"; } else { $from = "\"" . w2u($fromaddr) . "\" [MOBILE:" . w2u($fromaddr) . "]"; } //changed dw2412 to get rid at HTC Mail (Android) from error message... Not nice but effective... } else { if (isset($messageprops[PR_SENT_REPRESENTING_NAME])) { $fromname = $messageprops[PR_SENT_REPRESENTING_NAME]; } if (isset($messageprops[PR_SENT_REPRESENTING_ENTRYID])) { $fromaddr = $this->_getSMTPAddressFromEntryID($messageprops[PR_SENT_REPRESENTING_ENTRYID]); } if ($fromname == $fromaddr) { $fromname = ""; } if ($fromname) { $from = "\"" . w2u($fromname) . "\" <" . w2u($fromaddr) . ">"; } else { $from = "\"" . w2u($fromaddr) . "\" <" . w2u($fromaddr) . ">"; } //changed dw2412 to get rid at HTC Mail (Android) from error message... Not nice but effective... if (isset($messageprops[PR_SENDER_NAME])) { $sendername = $messageprops[PR_SENDER_NAME]; } if (isset($messageprops[PR_SENDER_ENTRYID])) { $senderaddr = $this->_getSMTPAddressFromEntryID($messageprops[PR_SENDER_ENTRYID]); } } if (isset($senderaddr) && $fromaddr != $senderaddr) { $message->sender = isset($sendername) ? $sendername : $senderaddr; } $message->from = $from; // START DETECTING BCC Received if (isset($messageprops[PR_RECEIVED_BY_NAME])) { debugLog($messageprops[PR_DISPLAY_TO] . "|" . $messageprops[PR_DISPLAY_CC] . "|" . $messageprops[PR_RECEIVED_BY_NAME]); if (strpos($messageprops[PR_DISPLAY_CC], $messageprops[PR_RECEIVED_BY_NAME]) === false && strpos($messageprops[PR_DISPLAY_TO], $messageprops[PR_RECEIVED_BY_NAME]) === false) { $message->receivedasbcc = true; } } // START ADDED dw2412 to honor reply to address if (isset($messageprops[PR_REPLY_RECIPIENT_ENTRIES])) { $replyto = $this->_readReplyRecipientEntry($messageprops[PR_REPLY_RECIPIENT_ENTRIES]); foreach ($replyto as $value) { $message->reply_to .= $value['email_address'] . ";"; } $message->reply_to = substr($message->reply_to, 0, strlen($message->reply_to) - 1); } // END ADDED dw2412 to honor reply to address // START ADDED dw2412 conversation index $messageprops = mapi_getprops($mapimessage, array(PR_CONVERSATION_INDEX)); if (CONVERSATIONINDEX == true) { if (isset($messageprops[PR_CONVERSATION_INDEX]) && strlen($messageprops[PR_CONVERSATION_INDEX]) >= 22) { $tmp = $messageprops[PR_CONVERSATION_INDEX]; $convid = substr($tmp, 6, 16); $convindex = substr($tmp, 0, 22); $tmp = substr($messageprops[PR_CONVERSATION_INDEX], 22, strlen($messageprops[PR_CONVERSATION_INDEX] - 22)); while (strlen($tmp) > 0) { $convindex .= substr($tmp, 0, 5); $tmp = substr($tmp, 5, strlen($tmp) - 5); } } else { debugLog("New conversation Index"); $ci = new ConversationIndex(); $ci->Create(); $tmp = $ci->Encode(); $convid = substr($tmp, 6, 16); $convindex = substr($tmp, 0, 22); } $message->conversationid = $convid; $message->conversationindex = $convindex; } // END ADDED dw2412 conversation index // process Meeting Requests if (isset($message->messageclass) && strpos($message->messageclass, "IPM.Schedule.Meeting") === 0) { $message->meetingrequest = new SyncMeetingRequest(); $this->_getPropsFromMAPI($message->meetingrequest, $mapimessage, $this->_meetingrequestmapping); $goidtag = $this->_getPropIdFromString("PT_BINARY:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0x3"); $timezonetag = $this->_getPropIDFromString("PT_BINARY:{00062002-0000-0000-C000-000000000046}:0x8233"); $recReplTime = $this->_getPropIDFromString("PT_SYSTIME:{00062002-0000-0000-C000-000000000046}:0x8228"); $isrecurringtag = $this->_getPropIDFromString("PT_BOOLEAN:{00062002-0000-0000-C000-000000000046}:0x8223"); $recurringstate = $this->_getPropIDFromString("PT_BINARY:{00062002-0000-0000-C000-000000000046}:0x8216"); $appSeqNr = $this->_getPropIDFromString("PT_LONG:{00062002-0000-0000-C000-000000000046}:0x8201"); $lidIsException = $this->_getPropIDFromString("PT_BOOLEAN:{00062002-0000-0000-C000-000000000046}:0xA"); $recurStartTime = $this->_getPropIDFromString("PT_LONG:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0xE"); $props = mapi_getprops($mapimessage, array($goidtag, $timezonetag, $recReplTime, $isrecurringtag, $recurringstate, $appSeqNr, $lidIsException, $recurStartTime)); // Get the GOID if (isset($props[$goidtag])) { $message->meetingrequest->globalobjid = base64_encode($props[$goidtag]); } // Set Timezone if (isset($props[$timezonetag])) { $tz = $this->_getTZFromMAPIBlob($props[$timezonetag]); } else { $tz = $this->_getGMTTZ(); } $message->meetingrequest->timezone = base64_encode($this->_getSyncBlobFromTZ($tz)); // send basedate if exception if (isset($props[$recReplTime]) || isset($props[$lidIsException]) && $props[$lidIsException] == true) { if (isset($props[$recReplTime])) { $basedate = $props[$recReplTime]; $message->meetingrequest->recurrenceid = $this->_getGMTTimeByTZ($basedate, $this->_getGMTTZ()); } else { if (!isset($props[$goidtag]) || !isset($props[$recurStartTime]) || !isset($props[$timezonetag])) { debugLog("Missing property to set correct basedate for exception"); } else { $basedate = extractBaseDate($props[$goidtag], $props[$recurStartTime]); $message->meetingrequest->recurrenceid = $this->_getGMTTimeByTZ($basedate, $tz); } } } // Organizer is the sender $message->meetingrequest->organizer = $message->from; // Process recurrence if (isset($props[$isrecurringtag]) && $props[$isrecurringtag]) { $myrec = new SyncMeetingRequestRecurrence(); // get recurrence -> put $message->meetingrequest as message so the 'alldayevent' is set correctly $this->_getRecurrence($mapimessage, $props, $message->meetingrequest, $myrec, $tz); $message->meetingrequest->recurrences = array($myrec); } // Force the 'alldayevent' in the object at all times. (non-existent == 0) if (!isset($message->meetingrequest->alldayevent) || $message->meetingrequest->alldayevent == "") { $message->meetingrequest->alldayevent = 0; } // Instancetype // 0 = single appointment // 1 = master recurring appointment // 2 = single instance of recurring appointment // 3 = exception of recurring appointment $message->meetingrequest->instancetype = 0; if (isset($props[$isrecurringtag]) && $props[$isrecurringtag] == 1) { $message->meetingrequest->instancetype = 1; } else { if ((!isset($props[$isrecurringtag]) || $props[$isrecurringtag] == 0) && isset($message->meetingrequest->recurrenceid)) { if (isset($props[$appSeqNr]) && $props[$appSeqNr] == 0) { $message->meetingrequest->instancetype = 2; } else { $message->meetingrequest->instancetype = 3; } } } // Disable reminder if it is off $reminderset = $this->_getPropIDFromString("PT_BOOLEAN:{00062008-0000-0000-C000-000000000046}:0x8503"); $remindertime = $this->_getPropIDFromString("PT_LONG:{00062008-0000-0000-C000-000000000046}:0x8501"); $messageprops = mapi_getprops($mapimessage, array($reminderset, $remindertime)); if (!isset($messageprops[$reminderset]) || $messageprops[$reminderset] == false) { $message->meetingrequest->reminder = ""; } else { ///set the default reminder time to seconds if ($messageprops[$remindertime] == 0x5ae980e1) { $message->meetingrequest->reminder = 900; } else { $message->meetingrequest->reminder = $messageprops[$remindertime] * 60; } } // Set sensitivity to 0 if missing if (!isset($message->meetingrequest->sensitivity)) { $message->meetingrequest->sensitivity = 0; } } // Add attachments $attachtable = mapi_message_getattachmenttable($mapimessage); // START CHANGED dw2412 to contain the Attach Method (needed for eml discovery) $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM, PR_ATTACH_METHOD)); // END CHANGED dw2412 to contain the Attach Method (needed for eml discovery) $n = 1; foreach ($rows as $row) { if (isset($row[PR_ATTACH_NUM])) { $mapiattach = mapi_message_openattach($mapimessage, $row[PR_ATTACH_NUM]); // CHANGED dw2412 for HTML eMail Inline Attachments... $attachprops = mapi_getprops($mapiattach, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME, PR_DISPLAY_NAME, PR_ATTACH_FLAGS, PR_ATTACH_CONTENT_ID, PR_ATTACH_MIME_TAG)); $attach = new SyncAttachment(); // START CHANGED dw2412 EML Attachment if ($row[PR_ATTACH_METHOD] == ATTACH_EMBEDDED_MSG) { $stream = buildEMLAttachment($mapiattach); } else { $stream = mapi_openpropertytostream($mapiattach, PR_ATTACH_DATA_BIN); } // END CHANGED dw2412 EML Attachment if ($stream) { $stat = mapi_stream_stat($stream); if (isset($message->_mapping['POOMMAIL:Attachments'])) { $attach = new SyncAttachment(); } else { if (isset($message->_mapping['AirSyncBase:Attachments'])) { $attach = new SyncAirSyncBaseAttachment(); } } $attach->attsize = $stat["cb"]; $attach->attname = bin2hex($this->_folderid) . ":" . bin2hex($sourcekey) . ":" . $row[PR_ATTACH_NUM]; // START CHANGED dw2412 EML Attachment debugLog("Mime Tag for attachment='" . strtolower(trim($attachprops[PR_ATTACH_MIME_TAG])) . "'"); if (isset($attachprops[PR_ATTACH_LONG_FILENAME])) { $attach->displayname = w2u($attachprops[PR_ATTACH_LONG_FILENAME]); } else { if (isset($attachprops[PR_ATTACH_FILENAME])) { $attach->displayname = w2u($attachprops[PR_ATTACH_FILENAME]); } else { if (isset($attachprops[PR_DISPLAY_NAME])) { $attach->displayname = w2u($attachprops[PR_DISPLAY_NAME]); } else { if (strtolower(trim($attachprops[PR_ATTACH_MIME_TAG])) == 'multipart/signed') { $attach->displayname = w2u("smime.p7m"); } else { $attach->displayname = w2u("untitled"); } } } } if (strlen($attach->displayname) == 0) { $attach->displayname = "Untitled_" . $n; $n++; } if ($row[PR_ATTACH_METHOD] == ATTACH_EMBEDDED_MSG) { $attach->displayname .= w2u(".eml"); } // END CHANGED dw2412 EML Attachment // in case the attachment has got a content id it is an inline one... if (isset($attachprops[PR_ATTACH_CONTENT_ID])) { $attach->isinline = true; $attach->method = 6; $attach->contentid = $attachprops[PR_ATTACH_CONTENT_ID]; $attach->contenttype = $attachprops[PR_ATTACH_MIME_TAG]; // for inline images the displayname extension must match the content type // otherwise on i.e. windows mobile the image is not being displayed / automatically downloaded switch (strtolower($attachprops[PR_ATTACH_MIME_TAG])) { case 'image/gif': if (substr(strtolower($attach->displayname), strlen($attach->displayname) - 4) != '.gif') { $attach->displayname .= '.gif'; } break; case 'image/jpg': case 'image/jpeg': if (substr(strtolower($attach->displayname), strlen($attach->displayname) - 4) != '.jpg') { $attach->displayname .= '.jpg'; } break; case 'image/png': if (substr(strtolower($attach->displayname), strlen($attach->displayname) - 4) != '.png') { $attach->displayname .= '.png'; } break; } } else { $attach->attmethod = 1; } if (isset($message->_mapping['POOMMAIL:Attachments'])) { if (!isset($message->attachments) || !is_array($message->attachments)) { $message->attachments = array(); } array_push($message->attachments, $attach); } else { if (isset($message->_mapping['AirSyncBase:Attachments'])) { if (!isset($message->airsyncbaseattachments) || !is_array($message->airsyncbaseattachments)) { $message->airsyncbaseattachments = array(); } array_push($message->airsyncbaseattachments, $attach); } } } } } // Get To/Cc as SMTP addresses (this is different from displayto and displaycc because we are putting // in the SMTP addresses as well, while displayto and displaycc could just contain the display names $to = array(); $cc = array(); $reciptable = mapi_message_getrecipienttable($mapimessage); $rows = mapi_table_queryallrows($reciptable, array(PR_RECIPIENT_TYPE, PR_DISPLAY_NAME, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS)); foreach ($rows as $row) { $address = ""; $fulladdr = ""; $addrtype = isset($row[PR_ADDRTYPE]) ? $row[PR_ADDRTYPE] : ""; if (isset($row[PR_SMTP_ADDRESS])) { $address = $row[PR_SMTP_ADDRESS]; } else { if ($addrtype == "SMTP" && isset($row[PR_EMAIL_ADDRESS])) { $address = $row[PR_EMAIL_ADDRESS]; } else { if ($addrtype == "MOBILE" && isset($row[PR_EMAIL_ADDRESS])) { $address = $row[PR_EMAIL_ADDRESS]; } } } $name = isset($row[PR_DISPLAY_NAME]) ? $row[PR_DISPLAY_NAME] : ""; if ($message->messageclass == "IPM.Note.Mobile.SMS") { if ($name == "" || $name == $address) { $fulladdr = "\"" . w2u($address) . "\" [MOBILE:" . w2u($address) . "]"; } else { if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') { $fulladdr = "\"" . w2u($name) . "\" [MOBILE:" . w2u($address) . "]"; } else { $fulladdr = w2u($name) . " [MOBILE:" . w2u($address) . "]"; } } } else { if ($name == "" || $name == $address) { $fulladdr = w2u($address); } else { if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') { $fulladdr = "\"" . w2u($name) . "\" <" . w2u($address) . ">"; } else { $fulladdr = w2u($name) . "<" . w2u($address) . ">"; } } } if ($row[PR_RECIPIENT_TYPE] == MAPI_TO) { array_push($to, $fulladdr); } else { if ($row[PR_RECIPIENT_TYPE] == MAPI_CC) { array_push($cc, $fulladdr); } } } if (defined('LIMIT_RECIPIENTS')) { if (count($to) > LIMIT_RECIPIENTS) { debugLog("Recipient amount limitted. No to recipients added!"); $to = array(); $message->displayto = ""; } if (count($cc) > LIMIT_RECIPIENTS) { debugLog("Recipient amount limitted. No cc recipients added!"); $cc = array(); } } $message->to = implode(", ", $to); $message->cc = implode(", ", $cc); // CHANGED dw2412 to not have this problem at my system with mapi_inetmapi_imtoinet segfault if ($mimesupport == 2 && function_exists("mapi_inetmapi_imtoinet") && !isset($message->airsyncbasebody) && (!defined('ICS_IMTOINET_SEGFAULT') || ICS_IMTOINET_SEGFAULT == false)) { $addrBook = mapi_openaddressbook($this->_session); $mstream = mapi_inetmapi_imtoinet($this->_session, $addrBook, $mapimessage, array()); $mstreamstat = mapi_stream_stat($mstream); if ($mstreamstat['cb'] < MAX_EMBEDDED_SIZE) { $message->mimetruncated = 0; $mstreamcontent = mapi_stream_read($mstream, MAX_EMBEDDED_SIZE); $message->mimedata = $mstreamcontent; $message->mimesize = $mstreamstat["cb"]; unset($message->body, $message->bodytruncated); } } return $message; }
/** * Reads an email object from MAPI * * @param mixed $mapimessage * @param ContentParameters $contentparameters * * @access private * @return SyncEmail */ private function getEmail($mapimessage, $contentparameters) { // This workaround fixes ZP-729 and still works with Outlook. // FIXME: It should be properly fixed when refactoring. $bpReturnType = Utils::GetBodyPreferenceBestMatch($contentparameters->GetBodyPreference()); if ($contentparameters->GetMimeSupport() == SYNC_MIMESUPPORT_NEVER || ($key = array_search(SYNC_BODYPREFERENCE_MIME, $contentparameters->GetBodyPreference()) === false) || $bpReturnType != SYNC_BODYPREFERENCE_MIME) { MAPIUtils::ParseSmime($this->session, $this->store, $this->getAddressbook(), $mapimessage); } $message = new SyncMail(); $this->getPropsFromMAPI($message, $mapimessage, MAPIMapping::GetEmailMapping()); $emailproperties = MAPIMapping::GetEmailProperties(); $messageprops = $this->getProps($mapimessage, $emailproperties); if (isset($messageprops[PR_SOURCE_KEY])) { $sourcekey = $messageprops[PR_SOURCE_KEY]; } else { return false; } //set the body according to contentparameters and supported AS version $this->setMessageBody($mapimessage, $contentparameters, $message); $fromname = $fromaddr = ""; if (isset($messageprops[$emailproperties["representingname"]])) { // remove encapsulating double quotes from the representingname $fromname = preg_replace('/^\\"(.*)\\"$/', "\${1}", $messageprops[$emailproperties["representingname"]]); } if (isset($messageprops[$emailproperties["representingentryid"]])) { $fromaddr = $this->getSMTPAddressFromEntryID($messageprops[$emailproperties["representingentryid"]]); } if ($fromname == $fromaddr) { $fromname = ""; } if ($fromname) { $from = "\"" . w2u($fromname) . "\" <" . w2u($fromaddr) . ">"; } else { //START CHANGED dw2412 HTC shows "error" if sender name is unknown $from = "\"" . w2u($fromaddr) . "\" <" . w2u($fromaddr) . ">"; } //END CHANGED dw2412 HTC shows "error" if sender name is unknown $message->from = $from; // process Meeting Requests if (isset($message->messageclass) && strpos($message->messageclass, "IPM.Schedule.Meeting") === 0) { $message->meetingrequest = new SyncMeetingRequest(); $this->getPropsFromMAPI($message->meetingrequest, $mapimessage, MAPIMapping::GetMeetingRequestMapping()); $meetingrequestproperties = MAPIMapping::GetMeetingRequestProperties(); $props = $this->getProps($mapimessage, $meetingrequestproperties); // Get the GOID if (isset($props[$meetingrequestproperties["goidtag"]])) { // GlobalObjId support was removed in AS 16.0 if (Request::IsGlobalObjIdHexClient()) { $message->meetingrequest->globalobjid = strtoupper(bin2hex($props[$meetingrequestproperties["goidtag"]])); } else { $message->meetingrequest->globalobjid = base64_encode($props[$meetingrequestproperties["goidtag"]]); } } // Set Timezone if (isset($props[$meetingrequestproperties["timezonetag"]])) { $tz = $this->getTZFromMAPIBlob($props[$meetingrequestproperties["timezonetag"]]); } else { $tz = $this->getGMTTZ(); } $message->meetingrequest->timezone = base64_encode(TimezoneUtil::GetSyncBlobFromTZ($tz)); // send basedate if exception if (isset($props[$meetingrequestproperties["recReplTime"]]) || isset($props[$meetingrequestproperties["lidIsException"]]) && $props[$meetingrequestproperties["lidIsException"]] == true) { if (isset($props[$meetingrequestproperties["recReplTime"]])) { $basedate = $props[$meetingrequestproperties["recReplTime"]]; $message->meetingrequest->recurrenceid = $this->getGMTTimeByTZ($basedate, $this->getGMTTZ()); } else { if (!isset($props[$meetingrequestproperties["goidtag"]]) || !isset($props[$meetingrequestproperties["recurStartTime"]]) || !isset($props[$meetingrequestproperties["timezonetag"]])) { ZLog::Write(LOGLEVEL_WARN, "Missing property to set correct basedate for exception"); } else { $basedate = Utils::ExtractBaseDate($props[$meetingrequestproperties["goidtag"]], $props[$meetingrequestproperties["recurStartTime"]]); $message->meetingrequest->recurrenceid = $this->getGMTTimeByTZ($basedate, $tz); } } } // Organizer is the sender if (strpos($message->messageclass, "IPM.Schedule.Meeting.Resp") === 0) { $message->meetingrequest->organizer = $message->to; } else { $message->meetingrequest->organizer = $message->from; } // Process recurrence if (isset($props[$meetingrequestproperties["isrecurringtag"]]) && $props[$meetingrequestproperties["isrecurringtag"]]) { $myrec = new SyncMeetingRequestRecurrence(); // get recurrence -> put $message->meetingrequest as message so the 'alldayevent' is set correctly $this->getRecurrence($mapimessage, $props, $message->meetingrequest, $myrec, $tz); $message->meetingrequest->recurrences = array($myrec); } // Force the 'alldayevent' in the object at all times. (non-existent == 0) if (!isset($message->meetingrequest->alldayevent) || $message->meetingrequest->alldayevent == "") { $message->meetingrequest->alldayevent = 0; } // Instancetype // 0 = single appointment // 1 = master recurring appointment // 2 = single instance of recurring appointment // 3 = exception of recurring appointment $message->meetingrequest->instancetype = 0; if (isset($props[$meetingrequestproperties["isrecurringtag"]]) && $props[$meetingrequestproperties["isrecurringtag"]] == 1) { $message->meetingrequest->instancetype = 1; } else { if ((!isset($props[$meetingrequestproperties["isrecurringtag"]]) || $props[$meetingrequestproperties["isrecurringtag"]] == 0) && isset($message->meetingrequest->recurrenceid)) { if (isset($props[$meetingrequestproperties["appSeqNr"]]) && $props[$meetingrequestproperties["appSeqNr"]] == 0) { $message->meetingrequest->instancetype = 2; } else { $message->meetingrequest->instancetype = 3; } } } // Disable reminder if it is off if (!isset($props[$meetingrequestproperties["reminderset"]]) || $props[$meetingrequestproperties["reminderset"]] == false) { $message->meetingrequest->reminder = ""; } else { ///set the default reminder time to seconds if ($props[$meetingrequestproperties["remindertime"]] == 0x5ae980e1) { $message->meetingrequest->reminder = 900; } else { $message->meetingrequest->reminder = $props[$meetingrequestproperties["remindertime"]] * 60; } } // Set sensitivity to 0 if missing if (!isset($message->meetingrequest->sensitivity)) { $message->meetingrequest->sensitivity = 0; } // If the user is working from a location other than the office the busystatus should be interpreted as free. if (isset($message->meetingrequest->busystatus) && $message->meetingrequest->busystatus == fbWorkingElsewhere) { $message->meetingrequest->busystatus = fbFree; } // If the busystatus has the value of -1, we should be interpreted as tentative (1) / ZP-581 if (isset($message->meetingrequest->busystatus) && $message->meetingrequest->busystatus == -1) { $message->meetingrequest->busystatus = fbTentative; } // if a meeting request response hasn't been processed yet, // do it so that the attendee status is updated on the mobile if (!isset($messageprops[$emailproperties["processed"]])) { // check if we are not sending the MR so we can process it - ZP-581 $cuser = ZPush::GetBackend()->GetUserDetails(ZPush::GetBackend()->GetCurrentUsername()); if (isset($cuser["emailaddress"]) && $cuser["emailaddress"] != $fromaddr) { $req = new Meetingrequest($this->store, $mapimessage, $this->session); if ($req->isMeetingRequestResponse()) { $req->processMeetingRequestResponse(); } if ($req->isMeetingCancellation()) { $req->processMeetingCancellation(); } } } $message->contentclass = DEFAULT_CALENDAR_CONTENTCLASS; } // Add attachments $attachtable = mapi_message_getattachmenttable($mapimessage); $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM)); $entryid = bin2hex($messageprops[$emailproperties["entryid"]]); $parentSourcekey = bin2hex($messageprops[$emailproperties["parentsourcekey"]]); foreach ($rows as $row) { if (isset($row[PR_ATTACH_NUM])) { if (Request::GetProtocolVersion() >= 12.0) { $attach = new SyncBaseAttachment(); } else { $attach = new SyncAttachment(); } $mapiattach = mapi_message_openattach($mapimessage, $row[PR_ATTACH_NUM]); $attachprops = mapi_getprops($mapiattach, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME, PR_ATTACHMENT_HIDDEN, PR_ATTACH_CONTENT_ID, PR_ATTACH_CONTENT_ID_W, PR_ATTACH_MIME_TAG, PR_ATTACH_MIME_TAG_W, PR_ATTACH_METHOD, PR_DISPLAY_NAME, PR_DISPLAY_NAME_W, PR_ATTACH_SIZE)); if (isset($attachprops[PR_ATTACH_MIME_TAG]) && strpos(strtolower($attachprops[PR_ATTACH_MIME_TAG]), 'signed') !== false || isset($attachprops[PR_ATTACH_MIME_TAG_W]) && strpos(strtolower($attachprops[PR_ATTACH_MIME_TAG_W]), 'signed') !== false) { continue; } // the displayname is handled equaly for all AS versions $attach->displayname = w2u(isset($attachprops[PR_ATTACH_LONG_FILENAME]) ? $attachprops[PR_ATTACH_LONG_FILENAME] : (isset($attachprops[PR_ATTACH_FILENAME]) ? $attachprops[PR_ATTACH_FILENAME] : (isset($attachprops[PR_DISPLAY_NAME]) ? $attachprops[PR_DISPLAY_NAME] : "attachment.bin"))); // fix attachment name in case of inline images if ($attach->displayname == "inline.txt" && (isset($attachprops[PR_ATTACH_MIME_TAG]) || $attachprops[PR_ATTACH_MIME_TAG_W])) { $mimetype = isset($attachprops[PR_ATTACH_MIME_TAG]) ? $attachprops[PR_ATTACH_MIME_TAG] : $attachprops[PR_ATTACH_MIME_TAG_W]; $mime = explode("/", $mimetype); if (count($mime) == 2 && $mime[0] == "image") { $attach->displayname = "inline." . $mime[1]; } } // set AS version specific parameters if (Request::GetProtocolVersion() >= 12.0) { $attach->filereference = sprintf("%s:%s:%s", $entryid, $row[PR_ATTACH_NUM], $parentSourcekey); $attach->method = isset($attachprops[PR_ATTACH_METHOD]) ? $attachprops[PR_ATTACH_METHOD] : ATTACH_BY_VALUE; // if displayname does not have the eml extension for embedde messages, android and WP devices won't open it if ($attach->method == ATTACH_EMBEDDED_MSG) { if (strtolower(substr($attach->displayname, -4)) != '.eml') { $attach->displayname .= '.eml'; } } // android devices require attachment size in order to display an attachment properly if (!isset($attachprops[PR_ATTACH_SIZE])) { $stream = mapi_openpropertytostream($mapiattach, PR_ATTACH_DATA_BIN); $stat = mapi_stream_stat($stream); $attach->estimatedDataSize = $stat['cb']; } else { $attach->estimatedDataSize = $attachprops[PR_ATTACH_SIZE]; } if (isset($attachprops[PR_ATTACH_CONTENT_ID]) && $attachprops[PR_ATTACH_CONTENT_ID]) { $attach->contentid = $attachprops[PR_ATTACH_CONTENT_ID]; } if (!isset($attach->contentid) && isset($attachprops[PR_ATTACH_CONTENT_ID_W]) && $attachprops[PR_ATTACH_CONTENT_ID_W]) { $attach->contentid = $attachprops[PR_ATTACH_CONTENT_ID_W]; } if (isset($attachprops[PR_ATTACHMENT_HIDDEN]) && $attachprops[PR_ATTACHMENT_HIDDEN]) { $attach->isinline = 1; } if (!isset($message->asattachments)) { $message->asattachments = array(); } array_push($message->asattachments, $attach); } else { $attach->attsize = $attachprops[PR_ATTACH_SIZE]; $attach->attname = sprintf("%s:%s:%s", $entryid, $row[PR_ATTACH_NUM], $parentSourcekey); if (!isset($message->attachments)) { $message->attachments = array(); } array_push($message->attachments, $attach); } } } // Get To/Cc as SMTP addresses (this is different from displayto and displaycc because we are putting // in the SMTP addresses as well, while displayto and displaycc could just contain the display names $message->to = array(); $message->cc = array(); $reciptable = mapi_message_getrecipienttable($mapimessage); $rows = mapi_table_queryallrows($reciptable, array(PR_RECIPIENT_TYPE, PR_DISPLAY_NAME, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS, PR_ENTRYID)); foreach ($rows as $row) { $address = ""; $fulladdr = ""; $addrtype = isset($row[PR_ADDRTYPE]) ? $row[PR_ADDRTYPE] : ""; if (isset($row[PR_SMTP_ADDRESS])) { $address = $row[PR_SMTP_ADDRESS]; } elseif ($addrtype == "SMTP" && isset($row[PR_EMAIL_ADDRESS])) { $address = $row[PR_EMAIL_ADDRESS]; } elseif ($addrtype == "ZARAFA" && isset($row[PR_ENTRYID])) { $address = $this->getSMTPAddressFromEntryID($row[PR_ENTRYID]); } $name = isset($row[PR_DISPLAY_NAME]) ? $row[PR_DISPLAY_NAME] : ""; if ($name == "" || $name == $address) { $fulladdr = w2u($address); } else { if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') { $fulladdr = "\"" . w2u($name) . "\" <" . w2u($address) . ">"; } else { $fulladdr = w2u($name) . "<" . w2u($address) . ">"; } } if ($row[PR_RECIPIENT_TYPE] == MAPI_TO) { array_push($message->to, $fulladdr); } else { if ($row[PR_RECIPIENT_TYPE] == MAPI_CC) { array_push($message->cc, $fulladdr); } } } if (is_array($message->to) && !empty($message->to)) { $message->to = implode(", ", $message->to); } if (is_array($message->cc) && !empty($message->cc)) { $message->cc = implode(", ", $message->cc); } // without importance some mobiles assume "0" (low) - Mantis #439 if (!isset($message->importance)) { $message->importance = IMPORTANCE_NORMAL; } //TODO contentclass and nativebodytype and internetcpid if (!isset($message->internetcpid)) { $message->internetcpid = defined('STORE_INTERNET_CPID') ? constant('STORE_INTERNET_CPID') : INTERNET_CPID_WINDOWS1252; } $this->setFlag($mapimessage, $message); if (!isset($message->contentclass)) { $message->contentclass = DEFAULT_EMAIL_CONTENTCLASS; } if (!isset($message->nativebodytype)) { $message->nativebodytype = $this->getNativeBodyType($messageprops); } // reply, reply to all, forward flags if (isset($message->lastverbexecuted) && $message->lastverbexecuted) { $message->lastverbexecuted = Utils::GetLastVerbExecuted($message->lastverbexecuted); } return $message; }
function _getEmail($mapimessage, $truncsize, $bodypreference, $mimesupport = 0) { $message = new SyncMail(); $this->_getPropsFromMAPI($message, $mapimessage, $this->_emailmapping); // start added dw2412 AS V12.0 Flag support // should not break anything since in proto AS12 Fields get excluded in case a lower protocol is in use $message->poommailflag = new SyncPoommailFlag(); $this->_getPropsFromMAPI($message->poommailflag, $mapimessage, $this->_emailflagmapping); if (!isset($message->poommailflag->flagstatus)) { $message->poommailflag->flagstatus = 0; } if (!isset($message->contentclass) || $message->contentclass == "") { $message->contentclass = "urn:content-classes:message"; } // end added dw2412 AS V12.0 Flag Support // Override 'From' to show "Full Name <*****@*****.**>" // CHANGED dw2412 to honor the Reply-To Information in messages $messageprops = mapi_getprops($mapimessage, array(PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ENTRYID, PR_SOURCE_KEY, PR_REPLY_RECIPIENT_ENTRIES)); // Override 'body' for truncation // START CHANGED dw2412 Support Protocol Version 12 (added bodypreference compare) if ($bodypreference == false) { $body = mapi_openproperty($mapimessage, PR_BODY); $bodysize = strlen($body); if ($bodysize > $truncsize) { $body = substr($body, 0, $truncsize); $message->bodysize = $bodysize; $message->bodytruncated = 1; } else { $message->bodytruncated = 0; } $message->body = str_replace("\n", "\r\n", w2u(str_replace("\r", "", $body))); if (!isset($message->body) || strlen($message->body) == 0) { $message->body = " "; } } else { $rtf = mapi_message_openproperty($mapimessage, PR_RTF_COMPRESSED); if (!$rtf) { $message->airsyncbasenativebodytype = 1; } else { $rtf = preg_replace("/(\n.*)/m", "", mapi_decompressrtf($rtf)); if (strpos($rtf, "\\fromtext") != false) { $message->airsyncbasenativebodytype = 1; } else { $message->airsyncbasenativebodytype = 2; } } if (!isset($bodypreference[1]["TruncationSize"])) { $bodypreference[1]["TruncationSize"] = 1024 * 1024; } $message->airsyncbasebody = new SyncAirSyncBaseBody(); debugLog("airsyncbasebody!"); if (isset($bodypreference[4]) && isset($mstream)) { $mstreamcontent = mapi_stream_read($mstream, MAX_EMBEDDED_SIZE); $message->airsyncbasebody->type = 4; if (isset($bodypreference[4]["TruncationSize"])) { $hdrend = strpos("\r\n\r\n", $mstreamcontent); $message->airsyncbasebody->data = substr($mstreamcontent, 0, $hdrend + $bodypreference[4]["TruncationSize"]); } else { $message->airsyncbasebody->data = $mstreamcontent; } if (strlen($message->airsyncbasebody->data) < $mstreamstat["cb"]) { $message->airsyncbasebody->truncated = 1; } $message->airsyncbasebody->estimateddatasize = strlen($mstreamcontent); } else { if (isset($bodypreference[3]) && $message->airsyncbasenativebodytype == 3) { $message->airsyncbasebody->type = 3; $rtf = mapi_openproperty($mapimessage, PR_RTF_COMPRESSED); $message->airsyncbasebody->data = base64_encode($rtf); $message->airsyncbasebody->estimateddatasize = strlen($rtf); $message->airsyncbasebody->truncated = 0; unset($message->airsyncbasebody->truncated); debugLog("RTF Body!"); } elseif (isset($bodypreference[2]) && $message->airsyncbasenativebodytype == 2) { $message->airsyncbasebody->type = 2; $html = mapi_openproperty($mapimessage, PR_HTML); if (isset($bodypreference[2]["TruncationSize"]) && strlen($html) > $bodypreference[2]["TruncationSize"]) { $html = substr($html, 0, $bodypreference[2]["TruncationSize"]); $message->airsyncbasebody->truncated = 1; } else { $message->airsyncbasebody->truncated = 0; unset($message->airsyncbasebody->truncated); } $message->airsyncbasebody->data = $html; $message->airsyncbasebody->estimateddatasize = strlen($html); debugLog("HTML Body!"); } else { $body = mapi_openproperty($mapimessage, PR_BODY); $message->airsyncbasebody->type = 1; if (isset($bodypreference[1]["TruncationSize"]) && strlen($body) > $bodypreference[1]["TruncationSize"]) { $body = substr($body, 0, $bodypreference[1]["TruncationSize"]); $message->airsyncbasebody->truncated = 1; } else { $message->airsyncbasebody->truncated = 0; unset($message->airsyncbasebody->truncated); } $message->airsyncbasebody->estimateddatasize = strlen($body); $message->airsyncbasebody->data = str_replace("\n", "\r\n", w2u(str_replace("\r", "", $body))); debugLog("Plain Body!"); } } if (!isset($message->airsyncbasebody->data) || strlen($message->airsyncbasebody->data) == 0) { $message->airsyncbasebody->data = " "; } } // END CHANGED dw2412 Support Protocol Version 12 (added bodypreference compare) if (isset($messageprops[PR_SOURCE_KEY])) { $sourcekey = $messageprops[PR_SOURCE_KEY]; } else { return false; } $fromname = $fromaddr = ""; if (isset($messageprops[PR_SENT_REPRESENTING_NAME])) { $fromname = $messageprops[PR_SENT_REPRESENTING_NAME]; } if (isset($messageprops[PR_SENT_REPRESENTING_ENTRYID])) { $fromaddr = $this->_getSMTPAddressFromEntryID($messageprops[PR_SENT_REPRESENTING_ENTRYID]); } if ($fromname == $fromaddr) { $fromname = ""; } if ($fromname) { $from = "\"" . w2u($fromname) . "\" <" . w2u($fromaddr) . ">"; } else { $from = "\"" . w2u($fromaddr) . "\" <" . w2u($fromaddr) . ">"; } //changed dw2412 to get rid at HTC Mail (Android) from error message... Not nice but effective... $message->from = $from; // START ADDED dw2412 to honor reply to address if (isset($messageprops[PR_REPLY_RECIPIENT_ENTRIES])) { $replyto = $this->_readReplyRecipientEntry($messageprops[PR_REPLY_RECIPIENT_ENTRIES]); foreach ($replyto as $value) { $message->reply_to .= $value['email_address'] . ";"; } $message->reply_to = substr($message->reply_to, 0, strlen($message->reply_to) - 1); } // END ADDED dw2412 to honor reply to address // process Meeting Requests if (isset($message->messageclass) && strpos($message->messageclass, "IPM.Schedule.Meeting") === 0) { $message->meetingrequest = new SyncMeetingRequest(); $this->_getPropsFromMAPI($message->meetingrequest, $mapimessage, $this->_meetingrequestmapping); $goidtag = $this->_getPropIdFromString("PT_BINARY:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0x3"); $timezonetag = $this->_getPropIDFromString("PT_BINARY:{00062002-0000-0000-C000-000000000046}:0x8233"); $recReplTime = $this->_getPropIDFromString("PT_SYSTIME:{00062002-0000-0000-C000-000000000046}:0x8228"); $isrecurringtag = $this->_getPropIDFromString("PT_BOOLEAN:{00062002-0000-0000-C000-000000000046}:0x8223"); $recurringstate = $this->_getPropIDFromString("PT_BINARY:{00062002-0000-0000-C000-000000000046}:0x8216"); $appSeqNr = $this->_getPropIDFromString("PT_LONG:{00062002-0000-0000-C000-000000000046}:0x8201"); $lidIsException = $this->_getPropIDFromString("PT_BOOLEAN:{00062002-0000-0000-C000-000000000046}:0xA"); $recurStartTime = $this->_getPropIDFromString("PT_LONG:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0xE"); $props = mapi_getprops($mapimessage, array($goidtag, $timezonetag, $recReplTime, $isrecurringtag, $recurringstate, $appSeqNr, $lidIsException, $recurStartTime)); // Get the GOID if (isset($props[$goidtag])) { $message->meetingrequest->globalobjid = base64_encode($props[$goidtag]); } // Set Timezone if (isset($props[$timezonetag])) { $tz = $this->_getTZFromMAPIBlob($props[$timezonetag]); } else { $tz = $this->_getGMTTZ(); } $message->meetingrequest->timezone = base64_encode($this->_getSyncBlobFromTZ($tz)); // send basedate if exception if (isset($props[$recReplTime]) || isset($props[$lidIsException]) && $props[$lidIsException] == true) { if (isset($props[$recReplTime])) { $basedate = $props[$recReplTime]; $message->meetingrequest->recurrenceid = $this->_getGMTTimeByTZ($basedate, $this->_getGMTTZ()); } else { if (!isset($props[$goidtag]) || !isset($props[$recurStartTime]) || !isset($props[$timezonetag])) { debugLog("Missing property to set correct basedate for exception"); } else { $basedate = extractBaseDate($props[$goidtag], $props[$recurStartTime]); $message->meetingrequest->recurrenceid = $this->_getGMTTimeByTZ($basedate, $tz); } } } // Organizer is the sender $message->meetingrequest->organizer = $message->from; // Process recurrence if (isset($props[$isrecurringtag]) && $props[$isrecurringtag]) { $myrec = new SyncMeetingRequestRecurrence(); // get recurrence -> put $message->meetingrequest as message so the 'alldayevent' is set correctly $this->_getRecurrence($mapimessage, $props, $message->meetingrequest, $myrec, $tz); $message->meetingrequest->recurrences = array($myrec); } // Force the 'alldayevent' in the object at all times. (non-existent == 0) if (!isset($message->meetingrequest->alldayevent) || $message->meetingrequest->alldayevent == "") { $message->meetingrequest->alldayevent = 0; } // Instancetype // 0 = single appointment // 1 = master recurring appointment // 2 = single instance of recurring appointment // 3 = exception of recurring appointment $message->meetingrequest->instancetype = 0; if (isset($props[$isrecurringtag]) && $props[$isrecurringtag] == 1) { $message->meetingrequest->instancetype = 1; } else { if ((!isset($props[$isrecurringtag]) || $props[$isrecurringtag] == 0) && isset($message->meetingrequest->recurrenceid)) { if (isset($props[$appSeqNr]) && $props[$appSeqNr] == 0) { $message->meetingrequest->instancetype = 2; } else { $message->meetingrequest->instancetype = 3; } } } // Disable reminder if it is off $reminderset = $this->_getPropIDFromString("PT_BOOLEAN:{00062008-0000-0000-C000-000000000046}:0x8503"); $remindertime = $this->_getPropIDFromString("PT_LONG:{00062008-0000-0000-C000-000000000046}:0x8501"); $messageprops = mapi_getprops($mapimessage, array($reminderset, $remindertime)); if (!isset($messageprops[$reminderset]) || $messageprops[$reminderset] == false) { $message->meetingrequest->reminder = ""; } else { ///set the default reminder time to seconds if ($messageprops[$remindertime] == 0x5ae980e1) { $message->meetingrequest->reminder = 900; } else { $message->meetingrequest->reminder = $messageprops[$remindertime] * 60; } } // Set sensitivity to 0 if missing if (!isset($message->meetingrequest->sensitivity)) { $message->meetingrequest->sensitivity = 0; } } // Add attachments $attachtable = mapi_message_getattachmenttable($mapimessage); // START CHANGED dw2412 to contain the Attach Method (needed for eml discovery) $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM, PR_ATTACH_METHOD)); // END CHANGED dw2412 to contain the Attach Method (needed for eml discovery) $n = 1; foreach ($rows as $row) { if (isset($row[PR_ATTACH_NUM])) { $mapiattach = mapi_message_openattach($mapimessage, $row[PR_ATTACH_NUM]); // CHANGED dw2412 for HTML eMail Inline Attachments... $attachprops = mapi_getprops($mapiattach, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME, PR_DISPLAY_NAME, PR_ATTACH_FLAGS, PR_ATTACH_CONTENT_ID, PR_ATTACH_MIME_TAG)); // START CHANGED dw2412 EML Attachment if ($row[PR_ATTACH_METHOD] == ATTACH_EMBEDDED_MSG) { $stream = buildEMLAttachment($mapiattach); } else { $stream = mapi_openpropertytostream($mapiattach, PR_ATTACH_DATA_BIN); } // END CHANGED dw2412 EML Attachment if ($stream) { $stat = mapi_stream_stat($stream); if (isset($message->_mapping['POOMMAIL:Attachments'])) { $attach = new SyncAttachment(); } else { if (isset($message->_mapping['AirSyncBase:Attachments'])) { $attach = new SyncAirSyncBaseAttachment(); } } $attach->attsize = $stat["cb"]; $attach->attname = bin2hex($this->_folderid) . ":" . bin2hex($sourcekey) . ":" . $row[PR_ATTACH_NUM]; // START CHANGED dw2412 EML Attachment if (isset($attachprops[PR_ATTACH_LONG_FILENAME])) { $attach->displayname = w2u($attachprops[PR_ATTACH_LONG_FILENAME]); } else { if (isset($attachprops[PR_ATTACH_FILENAME])) { $attach->displayname = w2u($attachprops[PR_ATTACH_FILENAME]); } else { if (isset($attachprops[PR_DISPLAY_NAME])) { $attach->displayname = w2u($attachprops[PR_DISPLAY_NAME]); } else { $attach->displayname = w2u("untitled"); } } } if (strlen($attach->displayname) == 0) { $attach->displayname = "Untitled_" . $n; $n++; } if ($row[PR_ATTACH_METHOD] == ATTACH_EMBEDDED_MSG) { $attach->displayname .= w2u(".eml"); } // END CHANGED dw2412 EML Attachment // in case the attachment has got a content id it is an inline one... if (isset($attachprops[PR_ATTACH_CONTENT_ID])) { $attach->isinline = true; $attach->method = 6; $attach->contentid = $attachprops[PR_ATTACH_CONTENT_ID]; $attach->contenttype = $attachprops[PR_ATTACH_MIME_TAG]; } if (isset($message->_mapping['POOMMAIL:Attachments'])) { if (!isset($message->attachments) || !is_array($message->attachments)) { $message->attachments = array(); } array_push($message->attachments, $attach); } else { if (isset($message->_mapping['AirSyncBase:Attachments'])) { if (!isset($message->airsyncbaseattachments) || !is_array($message->airsyncbaseattachments)) { $message->airsyncbaseattachments = array(); } array_push($message->airsyncbaseattachments, $attach); } } } } } // Get To/Cc as SMTP addresses (this is different from displayto and displaycc because we are putting // in the SMTP addresses as well, while displayto and displaycc could just contain the display names $to = array(); $cc = array(); $reciptable = mapi_message_getrecipienttable($mapimessage); $rows = mapi_table_queryallrows($reciptable, array(PR_RECIPIENT_TYPE, PR_DISPLAY_NAME, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS)); foreach ($rows as $row) { $address = ""; $fulladdr = ""; $addrtype = isset($row[PR_ADDRTYPE]) ? $row[PR_ADDRTYPE] : ""; if (isset($row[PR_SMTP_ADDRESS])) { $address = $row[PR_SMTP_ADDRESS]; } else { if ($addrtype == "SMTP" && isset($row[PR_EMAIL_ADDRESS])) { $address = $row[PR_EMAIL_ADDRESS]; } } $name = isset($row[PR_DISPLAY_NAME]) ? $row[PR_DISPLAY_NAME] : ""; if ($name == "" || $name == $address) { $fulladdr = w2u($address); } else { if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') { $fulladdr = "\"" . w2u($name) . "\" <" . w2u($address) . ">"; } else { $fulladdr = w2u($name) . "<" . w2u($address) . ">"; } } if ($row[PR_RECIPIENT_TYPE] == MAPI_TO) { array_push($to, $fulladdr); } else { if ($row[PR_RECIPIENT_TYPE] == MAPI_CC) { array_push($cc, $fulladdr); } } } if (defined('LIMIT_RECIPIENTS')) { if (count($to) > LIMIT_RECIPIENTS) { debugLog("Recipient amount limitted. No to recipients added!"); $to = array(); $message->displayto = ""; } if (count($cc) > LIMIT_RECIPIENTS) { debugLog("Recipient amount limitted. No cc recipients added!"); $cc = array(); } } $message->to = implode(", ", $to); $message->cc = implode(", ", $cc); // CHANGED dw2412 to not have this problem at my system with mapi_inetmapi_imtoinet segfault if ($mimesupport == 2 && function_exists("mapi_inetmapi_imtoinet") && !isset($message->airsyncbasebody) && !defined('ICS_IMTOINET_SEGFAULT')) { $addrBook = mapi_openaddressbook($this->_session); $mstream = mapi_inetmapi_imtoinet($this->_session, $addrBook, $mapimessage, array()); $mstreamstat = mapi_stream_stat($mstream); if ($mstreamstat['cb'] < MAX_EMBEDDED_SIZE) { $message->mimetruncated = 0; $mstreamcontent = mapi_stream_read($mstream, MAX_EMBEDDED_SIZE); $message->mimedata = $mstreamcontent; $message->mimesize = $mstreamstat["cb"]; unset($message->body, $message->bodytruncated); } } return $message; }