From 6287e02ce8484cd6bfb7f15a41635db5d467b460 Mon Sep 17 00:00:00 2001 From: Jan Schneider Date: Thu, 27 Jan 2011 15:17:23 +0100 Subject: [PATCH] Send alarms as multipart messages. --- nag/docs/CHANGES | 1 + nag/lib/Nag.php | 53 ++++++++++++++++++++++++++++++ nag/lib/Task.php | 20 +++++++---- nag/templates/alarm/mail.html.php | 36 ++++++++++++++++++++ nag/templates/alarm/mail.plain.php | 12 +++++++ nag/themes/default/graphics/big_alarm.png | Bin 0 -> 15893 bytes 6 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 nag/templates/alarm/mail.html.php create mode 100644 nag/templates/alarm/mail.plain.php create mode 100644 nag/themes/default/graphics/big_alarm.png diff --git a/nag/docs/CHANGES b/nag/docs/CHANGES index f121f411e..558b3a60d 100644 --- a/nag/docs/CHANGES +++ b/nag/docs/CHANGES @@ -2,6 +2,7 @@ v3.0-git -------- +[jan] Send alarm notifications with HTML part and convert to Horde_View. [jan] Default task lists no longer have the user name as the ID. [jan] Create a default task list if the user doesn't own any yet. [jan] Add start date to possible colums in task list (Joel Smith diff --git a/nag/lib/Nag.php b/nag/lib/Nag.php index 6d3e9fdba..37076d0ee 100644 --- a/nag/lib/Nag.php +++ b/nag/lib/Nag.php @@ -1020,6 +1020,59 @@ class Nag } /** + * Builds the body MIME part of a multipart message. + * + * @param Horde_View $view A view to render the HTML and plain text + * templates for the messate. + * @param string $template The template base name for the view. + * @param Horde_Mime_Part $image The MIME part of a related image. + * + * @return Horde_Mime_Part A multipart/alternative MIME part. + */ + public static function buildMimeMessage(Horde_View $view, $template, + Horde_Mime_Part $image) + { + $multipart = new Horde_Mime_Part(); + $multipart->setType('multipart/alternative'); + $bodyText = new Horde_Mime_Part(); + $bodyText->setType('text/plain'); + $bodyText->setCharset('UTF-8'); + $bodyText->setContents($view->render($template . '.plain.php')); + $bodyText->setDisposition('inline'); + $multipart->addPart($bodyText); + $bodyHtml = new Horde_Mime_Part(); + $bodyHtml->setType('text/html'); + $bodyHtml->setCharset('UTF-8'); + $bodyHtml->setContents($view->render($template . '.html.php')); + $bodyHtml->setDisposition('inline'); + $related = new Horde_Mime_Part(); + $related->setType('multipart/related'); + $related->setContentTypeParameter('start', $bodyHtml->setContentId()); + $related->addPart($bodyHtml); + $related->addPart($image); + $multipart->addPart($related); + return $multipart; + } + + /** + * Returns a MIME part for an image to be embedded into a HTML document. + * + * @param string $file An image file name. + * + * @return Horde_Mime_Part A MIME part representing the image. + */ + public static function getImagePart($file) + { + $background = Horde_Themes::img($file); + $image = new Horde_Mime_Part(); + $image->setType('image/png'); + $image->setContents(file_get_contents($background->fs)); + $image->setContentId(); + $image->setDisposition('attachment'); + return $image; + } + + /** * Returns the real name, if available, of a user. */ public static function getUserName($uid) diff --git a/nag/lib/Task.php b/nag/lib/Task.php index bdbc3b961..ace88e244 100644 --- a/nag/lib/Task.php +++ b/nag/lib/Task.php @@ -762,12 +762,20 @@ class Nag_Task { } } if (isset($methods['mail'])) { - $methods['mail']['body'] = sprintf( - _("We would like to remind you of this due task.\n\n%s\n\nDate: %s\nTime: %s\n\n%s"), - $this->name, - strftime($prefs->getValue('date_format'), $this->due), - date($prefs->getValue('twentyFour') ? 'H:i' : 'h:ia', $this->due), - $this->desc); + $image = Nag::getImagePart('big_alarm.png'); + + $view = new Horde_View(array('templatePath' => NAG_TEMPLATES . '/alarm', 'encoding' => 'UTF-8')); + new Horde_View_Helper_Text($view); + $view->task = $this; + $view->imageId = $image->getContentId(); + $view->due = new Horde_Date($this->due); + $view->dateFormat = $prefs->getValue('date_format'); + $view->timeFormat = $prefs->getValue('twentyFour') ? 'H:i' : 'h:ia'; + if (!$prefs->isLocked('task_alarms')) { + $view->prefsUrl = Horde::url(Horde::getServiceLink('prefs', 'nag'), true)->remove(session_name()); + } + + $methods['mail']['mimepart'] = Nag::buildMimeMessage($view, 'mail', $image); } return array( 'id' => $this->uid, diff --git a/nag/templates/alarm/mail.html.php b/nag/templates/alarm/mail.html.php new file mode 100644 index 000000000..f35ea01c3 --- /dev/null +++ b/nag/templates/alarm/mail.html.php @@ -0,0 +1,36 @@ +

h($this->task->name) ?>

+ + + + +
+ + + + + + > + + + + + + task->desc)): ?> + + > + + + + + + +
+ +  due->strftime($this->dateFormat) ?>, due->format($this->timeFormat) ?>
+ +  getInstance('Horde_Core_Factory_TextFilter')->filter($this->task->desc, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO, 'callback' => null)) ?>
+
+ +prefsUrl): ?> +

prefsUrl . '">', '') ?>

+ diff --git a/nag/templates/alarm/mail.plain.php b/nag/templates/alarm/mail.plain.php new file mode 100644 index 000000000..9c5647ad0 --- /dev/null +++ b/nag/templates/alarm/mail.plain.php @@ -0,0 +1,12 @@ + + + +task->name ?> + + + due->strftime($this->dateFormat) ?> + + due->format($this->timeFormat) ?> + + +task->desc ?> diff --git a/nag/themes/default/graphics/big_alarm.png b/nag/themes/default/graphics/big_alarm.png new file mode 100644 index 0000000000000000000000000000000000000000..641a1ddc1fbe6a22dd633a1173aa4e2ff761a2c2 GIT binary patch literal 15893 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 literal 0 HcmV?d00001 -- 2.11.0