Email this post as a PDFDevelopment · 5 October 2026 · 2 min read

Sending email from AL: the Email module, scenarios and attachments

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.

Contents
  1. Sending a message
  2. Scenarios
  3. Related records and the log
  4. Templates
  5. Sandbox safety
  6. The errors

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.

Sending a message

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.

Scenarios

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.

Templates

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.

Sandbox safety

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.

The errors

  • "No email account set up": the scenario (or default) is unmapped. Admin, not code.
  • Attachments that are empty: the stream was read before it was written (streams post).
  • Sending from a posting routine synchronously: a slow mail server now blocks posting. Enqueue.
Email this post as a PDF
A branded PDF of this post, sent to your inbox to keep, print or share. Copy in colleagues if you like.
We only use these addresses to send this PDF. Nobody is added to a mailing list. Mike at Business Boxed receives a copy. See our privacy notice.
Email this post
Talk to us
Want this done in your Business Central?
Book a 30 minute callGet the monthly newsletter

Related posts