Ga naar hoofdinhoud

Mail Integration (Sidebar + Smart Picker)

Standards​

  • GEMMA Zaakcorrespondentiecomponent -- Links email correspondence to case objects, supporting the Dutch government standard for case-related communication management.

Status​

Implemented -- Backend API endpoints operational, frontend sidebar and smart picker components built, database migration in place.

Overview​

The Mail Integration feature connects OpenRegister objects to Nextcloud Mail through two mechanisms:

  1. Mail Sidebar -- A sidebar panel injected into the Nextcloud Mail app that displays OpenRegister objects linked to the currently viewed email. Users can link/unlink objects, discover related objects by sender, and navigate directly to object detail pages.

  2. Smart Picker -- A Nextcloud reference provider that enables rich object references in Mail compose and other apps. Users can search for and embed OpenRegister objects as interactive preview widgets.

Key Capabilities​

CapabilityDescription
Link emails to objectsExplicitly associate any email with one or more OpenRegister objects via the sidebar quick-link action. Links are stored in the openregister_email_links table with full metadata (subject, sender, date).
Sender-based discoveryAutomatically suggests objects previously linked to emails from the same sender, surfacing relevant context without manual lookup.
Quick linkOne-click linking from the sidebar: select an object from a search dialog and bind it to the current email.
Rich preview widgetSmart Picker reference provider renders linked objects as interactive cards showing title, schema, register, and a deep link back to the object in OpenRegister.
UnlinkRemove an email-object association via the sidebar or API.
NL Design System themingSidebar and cards use Nextcloud CSS variables, compatible with nldesign token sets (Rijkshuisstijl, Utrecht, etc.).

API Endpoints​

MethodEndpointPurposeAuth
GET/api/emails/by-message/{accountId}/{messageId}Retrieve objects linked to a specific emailUser session
GET/api/emails/by-sender?sender={email}Discover objects linked to emails from the same senderUser session
POST/api/emails/quick-linkCreate a new email-to-object link (body: mailAccountId, mailMessageId, objectUuid, registerId)User session
DELETE/api/emails/{linkId}Remove an email-object linkUser session

Architecture​

Backend​

ComponentPathRole
EmailLink entitylib/Db/EmailLink.phpORM entity for openregister_email_links table
EmailLinkMapperlib/Db/EmailLinkMapper.phpDatabase queries: findByAccountAndMessage, findBySender, findExistingLink
EmailServicelib/Service/EmailService.phpBusiness logic: reverse-lookup, quickLink creation, deleteLink
EmailsControllerlib/Controller/EmailsController.phpREST API controller for all email link endpoints
MailAppScriptListenerlib/Listener/MailAppScriptListener.phpEvent listener that injects the sidebar script into the Mail app

Frontend​

ComponentPathRole
mail-sidebar.jssrc/mail-sidebar.jsWebpack entry point, mounts Vue sidebar into Mail DOM
MailSidebar.vuesrc/mail-sidebar/MailSidebar.vueRoot sidebar component; hosts the three NcAppSidebarTab children
ObjectsTab.vuesrc/mail-sidebar/components/ObjectsTab.vue"Connections" tab — the objects linked to this email
ActionsTab.vuesrc/mail-sidebar/components/ActionsTab.vue"Connect" tab — per-schema search-and-link, and create-from-email
EntitiesTab.vuesrc/mail-sidebar/components/EntitiesTab.vue"Entities" tab — extracted-entity view
LinkedObjectsList.vuesrc/mail-sidebar/components/LinkedObjectsList.vueDisplays explicitly linked objects
SuggestedObjectsList.vuesrc/mail-sidebar/components/SuggestedObjectsList.vueDisplays sender-based discovery results
ObjectCard.vuesrc/mail-sidebar/components/ObjectCard.vueCard with title, schema, register, deep link, unlink button
CreateConnectedObjectDialog.vuesrc/dialogs/mail/CreateConnectedObjectDialog.vueCreate a new object from the current email
RemoveConnectionDialog.vuesrc/dialogs/mail/RemoveConnectionDialog.vueConfirm removing a link
useMailObserver.jssrc/mail-sidebar/composables/useMailObserver.jsObserves Mail app URL changes (hash-based routing)
useEmailLinks.jssrc/mail-sidebar/composables/useEmailLinks.jsAPI state management with caching and abort control
useAttachmentDrag.jssrc/mail-sidebar/composables/useAttachmentDrag.jsDrag-and-drop of mail attachments onto objects
emailLinks.jssrc/mail-sidebar/api/emailLinks.jsAxios API wrapper
icons.jssrc/mail-sidebar/icons.jsSchema-to-icon resolution
mail-sidebar.csscss/mail-sidebar.cssNL Design System compatible styles

Every path above was verified to exist. The previous version of this table listed ten files of which eight did not exist — it described a src/views/mail/ + src/components/mail/ layout that predates the move to src/mail-sidebar/, and included LinkObjectDialog.vue, a component that was superseded by the Connect tab (REQ-001) and has since been removed.

Database​

Table openregister_email_links:

ColumnTypeDescription
idinteger (PK)Auto-increment identifier
mail_account_idintegerNextcloud Mail account ID
mail_message_idintegerMail message ID
mail_message_uidstringMail message UID
subjectstringEmail subject line
senderstringSender email address
mail_datedatetimeEmail date
object_uuidstringLinked OpenRegister object UUID
register_idintegerRegister containing the object
schema_idintegerSchema of the object
linked_bystringUser who created the link
linked_atdatetimeTimestamp of link creation

Indexes: composite on (mail_account_id, mail_message_id), sender, object_uuid. Unique constraint on (mail_account_id, mail_message_id, object_uuid).

Dependencies​

  • Nextcloud Mail app -- Required for sidebar injection. OpenRegister functions normally without it; the sidebar simply does not appear.
  • OpenRegister registers/schemas -- At least one register with objects must exist for linking to be useful.

Verification Results (2026-03-25)​

EndpointHTTP StatusResponse
GET /api/emails/by-message/1/1200{"results":{"results":[],"total":0},"total":2} -- No links found (expected, clean DB)
GET /api/emails/by-sender?sender=admin@example.com200[] -- No sender matches (expected)
POST /api/emails/quick-link500Internal Server Error -- Expected: no valid object UUID/register exists for dummy test data
DELETE /api/emails/999500Internal Server Error -- Expected: link ID 999 does not exist
Mail app browser testOKMail app loads successfully at /apps/mail/setup (no account configured). Zero console errors.