Skip to content

Commit

Permalink
[Email] Filtering for email retrievals (#2275)
Browse files Browse the repository at this point in the history
<!-- Thank you for submitting a Pull Request. If you're new to
contributing to BCApps please read our pull request guideline below
* https://github.com/microsoft/BCApps/Contributing.md
-->
#### Summary <!-- Provide a general summary of your changes -->
- Adds a new codeunit "Email Retrieval Filters" for specifying the
filters to be used when retrieving an email.
- Update APIs to work with both v2 and v3 interfaces
- Obsolete the v2 interface as it's the same just without the filtering.
- Update tests

#### Work Item(s) <!-- Add the issue number here after the #. The issue
needs to be open and approved. Submitting PRs with no linked issues or
unapproved issues is highly discouraged. -->
Fixes
[AB#550315](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/550315)
  • Loading branch information
darjoo authored Nov 21, 2024
1 parent 62bc4e5 commit 6c4aef6
Show file tree
Hide file tree
Showing 18 changed files with 718 additions and 79 deletions.
10 changes: 10 additions & 0 deletions src/System Application/App/DotNet Aliases/src/dotnet.al
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,16 @@ dotnet
}
}

assembly("Microsoft.Dynamics.Nav.AppHTMLSanitizer")
{
Culture = 'neutral';
PublicKeyToken = '31bf3856ad364e35';

type("Microsoft.Dynamics.Nav.AppHTMLSanitizer.AppHtmlSanitizer"; "AppHtmlSanitizer")
{
}
}

assembly("Microsoft.Dynamics.Nav.AzureADGraphClient")
{
type("Microsoft.Dynamics.Nav.AzureADGraphClient.GroupInfoPage"; "GroupInfoPage")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ codeunit 8889 "Email Account Impl."
var
EmailAccounts: Record "Email Account";
Connector: Enum "Email Connector";
IEmailConnector: Interface "Email Connector";
EmailConnector: Interface "Email Connector";
begin
TempEmailAccount.Reset();
TempEmailAccount.DeleteAll();

foreach Connector in Connector.Ordinals do begin
IEmailConnector := Connector;
EmailConnector := Connector;

EmailAccounts.DeleteAll();
IEmailConnector.GetAccounts(EmailAccounts);
EmailConnector.GetAccounts(EmailAccounts);

if EmailAccounts.FindSet() then
repeat
Expand Down
32 changes: 25 additions & 7 deletions src/System Application/App/Email/src/Account/EmailAccounts.Page.al
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ page 8887 "Email Accounts"
IsSelected := not IsNullGuid(SelectedAccountId);

EmailAccount.GetAllAccounts(true, Rec); // Refresh the email accounts
if V2Filter then
FilterToConnectorv2Accounts(Rec);
if V2V3Filter then
FilterToConnectorv2v3Accounts(Rec);
EmailScenario.GetDefaultEmailAccount(DefaultEmailAccount); // Refresh the default email account

if IsSelected then begin
Expand All @@ -402,7 +402,7 @@ page 8887 "Email Accounts"
CurrPage.Update(false);
end;

local procedure FilterToConnectorv2Accounts(var EmailAccounts: Record "Email Account")
local procedure FilterToConnectorv2v3Accounts(var EmailAccounts: Record "Email Account")
var
IConnector: Interface "Email Connector";
begin
Expand All @@ -411,7 +411,13 @@ page 8887 "Email Accounts"

repeat
IConnector := EmailAccounts.Connector;
if not (IConnector is "Email Connector v2") then
#if not CLEAN26
#pragma warning disable AL0432
if not (IConnector is "Email Connector v2") and not (IConnector is "Email Connector v3") then
#pragma warning restore AL0432
#else
if not (IConnector is "Email Connector v3") then
#endif
EmailAccounts.Delete();
until EmailAccounts.Next() = 0;
end;
Expand Down Expand Up @@ -457,12 +463,24 @@ page 8887 "Email Accounts"
end;

/// <summary>
/// Filters the email accounts to only show accounts that are using the Email Connector v2.
/// Filters the email accounts to only show accounts that are using the Email Connector v2 or v3.
/// </summary>
/// <param name="Filter">True to filter the email accounts, false to show all email accounts</param>
#if not CLEAN26
[Obsolete('Replaced by FilterConnectorV3Accounts. In addition, this function now returns both v2 and v3 accounts.', '26.0')]
procedure FilterConnectorV2Accounts(Filter: Boolean)
begin
V2Filter := Filter;
V2V3Filter := Filter;
end;
#endif

/// <summary>
/// Filters the email accounts to only show accounts that are using the Email Connector v2 or v3.
/// </summary>
/// <param name="Filter">True to filter the email accounts, false to show all email accounts</param>
procedure FilterConnectorV3Accounts(Filter: Boolean)
begin
V2V3Filter := Filter;
end;

var
Expand All @@ -477,6 +495,6 @@ page 8887 "Email Accounts"
ShowLogo: Boolean;
IsLookupMode: Boolean;
HasEmailAccount: Boolean;
V2Filter: Boolean;
V2V3Filter: Boolean;
EmailConnectorHasBeenUninstalledMsg: Label 'The selected email extension has been uninstalled. To view information about the email account, you must reinstall the extension.';
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ namespace System.Email;
/// <summary>
/// This is the default implementation of the Email Connector v2 interface which adds the reply, retrievial of emails and marking them as read functionalities.
/// </summary>
codeunit 8998 "Default Email Connector v2" implements "Email Connector v2"
#if not CLEAN26
#pragma warning disable AL0432
codeunit 8998 "Default Email Connector v2" implements "Email Connector v2", "Email Connector v3"
#pragma warning restore AL0432
#else
codeunit 8998 "Default Email Connector v2" implements "Email Connector v3"
#endif
{

procedure Send(EmailMessage: Codeunit "Email Message"; AccountId: Guid)
begin

Expand Down Expand Up @@ -50,10 +57,18 @@ codeunit 8998 "Default Email Connector v2" implements "Email Connector v2"

end;

#if not CLEAN26
[Obsolete('Replaced by RetrieveEmails with an additional Filters parameter of type Record "Email Retrieval Filters".', '26.0')]
procedure RetrieveEmails(AccountId: Guid; var EmailInbox: Record "Email Inbox")
begin

end;
#endif

procedure RetrieveEmails(AccountId: Guid; var EmailInbox: Record "Email Inbox"; var Filters: Record "Email Retrieval Filters" temporary)
begin

end;

procedure MarkAsRead(AccountId: Guid; ExternalId: Text)
begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@ namespace System.Email;
/// <summary>
/// Enum that holds all of the available email connectors.
/// </summary>
enum 8889 "Email Connector" implements "Email Connector", "Email Connector v2", "Default Email Rate Limit"
#if not CLEAN26
#pragma warning disable AL0432
enum 8889 "Email Connector" implements "Email Connector", "Email Connector v2", "Email Connector v3", "Default Email Rate Limit"
#pragma warning restore AL0432
#else
enum 8889 "Email Connector" implements "Email Connector", "Email Connector v3", "Default Email Rate Limit"
#endif
{
Extensible = true;
DefaultImplementation = "Default Email Rate Limit" = "Default Email Rate Limit",
"Email Connector v2" = "Default Email Connector v2";
#if not CLEAN26
"Email Connector v2" = "Default Email Connector v2",
#endif
"Email Connector v3" = "Default Email Connector v2";
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if not CLEAN26
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
Expand All @@ -10,6 +11,10 @@ namespace System.Email;
/// </summary>
interface "Email Connector v2" extends "Email Connector"
{
ObsoleteReason = 'Replaced by "Email Connector v3" which adds filtering capability for retrieval of emails';
ObsoleteState = Pending;
ObsoleteTag = '26.0';

/// <summary>
/// Reply to an e-mail using the provided account.
/// </summary>
Expand All @@ -30,4 +35,5 @@ interface "Email Connector v2" extends "Email Connector"
/// <param name="AccountId">The email account ID.</param>
/// <param name="ExternalId">The external ID of the email.</param>
procedure MarkAsRead(AccountId: Guid; ExternalId: Text);
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// ------------------------------------------------------------------------------------------------
// 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;

/// <summary>
/// An e-mail connector interface enhances the "Email Connector" with reading, replying to e-mails and marking emails as read.
/// </summary>
interface "Email Connector v3" extends "Email Connector"
{
/// <summary>
/// Reply to an e-mail using the provided account.
/// </summary>
/// <param name="EmailMessage">The email message that is to be sent out.</param>
/// <param name="AccountId">The email account ID which is used to send out the email.</param>
procedure Reply(var EmailMessage: Codeunit "Email Message"; AccountId: Guid);

/// <summary>
/// Read e-mails from the provided account.
/// </summary>
/// <param name="AccountId">The email account ID which is used to send out the email.</param>
/// <param name="EmailInbox">The email inbox record that will store the emails.</param>
/// <param name="Filters">Filters to be used when retrieving emails.</param>
procedure RetrieveEmails(AccountId: Guid; var EmailInbox: Record "Email Inbox"; var Filters: Record "Email Retrieval Filters" temporary);

/// <summary>
/// Mark an e-mail as read in the provided account.
/// </summary>
/// <param name="AccountId">The email account ID.</param>
/// <param name="ExternalId">The external ID of the email.</param>
procedure MarkAsRead(AccountId: Guid; ExternalId: Text);
}
15 changes: 14 additions & 1 deletion src/System Application/App/Email/src/Email/Email.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -253,17 +253,30 @@ codeunit 8901 Email
#endregion

#region RetrieveEmails

#if not CLEAN26
/// <summary>
/// Retrieves emails from the email account.
/// </summary>
/// <param name="EmailAccountId">The ID of the email account to use for sending the email.</param>
/// <param name="EmailConnector">The email connector to use for sending the email.</param>
/// <param name="EmailInbox">The return record of all new emails that were retrieved.</param>
[Obsolete('Replaced by RetrieveEmails with an additional Filters parameter of type Record "Email Retrieval Filters".', '26.0')]
procedure RetrieveEmails(EmailAccountId: Guid; EmailConnector: Enum "Email Connector"; var EmailInbox: Record "Email Inbox")
begin
EmailImpl.RetrieveEmails(EmailAccountId, EmailConnector, EmailInbox);
end;
#endif
/// <summary>
/// Retrieves emails from the email account.
/// </summary>
/// <param name="EmailAccountId">The ID of the email account to use for sending the email.</param>
/// <param name="EmailConnector">The email connector to use for sending the email.</param>
/// <param name="EmailInbox">The return record of all new emails that were retrieved.</param>
/// <param name="Filters">Filters to be used when retrieving emails.</param>
procedure RetrieveEmails(EmailAccountId: Guid; EmailConnector: Enum "Email Connector"; var EmailInbox: Record "Email Inbox"; var Filters: Record "Email Retrieval Filters" temporary)
begin
EmailImpl.RetrieveEmails(EmailAccountId, EmailConnector, EmailInbox, Filters);
end;

#endregion

Expand Down
95 changes: 79 additions & 16 deletions src/System Application/App/Email/src/Email/EmailImpl.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,41 @@ codeunit 8900 "Email Impl"

procedure RetrieveEmails(EmailAccountId: Guid; Connector: Enum "Email Connector"; var EmailInbox: Record "Email Inbox")
var
IEmailConnectorv2: Interface "Email Connector v2";
Filters: Record "Email Retrieval Filters";
begin
Filters.Insert();
RetrieveEmails(EmailAccountId, Connector, EmailInbox, Filters);
end;

procedure RetrieveEmails(EmailAccountId: Guid; Connector: Enum "Email Connector"; var EmailInbox: Record "Email Inbox"; var Filters: Record "Email Retrieval Filters" temporary)
var
#if not CLEAN26
#pragma warning disable AL0432
EmailConnectorv2: Interface "Email Connector v2";
#pragma warning restore AL0432
#endif
EmailConnectorv3: Interface "Email Connector v3";
begin
CheckRequiredPermissions();

if CheckAndGetEmailConnectorv2(Connector, IEmailConnectorv2) then begin
if CheckAndGetEmailConnectorv3(Connector, EmailConnectorv3) then begin
TelemetryAppsAndPublishers(TelemetryRetrieveEmailsUsedTxt);
IEmailConnectorv2.RetrieveEmails(EmailAccountId, EmailInbox);
end else
Error(EmailConnectorDoesNotSupportRetrievingEmailsErr);
EmailConnectorv3.RetrieveEmails(EmailAccountId, EmailInbox, Filters);
EmailInbox.MarkedOnly(true);
exit;
end;
#if not CLEAN26
#pragma warning disable AL0432
if CheckAndGetEmailConnectorv2(Connector, EmailConnectorv2) then begin
#pragma warning restore AL0432
TelemetryAppsAndPublishers(TelemetryRetrieveEmailsUsedTxt);
EmailConnectorv2.RetrieveEmails(EmailAccountId, EmailInbox);
EmailInbox.MarkedOnly(true);
exit;
end;
#endif

EmailInbox.MarkedOnly(true);
Error(EmailConnectorDoesNotSupportRetrievingEmailsErr);
end;

local procedure TelemetryAppsAndPublishers(Message: Text)
Expand All @@ -236,37 +260,76 @@ codeunit 8900 "Email Impl"

procedure MarkAsRead(EmailAccountId: Guid; Connector: Enum "Email Connector"; ExternalId: Text)
var
IEmailConnectorv2: Interface "Email Connector v2";
#if not CLEAN26
#pragma warning disable AL0432
EmailConnectorv2: Interface "Email Connector v2";
#pragma warning restore AL0432
#endif
EmailConnectorv3: Interface "Email Connector v3";
begin
CheckRequiredPermissions();

if ExternalId = '' then
Error(ExternalIdCannotBeEmptyErr);

if CheckAndGetEmailConnectorv2(Connector, IEmailConnectorv2) then
IEmailConnectorv2.MarkAsRead(EmailAccountId, ExternalId)
else
Error(EmailConnectorDoesNotSupportMarkAsReadErr);
if CheckAndGetEmailConnectorv3(Connector, EmailConnectorv3) then begin
EmailConnectorv3.MarkAsRead(EmailAccountId, ExternalId);
exit;
end;
#if not CLEAN26
#pragma warning disable AL0432
if CheckAndGetEmailConnectorv2(Connector, EmailConnectorv2) then begin
#pragma warning restore AL0432
EmailConnectorv2.MarkAsRead(EmailAccountId, ExternalId);
exit;
end;
#endif

Error(EmailConnectorDoesNotSupportMarkAsReadErr);
end;

procedure CheckReplySupported(Connector: Enum "Email Connector"): Boolean
var
IEmailConnectorv2: Interface "Email Connector v2";
#if not CLEAN26
#pragma warning disable AL0432
EmailConnectorv2: Interface "Email Connector v2";
#pragma warning restore AL0432
#endif
EmailConnectorv3: Interface "Email Connector v3";
begin
if not CheckAndGetEmailConnectorv2(Connector, IEmailConnectorv2) then
Error(EmailconnectorDoesNotSupportReplyingErr);
if CheckAndGetEmailConnectorv3(Connector, EmailConnectorv3) then
exit(true);
#if not CLEAN26
#pragma warning disable AL0432
if CheckAndGetEmailConnectorv2(Connector, EmailConnectorv2) then
exit(true);
#pragma warning restore AL0432
#endif

exit(true);
Error(EmailconnectorDoesNotSupportReplyingErr);
end;

#if not CLEAN26
#pragma warning disable AL0432
[Obsolete('Replaced by CheckAndGetEmailConnectorv3.', '26.0')]
procedure CheckAndGetEmailConnectorv2(Connector: Interface "Email Connector"; var Connectorv2: Interface "Email Connector v2"): Boolean
#pragma warning restore AL0432
begin
if Connector is "Email Connector v2" then begin
Connectorv2 := Connector as "Email Connector v2";
exit(true);
end else
exit(false);
end;
#endif

procedure CheckAndGetEmailConnectorv3(Connector: Interface "Email Connector"; var Connectorv3: Interface "Email Connector v3"): Boolean
begin
if Connector is "Email Connector v3" then begin
Connectorv3 := Connector as "Email Connector v3";
exit(true);
end else
exit(false);
end;

procedure OpenInEditor(EmailMessage: Codeunit "Email Message"; EmailScenario: Enum "Email Scenario"; IsModal: Boolean): Enum "Email Action"
var
Expand Down
Loading

0 comments on commit 6c4aef6

Please sign in to comment.