From fc432b67d90e26196feaf2fcb2484bfa0aff6f6a Mon Sep 17 00:00:00 2001 From: Darrick Joo Date: Mon, 2 Feb 2026 15:27:25 +0100 Subject: [PATCH] Add categories API and new connector v5 --- .../Connector/EmailConnectorv5.Interface.al | 36 ++++++++++ .../App/Email/src/Email/Email.Codeunit.al | 67 +++++++++++++++++++ .../App/Email/src/Email/EmailImpl.Codeunit.al | 53 ++++++++++++++- .../src/Email/Inbox/EmailCategories.Table.al | 53 +++++++++++++++ .../Inbox/EmailRetrievalFilters.Table.al | 29 ++++++++ 5 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 src/System Application/App/Email/src/Connector/EmailConnectorv5.Interface.al create mode 100644 src/System Application/App/Email/src/Email/Inbox/EmailCategories.Table.al diff --git a/src/System Application/App/Email/src/Connector/EmailConnectorv5.Interface.al b/src/System Application/App/Email/src/Connector/EmailConnectorv5.Interface.al new file mode 100644 index 0000000000..46b8542def --- /dev/null +++ b/src/System Application/App/Email/src/Connector/EmailConnectorv5.Interface.al @@ -0,0 +1,36 @@ +// ------------------------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// ------------------------------------------------------------------------------------------------ + +namespace System.Email; + +/// +/// An e-mail connector interface enhances the "Email Connector v4" with email category management. +/// +interface "Email Connector v5" extends "Email Connector v4" +{ + /// + /// Get email categories from the provided account. + /// + /// The email account ID. + /// The email categories retrieved. + procedure GetEmailCategories(AccountId: Guid; var EmailCategories: Record "Email Categories" temporary); + + /// + /// Create a new email category in the provided account. + /// + /// The email account ID. + /// The display name of the category to create. + /// The color of the category (optional). + /// The ID of the created category. + procedure CreateEmailCategory(AccountId: Guid; CategoryDisplayName: Text; CategoryColor: Text): Text; + + /// + /// Apply email categories to an email message. + /// + /// The email account ID. + /// The external message ID of the email to update. + /// The list of category display names to apply to the email. + procedure ApplyEmailCategory(AccountId: Guid; ExternalId: Text; Categories: List of [Text]); +} diff --git a/src/System Application/App/Email/src/Email/Email.Codeunit.al b/src/System Application/App/Email/src/Email/Email.Codeunit.al index d0af21ff22..1e8b55a9db 100644 --- a/src/System Application/App/Email/src/Email/Email.Codeunit.al +++ b/src/System Application/App/Email/src/Email/Email.Codeunit.al @@ -353,6 +353,73 @@ codeunit 8901 Email #endregion + #region Categories + + /// + /// Gets email categories from the specified email account. + /// + /// The ID of the email account to retrieve categories from. + /// The email connector to use. + /// The return record of all categories that were retrieved. + procedure GetEmailCategories(EmailAccountId: Guid; EmailConnector: Enum "Email Connector"; var EmailCategories: Record "Email Categories" temporary) + begin + EmailImpl.GetEmailCategories(EmailAccountId, EmailConnector, EmailCategories); + end; + + /// + /// Creates a new email category in the specified email account. + /// + /// The ID of the email account to create the category in. + /// The email connector to use. + /// The display name of the category to create. + /// The ID of the created category. + procedure CreateEmailCategory(EmailAccountId: Guid; EmailConnector: Enum "Email Connector"; CategoryDisplayName: Text): Text + begin + exit(EmailImpl.CreateEmailCategory(EmailAccountId, EmailConnector, CategoryDisplayName, '')); + end; + + /// + /// Creates a new email category with a specified color in the specified email account. + /// + /// The ID of the email account to create the category in. + /// The email connector to use. + /// The display name of the category to create. + /// The color of the category. + /// The ID of the created category. + procedure CreateEmailCategory(EmailAccountId: Guid; EmailConnector: Enum "Email Connector"; CategoryDisplayName: Text; CategoryColor: Text): Text + begin + exit(EmailImpl.CreateEmailCategory(EmailAccountId, EmailConnector, CategoryDisplayName, CategoryColor)); + end; + + /// + /// Applies email categories to an email message. + /// + /// The ID of the email account containing the email. + /// The email connector to use. + /// The external message ID of the email to update. + /// The display name of the category to apply. + procedure ApplyEmailCategory(EmailAccountId: Guid; EmailConnector: Enum "Email Connector"; ExternalId: Text; CategoryDisplayName: Text) + var + Categories: List of [Text]; + begin + Categories.Add(CategoryDisplayName); + EmailImpl.ApplyEmailCategory(EmailAccountId, EmailConnector, ExternalId, Categories); + end; + + /// + /// Applies email categories to an email message. + /// + /// The ID of the email account containing the email. + /// The email connector to use. + /// The external message ID of the email to update. + /// The list of category display names to apply to the email. + procedure ApplyEmailCategory(EmailAccountId: Guid; EmailConnector: Enum "Email Connector"; ExternalId: Text; Categories: List of [Text]) + begin + EmailImpl.ApplyEmailCategory(EmailAccountId, EmailConnector, ExternalId, Categories); + end; + + #endregion + #region OpenInEditor /// diff --git a/src/System Application/App/Email/src/Email/EmailImpl.Codeunit.al b/src/System Application/App/Email/src/Email/EmailImpl.Codeunit.al index a84406bc93..c3648ad5da 100644 --- a/src/System Application/App/Email/src/Email/EmailImpl.Codeunit.al +++ b/src/System Application/App/Email/src/Email/EmailImpl.Codeunit.al @@ -44,6 +44,7 @@ codeunit 8900 "Email Impl" EmailConnectorDoesNotSupportRetrievingEmailsErr: Label 'The selected email connector does not support retrieving emails.'; EmailConnectorDoesNotSupportMarkAsReadErr: Label 'The selected email connector does not support marking emails as read.'; EmailconnectorDoesNotSupportReplyingErr: Label 'The selected email connector does not support replying to emails.'; + EmailConnectorDoesNotSupportCategoriesErr: Label 'The selected email connector does not support email categories.'; ExternalIdCannotBeEmptyErr: Label 'The external ID cannot be empty.'; TelemetryRetrieveEmailsUsedTxt: Label 'Retrieving emails is used', Locked = true; ErrorCallStackNotFoundErr: Label 'Error call stack not found for the email message with ID %1.', Locked = true; @@ -270,6 +271,45 @@ codeunit 8900 "Email Impl" EmailConnectorv4.GetEmailFolders(EmailAccountId, EmailFolders); end; + procedure GetEmailCategories(EmailAccountId: Guid; Connector: Enum "Email Connector"; var EmailCategories: Record "Email Categories" temporary) + var + EmailConnectorv5: Interface "Email Connector v5"; + begin + CheckRequiredPermissions(); + + if not CheckAndGetEmailConnectorv5(Connector, EmailConnectorv5) then + Error(EmailConnectorDoesNotSupportCategoriesErr); + + EmailConnectorv5.GetEmailCategories(EmailAccountId, EmailCategories); + end; + + procedure CreateEmailCategory(EmailAccountId: Guid; Connector: Enum "Email Connector"; CategoryDisplayName: Text; CategoryColor: Text): Text + var + EmailConnectorv5: Interface "Email Connector v5"; + begin + CheckRequiredPermissions(); + + if not CheckAndGetEmailConnectorv5(Connector, EmailConnectorv5) then + Error(EmailConnectorDoesNotSupportCategoriesErr); + + exit(EmailConnectorv5.CreateEmailCategory(EmailAccountId, CategoryDisplayName, CategoryColor)); + end; + + procedure ApplyEmailCategory(EmailAccountId: Guid; Connector: Enum "Email Connector"; ExternalId: Text; Categories: List of [Text]) + var + EmailConnectorv5: Interface "Email Connector v5"; + begin + CheckRequiredPermissions(); + + if ExternalId = '' then + Error(ExternalIdCannotBeEmptyErr); + + if not CheckAndGetEmailConnectorv5(Connector, EmailConnectorv5) then + Error(EmailConnectorDoesNotSupportCategoriesErr); + + EmailConnectorv5.ApplyEmailCategory(EmailAccountId, ExternalId, Categories); + end; + local procedure TelemetryAppsAndPublishers(Message: Text) var Telemetry: Codeunit Telemetry; @@ -393,10 +433,19 @@ codeunit 8900 "Email Impl" end; #endif - procedure CheckAndGetEmailConnectorv4(Connector: Interface "Email Connector"; var Connectorv3: Interface "Email Connector v4"): Boolean + procedure CheckAndGetEmailConnectorv4(Connector: Interface "Email Connector"; var Connectorv4: Interface "Email Connector v4"): Boolean begin if Connector is "Email Connector v4" then begin - Connectorv3 := Connector as "Email Connector v4"; + Connectorv4 := Connector as "Email Connector v4"; + exit(true); + end else + exit(false); + end; + + procedure CheckAndGetEmailConnectorv5(Connector: Interface "Email Connector"; var Connectorv5: Interface "Email Connector v5"): Boolean + begin + if Connector is "Email Connector v5" then begin + Connectorv5 := Connector as "Email Connector v5"; exit(true); end else exit(false); diff --git a/src/System Application/App/Email/src/Email/Inbox/EmailCategories.Table.al b/src/System Application/App/Email/src/Email/Inbox/EmailCategories.Table.al new file mode 100644 index 0000000000..8b17f7a5aa --- /dev/null +++ b/src/System Application/App/Email/src/Email/Inbox/EmailCategories.Table.al @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// ------------------------------------------------------------------------------------------------ + +namespace System.Email; + +/// +/// Holds information about email categories used for tagging emails. +/// +table 8883 "Email Categories" +{ + Access = Public; + TableType = Temporary; + Extensible = false; + InherentEntitlements = RIMDX; + InherentPermissions = RIMDX; + + fields + { + field(1; Ordering; Integer) + { + Caption = 'Ordering'; + DataClassification = SystemMetadata; + } + field(2; Id; Text[2048]) + { + Caption = 'Category Id'; + DataClassification = CustomerContent; + } + field(3; "Display Name"; Text[2048]) + { + Caption = 'Display Name'; + DataClassification = CustomerContent; + } + field(4; Color; Text[50]) + { + Caption = 'Color'; + DataClassification = CustomerContent; + } + } + + keys + { + key(PK; Ordering) + { + Clustered = true; + } + key(CategoryId; Id) + { + } + } +} diff --git a/src/System Application/App/Email/src/Email/Inbox/EmailRetrievalFilters.Table.al b/src/System Application/App/Email/src/Email/Inbox/EmailRetrievalFilters.Table.al index 482838ea74..bd5f7175cd 100644 --- a/src/System Application/App/Email/src/Email/Inbox/EmailRetrievalFilters.Table.al +++ b/src/System Application/App/Email/src/Email/Inbox/EmailRetrievalFilters.Table.al @@ -61,6 +61,12 @@ table 8885 "Email Retrieval Filters" Caption = 'Folder Id'; DataClassification = CustomerContent; } + field(10; "Category Filter Type"; Option) + { + OptionMembers = "Include","Exclude"; + InitValue = "Include"; + Caption = 'Category Filter Type'; + } } keys @@ -70,4 +76,27 @@ table 8885 "Email Retrieval Filters" Clustered = true; } } + + var + CategoryFilters: List of [Text]; + + /// Clears all category filters. + procedure ClearCategoryFilters() + begin + Clear(CategoryFilters); + end; + + /// Adds a category to the filter list. + /// The category to add to the filter. + procedure AddCategoryFilter(Category: Text) + begin + CategoryFilters.Add(Category); + end; + + /// Gets the list of category filters. + /// The list of category filters. + procedure GetCategoryFilters(): List of [Text] + begin + exit(CategoryFilters); + end; } \ No newline at end of file