bcquality/microsoft/knowledge/breaking-changes/prefer-email-module.md
Michael Dieringer a28ba1a1d7 Address second round of Jesper Schulz-Wedde's review on PR #156
- dimension-management-wiring.md/.good.al: split into the two distinct
  models the article was conflating - master data (Default Dimension
  records via ValidateDimValueCode/SaveDefaultDim) vs. transactional/
  document data (a single Dimension Set ID assembled via AddDimSource +
  GetDefaultDimID, verified against BCApps' ExchRateAdjmtProcess.Codeunit.al).
  Added a compiling document-table example alongside the existing master
  table one.
- Deleted api-page-flowfields-must-be-calcfields (.md/.good.al/.bad.al):
  Microsoft's own FlowFields documentation states a FlowField used as a
  control's direct source expression is automatically calculated on any
  page - no API-page exception is documented, and none could be
  reproduced.
- prefer-email-module.bad.al/.md: Codeunit Mail has no Send/GetErrorDesc
  members; fixed to the real current 7-argument CreateMessage signature,
  and corrected the claim that the legacy path "still runs" - its base
  implementation no longer sends anything, only raises integration events.
- check-post-line-batch-pattern.md/.good.al: reframed from a universal
  invariant to the standard shape, naming the real Gen./Item/CA/Res./Job/
  Insurance/Mfg. Item/FA Jnl.-Check Line/-Post Line/-Post Batch codeunits
  it's based on. Added the missing Check Line companion codeunit so the
  good fixture is internally complete.
- test-data-must-be-random-and-complete.good.al: removed leftover
  "collision-free" wording contradicting the already-corrected article text.
- fixed-choice-set-must-use-enum-not-integer.md: removed the reintroduced
  state-count heuristic ("the line is the state count"), aligned with
  binary-choice-must-be-boolean.md's semantics-based distinction.
- namespace-must-be-verified-from-source.md: removed the false claim that
  the compiler and AL Language Server use different namespace-resolution
  rules.
- intrinsic-al-functions-must-use-modern-casing.md: removed the unverified
  claim that PascalCase is the VS Code formatter's default output.

Worklist completeness: added cues for the 8 rules in data-modeling,
testing, performance, and web-services that had none (Jesper's explicit
ask), plus the same gap in all 7 style rules from this PR (not explicitly
named this round, but the identical systemic issue) - 15 cues total across
al-data-modeling-review.md, al-testing-review.md, al-performance-review.md,
al-web-services-review.md, and al-style-review.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 22:26:33 +02:00

1.9 KiB

bc-version domain keywords technologies countries application-area
all
breaking-changes
email
codeunit-mail
email-message
email-scenario
email-account
smtp
sending-email
al
w1
all

Send email through the Email module, not Codeunit Mail (397)

Contributions welcome — open a PR to refine or extend this article.

Description

Older AL code sends email by calling Codeunit Mail (397). Business Central's current extensibility model is a different, richer object set — Codeunit Email, Codeunit "Email Message", enum "Email Scenario", and the Email Account/Email Connector interface (Microsoft 365, Current User, SMTP, or a custom connector). Codeunit "Email Message" is the in-memory object you build the message on; it is not itself the persisted Sent/Outbox/Draft record — that storage is managed separately once the message is queued or sent. New code built on Codeunit Mail inherits its SMTP-era, single-connector assumptions and leaves no Sent/Outbox trail behind.

Best Practice

Build on Codeunit Email and Codeunit "Email Message". Route the message through an Email Scenario so different document types can use different accounts without the calling code needing to know which account that is, and get a tracked Sent/Outbox/Draft record for free.

See sample: prefer-email-module.good.al.

Anti Pattern

Calling Codeunit Mail's CreateMessage. It still compiles and runs, but current Codeunit Mail's own implementation of CreateMessage no longer sends anything by itself — it only raises integration events for a legacy subscriber to act on — so building new code on it means depending on whatever compatibility shim happens to still be wired up, with no first-class connector selection and no queryable Sent/Outbox/Draft record. Send and GetErrorDesc are not current members of Codeunit Mail at all; do not reference them.

See sample: prefer-email-module.bad.al.