Skip to content

Commit

Permalink
Abstract out Horde_Core_ActiveSync_Mail_Draft
Browse files Browse the repository at this point in the history
  • Loading branch information
mrubinsk committed Sep 11, 2016
1 parent b010943 commit d624284
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 67 deletions.
79 changes: 14 additions & 65 deletions framework/Core/lib/Horde/Core/ActiveSync/Driver.php
Expand Up @@ -1999,78 +1999,27 @@ public function changeMessage($folderid, $id, Horde_ActiveSync_Message_Base $mes

// Are we addding/changing a draft email?
if ($message->airsyncbasebody) {

$msg = $message->draftToMime();
$msg['headers']->addHeader(
'From',
Horde_Core_ActiveSync_Mail::getFromAddress($this->_user)
$draft_folder = $this->getSpecialFolderNameByType(
self::SPECIAL_DRAFTS
);
$msg['headers']->addHeaderOb(Horde_Mime_Headers_Date::create());
$msg['headers']->addHeaderOb(Horde_Mime_Headers_ContentId::create());
$msg['headers']->addHeader('X-IMP-Draft', 'Yes');

$base = new Horde_Mime_Part();
$base->setType('multipart/mixed');
$draft = new Horde_Core_ActiveSync_Mail_Draft(
$this->_imap,
$this->_user,
$this->_version
);
$draft->setDraftMessage($message);

// If we have a change to attachments we need to
// download the existing IMAP message.
// Do we need an existing Draft message?
if ($id && !empty($message->airsyncbaseattachments)) {
$imap_msg = $this->_imap->getImapMessage(
$this->getSpecialFolderNameByType(self::SPECIAL_DRAFTS),
$id
);
foreach ($imap_msg[$id]->getStructure() as $part) {
if ($part->isAttachment()) {
$base->addPart($imap_msg[$id]->getMimePart($part->getMimeId()));
}
}
}
$base->addPart($msg['part']);
$base->addMimeHeaders(array('headers' => $msg['headers']));

// Attachments.
$delete = array();
foreach ($message->airsyncbaseattachments as $atc) {
switch (get_class($atc)) {
case 'Horde_ActiveSync_Message_AirSyncBaseAdd':
$atc_map[$atc->displayname] = $atc->clientid;
$atc_mime = new Horde_Mime_Part();
$atc_mime->setType($atc->contenttype);
$atc_mime->setName($atc->displayname);
$atc_mime->setContents($atc->content);
$base->addPart($atc_mime);
break;
case 'Horde_ActiveSync_Message_AirSyncBaseDelete':
list($mailbox, $uid, $part) = explode(':', $name, 3);
$base->removePart($part);
}
$draft->getExistingDraftMessage($draft_folder, $id);
}
$stream = $base->toString(array(
'stream' => true,
'headers' => $msg['headers']->toString()
));

$stat['id'] = $this->_imap->appendMessage(
$this->getSpecialFolderNameByType(self::SPECIAL_DRAFTS),
$stream,
array('\draft', '\seen')
);

$atc_hash = array();
foreach ($base as $mid => $part) {
if ($part->isAttachment() &&
!empty($atc_map[$part->getName()])) {
$atc_hash['add'][$atc_map[$part->getName()]] = $folderid . ':' . $stat['id'] . ':' . $mid;
}
}
// Append the message and return results.
$results = $draft->append($draft_folder);
$stat['id'] = $results['uid'];
$stat['atchash'] = $results['atchash'];
$stat['conversationid'] = bin2hex($message->subject);
$stat['conversationindex'] = time();
$stat['atchash'] = $atc_hash;

if (!empty($id)) {
// Delete.
$this->_imap->deleteMessages(array($id), $folderid);
}

return $stat;
}
Expand Down
207 changes: 207 additions & 0 deletions framework/Core/lib/Horde/Core/ActiveSync/Mail/Draft.php
@@ -0,0 +1,207 @@
<?php
/**
* Horde_Core_ActiveSync_Mail_Draft::
*
* @copyright 2016 Horde LLC (http://www.horde.org/)
* @license http://www.horde.org/licenses/lgpl21 LGPL
* @author Michael J Rubinsky <mrubinsk@horde.org>
* @package Core
*/
/**
* Horde_Core_ActiveSync_Mail_Draft::
*
* Wraps functionality related to handling Draft email messages during sync.
*
* @copyright 2016 Horde LLC (http://www.horde.org/)
* @license http://www.horde.org/licenses/lgpl21 LGPL
* @author Michael J Rubinsky <mrubinsk@horde.org>
* @package Core
*
* @todo Move this, along with the parent class to the ActiveSync package and
* inject any needed Core dependencies.
*/
class Horde_Core_ActiveSync_Mail_Draft extends Horde_Core_ActiveSync_Mail
{
/**
* Text part of Draft message.
*
* @var Horde_Mime_Part
*/
protected $_textPart;

/**
* Existing Draft message.
*
* @var Horde_ActiveSync_Imap_Message
*/
protected $_imapMessage;

/**
* Existing Draft message's UID.
*
* @var integer
*/
protected $_draftUid;

/**
* Draft Email from client.
*
* @var Horde_ActiveSync_Message_Email
*/
protected $_draftMessage;

/**
* Append the current Draft message to the IMAP server.
*
* @return array An array with the following keys:
* - uid: (integer) The new draft message's IMAP UID.
* - atchash: (array) An attachment hash of newly added attachments.
*/
public function append($folderid)
{
// Init
$atc_map = array();
$atc_hash = array();

// Create the wrapper part.
$base = new Horde_Mime_Part();
$base->setType('multipart/mixed');

// Check to see if we have any existing parts to add.
if (!empty($this->_imapMessage)) {
foreach ($this->_imapMessage->getStructure() as $part) {
if ($part->isAttachment()) {
$base->addPart(
$this->_imapMessage->getMimePart($part->getMimeId())
);
}
}
}

// Add body
$base->addPart($this->_textPart);

// Add Mime headers
$base->addMimeHeaders(array(
'headers' => $this->_headers)
);

// New attachments
foreach ($this->_draftMessage->airsyncbaseattachments as $atc) {
switch (get_class($atc)) {
case 'Horde_ActiveSync_Message_AirSyncBaseAdd':
$atc_map[$atc->displayname] = $atc->clientid;
$atc_mime = new Horde_Mime_Part();
$atc_mime->setType($atc->contenttype);
$atc_mime->setName($atc->displayname);
$atc_mime->setContents($atc->content);
$base->addPart($atc_mime);
break;
case 'Horde_ActiveSync_Message_AirSyncBaseDelete':
list($mailbox, $uid, $part) = explode(':', $name, 3);
$base->removePart($part);
}
}

$stream = $base->toString(array(
'stream' => true,
'headers' => $this->_headers->toString()
));

$new_uid = $this->_imap->appendMessage(
$folderid,
$stream,
array('\draft', '\seen')
);

foreach ($base as $part) {
if ($part->isAttachment() &&
!empty($atc_map[$part->getName()])) {
$atc_hash['add'][$atc_map[$part->getName()]] = $folderid . ':' . $stat['id'] . ':' . $part->getMimeId();
}
}

// If we pulled down an existing Draft, delete it now since the
// new one will replace it.
if (!empty($this->_imapMessage)) {
$this->_imap->deleteMessages(array($this->_draftUid), $folderid);
}

return array(
'uid' => $new_uid,
'atchash' => $atc_hash
);
}

/**
* Add the Draft message sent from the client.
*
* @param Horde_ActiveSync_Message_Mail $draft The draft message object.
*/
public function setDraftMessage(Horde_ActiveSync_Message_Mail $draft)
{
// Save for later.
$this->_draftMessage = $draft;

// Create headers
$this->_headers = new Horde_Mime_Headers();
if ($draft->to) {
$this->_headers->addHeader('To', $draft->to);
}
if ($draft->cc) {
$this->_headers->addHeader('Cc', $draft->cc);
}
if ($draft->subject) {
$this->_headers->addHeader('Subject', $draft->subject);
}
if ($draft->bcc) {
$this->_headers->addHeader('Bcc', $draft->bcc);
}
if ($draft->importance) {
$this->_headers->addHeader('importance', $draft->importance);
}
if ($from = $this->_getIdentityFromAddress()) {
$this->_headers->removeHeader('From');
$this->_headers->addHeader('From', $from);
}
if ($replyto = $this->_getReplyToAddress()) {
$this->_headers->addHeader('Reply-To', $replyto);
}
$this->_headers->addHeaderOb(Horde_Mime_Headers_Date::create());
$this->_headers->addHeaderOb(Horde_Mime_Headers_ContentId::create());
$this->_headers->addHeader('X-IMP-Draft', 'Yes');

// Get the text part and create a mime object for it.
$this->_textPart = new Horde_Mime_Part();
$this->_textPart->setContents($draft->airsyncbasebody->data);
$this->_textPart->setType(
$draft->airsyncbasebody->type == Horde_ActiveSync::BODYPREF_TYPE_HTML
? 'text/html'
: 'text/plain'
);
}

/**
* Fetch an existing message from the Draft folder. This message will
* be expunged after the new draft is appended to the IMAP server.
*
* @param string $folderid The Draft folder's folderid.
* @param integer $uid The UID of the existing Draft message.
*
* @throws Horde_ActiveSync_Exception
*/
public function getExistingDraftMessage($folderid, $uid)
{
$imap_msg = $this->_imap->getImapMessage($folderid,$uid);
if (!empty($imap_msg[$uid])) {
$this->_imapMessage = $imap_msg[$uid];
$this->_draftUid = $uid;
} else {
throw new Horde_ActiveSync_Exception(sprintf(
'Unable to fetch %d from %s.',
$uid, $folderid)
);
}
}

}
8 changes: 6 additions & 2 deletions framework/Core/package.xml
Expand Up @@ -28,7 +28,7 @@
<email>mrubinsk@horde.org</email>
<active>yes</active>
</developer>
<date>2016-09-06</date>
<date>2016-09-11</date>
<version>
<release>2.26.1</release>
<api>2.26.0</api>
Expand Down Expand Up @@ -301,6 +301,9 @@
<dir name="Logger">
<file name="Factory.php" role="php" />
</dir> <!-- /lib/Horde/Core/ActiveSync/Logger -->
<dir name="Mail">
<file name="Draft.php" role="php" />
</dir> <!-- /lib/Horde/Core/ActiveSync/Mail -->
<file name="Auth.php" role="php" />
<file name="Connector.php" role="php" />
<file name="Driver.php" role="php" />
Expand Down Expand Up @@ -1773,6 +1776,7 @@
<install as="Horde/Core/ActiveSync/Mdn.php" name="lib/Horde/Core/ActiveSync/Mdn.php" />
<install as="Horde/Core/ActiveSync/Imap/Factory.php" name="lib/Horde/Core/ActiveSync/Imap/Factory.php" />
<install as="Horde/Core/ActiveSync/Logger/Factory.php" name="lib/Horde/Core/ActiveSync/Logger/Factory.php" />
<install as="Horde/Core/ActiveSync/Mail/Draft.php" name="lib/Horde/Core/ActiveSync/Mail/Draft.php" />
<install as="Horde/Core/Ajax/Application.php" name="lib/Horde/Core/Ajax/Application.php" />
<install as="Horde/Core/Ajax/Imple.php" name="lib/Horde/Core/Ajax/Imple.php" />
<install as="Horde/Core/Ajax/Response.php" name="lib/Horde/Core/Ajax/Response.php" />
Expand Down Expand Up @@ -4237,7 +4241,7 @@
<stability>
<release>stable</release>
<api>stable</api></stability>
<date>2016-09-06</date>
<date>2016-09-11</date>
<license uri="http://www.horde.org/licenses/lgpl21">LGPL-2.1</license>
<notes>
*
Expand Down

0 comments on commit d624284

Please sign in to comment.