From aae805cf3895a62ffb96d77095f6499133f7aeee Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Wed, 1 Apr 2009 13:11:54 -0600 Subject: [PATCH] Implement $MDNSent keyword support (RFC 3503) --- imp/ajax.php | 2 +- imp/docs/CHANGES | 1 + imp/docs/RFCS | 1 + imp/lib/Compose.php | 14 +++++++- imp/lib/UI/Message.php | 77 ++++++++++++++++++++++++++++++------------- imp/lib/Views/ShowMessage.php | 2 +- imp/message.php | 2 +- 7 files changed, 73 insertions(+), 26 deletions(-) diff --git a/imp/ajax.php b/imp/ajax.php index 11252941f..8ab58acad 100644 --- a/imp/ajax.php +++ b/imp/ajax.php @@ -685,7 +685,7 @@ case 'SendMDN': } $imp_ui = new IMP_UI_Message(); - $imp_ui->MDNCheck(reset($fetch_ret[$index]['headertext']), true); + $imp_ui->MDNCheck($mbox, $index, $reset($fetch_ret[$index]['headertext']), true); break; case 'PGPSymmetric': diff --git a/imp/docs/CHANGES b/imp/docs/CHANGES index e8570ee76..759a861d4 100644 --- a/imp/docs/CHANGES +++ b/imp/docs/CHANGES @@ -2,6 +2,7 @@ v5.0-git -------- +[mms] Support $MDNSent keyword (RFC 3503) on IMAP server. [mms] Link URLs/e-mails in subjects in message views (Request #7487). [mms] Implement spellcheck on send in DIMP. [mms] Sanity check - don't do message operations reliant on UID list if diff --git a/imp/docs/RFCS b/imp/docs/RFCS index e1b45b7c4..57775b823 100644 --- a/imp/docs/RFCS +++ b/imp/docs/RFCS @@ -25,6 +25,7 @@ RFC 2595/4616 TLS & AUTH=PLAIN RFC 2831 DIGEST-MD5 authentication mechanism. RFC 2971 ID RFC 3502 MULTIAPPEND +RFC 3503 $MDNSent keyword RFC 3516 BINARY RFC 3691 UNSELECT RFC 4315 UIDPLUS diff --git a/imp/lib/Compose.php b/imp/lib/Compose.php index ef3dffefa..b02371626 100644 --- a/imp/lib/Compose.php +++ b/imp/lib/Compose.php @@ -236,6 +236,10 @@ class IMP_Compose $append_flags[] = '\\seen'; } + /* RFC 3503 [3.4] states that when saving a draft, the client MUST + * set the $MDNSent keyword. However, IMP doesn't write MDN headers + * until send time so no need to set the flag here. */ + /* Get the message ID. */ $headers = Horde_Mime_Headers::parseHeaders($data); @@ -433,6 +437,7 @@ class IMP_Compose $headers->addHeader('Date', date('r')); /* Add Return Receipt Headers. */ + $mdn = null; if (!empty($opts['readreceipt']) && $conf['compose']['allow_receipts']) { $mdn = new Horde_Mime_Mdn(); @@ -584,8 +589,15 @@ class IMP_Compose $imp_folder->create($opts['sent_folder'], $prefs->getValue('subscribe')); } + $flags = array('\\seen'); + + /* RFC 3503 [3.3] - set $MDNSent flag on sent message. */ + if ($mdn) { + $flags[] = array('$MDNSent'); + } + try { - $GLOBALS['imp_imap']->ob->append(String::convertCharset($opts['sent_folder'], NLS::getCharset(), 'UTF-8'), array(array('data' => $fcc, 'flags' => array('\\seen')))); + $GLOBALS['imp_imap']->ob->append(String::convertCharset($opts['sent_folder'], NLS::getCharset(), 'UTF-8'), array(array('data' => $fcc, 'flags' => $flags))); } catch (Horde_Imap_Client_Exception $e) { $notification->push(sprintf(_("Message sent successfully, but not saved to %s"), IMP::displayFolder($opts['sent_folder']))); $sent_saved = false; diff --git a/imp/lib/UI/Message.php b/imp/lib/UI/Message.php index 5f0fa6c4b..782178c56 100644 --- a/imp/lib/UI/Message.php +++ b/imp/lib/UI/Message.php @@ -57,11 +57,19 @@ class IMP_UI_Message } /** - * TODO + * Check if we need to send a MDN, and send if needed. + * + * @param string $mailbox The mailbox of the message. + * @param integer $uid The UID of the message. + * @param array $headers The headers of the message. + * @param boolean $confirmed Has the MDN request been confirmed? + * + * @return boolean True if the MDN request needs to be confirmed. */ - public function MDNCheck($headers, $confirmed = false) + public function MDNCheck($mailbox, $uid, $headers, $confirmed = false) { - if (!$GLOBALS['prefs']->getValue('disposition_send_mdn')) { + if (!$GLOBALS['prefs']->getValue('disposition_send_mdn') || + $GLOBALS['imp_imap']->isReadOnly($mailbox)) { return false; } @@ -73,29 +81,54 @@ class IMP_UI_Message } $msg_id = $headers->getValue('message-id'); + $mdn_flag = $need_mdn = false; /* See if we have already processed this message. */ - if (!IMP_Maillog::sentMDN($msg_id, 'displayed')) { - /* See if we need to query the user. */ - if ($mdn->userConfirmationNeeded() && !$confirmed) { - return true; - } else { - /* Send out the MDN now. */ - $mail_driver = IMP_Compose::getMailDriver(); - - try { - $mdn->generate(false, $confirmed, 'displayed', $mail_driver['driver'], $mail_driver['params']); - IMP_Maillog::log('mdn', $msg_id, 'displayed'); - $success = true; - } catch (Horde_Mime_Exception $e) { - $success = false; - } + /* 1st test: $MDNSent keyword (RFC 3503 [3.1]). */ + try { + $status = $GLOBALS['imp_imap']->ob->status($mailbox, Horde_Imap_Client::STATUS_PERMFLAGS); + if (in_array('\\*', $status['permflags']) || + in_array('$mdnsent', $status['permflags'])) { + $mdn_flag = true; + $res = $GLOBALS['imp_imap']->ob->fetch($mailbox, array( + Horde_Imap_Client::FETCH_FLAGS => true + ), array('ids' => array($uid))); + $need_mdn = in_array('$mdnsent', $res[$uid]['flags']); + } + } catch (Horde_Imap_Client_Exception $e) {} - if ($GLOBALS['conf']['sentmail']['driver'] != 'none') { - $sentmail = IMP_Sentmail::factory(); - $sentmail->log('mdn', '', $return_addr, $success); - } + if (!$mdn_flag) { + /* 2nd test: Use Maillog as a fallback. */ + $need_mdn = !IMP_Maillog::sentMDN($msg_id, 'displayed'); + } + + if (!$need_mdn) { + return false; + } + + /* See if we need to query the user. */ + if ($mdn->userConfirmationNeeded() && !$confirmed) { + return true; + } + + /* Send out the MDN now. */ + try { + $mail_driver = IMP_Compose::getMailDriver(); + $mdn->generate(false, $confirmed, 'displayed', $mail_driver['driver'], $mail_driver['params']); + IMP_Maillog::log('mdn', $msg_id, 'displayed'); + $success = true; + + if ($mdn_flag) { + $imp_message = &IMP_Message::singleton(); + $imp_message->flag(array('$MDNSent'), $uid . IMP::IDX_SEP . $mailbox, true); } + } catch (Horde_Mime_Exception $e) { + $success = false; + } + + if ($GLOBALS['conf']['sentmail']['driver'] != 'none') { + $sentmail = IMP_Sentmail::factory(); + $sentmail->log('mdn', '', $return_addr, $success); } return false; diff --git a/imp/lib/Views/ShowMessage.php b/imp/lib/Views/ShowMessage.php index ae23cb97b..bb71a4991 100644 --- a/imp/lib/Views/ShowMessage.php +++ b/imp/lib/Views/ShowMessage.php @@ -342,7 +342,7 @@ class IMP_Views_ShowMessage } /* Do MDN processing now. */ - if ($imp_ui->MDNCheck($mime_headers)) { + if ($imp_ui->MDNCheck($folder, $index, $mime_headers)) { $confirm_link = Horde::link('', '', '', '', 'DimpCore.doAction(\'SendMDN\',{folder:\'' . $folder . '\',index:' . $index . '}); return false;', '', '') . _("HERE") . ''; $GLOBALS['notification']->push(sprintf(_("The sender of this message is requesting a Message Disposition Notification from you when you have read this message. Click %s to send the notification message."), $confirm_link), 'dimp.request', array('content.raw')); } diff --git a/imp/message.php b/imp/message.php index 7cb3f725b..337596aa7 100644 --- a/imp/message.php +++ b/imp/message.php @@ -385,7 +385,7 @@ $view_link = IMP::generateIMPUrl('view.php', $imp_mbox['mailbox'], $index, $mail /* Retrieve any history information for this message. */ if (!IMP::$printMode && !empty($conf['maillog']['use_maillog'])) { /* Do MDN processing now. */ - if ($imp_ui->MDNCheck($mime_headers, Util::getFormData('mdn_confirm'))) { + if ($imp_ui->MDNCheck($imp_mbox['mailbox'], $index, $mime_headers, Util::getFormData('mdn_confirm'))) { $confirm_link = Horde::link(htmlspecialchars(Util::addParameter($selfURL, 'mdn_confirm', 1))) . _("HERE") . ''; $notification->push(sprintf(_("The sender of this message is requesting a Message Disposition Notification from you when you have read this message. Please click %s to send the notification message."), $confirm_link), 'horde.message', array('content.raw')); } -- 2.11.0