diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 9641df219c23ee1e7ee65c28c08dfe3e2650c64b..c0db02ac00261e87cf4899c68439cf71b1e2a06a 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -204,6 +204,7 @@ return array(
     'OCA\\DAV\\Files\\Sharing\\FilesDropPlugin' => $baseDir . '/../lib/Files/Sharing/FilesDropPlugin.php',
     'OCA\\DAV\\Files\\Sharing\\PublicLinkCheckPlugin' => $baseDir . '/../lib/Files/Sharing/PublicLinkCheckPlugin.php',
     'OCA\\DAV\\HookManager' => $baseDir . '/../lib/HookManager.php',
+    'OCA\\DAV\\Listener\\CalendarContactInteractionListener' => $baseDir . '/../lib/Listener/CalendarContactInteractionListener.php',
     'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndex.php',
     'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php',
     'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => $baseDir . '/../lib/Migration/BuildSocialSearchIndex.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 37b0b28ef19802e33b10cee0bf997193872d743f..026ebec50cfc4fd43dc43cc4d17f5788c83c2891 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -219,6 +219,7 @@ class ComposerStaticInitDAV
         'OCA\\DAV\\Files\\Sharing\\FilesDropPlugin' => __DIR__ . '/..' . '/../lib/Files/Sharing/FilesDropPlugin.php',
         'OCA\\DAV\\Files\\Sharing\\PublicLinkCheckPlugin' => __DIR__ . '/..' . '/../lib/Files/Sharing/PublicLinkCheckPlugin.php',
         'OCA\\DAV\\HookManager' => __DIR__ . '/..' . '/../lib/HookManager.php',
+        'OCA\\DAV\\Listener\\CalendarContactInteractionListener' => __DIR__ . '/..' . '/../lib/Listener/CalendarContactInteractionListener.php',
         'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndex.php',
         'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php',
         'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildSocialSearchIndex.php',
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php
index 1bad3cb1ebac22acf0345104e77e1dd3ce95076c..0908140314079252056a9918fd0ac373a0b414c0 100644
--- a/apps/dav/lib/AppInfo/Application.php
+++ b/apps/dav/lib/AppInfo/Application.php
@@ -53,7 +53,9 @@ use OCA\DAV\CardDAV\CardDavBackend;
 use OCA\DAV\CardDAV\ContactsManager;
 use OCA\DAV\CardDAV\PhotoCache;
 use OCA\DAV\CardDAV\SyncService;
+use OCA\DAV\Events\CalendarShareUpdatedEvent;
 use OCA\DAV\HookManager;
+use OCA\DAV\Listener\CalendarContactInteractionListener;
 use OCA\DAV\Search\ContactsSearchProvider;
 use OCA\DAV\Search\EventsSearchProvider;
 use OCA\DAV\Search\TasksSearchProvider;
@@ -106,6 +108,11 @@ class Application extends App implements IBootstrap {
 		$context->registerSearchProvider(ContactsSearchProvider::class);
 		$context->registerSearchProvider(EventsSearchProvider::class);
 		$context->registerSearchProvider(TasksSearchProvider::class);
+
+		/**
+		 * Register event listeners
+		 */
+		$context->registerEventListener(CalendarShareUpdatedEvent::class, CalendarContactInteractionListener::class);
 	}
 
 	public function boot(IBootContext $context): void {
diff --git a/apps/dav/lib/Listener/CalendarContactInteractionListener.php b/apps/dav/lib/Listener/CalendarContactInteractionListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0b94c34f1f9fc31d7b9787abc4399ff3aa826a7
--- /dev/null
+++ b/apps/dav/lib/Listener/CalendarContactInteractionListener.php
@@ -0,0 +1,96 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\DAV\Listener;
+
+use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\Events\CalendarShareUpdatedEvent;
+use OCP\Contacts\Events\ContactInteractedWithEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\EventDispatcher\IEventListener;
+use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
+use function strlen;
+use function strpos;
+use function substr;
+
+class CalendarContactInteractionListener implements IEventListener {
+	private const URI_USERS = 'principals/users/';
+
+	/** @var IEventDispatcher */
+	private $dispatcher;
+
+	/** @var IUserSession */
+	private $userManager;
+
+	/** @var Principal */
+	private $principalConnector;
+
+	/** @var LoggerInterface */
+	private $logger;
+
+	public function __construct(IEventDispatcher $dispatcher,
+								IUserSession $userManager,
+								Principal $principalConnector,
+								LoggerInterface $logger) {
+		$this->dispatcher = $dispatcher;
+		$this->userManager = $userManager;
+		$this->principalConnector = $principalConnector;
+		$this->logger = $logger;
+	}
+
+	public function handle(Event $event): void {
+		if (($user = $this->userManager->getUser()) === null) {
+			// Without user context we can't do anything
+			return;
+		}
+
+		if ($event instanceof CalendarShareUpdatedEvent && !empty($event->getAdded())) {
+			// group: href => principal:principals/groups/admin
+			// users: href => principal:principals/users/admin
+			foreach ($event->getAdded() as $added) {
+				if (!isset($added['href'])) {
+					// Nothing to work with
+					continue;
+				}
+				$principal = $this->principalConnector->findByUri(
+					$added['href'],
+					$this->principalConnector->getPrincipalPrefix()
+				);
+				if ($principal === null) {
+					// Invalid principal
+					continue;
+				}
+				if (strpos($principal, self::URI_USERS) === 0) {
+					$uid = substr($principal, strlen(self::URI_USERS));
+					$this->dispatcher->dispatchTyped(
+						(new ContactInteractedWithEvent($user))->setUid($uid)
+					);
+				}
+			}
+		}
+	}
+}