Since version 17 there is one supported way to send email from an extension. Email accounts, scenarios, building a message with HTML and attachments, sending now versus queuing, the sent-email log, and why you never hard-code an address or an SMTP server again.
Older code sent mail with the SMTP codeunit and a server name in a setup table. That is gone. The Email module in the System Application (version 17 onwards) separates accounts (configured by the administrator: Microsoft 365 shared mailbox, current user, SMTP), scenarios (which account is used for which purpose) and messages (what your code builds). Your extension builds messages and names a scenario. It never knows the server.
procedure EmailLabel(Shipment: Record "CON Courier Shipment")
var
EmailMessage: Codeunit "Email Message";
Email: Codeunit Email;
TempBlob: Codeunit "Temp Blob";
InStr: InStream;
begin
EmailMessage.Create(Shipment."Recipient E-Mail", StrSubstNo(SubjectLbl, Shipment."No."), BuildHtmlBody(Shipment), true);
GetLabelPdf(Shipment, TempBlob);
TempBlob.CreateInStream(InStr);
EmailMessage.AddAttachment(StrSubstNo(AttachmentNameTok, Shipment."No."), PdfMimeTypeTok, InStr);
Email.Send(EmailMessage, Enum::"Email Scenario"::"CON Courier");
end;
Create takes recipient(s), subject, body and whether the body is HTML. AddAttachment takes a name, MIME type and stream. Send is synchronous and errors on failure; Enqueue queues it to the job queue and returns, which is what you want from a posting routine or any user action that should not wait on a mail server.
Add your own with an enum extension of "Email Scenario". The administrator maps it to an account on the Email Scenario Assignment page; unmapped scenarios fall back to the default account. This is how "courier labels come from despatch@" and "invoices come from accounts@" is configured, not coded.
Email.AddRelation(EmailMessage, Database::"CON Courier Shipment", Shipment.SystemId, Enum::"Email Relation Type"::"Primary Source", Enum::"Email Relation Origin"::"Compose Context") links the sent mail to the record, so the Sent Emails list and the record's related emails FactBox show it. Every send is logged (Sent Emails, Email Outbox for queued and failed), with retry from the outbox.
There is no general email template object in the base application. For text the business should be able to edit, either render a Word report layout to HTML (Report.SaveAs with ReportFormat::Html) and use that as the body, or keep a small setup table of HTML with placeholders that your code fills. Fixed text stays in labels.
A sandbox copied from production has production's email accounts. Business Central blocks sending from sandboxes by default unless the administrator allows it; still, check EnvironmentInformation.IsSandbox before any bulk send and route to a test address.