/**
  * Sets the properties in a MAPI object according to an Sync object and a property mapping
  *
  * @param mixed             $mapimessage
  * @param SyncObject        $message
  * @param array             $mapping
  *
  * @access private
  * @return
  */
 private function setPropsInMAPI($mapimessage, $message, $mapping)
 {
     $mapiprops = $this->getPropIdsFromStrings($mapping);
     $unsetVars = $message->getUnsetVars();
     $propsToDelete = array();
     $propsToSet = array();
     foreach ($mapiprops as $asprop => $mapiprop) {
         if (isset($message->{$asprop})) {
             // UTF8->windows1252.. this is ok for all numerical values
             if (mapi_prop_type($mapiprop) != PT_BINARY && mapi_prop_type($mapiprop) != PT_MV_BINARY) {
                 if (is_array($message->{$asprop})) {
                     $value = array_map("u2wi", $message->{$asprop});
                 } else {
                     $value = u2wi($message->{$asprop});
                 }
             } else {
                 $value = $message->{$asprop};
             }
             // Make sure the php values are the correct type
             switch (mapi_prop_type($mapiprop)) {
                 case PT_BINARY:
                 case PT_STRING8:
                     settype($value, "string");
                     break;
                 case PT_BOOLEAN:
                     settype($value, "boolean");
                     break;
                 case PT_SYSTIME:
                 case PT_LONG:
                     settype($value, "integer");
                     break;
             }
             // decode base64 value
             if ($mapiprop == PR_RTF_COMPRESSED) {
                 $value = base64_decode($value);
                 if (strlen($value) == 0) {
                     continue;
                 }
                 // PDA will sometimes give us an empty RTF, which we'll ignore.
                 // Note that you can still remove notes because when you remove notes it gives
                 // a valid compressed RTF with nothing in it.
             }
             // if an "empty array" is to be saved, it the mvprop should be deleted - fixes Mantis #468
             if (is_array($value) && empty($value)) {
                 $propsToDelete[] = $mapiprop;
                 ZLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIProvider->setPropsInMAPI(): Property '%s' to be deleted as it is an empty array", $asprop));
             } else {
                 // all properties will be set at once
                 $propsToSet[$mapiprop] = $value;
             }
         } elseif (in_array($asprop, $unsetVars)) {
             $propsToDelete[] = $mapiprop;
         }
     }
     mapi_setprops($mapimessage, $propsToSet);
     if (mapi_last_hresult()) {
         Zlog::Write(LOGLEVEL_WARN, sprintf("Failed to set properties, trying to set them separately. Error code was:%x", mapi_last_hresult()));
         $this->setPropsIndividually($mapimessage, $propsToSet, $mapiprops);
     }
     mapi_deleteprops($mapimessage, $propsToDelete);
     //clean up
     unset($unsetVars, $propsToDelete);
 }
 /**
  * Sends an e-mail
  * This messages needs to be saved into the 'sent items' folder
  *
  * @param SyncSendMail  $sm     SyncSendMail object
  *
  * @access public
  * @return boolean
  * @throws StatusException
  */
 public function SendMail($sm)
 {
     ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->SendMail(): RFC822: %d bytes  forward-id: '%s' reply-id: '%s' parent-id: '%s' SaveInSent: '%s' ReplaceMIME: '%s'", strlen($sm->mime), Utils::PrintAsString($sm->forwardflag), Utils::PrintAsString($sm->replyflag), Utils::PrintAsString(isset($sm->source->folderid) ? $sm->source->folderid : false), Utils::PrintAsString($sm->saveinsent), Utils::PrintAsString(isset($sm->replacemime))));
     // by splitting the message in several lines we can easily grep later
     foreach (preg_split("/((\r)?\n)/", $sm->mime) as $rfc822line) {
         ZLog::Write(LOGLEVEL_WBXML, "RFC822: " . $rfc822line);
     }
     $mimeParams = array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'charset' => 'utf-8');
     $mimeObject = new Mail_mimeDecode($sm->mime);
     $message = $mimeObject->decode($mimeParams);
     $sendMailProps = MAPIMapping::GetSendMailProperties();
     $sendMailProps = getPropIdsFromStrings($this->store, $sendMailProps);
     // Open the outbox and create the message there
     $storeprops = mapi_getprops($this->store, array($sendMailProps["outboxentryid"], $sendMailProps["ipmsentmailentryid"]));
     if (isset($storeprops[$sendMailProps["outboxentryid"]])) {
         $outbox = mapi_msgstore_openentry($this->store, $storeprops[$sendMailProps["outboxentryid"]]);
     }
     if (!$outbox) {
         throw new StatusException(sprintf("ZarafaBackend->SendMail(): No Outbox found or unable to create message: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_SERVERERROR);
     }
     $mapimessage = mapi_folder_createmessage($outbox);
     //message properties to be set
     $mapiprops = array();
     // only save the outgoing in sent items folder if the mobile requests it
     $mapiprops[$sendMailProps["sentmailentryid"]] = $storeprops[$sendMailProps["ipmsentmailentryid"]];
     // Check if imtomapi function is available and use it to send the mime message.
     // It is available since ZCP 7.0.6
     // @see http://jira.zarafa.com/browse/ZCP-9508
     if (function_exists('mapi_feature') && mapi_feature('INETMAPI_IMTOMAPI')) {
         ZLog::Write(LOGLEVEL_DEBUG, "Use the mapi_inetmapi_imtomapi function");
         $ab = mapi_openaddressbook($this->session);
         mapi_inetmapi_imtomapi($this->session, $this->store, $ab, $mapimessage, $sm->mime, array());
         // Set the appSeqNr so that tracking tab can be updated for meeting request updates
         // @see http://jira.zarafa.com/browse/ZP-68
         $meetingRequestProps = MAPIMapping::GetMeetingRequestProperties();
         $meetingRequestProps = getPropIdsFromStrings($this->store, $meetingRequestProps);
         $props = mapi_getprops($mapimessage, array(PR_MESSAGE_CLASS, $meetingRequestProps["goidtag"]));
         if (stripos($props[PR_MESSAGE_CLASS], "IPM.Schedule.Meeting.Resp.") === 0) {
             // search for calendar items using goid
             $mr = new Meetingrequest($this->store, $mapimessage);
             $appointments = $mr->findCalendarItems($props[$meetingRequestProps["goidtag"]]);
             if (is_array($appointments) && !empty($appointments)) {
                 $app = mapi_msgstore_openentry($this->store, $appointments[0]);
                 $appprops = mapi_getprops($app, array($meetingRequestProps["appSeqNr"]));
                 if (isset($appprops[$meetingRequestProps["appSeqNr"]]) && $appprops[$meetingRequestProps["appSeqNr"]]) {
                     $mapiprops[$meetingRequestProps["appSeqNr"]] = $appprops[$meetingRequestProps["appSeqNr"]];
                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("Set sequence number to:%d", $appprops[$meetingRequestProps["appSeqNr"]]));
                 }
             }
         }
         // Delete the PR_SENT_REPRESENTING_* properties because some android devices
         // do not send neither From nor Sender header causing empty PR_SENT_REPRESENTING_NAME and
         // PR_SENT_REPRESENTING_EMAIL_ADDRESS properties and "broken" PR_SENT_REPRESENTING_ENTRYID
         // which results in spooler not being able to send the message.
         // @see http://jira.zarafa.com/browse/ZP-85
         mapi_deleteprops($mapimessage, array($sendMailProps["sentrepresentingname"], $sendMailProps["sentrepresentingemail"], $sendMailProps["representingentryid"], $sendMailProps["sentrepresentingaddt"], $sendMailProps["sentrepresentinsrchk"]));
         if (isset($sm->source->itemid) && $sm->source->itemid) {
             $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($sm->source->folderid), hex2bin($sm->source->itemid));
             if ($entryid) {
                 $fwmessage = mapi_msgstore_openentry($this->store, $entryid);
             }
             if (!isset($fwmessage) || !$fwmessage) {
                 throw new StatusException(sprintf("ZarafaBackend->SendMail(): Could not open message id '%s' in folder id '%s' to be replied/forwarded: 0x%X", $sm->source->itemid, $sm->source->folderid, mapi_last_hresult()), SYNC_COMMONSTATUS_ITEMNOTFOUND);
             }
             //update icon when forwarding or replying message
             if ($sm->forwardflag) {
                 mapi_setprops($fwmessage, array(PR_ICON_INDEX => 262));
             } elseif ($sm->replyflag) {
                 mapi_setprops($fwmessage, array(PR_ICON_INDEX => 261));
             }
             mapi_savechanges($fwmessage);
             // only attach the original message if the mobile does not send it itself
             if (!isset($sm->replacemime)) {
                 // get message's body in order to append forward or reply text
                 $body = MAPIUtils::readPropStream($mapimessage, PR_BODY);
                 $bodyHtml = MAPIUtils::readPropStream($mapimessage, PR_HTML);
                 $cpid = mapi_getprops($fwmessage, array($sendMailProps["internetcpid"]));
                 if ($sm->forwardflag) {
                     // attach the original attachments to the outgoing message
                     $this->copyAttachments($mapimessage, $fwmessage);
                 }
                 if (strlen($body) > 0) {
                     $fwbody = MAPIUtils::readPropStream($fwmessage, PR_BODY);
                     $fwbody = isset($cpid[$sendMailProps["internetcpid"]]) ? Utils::ConvertCodepageStringToUtf8($cpid[$sendMailProps["internetcpid"]], $fwbody) : w2u($fwbody);
                     $mapiprops[$sendMailProps["body"]] = $body . "\r\n\r\n" . $fwbody;
                 }
                 if (strlen($bodyHtml) > 0) {
                     $fwbodyHtml = MAPIUtils::readPropStream($fwmessage, PR_HTML);
                     $fwbodyHtml = isset($cpid[$sendMailProps["internetcpid"]]) ? Utils::ConvertCodepageStringToUtf8($cpid[$sendMailProps["internetcpid"]], $fwbodyHtml) : w2u($fwbodyHtml);
                     $mapiprops[$sendMailProps["html"]] = $bodyHtml . "<br><br>" . $fwbodyHtml;
                 }
             }
         }
         mapi_setprops($mapimessage, $mapiprops);
         mapi_message_savechanges($mapimessage);
         mapi_message_submitmessage($mapimessage);
         $hr = mapi_last_hresult();
         if ($hr) {
             throw new StatusException(sprintf("ZarafaBackend->SendMail(): Error saving/submitting the message to the Outbox: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_MAILSUBMISSIONFAILED);
         }
         ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->SendMail(): email submitted");
         return true;
     }
     $mapiprops[$sendMailProps["subject"]] = u2wi(isset($message->headers["subject"]) ? $message->headers["subject"] : "");
     $mapiprops[$sendMailProps["messageclass"]] = "IPM.Note";
     $mapiprops[$sendMailProps["deliverytime"]] = time();
     if (isset($message->headers["x-priority"])) {
         $this->getImportanceAndPriority($message->headers["x-priority"], $mapiprops, $sendMailProps);
     }
     $this->addRecipients($message->headers, $mapimessage);
     // Loop through message subparts.
     $body = "";
     $body_html = "";
     if ($message->ctype_primary == "multipart" && ($message->ctype_secondary == "mixed" || $message->ctype_secondary == "alternative")) {
         $mparts = $message->parts;
         for ($i = 0; $i < count($mparts); $i++) {
             $part = $mparts[$i];
             // palm pre & iPhone send forwarded messages in another subpart which are also parsed
             if ($part->ctype_primary == "multipart" && ($part->ctype_secondary == "mixed" || $part->ctype_secondary == "alternative" || $part->ctype_secondary == "related")) {
                 foreach ($part->parts as $spart) {
                     $mparts[] = $spart;
                 }
                 continue;
             }
             // standard body
             if ($part->ctype_primary == "text" && $part->ctype_secondary == "plain" && isset($part->body) && (!isset($part->disposition) || $part->disposition != "attachment")) {
                 $body .= u2wi($part->body);
                 // assume only one text body
             } elseif ($part->ctype_primary == "text" && $part->ctype_secondary == "html") {
                 $body_html .= u2wi($part->body);
             } elseif ($part->ctype_primary == "ms-tnef" || $part->ctype_secondary == "ms-tnef") {
                 if (!isset($tnefAndIcalProps)) {
                     $tnefAndIcalProps = MAPIMapping::GetTnefAndIcalProperties();
                     $tnefAndIcalProps = getPropIdsFromStrings($this->store, $tnefAndIcalProps);
                 }
                 require_once 'tnefparser.php';
                 $zptnef = new TNEFParser($this->store, $tnefAndIcalProps);
                 $zptnef->ExtractProps($part->body, $mapiprops);
                 if (is_array($mapiprops) && !empty($mapiprops)) {
                     //check if it is a recurring item
                     if (isset($mapiprops[$tnefAndIcalProps["tnefrecurr"]])) {
                         MAPIUtils::handleRecurringItem($mapiprops, $tnefAndIcalProps);
                     }
                 } else {
                     ZLog::Write(LOGLEVEL_WARN, "ZarafaBackend->Sendmail(): TNEFParser: Mapi property array was empty");
                 }
             } elseif ($part->ctype_primary == "text" && $part->ctype_secondary == "calendar") {
                 if (!isset($tnefAndIcalProps)) {
                     $tnefAndIcalProps = MAPIMapping::GetTnefAndIcalProperties();
                     $tnefAndIcalProps = getPropIdsFromStrings($this->store, $tnefAndIcalProps);
                 }
                 require_once 'icalparser.php';
                 $zpical = new ICalParser($this->store, $tnefAndIcalProps);
                 $zpical->ExtractProps($part->body, $mapiprops);
                 // iPhone sends a second ICS which we ignore if we can
                 if (!isset($mapiprops[PR_MESSAGE_CLASS]) && strlen(trim($body)) == 0) {
                     ZLog::Write(LOGLEVEL_WARN, "ZarafaBackend->Sendmail(): Secondary iPhone response is being ignored!! Mail dropped!");
                     return true;
                 }
                 if (!Utils::CheckMapiExtVersion("6.30") && is_array($mapiprops) && !empty($mapiprops)) {
                     mapi_setprops($mapimessage, $mapiprops);
                 } else {
                     // store ics as attachment
                     //see Utils::IcalTimezoneFix() in utils.php for more information
                     $part->body = Utils::IcalTimezoneFix($part->body);
                     MAPIUtils::StoreAttachment($mapimessage, $part);
                     ZLog::Write(LOGLEVEL_INFO, "ZarafaBackend->Sendmail(): Sending ICS file as attachment");
                 }
             } else {
                 MAPIUtils::StoreAttachment($mapimessage, $part);
             }
         }
     } else {
         if ($message->ctype_primary == "text" && $message->ctype_secondary == "html") {
             $body_html .= u2wi($message->body);
         } else {
             $body = u2wi($message->body);
         }
     }
     // some devices only transmit a html body
     if (strlen($body) == 0 && strlen($body_html) > 0) {
         ZLog::Write(LOGLEVEL_WARN, "ZarafaBackend->SendMail(): only html body sent, transformed into plain text");
         $body = strip_tags($body_html);
     }
     if (isset($sm->source->itemid) && $sm->source->itemid) {
         // Append the original text body for reply/forward
         $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($sm->source->folderid), hex2bin($sm->source->itemid));
         if ($entryid) {
             $fwmessage = mapi_msgstore_openentry($this->store, $entryid);
         }
         if (!isset($fwmessage) || !$fwmessage) {
             throw new StatusException(sprintf("ZarafaBackend->SendMail(): Could not open message id '%s' in folder id '%s' to be replied/forwarded: 0x%X", $sm->source->itemid, $sm->source->folderid, mapi_last_hresult()), SYNC_COMMONSTATUS_ITEMNOTFOUND);
         }
         //update icon when forwarding or replying message
         if ($sm->forwardflag) {
             mapi_setprops($fwmessage, array(PR_ICON_INDEX => 262));
         } elseif ($sm->replyflag) {
             mapi_setprops($fwmessage, array(PR_ICON_INDEX => 261));
         }
         mapi_savechanges($fwmessage);
         // only attach the original message if the mobile does not send it itself
         if (!isset($sm->replacemime)) {
             $fwbody = MAPIUtils::readPropStream($fwmessage, PR_BODY);
             $fwbodyHtml = MAPIUtils::readPropStream($fwmessage, PR_HTML);
             if ($sm->forwardflag) {
                 // During a forward, we have to add the forward header ourselves. This is because
                 // normally the forwarded message is added as an attachment. However, we don't want this
                 // because it would be rather complicated to copy over the entire original message due
                 // to the lack of IMessage::CopyTo ..
                 $fwheader = $this->getForwardHeaders($fwmessage);
                 // add fwheader to body and body_html
                 $body .= $fwheader;
                 if (strlen($body_html) > 0) {
                     $body_html .= str_ireplace("\r\n", "<br>", $fwheader);
                 }
                 // attach the original attachments to the outgoing message
                 $this->copyAttachments($mapimessage, $fwmessage);
             }
             if (strlen($body) > 0) {
                 $body .= $fwbody;
             }
             if (strlen($body_html) > 0) {
                 $body_html .= $fwbodyHtml;
             }
         }
     }
     //set PR_INTERNET_CPID to 65001 (utf-8) if store supports it and to 1252 otherwise
     $internetcpid = INTERNET_CPID_WINDOWS1252;
     if (defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) {
         $internetcpid = INTERNET_CPID_UTF8;
     }
     $mapiprops[$sendMailProps["body"]] = $body;
     $mapiprops[$sendMailProps["internetcpid"]] = $internetcpid;
     if (strlen($body_html) > 0) {
         $mapiprops[$sendMailProps["html"]] = $body_html;
     }
     //TODO if setting all properties fails, try setting them infividually like in mapiprovider
     mapi_setprops($mapimessage, $mapiprops);
     mapi_savechanges($mapimessage);
     mapi_message_submitmessage($mapimessage);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ZarafaBackend->SendMail(): Error saving/submitting the message to the Outbox: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_MAILSUBMISSIONFAILED);
     }
     ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->SendMail(): email submitted");
     return true;
 }
function zpa_remove_device($adminStore, $session, $user, $deviceid)
{
    $userEntryId = @mapi_msgstore_createentryid($adminStore, $user);
    $userStore = @mapi_openmsgstore($session, $userEntryId);
    $hresult = mapi_last_hresult();
    if ($hresult != NOERROR) {
        echo "Could not open store for {$user}. The script will exit.\n";
        exit(1);
    }
    $devicesprops = mapi_getprops($userStore, array(0x6880101e, 0x6881101e, 0x6882101e, 0x6883101e, 0x68841003, 0x6885101e, 0x6886101e, 0x6887101e, 0x68881040, 0x68891040));
    if (isset($devicesprops[0x6881101e]) && is_array($devicesprops[0x6881101e])) {
        $ak = array_search($deviceid, $devicesprops[0x6881101e]);
        if ($ak !== false) {
            if (count($devicesprops[0x6880101e]) == 1) {
                mapi_deleteprops($userStore, array(0x6880101e, 0x6881101e, 0x6882101e, 0x6883101e, 0x68841003, 0x6885101e, 0x6886101e, 0x6887101e, 0x68881040, 0x68891040));
            } else {
                unset($devicesprops[0x6880101e][$ak], $devicesprops[0x6881101e][$ak], $devicesprops[0x6882101e][$ak], $devicesprops[0x6883101e][$ak], $devicesprops[0x68841003][$ak], $devicesprops[0x6885101e][$ak], $devicesprops[0x6886101e][$ak], $devicesprops[0x6887101e][$ak], $devicesprops[0x68881040][$ak], $devicesprops[0x68891040][$ak]);
                mapi_setprops($userStore, array(0x6880101e => isset($devicesprops[0x6880101e]) ? $devicesprops[0x6880101e] : array(), 0x6881101e => isset($devicesprops[0x6881101e]) ? $devicesprops[0x6881101e] : array(), 0x6882101e => isset($devicesprops[0x6882101e]) ? $devicesprops[0x6882101e] : array(), 0x6883101e => isset($devicesprops[0x6883101e]) ? $devicesprops[0x6883101e] : array(), 0x68841003 => isset($devicesprops[0x68841003]) ? $devicesprops[0x68841003] : array(), 0x6885101e => isset($devicesprops[0x6885101e]) ? $devicesprops[0x6885101e] : array(), 0x6886101e => isset($devicesprops[0x6886101e]) ? $devicesprops[0x6886101e] : array(), 0x6887101e => isset($devicesprops[0x6887101e]) ? $devicesprops[0x6887101e] : array(), 0x68881040 => isset($devicesprops[0x68881040]) ? $devicesprops[0x68881040] : array(), 0x68891040 => isset($devicesprops[0x68891040]) ? $devicesprops[0x68891040] : array()));
            }
            $hresult = mapi_last_hresult();
            if ($hresult != NOERROR) {
                echo "Could not remove device from list for {$user}. Errorcode 0x" . sprintf("%x", $hresult) . ". The script will exit.\n";
                exit(1);
            } else {
                echo "Removed device from list.\n";
            }
        } else {
            echo "No device found with the given id.\n";
            exit(1);
        }
    } else {
        echo "No devices found for the user {$user}.\n";
        exit(1);
    }
}
 /** Reclaims ownership of a decline task
  *
  * Deletes taskrequest properties and recipients from the task message.
  */
 function reclaimownership()
 {
     // Delete task request properties
     mapi_deleteprops($this->message, array($this->props['taskglobalobjid'], $this->props['tasklastuser'], $this->props['tasklastdelegate']));
     mapi_setprops($this->message, array($this->props['updatecount'] => 2, $this->props['taskfcreator'] => true));
     // Delete recipients
     $this->deleteAllRecipients($this->message);
 }
Exemple #5
0
 function _setPropsInMAPI($mapimessage, $message, $mapping)
 {
     foreach ($mapping as $asprop => $mapiprop) {
         if (isset($message->{$asprop})) {
             $mapiprop = $this->_getPropIDFromString($mapiprop);
             // UTF8->windows1252.. this is ok for all numerical values
             if (mapi_prop_type($mapiprop) != PT_BINARY && mapi_prop_type($mapiprop) != PT_MV_BINARY) {
                 if (is_array($message->{$asprop})) {
                     $value = array_map("u2wi", $message->{$asprop});
                 } else {
                     $value = u2wi($message->{$asprop});
                 }
             } else {
                 $value = $message->{$asprop};
             }
             // Make sure the php values are the correct type
             switch (mapi_prop_type($mapiprop)) {
                 case PT_BINARY:
                 case PT_STRING8:
                     settype($value, "string");
                     break;
                 case PT_BOOLEAN:
                     settype($value, "boolean");
                     break;
                 case PT_SYSTIME:
                 case PT_LONG:
                     settype($value, "integer");
                     break;
             }
             // decode base64 value
             if ($mapiprop == PR_RTF_COMPRESSED) {
                 $value = base64_decode($value);
                 if (strlen($value) == 0) {
                     continue;
                 }
                 // PDA will sometimes give us an empty RTF, which we'll ignore.
                 // Note that you can still remove notes because when you remove notes it gives
                 // a valid compressed RTF with nothing in it.
             }
             mapi_setprops($mapimessage, array($mapiprop => $value));
             // fixes Mantis #468
             if (is_array($value) && empty($value)) {
                 debugLog(sprintf("mapi_deleteprops() for '%s' as it is an empty array", $asprop));
                 mapi_deleteprops($mapimessage, array($mapiprop));
             }
         }
     }
 }
Exemple #6
0
 function ImportMessageFlag($id, $flag)
 {
     $emailflag = $this->_emailflagmapping;
     $entryid = mapi_msgstore_entryidfromsourcekey($this->_store, hex2bin($id));
     $mapimessage = mapi_msgstore_openentry($this->_store, $entryid);
     if ($mapimessage == false) {
         debugLog("Unable to openentry in ImportMessageFlag: " . sprintf("%x", mapi_last_hresult()));
     } else {
         // we need this for importing changes in the end...
         $flags = 0;
         $props = array();
         $props = mapi_getprops($mapimessage, array(PR_PARENT_SOURCE_KEY, PR_SOURCE_KEY));
         // so now do the job with the flags. Delete flags not being sent, set flags that are in sync packet
         // flagicon is just necessary for Zarafa WebAccess. Outlook does not need it.
         $setflags = array();
         $delflags = array();
         if (isset($flag->flagstatus) && $flag->flagstatus != "") {
             $setflags += array($this->_getPropIDFromString($emailflag["flagstatus"]) => $flag->flagstatus);
             switch ($flag->flagstatus) {
                 case '2':
                     $setflags += array($this->_getPropIDFromString($emailflag["flagicon"]) => 6);
                     break;
                 default:
                     $setflags += array($this->_getPropIDFromString($emailflag["flagicon"]) => 0);
                     break;
             }
         } else {
             $delflags[] = $this->_getPropIDFromString($emailflag["flagstatus"]);
             $delflags[] = $this->_getPropIDFromString($emailflag["flagicon"]);
         }
         // dw2412 in case the flag should be removed... just do it compatible with o2k7
         if (isset($flag->flagstatus) && ($flag->flagstatus == 0 || $flag->flagstatus == "") || !isset($flag->flagstatus)) {
             $delflags[] = $this->_getPropIDFromString($emailflag["flagstatus"]);
             $delflags[] = $this->_getPropIDFromString($emailflag["flagicon"]);
             $delflags[] = $this->_getPropIDFromString("PT_SYSTIME:{00062003-0000-0000-C000-000000000046}:0x8104");
             $delflags[] = $this->_getPropIDFromString("PT_SYSTIME:{00062003-0000-0000-C000-000000000046}:0x8105");
             $delflags[] = $this->_getPropIDFromString("PT_SYSTIME:{00062008-0000-0000-C000-000000000046}:0x8516");
             $delflags[] = $this->_getPropIDFromString("PT_SYSTIME:{00062008-0000-0000-C000-000000000046}:0x8517");
             $delflags[] = $this->_getPropIDFromString("PT_SYSTIME:{00062006-0000-0000-C000-000000000046}:0x85A0");
             $delflags[] = $this->_getPropIDFromString("PT_STRING8:{00062006-0000-0000-C000-000000000046}:0x85A1");
             $delflags[] = $this->_getPropIDFromString("PT_STRING8:{00062006-0000-0000-C000-000000000046}:0x85A4");
             $setflags += array($this->_getPropIDFromString("PT_STRING8:{00062008-0000-0000-C000-000000000046}:0x8530") => "");
             $setflags += array($this->_getPropIDFromString("PT_BOOLEAN:{00062008-0000-0000-C000-000000000046}:0x8503") => "0");
             $setflags += array($this->_getPropIDFromString("PT_LONG:{00062003-0000-0000-C000-000000000046}:0x8101") => "0");
             $setflags += array($this->_getPropIDFromString("PT_DOUBLE:{00062003-0000-0000-C000-000000000046}:0x8102") => "0");
             $setflags += array($this->_getPropIDFromString("PT_BOOLEAN:{00062003-0000-0000-C000-000000000046}:0x811C") => "0");
             $setflags += array(mapi_prop_tag(PT_LONG, 0xe2b) => "0");
             //dw2412 responsible for displaying flag in O2K7, added as 'PR_TODO_ITEM_FLAGS' to the mapitags.php
             $setflags += array($this->_getPropIDFromString($emailflag["reminderset"]) => "0");
         } else {
             if (isset($flag->flagtype) && $flag->flagtype != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["flagtype"]) => $flag->flagtype);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["flagtype"]);
             }
             if (isset($flag->startdate) && $flag->startdate != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["startdate"]) => $flag->startdate);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["startdate"]);
             }
             if (isset($flag->duedate) && $flag->duedate != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["duedate"]) => $flag->duedate);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["duedate"]);
             }
             if (isset($flag->datecompleted) && $flag->datecompleted != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["datecompleted"]) => $flag->datecompleted);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["datecompleted"]);
             }
             if (isset($flag->reminderset) && $flag->reminderset != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["reminderset"]) => $flag->reminderset);
             } else {
                 if ($flag->flagstatus > 0) {
                     $setflags += array($this->_getPropIDFromString($emailflag["reminderset"]) => "0");
                 } else {
                     $delflags[] = $this->_getPropIDFromString($emailflag["reminderset"]);
                 }
             }
             if (isset($flag->remindertime) && $flag->remindertime != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["remindertime"]) => $flag->remindertime);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["remindertime"]);
             }
             if (isset($flag->ordinaldate) && $flag->ordinaldate != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["ordinaldate"]) => $flag->ordinaldate);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["ordinaldate"]);
             }
             if (isset($flag->subordinaldate) && $flag->subordinaldate != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["subordinaldate"]) => $flag->subordinaldate);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["subordinaldate"]);
             }
             if (isset($flag->completetime) && $flag->completetime != "") {
                 $setflags += array($this->_getPropIDFromString($emailflag["completetime"]) => $flag->completetime);
             } else {
                 $delflags[] = $this->_getPropIDFromString($emailflag["completetime"]);
             }
         }
         // hopefully I'm doing this right. It should prevent the back sync of whole message
         mapi_importcontentschanges_importmessagechange($this->importer, $props, $flags, $mapimessage);
         mapi_setprops($mapimessage, $setflags);
         mapi_deleteprops($mapimessage, $delflags);
         mapi_savechanges($mapimessage);
         return true;
     }
 }
Exemple #7
0
 /**
  * Sends an e-mail
  * This messages needs to be saved into the 'sent items' folder
  *
  * @param SyncSendMail  $sm     SyncSendMail object
  *
  * @access public
  * @return boolean
  * @throws StatusException
  */
 public function SendMail($sm)
 {
     // Check if imtomapi function is available and use it to send the mime message.
     // It is available since ZCP 7.0.6
     // @see http://jira.zarafa.com/browse/ZCP-9508
     if (!(function_exists('mapi_feature') && mapi_feature('INETMAPI_IMTOMAPI'))) {
         throw new StatusException("ZarafaBackend->SendMail(): ZCP version is too old, INETMAPI_IMTOMAPI is not available. Install at least ZCP version 7.0.6 or later.", SYNC_COMMONSTATUS_MAILSUBMISSIONFAILED, null, LOGLEVEL_FATAL);
         return false;
     }
     ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->SendMail(): RFC822: %d bytes  forward-id: '%s' reply-id: '%s' parent-id: '%s' SaveInSent: '%s' ReplaceMIME: '%s'", strlen($sm->mime), Utils::PrintAsString($sm->forwardflag), Utils::PrintAsString($sm->replyflag), Utils::PrintAsString(isset($sm->source->folderid) ? $sm->source->folderid : false), Utils::PrintAsString($sm->saveinsent), Utils::PrintAsString(isset($sm->replacemime))));
     // by splitting the message in several lines we can easily grep later
     foreach (preg_split("/((\r)?\n)/", $sm->mime) as $rfc822line) {
         ZLog::Write(LOGLEVEL_WBXML, "RFC822: " . $rfc822line);
     }
     $sendMailProps = MAPIMapping::GetSendMailProperties();
     $sendMailProps = getPropIdsFromStrings($this->store, $sendMailProps);
     // Open the outbox and create the message there
     $storeprops = mapi_getprops($this->store, array($sendMailProps["outboxentryid"], $sendMailProps["ipmsentmailentryid"]));
     if (isset($storeprops[$sendMailProps["outboxentryid"]])) {
         $outbox = mapi_msgstore_openentry($this->store, $storeprops[$sendMailProps["outboxentryid"]]);
     }
     if (!$outbox) {
         throw new StatusException(sprintf("ZarafaBackend->SendMail(): No Outbox found or unable to create message: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_SERVERERROR);
     }
     $mapimessage = mapi_folder_createmessage($outbox);
     //message properties to be set
     $mapiprops = array();
     // only save the outgoing in sent items folder if the mobile requests it
     $mapiprops[$sendMailProps["sentmailentryid"]] = $storeprops[$sendMailProps["ipmsentmailentryid"]];
     ZLog::Write(LOGLEVEL_DEBUG, "Use the mapi_inetmapi_imtomapi function");
     $ab = mapi_openaddressbook($this->session);
     mapi_inetmapi_imtomapi($this->session, $this->store, $ab, $mapimessage, $sm->mime, array());
     // Set the appSeqNr so that tracking tab can be updated for meeting request updates
     // @see http://jira.zarafa.com/browse/ZP-68
     $meetingRequestProps = MAPIMapping::GetMeetingRequestProperties();
     $meetingRequestProps = getPropIdsFromStrings($this->store, $meetingRequestProps);
     $props = mapi_getprops($mapimessage, array(PR_MESSAGE_CLASS, $meetingRequestProps["goidtag"], $sendMailProps["internetcpid"]));
     // Convert sent message's body to UTF-8.
     // @see http://jira.zarafa.com/browse/ZP-505
     if (isset($props[$sendMailProps["internetcpid"]]) && $props[$sendMailProps["internetcpid"]] != INTERNET_CPID_UTF8) {
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sent email cpid is not unicode (%d). Set it to unicode and convert email body.", $props[$sendMailProps["internetcpid"]]));
         $mapiprops[$sendMailProps["internetcpid"]] = INTERNET_CPID_UTF8;
         $body = MAPIUtils::readPropStream($mapimessage, PR_BODY);
         $body = Utils::ConvertCodepageStringToUtf8($props[$sendMailProps["internetcpid"]], $body);
         $mapiprops[$sendMailProps["body"]] = $body;
         $bodyHtml = MAPIUtils::readPropStream($mapimessage, PR_HTML);
         $bodyHtml = Utils::ConvertCodepageStringToUtf8($props[$sendMailProps["internetcpid"]], $bodyHtml);
         $mapiprops[$sendMailProps["html"]] = $bodyHtml;
         mapi_setprops($mapimessage, $mapiprops);
     }
     if (stripos($props[PR_MESSAGE_CLASS], "IPM.Schedule.Meeting.Resp.") === 0) {
         // search for calendar items using goid
         $mr = new Meetingrequest($this->store, $mapimessage);
         $appointments = $mr->findCalendarItems($props[$meetingRequestProps["goidtag"]]);
         if (is_array($appointments) && !empty($appointments)) {
             $app = mapi_msgstore_openentry($this->store, $appointments[0]);
             $appprops = mapi_getprops($app, array($meetingRequestProps["appSeqNr"]));
             if (isset($appprops[$meetingRequestProps["appSeqNr"]]) && $appprops[$meetingRequestProps["appSeqNr"]]) {
                 $mapiprops[$meetingRequestProps["appSeqNr"]] = $appprops[$meetingRequestProps["appSeqNr"]];
                 ZLog::Write(LOGLEVEL_DEBUG, sprintf("Set sequence number to:%d", $appprops[$meetingRequestProps["appSeqNr"]]));
             }
         }
     }
     // Delete the PR_SENT_REPRESENTING_* properties because some android devices
     // do not send neither From nor Sender header causing empty PR_SENT_REPRESENTING_NAME and
     // PR_SENT_REPRESENTING_EMAIL_ADDRESS properties and "broken" PR_SENT_REPRESENTING_ENTRYID
     // which results in spooler not being able to send the message.
     // @see http://jira.zarafa.com/browse/ZP-85
     mapi_deleteprops($mapimessage, array($sendMailProps["sentrepresentingname"], $sendMailProps["sentrepresentingemail"], $sendMailProps["representingentryid"], $sendMailProps["sentrepresentingaddt"], $sendMailProps["sentrepresentinsrchk"]));
     if (isset($sm->source->itemid) && $sm->source->itemid) {
         // answering an email in a public/shared folder
         if (!$this->Setup(ZPush::GetAdditionalSyncFolderStore($sm->source->folderid))) {
             throw new StatusException(sprintf("ZarafaBackend->SendMail() could not Setup() the backend for folder id '%s'", $sm->source->folderid), SYNC_COMMONSTATUS_SERVERERROR);
         }
         $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($sm->source->folderid), hex2bin($sm->source->itemid));
         if ($entryid) {
             $fwmessage = mapi_msgstore_openentry($this->store, $entryid);
         }
         if (!isset($fwmessage) || !$fwmessage) {
             throw new StatusException(sprintf("ZarafaBackend->SendMail(): Could not open message id '%s' in folder id '%s' to be replied/forwarded: 0x%X", $sm->source->itemid, $sm->source->folderid, mapi_last_hresult()), SYNC_COMMONSTATUS_ITEMNOTFOUND);
         }
         //update icon when forwarding or replying message
         if ($sm->forwardflag) {
             mapi_setprops($fwmessage, array(PR_ICON_INDEX => 262));
         } elseif ($sm->replyflag) {
             mapi_setprops($fwmessage, array(PR_ICON_INDEX => 261));
         }
         mapi_savechanges($fwmessage);
         // only attach the original message if the mobile does not send it itself
         if (!isset($sm->replacemime)) {
             // get message's body in order to append forward or reply text
             if (!isset($body)) {
                 $body = MAPIUtils::readPropStream($mapimessage, PR_BODY);
             }
             if (!isset($bodyHtml)) {
                 $bodyHtml = MAPIUtils::readPropStream($mapimessage, PR_HTML);
             }
             $cpid = mapi_getprops($fwmessage, array($sendMailProps["internetcpid"]));
             if ($sm->forwardflag) {
                 // attach the original attachments to the outgoing message
                 $this->copyAttachments($mapimessage, $fwmessage);
             }
             // regarding the conversion @see ZP-470
             if (strlen($body) > 0) {
                 $fwbody = MAPIUtils::readPropStream($fwmessage, PR_BODY);
                 // if only the old message's cpid is set, convert from old charset to utf-8
                 if (isset($cpid[$sendMailProps["internetcpid"]]) && $cpid[$sendMailProps["internetcpid"]] != INTERNET_CPID_UTF8) {
                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->SendMail(): convert plain forwarded message charset (only fw set) from '%s' to '65001'", $cpid[$sendMailProps["internetcpid"]]));
                     $fwbody = Utils::ConvertCodepageStringToUtf8($cpid[$sendMailProps["internetcpid"]], $fwbody);
                 } else {
                     ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->SendMail(): no charset conversion done for plain forwarded message");
                     $fwbody = w2u($fwbody);
                 }
                 $mapiprops[$sendMailProps["body"]] = $body . "\r\n\r\n" . $fwbody;
             }
             if (strlen($bodyHtml) > 0) {
                 $fwbodyHtml = MAPIUtils::readPropStream($fwmessage, PR_HTML);
                 // if only new message's cpid is set, convert to UTF-8
                 if (isset($cpid[$sendMailProps["internetcpid"]]) && $cpid[$sendMailProps["internetcpid"]] != INTERNET_CPID_UTF8) {
                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->SendMail(): convert html forwarded message charset (only fw set) from '%s' to '65001'", $cpid[$sendMailProps["internetcpid"]]));
                     $fwbodyHtml = Utils::ConvertCodepageStringToUtf8($cpid[$sendMailProps["internetcpid"]], $fwbodyHtml);
                 } else {
                     ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->SendMail(): no charset conversion done for html forwarded message");
                     $fwbodyHtml = w2u($fwbodyHtml);
                 }
                 $mapiprops[$sendMailProps["html"]] = $bodyHtml . "<br><br>" . $fwbodyHtml;
             }
         }
     }
     mapi_setprops($mapimessage, $mapiprops);
     mapi_message_savechanges($mapimessage);
     mapi_message_submitmessage($mapimessage);
     $hr = mapi_last_hresult();
     if ($hr) {
         throw new StatusException(sprintf("ZarafaBackend->SendMail(): Error saving/submitting the message to the Outbox: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_MAILSUBMISSIONFAILED);
     }
     ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->SendMail(): email submitted");
     return true;
 }
Exemple #8
0
 function SendMail($rfc822, $forward = false, $reply = false, $parent = false)
 {
     if (WBXML_DEBUG == true) {
         debugLog("SendMail: forward: {$forward}   reply: {$reply}   parent: {$parent}\n" . $rfc822);
     }
     // Open the outbox and create the message there
     $storeprops = mapi_getprops($this->_defaultstore, array(PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID));
     if (!isset($storeprops[PR_IPM_OUTBOX_ENTRYID])) {
         debugLog("Outbox not found to create message");
         return false;
     }
     $outbox = mapi_msgstore_openentry($this->_defaultstore, $storeprops[PR_IPM_OUTBOX_ENTRYID]);
     if (!$outbox) {
         debugLog("Unable to open outbox");
         return false;
     }
     $mapimessage = mapi_folder_createmessage($outbox);
     //message properties to be set
     $mapiprops = array();
     // only save the outgoing in sent items folder if the mobile requests it
     if (isset($storeprops[PR_IPM_SENTMAIL_ENTRYID])) {
         $mapiprops[PR_SENTMAIL_ENTRYID] = $storeprops[PR_IPM_SENTMAIL_ENTRYID];
     } else {
         debugLog("PR_SENTMAIL_ENTRYID is not set. The sent message will not be moved to Sent Items.");
     }
     if ($forward) {
         $orig = $forward;
     }
     if ($reply) {
         $orig = $reply;
     }
     // Check if imtomapi function is available and use it to send the mime message.
     // It is available since ZCP 7.0.6
     // @see http://jira.zarafa.com/browse/ZCP-9508
     if (function_exists('mapi_feature') && mapi_feature('INETMAPI_IMTOMAPI')) {
         debugLog("Use the mapi_inetmapi_imtomapi function");
         $ab = mapi_openaddressbook($this->_session);
         mapi_inetmapi_imtomapi($this->_session, $this->_defaultstore, $ab, $mapimessage, $rfc822, array());
         // Delete the PR_SENT_REPRESENTING_* properties because some android devices
         // do not send neither From nor Sender header causing empty PR_SENT_REPRESENTING_NAME and
         // PR_SENT_REPRESENTING_EMAIL_ADDRESS properties and "broken" PR_SENT_REPRESENTING_ENTRYID
         // which results in spooler not being able to send the message.
         // @see http://jira.zarafa.com/browse/ZP-85
         mapi_deleteprops($mapimessage, array(PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_ADDRTYPE, PR_SENT_REPRESENTING_SEARCH_KEY));
         if (isset($orig) && $orig) {
             $entryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($parent), hex2bin($orig));
             $fwmessage = mapi_msgstore_openentry($this->_defaultstore, $entryid);
             if ($fwmessage) {
                 //update icon when forwarding or replying message
                 if ($forward) {
                     mapi_setprops($fwmessage, array(PR_ICON_INDEX => 262));
                 } elseif ($reply) {
                     mapi_setprops($fwmessage, array(PR_ICON_INDEX => 261));
                 }
                 mapi_savechanges($fwmessage);
                 if ($forward) {
                     $this->_copyAttachments($mapimessage, $fwmessage);
                 }
                 $body = $this->_readPropStream($mapimessage, PR_BODY);
                 $body_html = $this->_readPropStream($mapimessage, PR_HTML);
                 if (strlen($body) > 0) {
                     $fwbody = $this->_readPropStream($fwmessage, PR_BODY);
                     $body .= $fwbody;
                 }
                 if (strlen($body_html) > 0) {
                     $fwbody_html = $this->_readPropStream($fwmessage, PR_HTML);
                     $body_html .= $fwbody_html;
                 }
                 mapi_setprops($mapimessage, array(PR_BODY => $body));
                 if (strlen($body_html) > 0) {
                     mapi_setprops($mapimessage, array(PR_HTML => $body_html));
                 }
             }
         }
         if (!empty($mapiprops)) {
             mapi_setprops($mapimessage, $mapiprops);
         }
         mapi_message_savechanges($mapimessage);
         mapi_message_submitmessage($mapimessage);
         $hr = mapi_last_hresult();
         if ($hr) {
             debugLog(sprintf("SendMail(): Error saving/submitting the message to the Outbox: 0x%X", mapi_last_hresult()));
             return false;
         }
         return true;
     }
     $mimeParams = array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'charset' => 'utf-8');
     $mimeObject = new Mail_mimeDecode($rfc822);
     $message = $mimeObject->decode($mimeParams);
     mapi_setprops($mapimessage, array(PR_SUBJECT => u2wi(isset($message->headers["subject"]) ? $message->headers["subject"] : ""), PR_SENTMAIL_ENTRYID => $storeprops[PR_IPM_SENTMAIL_ENTRYID], PR_MESSAGE_CLASS => "IPM.Note", PR_MESSAGE_DELIVERY_TIME => time()));
     if (isset($message->headers["x-priority"])) {
         switch ($message->headers["x-priority"]) {
             case 1:
             case 2:
                 $priority = PRIO_URGENT;
                 $importance = IMPORTANCE_HIGH;
                 break;
             case 4:
             case 5:
                 $priority = PRIO_NONURGENT;
                 $importance = IMPORTANCE_LOW;
                 break;
             case 3:
             default:
                 $priority = PRIO_NORMAL;
                 $importance = IMPORTANCE_NORMAL;
                 break;
         }
         mapi_setprops($mapimessage, array(PR_IMPORTANCE => $importance, PR_PRIORITY => $priority));
     }
     $addresses = array();
     $toaddr = $ccaddr = $bccaddr = array();
     $Mail_RFC822 = new Mail_RFC822();
     if (isset($message->headers["to"])) {
         $toaddr = $Mail_RFC822->parseAddressList($message->headers["to"]);
     }
     if (isset($message->headers["cc"])) {
         $ccaddr = $Mail_RFC822->parseAddressList($message->headers["cc"]);
     }
     if (isset($message->headers["bcc"])) {
         $bccaddr = $Mail_RFC822->parseAddressList($message->headers["bcc"]);
     }
     // Add recipients
     $recips = array();
     if (isset($toaddr)) {
         foreach (array(MAPI_TO => $toaddr, MAPI_CC => $ccaddr, MAPI_BCC => $bccaddr) as $type => $addrlist) {
             foreach ($addrlist as $addr) {
                 $mapirecip[PR_ADDRTYPE] = "SMTP";
                 $mapirecip[PR_EMAIL_ADDRESS] = $addr->mailbox . "@" . $addr->host;
                 if (isset($addr->personal) && strlen($addr->personal) > 0) {
                     $mapirecip[PR_DISPLAY_NAME] = u2wi($addr->personal);
                 } else {
                     $mapirecip[PR_DISPLAY_NAME] = $mapirecip[PR_EMAIL_ADDRESS];
                 }
                 $mapirecip[PR_RECIPIENT_TYPE] = $type;
                 $mapirecip[PR_ENTRYID] = mapi_createoneoff($mapirecip[PR_DISPLAY_NAME], $mapirecip[PR_ADDRTYPE], $mapirecip[PR_EMAIL_ADDRESS]);
                 array_push($recips, $mapirecip);
             }
         }
     }
     mapi_message_modifyrecipients($mapimessage, 0, $recips);
     // Loop through message subparts.
     $body = "";
     $body_html = "";
     if ($message->ctype_primary == "multipart" && ($message->ctype_secondary == "mixed" || $message->ctype_secondary == "alternative")) {
         $mparts = $message->parts;
         for ($i = 0; $i < count($mparts); $i++) {
             $part = $mparts[$i];
             // palm pre & iPhone send forwarded messages in another subpart which are also parsed
             if ($part->ctype_primary == "multipart" && ($part->ctype_secondary == "mixed" || $part->ctype_secondary == "alternative" || $part->ctype_secondary == "related")) {
                 foreach ($part->parts as $spart) {
                     $mparts[] = $spart;
                 }
                 continue;
             }
             // standard body
             if ($part->ctype_primary == "text" && $part->ctype_secondary == "plain" && isset($part->body) && (!isset($part->disposition) || $part->disposition != "attachment")) {
                 $body .= u2wi($part->body);
                 // assume only one text body
             } elseif ($part->ctype_primary == "text" && $part->ctype_secondary == "html") {
                 $body_html .= u2wi($part->body);
             } elseif ($part->ctype_primary == "ms-tnef" || $part->ctype_secondary == "ms-tnef") {
                 $zptnef = new ZPush_tnef($this->_defaultstore);
                 $mapiprops = array();
                 $zptnef->extractProps($part->body, $mapiprops);
                 if (is_array($mapiprops) && !empty($mapiprops)) {
                     //check if it is a recurring item
                     $tnefrecurr = GetPropIDFromString($this->_defaultstore, "PT_BOOLEAN:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0x5");
                     if (isset($mapiprops[$tnefrecurr])) {
                         $this->_handleRecurringItem($mapimessage, $mapiprops);
                     }
                     mapi_setprops($mapimessage, $mapiprops);
                 } else {
                     debugLog("TNEF: Mapi props array was empty");
                 }
             } elseif ($part->ctype_primary == "text" && $part->ctype_secondary == "calendar") {
                 $zpical = new ZPush_ical($this->_defaultstore);
                 $mapiprops = array();
                 $zpical->extractProps($part->body, $mapiprops);
                 // iPhone sends a second ICS which we ignore if we can
                 if (!isset($mapiprops[PR_MESSAGE_CLASS]) && strlen(trim($body)) == 0) {
                     debugLog("Secondary iPhone response is being ignored!! Mail dropped!");
                     return true;
                 }
                 if (!checkMapiExtVersion("6.30") && is_array($mapiprops) && !empty($mapiprops)) {
                     mapi_setprops($mapimessage, $mapiprops);
                 } else {
                     // store ics as attachment
                     //see icalTimezoneFix function in compat.php for more information
                     $part->body = icalTimezoneFix($part->body);
                     $this->_storeAttachment($mapimessage, $part);
                     debugLog("Sending ICS file as attachment");
                 }
             } else {
                 $this->_storeAttachment($mapimessage, $part);
             }
         }
     } else {
         if ($message->ctype_primary == "text" && $message->ctype_secondary == "html") {
             $body_html .= u2wi($message->body);
         } else {
             $body = u2wi($message->body);
         }
     }
     // some devices only transmit a html body
     if (strlen($body) == 0 && strlen($body_html) > 0) {
         debugLog("only html body sent, transformed into plain text");
         $body = strip_tags($body_html);
     }
     if (isset($orig) && $orig) {
         // Append the original text body for reply/forward
         $entryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($parent), hex2bin($orig));
         $fwmessage = mapi_msgstore_openentry($this->_defaultstore, $entryid);
         if ($fwmessage) {
             //update icon when forwarding or replying message
             if ($forward) {
                 mapi_setprops($fwmessage, array(PR_ICON_INDEX => 262));
             } elseif ($reply) {
                 mapi_setprops($fwmessage, array(PR_ICON_INDEX => 261));
             }
             mapi_savechanges($fwmessage);
             $fwbody = $this->_readPropStream($fwmessage, PR_BODY);
             $fwbody_html = $this->_readPropStream($fwmessage, PR_HTML);
             if ($forward) {
                 // During a forward, we have to add the forward header ourselves. This is because
                 // normally the forwarded message is added as an attachment. However, we don't want this
                 // because it would be rather complicated to copy over the entire original message due
                 // to the lack of IMessage::CopyTo ..
                 $fwmessageprops = mapi_getprops($fwmessage, array(PR_SENT_REPRESENTING_NAME, PR_DISPLAY_TO, PR_DISPLAY_CC, PR_SUBJECT, PR_CLIENT_SUBMIT_TIME));
                 $fwheader = "\r\n\r\n";
                 $fwheader .= "-----Original Message-----\r\n";
                 if (isset($fwmessageprops[PR_SENT_REPRESENTING_NAME])) {
                     $fwheader .= "From: " . $fwmessageprops[PR_SENT_REPRESENTING_NAME] . "\r\n";
                 }
                 if (isset($fwmessageprops[PR_DISPLAY_TO]) && strlen($fwmessageprops[PR_DISPLAY_TO]) > 0) {
                     $fwheader .= "To: " . $fwmessageprops[PR_DISPLAY_TO] . "\r\n";
                 }
                 if (isset($fwmessageprops[PR_DISPLAY_CC]) && strlen($fwmessageprops[PR_DISPLAY_CC]) > 0) {
                     $fwheader .= "Cc: " . $fwmessageprops[PR_DISPLAY_CC] . "\r\n";
                 }
                 if (isset($fwmessageprops[PR_CLIENT_SUBMIT_TIME])) {
                     $fwheader .= "Sent: " . strftime("%x %X", $fwmessageprops[PR_CLIENT_SUBMIT_TIME]) . "\r\n";
                 }
                 if (isset($fwmessageprops[PR_SUBJECT])) {
                     $fwheader .= "Subject: " . $fwmessageprops[PR_SUBJECT] . "\r\n";
                 }
                 $fwheader .= "\r\n";
                 // add fwheader to body and body_html
                 $body .= $fwheader;
                 if (strlen($body_html) > 0) {
                     $body_html .= str_ireplace("\r\n", "<br>", $fwheader);
                 }
             }
             if (strlen($body) > 0) {
                 $body .= $fwbody;
             }
             if (strlen($body_html) > 0) {
                 $body_html .= $fwbody_html;
             }
         } else {
             debugLog("Unable to open item with id {$orig} for forward/reply");
         }
     }
     if ($forward) {
         // Add attachments from the original message in a forward
         $entryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($parent), hex2bin($orig));
         $fwmessage = mapi_msgstore_openentry($this->_defaultstore, $entryid);
         $attachtable = mapi_message_getattachmenttable($fwmessage);
         $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM));
         foreach ($rows as $row) {
             if (isset($row[PR_ATTACH_NUM])) {
                 $attach = mapi_message_openattach($fwmessage, $row[PR_ATTACH_NUM]);
                 $newattach = mapi_message_createattach($mapimessage);
                 // Copy all attachments from old to new attachment
                 $attachprops = mapi_getprops($attach);
                 mapi_setprops($newattach, $attachprops);
                 if (isset($attachprops[mapi_prop_tag(PT_ERROR, mapi_prop_id(PR_ATTACH_DATA_BIN))])) {
                     // Data is in a stream
                     $srcstream = mapi_openpropertytostream($attach, PR_ATTACH_DATA_BIN);
                     $dststream = mapi_openpropertytostream($newattach, PR_ATTACH_DATA_BIN, MAPI_MODIFY | MAPI_CREATE);
                     while (1) {
                         $data = mapi_stream_read($srcstream, 4096);
                         if (strlen($data) == 0) {
                             break;
                         }
                         mapi_stream_write($dststream, $data);
                     }
                     mapi_stream_commit($dststream);
                 }
                 mapi_savechanges($newattach);
             }
         }
     }
     //set PR_INTERNET_CPID to 65001 (utf-8) if store supports it and to 1252 otherwise
     $internetcpid = 1252;
     if (defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) {
         $internetcpid = 65001;
     }
     mapi_setprops($mapimessage, array(PR_BODY => $body, PR_INTERNET_CPID => $internetcpid));
     if (strlen($body_html) > 0) {
         mapi_setprops($mapimessage, array(PR_HTML => $body_html));
     }
     mapi_savechanges($mapimessage);
     mapi_message_submitmessage($mapimessage);
     return true;
 }
 /**
  * Updates a card
  * 
  * @param mixed $addressBookId 
  * @param string $cardUri 
  * @param string $cardData 
  * @return bool 
  */
 public function updateCard($addressBookId, $cardUri, $cardData)
 {
     $this->logger->info("updateCard - {$cardUri}");
     if (READ_ONLY) {
         $this->logger->warn("Cannot update card: read-only");
         return false;
     }
     // Update object properties
     $entryId = $this->getContactEntryId($addressBookId, $cardUri);
     if ($entryId === 0) {
         $this->logger->warn("Cannot find contact");
         return false;
     }
     $mapiProperties = $this->bridge->vcardToMapiProperties($cardData);
     $contact = mapi_msgstore_openentry($this->bridge->getStore($addressBookId), $entryId);
     if (SAVE_RAW_VCARD) {
         // Save RAW vCard
         $this->logger->debug("Saving raw vcard");
         $mapiProperties[PR_CARDDAV_RAW_DATA] = $cardData;
         $mapiProperties[PR_CARDDAV_RAW_DATA_GENERATION_TIME] = time();
     } else {
         $this->logger->trace("Saving raw vcard skiped by config");
     }
     // Handle contact picture
     if (array_key_exists('ContactPicture', $mapiProperties)) {
         $this->logger->debug("Updating contact picture");
         $contactPicture = $mapiProperties['ContactPicture'];
         unset($mapiProperties['ContactPicture']);
         $this->bridge->setContactPicture($contact, $contactPicture);
     }
     // Remove NULL properties
     if (CLEAR_MISSING_PROPERTIES) {
         $this->logger->debug("Clearing missing properties");
         $nullProperties = array();
         foreach ($mapiProperties as $p => $v) {
             if ($v == NULL) {
                 $nullProperties[] = $p;
                 unset($mapiProperties[$p]);
             }
         }
         $dump = print_r($nullProperties, true);
         $this->logger->trace("Removing properties\n{$dump}");
         mapi_deleteprops($contact, $nullProperties);
     }
     // Set properties
     $mapiProperties[PR_LAST_MODIFICATION_TIME] = time();
     mapi_setprops($contact, $mapiProperties);
     // Save changes to backend
     mapi_savechanges($contact);
     return mapi_last_hresult() == 0;
 }
Exemple #10
0
 /**
  * Sets the out of office settings.
  *
  * @param SyncObject $oof
  *
  * @access private
  * @return void
  */
 private function settingsOofSet(&$oof)
 {
     $oof->Status = SYNC_SETTINGSSTATUS_SUCCESS;
     $props = array();
     if ($oof->oofstate == SYNC_SETTINGSOOF_GLOBAL || $oof->oofstate == SYNC_SETTINGSOOF_TIMEBASED) {
         $props[PR_EC_OUTOFOFFICE] = true;
         foreach ($oof->oofmessage as $oofmessage) {
             if (isset($oofmessage->appliesToInternal)) {
                 $props[PR_EC_OUTOFOFFICE_MSG] = isset($oofmessage->replymessage) ? u2w($oofmessage->replymessage) : "";
                 $props[PR_EC_OUTOFOFFICE_SUBJECT] = "Out of office";
             }
         }
         if ($oof->oofstate == SYNC_SETTINGSOOF_TIMEBASED) {
             if (isset($oof->starttime) && isset($oof->endtime)) {
                 $props[PR_EC_OUTOFOFFICE_FROM] = $oof->starttime;
                 $props[PR_EC_OUTOFOFFICE_UNTIL] = $oof->endtime;
             } elseif (isset($oof->starttime) || isset($oof->endtime)) {
                 $oof->Status = SYNC_SETTINGSSTATUS_PROTOCOLLERROR;
             }
         } else {
             $deleteProps = array(PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL);
         }
     } elseif ($oof->oofstate == SYNC_SETTINGSOOF_DISABLED) {
         $props[PR_EC_OUTOFOFFICE] = false;
         $deleteProps = array(PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL);
     }
     if (!empty($props)) {
         @mapi_setprops($this->defaultstore, $props);
         $result = mapi_last_hresult();
         if ($result != NOERROR) {
             ZLog::Write(LOGLEVEL_ERROR, sprintf("Setting oof information failed (%X)", $result));
             return false;
         }
     }
     if (!empty($deleteProps)) {
         @mapi_deleteprops($this->defaultstore, $deleteProps);
     }
     return true;
 }