aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav
diff options
context:
space:
mode:
authorLeon Klingele <leon@struktur.de>2017-09-07 16:33:45 +0200
committerGeorg Ehrke <developer@georgehrke.com>2017-11-03 11:19:39 +0100
commitc899f352615f498b183a020e5dcd6f9b1190db1f (patch)
tree98bcecda183ea01011b1d0a4e2963715b2b2023c /apps/dav
parentb3ff9a2248f18fac4b2a9ffa5be99c464effb4b6 (diff)
downloadnextcloud-server-c899f352615f498b183a020e5dcd6f9b1190db1f.tar.gz
nextcloud-server-c899f352615f498b183a020e5dcd6f9b1190db1f.zip
DAV: Initial email customization support
Signed-Off-By: Leon Klingele <leon@struktur.de> Signed-off-by: Georg Ehrke <developer@georgehrke.com>
Diffstat (limited to 'apps/dav')
-rw-r--r--apps/dav/appinfo/v1/caldav.php11
-rw-r--r--apps/dav/lib/CalDAV/Schedule/IMipPlugin.php162
-rw-r--r--apps/dav/lib/Server.php11
3 files changed, 168 insertions, 16 deletions
diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php
index a103f82a420..cb10b038051 100644
--- a/apps/dav/appinfo/v1/caldav.php
+++ b/apps/dav/appinfo/v1/caldav.php
@@ -87,9 +87,16 @@ $server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin());
if ($sendInvitations) {
- $server->addPlugin(new \OCA\DAV\CalDAV\Schedule\IMipPlugin( \OC::$server->getMailer(), \OC::$server->getLogger(), new \OC\AppFramework\Utility\TimeFactory()));
+ $server->addPlugin(new \OCA\DAV\CalDAV\Schedule\IMipPlugin(
+ 'dav', // TODO(leon): Retrieve dynamically, but where to find it? :(
+ \OC::$server->getUserSession()->getUser()->getUID(),
+ \OC::$server->getConfig(),
+ \OC::$server->getMailer(),
+ \OC::$server->getLogger(),
+ new \OC\AppFramework\Utility\TimeFactory(),
+ \OC::$server->getL10NFactory()
+ ));
}
-
$server->addPlugin(new ExceptionLoggerPlugin('caldav', \OC::$server->getLogger()));
// And off we go!
diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
index 8e1d7e2563d..714737413ac 100644
--- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
+++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
@@ -23,15 +23,19 @@
*/
namespace OCA\DAV\CalDAV\Schedule;
+use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\IConfig;
use OCP\ILogger;
+use OCP\L10N\IFactory as L10NFactory;
use OCP\Mail\IMailer;
+use Sabre\CalDAV\Schedule\IMipPlugin as SabreIMipPlugin;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\DateTimeParser;
use Sabre\VObject\ITip;
-use Sabre\CalDAV\Schedule\IMipPlugin as SabreIMipPlugin;
+use Sabre\VObject\Parameter;
use Sabre\VObject\Recur\EventIterator;
-
+use Swift_Attachment;
/**
* iMIP handler.
*
@@ -48,6 +52,15 @@ use Sabre\VObject\Recur\EventIterator;
*/
class IMipPlugin extends SabreIMipPlugin {
+ /** @var string */
+ private $appName;
+
+ /** @var string */
+ private $userId;
+
+ /** @var IConfig */
+ private $config;
+
/** @var IMailer */
private $mailer;
@@ -57,20 +70,35 @@ class IMipPlugin extends SabreIMipPlugin {
/** @var ITimeFactory */
private $timeFactory;
+ /** @var L10NFactory */
+ private $l10nFactory;
+
const MAX_DATE = '2038-01-01';
+ const METHOD_REQUEST = 'request';
+ const METHOD_REPLY = 'reply';
+ const METHOD_CANCEL = 'cancel';
+
/**
* Creates the email handler.
*
+ * @param string $appName
+ * @param string $userId
+ * @param IConfig $config
* @param IMailer $mailer
* @param ILogger $logger
* @param ITimeFactory $timeFactory
+ * @param L10NFactory $l10nFactory
*/
- function __construct(IMailer $mailer, ILogger $logger, ITimeFactory $timeFactory) {
+ function __construct($appName, $userId, IConfig $config, IMailer $mailer, ILogger $logger, ITimeFactory $timeFactory, L10NFactory $l10nFactory) {
parent::__construct('');
+ $this->appName = $appName;
+ $this->userId = $userId;
+ $this->config = $config;
$this->mailer = $mailer;
$this->logger = $logger;
$this->timeFactory = $timeFactory;
+ $this->l10nFactory = $l10nFactory;
}
/**
@@ -112,26 +140,73 @@ class IMipPlugin extends SabreIMipPlugin {
$recipientName = ($iTipMessage->recipientName) ? $iTipMessage->recipientName : null;
$subject = 'SabreDAV iTIP message';
- switch (strtoupper($iTipMessage->method)) {
- case 'REPLY' :
- $subject = 'Re: ' . $summary;
- break;
- case 'REQUEST' :
+ switch (strtolower($iTipMessage->method)) {
+ default: // Treat 'REQUEST' as the default
+ case self::METHOD_REQUEST:
$subject = $summary;
+ $templateName = self::METHOD_REQUEST;
+ break;
+ case self::METHOD_REPLY:
+ $subject = 'Re: ' . $summary;
+ $templateName = self::METHOD_REPLY;
break;
- case 'CANCEL' :
+ case self::METHOD_CANCEL:
$subject = 'Cancelled: ' . $summary;
+ $templateName = self::METHOD_CANCEL;
break;
}
- $contentType = 'text/calendar; charset=UTF-8; method=' . $iTipMessage->method;
+ $vevent = $iTipMessage->message->VEVENT;
+
+ $attendee = $this->getCurrentAttendee($iTipMessage);
+ $defaultLang = $this->config->getUserValue($this->userId, 'core', 'lang', $this->l10nFactory->findLanguage());
+ $lang = $this->getAttendeeLangOrDefault($attendee, $defaultLang);
+ $l10n = $this->l10nFactory->get($this->appName, $lang);
+
+ $meetingAttendeeName = !empty($recipientName) ? $recipientName : $recipient;
+ $meetingInviteeName = !empty($senderName) ? $senderName : $sender;
- $message = $this->mailer->createMessage();
+ $meetingTitle = $vevent->SUMMARY;
+ $meetingDescription = $vevent->DESCRIPTION;
- $message->setReplyTo([$sender => $senderName])
+ // TODO(leon): Maybe it's a good idea to make this locale dependent?
+ // TODO(leon): Don't show H:i if it's an all-day meeting
+ $dateFormatStr = 'Y-m-d H:i e';
+ $meetingStart = $vevent->DTSTART->getDateTime()->format($dateFormatStr);
+ $meetingEnd = $vevent->DTEND->getDateTime()->format($dateFormatStr);
+
+ $meetingUrl = $vevent->URL;
+
+ $defaultVal = '--';
+ $templateParams = array(
+ 'attendee_name' => (string)$meetingAttendeeName ?: $defaultVal,
+ 'invitee_name' => (string)$meetingInviteeName ?: $defaultVal,
+ 'meeting_title' => (string)$meetingTitle ?: $defaultVal,
+ 'meeting_description' => (string)$meetingDescription ?: $defaultVal,
+ 'meeting_start' => (string)$meetingStart,
+ 'meeting_end' => (string)$meetingEnd,
+ 'meeting_url' => (string)$meetingUrl ?: $defaultVal,
+ );
+ $templates = $this->getInviteTemplates($l10n, $templateParams);
+
+ $message = $this->mailer->createMessage()
+ ->setReplyTo([$sender => $senderName])
->setTo([$recipient => $recipientName])
->setSubject($subject)
- ->setBody($iTipMessage->message->serialize(), $contentType);
+ ->setPlainBody($templates[$templateName]->renderText())
+ ;
+ // We need to attach the event as 'attachment'
+ // Swiftmail can't properly handle inline-multipart-based files
+ // See https://github.com/swiftmailer/swiftmailer/issues/615
+ $filename = 'event.ics'; // TODO(leon): Make file name unique, e.g. add event id
+ $contentType = 'text/calendar; method=' . $iTipMessage->method;
+ $attachment = Swift_Attachment::newInstance()
+ ->setFilename($filename)
+ ->setContentType($contentType)
+ ->setBody($iTipMessage->message->serialize())
+ ;
+ $message->getSwiftMessage()->attach($attachment);
+
try {
$failed = $this->mailer->send($message);
if ($failed) {
@@ -190,4 +265,65 @@ class IMipPlugin extends SabreIMipPlugin {
$currentTime = $this->timeFactory->getTime();
return $lastOccurrence < $currentTime;
}
+
+ private function getEmptyInviteTemplate($scope) {
+ return $this->mailer->createEMailTemplate('dav.invite.' . $scope, array());
+ }
+
+ private function getInviteTemplates($l10n, $_) {
+ $ret = array();
+ $requestTmpl = $ret[self::METHOD_REQUEST] = $this->getEmptyInviteTemplate(self::METHOD_REQUEST);
+ $replyTmpl = $ret[self::METHOD_REPLY] = $this->getEmptyInviteTemplate(self::METHOD_REPLY);
+ $cancelTmpl = $ret[self::METHOD_CANCEL] = $this->getEmptyInviteTemplate(self::METHOD_CANCEL);
+
+ $commonPlainBodyStart = $l10n->t('Hello %s,', array($_['attendee_name']));
+ $commonPlainBodyEnd = $l10n->t(
+' Title: %s
+Description: %s
+ Start: %s
+ End: %s
+ URL: %s', array(
+ $_['meeting_title'],
+ $_['meeting_description'],
+ $_['meeting_start'],
+ $_['meeting_end'],
+ $_['meeting_url'],
+ ));
+
+ $requestTmpl->addBodyText('', $commonPlainBodyStart);
+ $requestTmpl->addBodyText('', $l10n->t('%s has invited you to a meeting.', array($_['invitee_name'])));
+ $requestTmpl->addBodyText('', $commonPlainBodyEnd);
+
+ $replyTmpl->addBodyText('', $commonPlainBodyStart);
+ $replyTmpl->addBodyText('', $l10n->t('the meeting with %s was updated.', array($_['invitee_name'])));
+ $replyTmpl->addBodyText('', $commonPlainBodyEnd);
+
+ $cancelTmpl->addBodyText('', $commonPlainBodyStart);
+ $cancelTmpl->addBodyText('', $l10n->t('the meeting with %s was canceled.', array($_['invitee_name'])));
+ $cancelTmpl->addBodyText('', $commonPlainBodyEnd);
+
+ return $ret;
+ }
+
+ private function getCurrentAttendee($iTipMessage) {
+ $vevent = $iTipMessage->message->VEVENT;
+ $attendees = $vevent->select('ATTENDEE');
+ foreach ($attendees as $attendee) {
+ if (strcasecmp($attendee->getValue(), $iTipMessage->recipient) === 0) {
+ return $attendee;
+ }
+ }
+ return null;
+ }
+
+ private function getAttendeeLangOrDefault($attendee, $default) {
+ if ($attendee) {
+ $lang = $attendee->offsetGet('LANGUAGE');
+ if ($lang instanceof Parameter) {
+ return $lang->getValue();
+ }
+ }
+ return $default;
+ }
+
}
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index 719e4974755..2d03f09b625 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -77,6 +77,7 @@ class Server {
$dispatcher = \OC::$server->getEventDispatcher();
$timezone = new TimeFactory();
$sendInvitations = \OC::$server->getConfig()->getAppValue('dav', 'sendInvitations', 'yes') === 'yes';
+ $l10nFactory = \OC::$server->getL10NFactory();
$root = new RootCollection();
$this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root));
@@ -139,7 +140,15 @@ class Server {
$this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin());
if ($sendInvitations) {
- $this->server->addPlugin(new IMipPlugin($mailer, $logger, $timezone));
+ $this->server->addPlugin(new IMipPlugin(
+ 'dav', // TODO(leon): Retrieve dynamically, but where to find it? :(
+ \OC::$server->getUserSession()->getUser()->getUID(),
+ \OC::$server->getConfig(),
+ $mailer,
+ $logger,
+ $timezone,
+ $l10nFactory
+ ));
}
$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());