I propose an improvement for the codeunit 9520 "Mail Management", procedure SendViaEmailModule.
The SendViaEmailModule procedure is calling on Email.OpenInEditorModallyWithScenario (where Email: Codeunit Email) that returns an Enum with complete information about the decisions made by the user. The current implementation reduces this information to a simple Cancelled:true/false before supplying it to the closing published event as:
OnSendViaEmailModuleOnAfterEmailSend(Message, TempEmailItem, MailSent, Cancelled, HideEmailSendingError);
I would propose that in place of the boolean parameter MailSent the event should take the returned enum value directly. The event subscriber would then be able to tell what really happened.
There are workflows that do not provide the enum value, they are only able to provide a boolean. In those cases and when the value provided is false the enum value should take the value of "Saved As Draft", which is the default anyway.The Cancelled parameter should still provide information to tell the subscriber the difference between controlled abort and failure.
OnSendViaEmailModuleOnAfterEmailSend is an integration event. It's structure is not guaranteed so we should be fine with such a change even if it is of a "breaking" nature.
Forgive the lack of formatting but this form apparently treats code as malicious input. :-/
local procedure SendViaEmailModule(): Boolean
var
Email: Codeunit Email;
Message: Codeunit "Email Message";
ErrorMessageManagement: Codeunit "Error Message Management";
Attachments: Codeunit "Temp Blob List";
Attachment: Codeunit "Temp Blob";
AttachmentNames: List of [Text];
AttachmentStream: Instream;
Index: Integer;
ToList: List of [Text];
CcList: List of [Text];
BccList: List of [Text];
SourceTableIDs, SourceRelationTypes : List of [Integer];
SourceIDs: List of [Guid];
EmailAction: Enum "Email Action";
begin
RecipientStringToList(TempEmailItem."Send to", ToList);
RecipientStringToList(TempEmailItem."Send CC", CcList);
RecipientStringToList(TempEmailItem."Send BCC", BccList);
Message.Create(ToList, TempEmailItem.Subject, TempEmailItem.GetBodyText(), TempEmailItem."Send As HTML", CcList, BccList);
TempEmailItem.GetSourceDocuments(SourceTableIDs, SourceIDs, SourceRelationTypes);
for Index := 1 to SourceTableIDs.Count() do
if SourceRelationTypes.Count() < Index then
Email.AddRelation(Message, SourceTableIDs.Get(Index), SourceIDs.Get(Index), Enum::"Email Relation Type"::"Related Entity", Enum::"Email Relation Origin"::"Compose Context")
else
Email.AddRelation(Message, SourceTableIDs.Get(Index), SourceIDs.Get(Index), Enum::"Email Relation Type".FromInteger(SourceRelationTypes.Get(Index)), Enum::"Email Relation Origin"::"Compose Context");
OnSendViaEmailModuleOnAfterCreateMessage(Message, TempEmailItem);
TempEmailItem.GetAttachments(Attachments, AttachmentNames);
for Index := 1 to Attachments.Count() do begin
Attachments.Get(Index, Attachment);
Attachment.CreateInStream(AttachmentStream);
Message.AddAttachment(GetAttachmentName(AttachmentNames, Index), '', AttachmentStream);
end;
Session.LogMessage('0000CTW', StrSubstNo(EmailScenarioMsg, Format(CurrentEmailScenario)), Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', EmailManagementCategoryTxt, 'EmailMessageID', Message.GetId());
OnSendViaEmailModuleOnAfterAddAttachments(Message, TempEmailItem);
ClearLastError();
Cancelled := false;
if not HideMailDialog then begin
Commit();
//MailSent := Email.OpenInEditorModallyWithScenario(Message, TempEmailModuleAccount, CurrentEmailScenario) = Enum::"Email Action"::Sent;
EmailAction := Email.OpenInEditorModallyWithScenario(Message, TempEmailModuleAccount, CurrentEmailScenario);
MailSent := EmailAction = Enum::"Email Action"::Sent;
Cancelled := not MailSent;
end else begin
MailSent := Email.Send(Message, TempEmailModuleAccount);
if MailSent then
EmailAction = Enum::"Email Action"::Sent;
end;
//OnSendViaEmailModuleOnAfterEmailSend(Message, TempEmailItem, MailSent, Cancelled, HideEmailSendingError);
OnSendViaEmailModuleOnAfterEmailSend(Message, TempEmailItem, EmailAction, Cancelled, HideEmailSendingError);
if not MailSent and not Cancelled and not HideEmailSendingError then
ErrorMessageManagement.LogSimpleErrorMessage(GetLastErrorText());
exit(MailSent);
end;
[IntegrationEvent(false, false)]
//local procedure OnSendViaEmailModuleOnAfterEmailSend(var Message: Codeunit "Email Message"; var TempEmailItem: Record "Email Item" temporary; var MailSent: Boolean; var Cancelled: Boolean; var HideEmailSendingError: Boolean) local procedure OnSendViaEmailModuleOnAfterEmailSend(var Message: Codeunit "Email Message"; var TempEmailItem: Record "Email Item" temporary; var MailSent: Boolean; var EmailAction: Enum "Email Action"; var HideEmailSendingError: Boolean)
begin
end;
I left the original lines in, commented.
This is the simplest, least impact solution. Alternatively you could extend the "Email Action" enum with a "Failed" value
enum 8891 "Email Action"
{
Extensible = false;
///
/// The email was saved as draft.
///
value(0; "Saved As Draft")
{
}
///
/// The email was discarded.
///
value(1; Discarded)
{
}
///
/// The email was sent.
///
value(2; Sent)
{
}
///
/// Sending the email failed.
///
value(3; Failed)
{
}
}
In this case, you'd be possibly able to drop both MailSent and Cancelled but the solution would have wider consequences. Anyway, I hope you get my gist.

Business Central Team (administrator)
Thank you for this suggestion! Currently this is not on our roadmap. We are tracking this idea and if it gathers more votes and comments we will consider it in the future. Best regards, Business Central Team