Skip to content

ExchangeOnline OOF support formatted HTML auto-reply messages with stable idempotency #176

@blindzero

Description

@blindzero

Problem Statement

Operators often configure Exchange Online automatic replies using the Outlook / OWA GUI, which supports formatted messages (HTML markup: bold, links, lists, line breaks).

IdLE's IdLE.Step.Mailbox.EnsureOutOfOffice currently accepts Config.InternalMessage and Config.ExternalMessage as plain strings and forwards them to the Exchange Online provider, which uses Set-MailboxAutoReplyConfiguration.

Two practical gaps remain:

  1. No explicit support contract for formatted messages
    Users cannot tell from IdLE docs/contracts whether HTML is allowed and what the expectations are.

  2. Idempotency can become unstable when formatting is used
    Exchange may normalize or wrap the message content (for example by adding HTML/body wrappers or normalizing line endings).
    If IdLE compares message strings naively, workflows may report Changed = $true on every run even if the effective message did not change.

This makes formatted auto-replies hard to use reliably in repeatable lifecycle workflows.

Exchange Online Capability Check

Exchange Online supports formatted automatic reply messages via the Exchange Online PowerShell cmdlet Set-MailboxAutoReplyConfiguration.
The -InternalMessage and -ExternalMessage values are stored/handled as HTML on the server side (plain text input is typically wrapped/normalized into HTML).
This means IdLE can treat HTML as a supported input, but must handle server-side canonicalization to keep idempotency stable.

Proposed Solution

A) Extend the step contract to support message formats (data-only)

Add explicit, data-only keys to With.Config for message format and semantics:

  • MessageFormat: 'Text' | 'Html' (optional, default: 'Text')
  • InternalMessage: string (optional)
  • ExternalMessage: string (optional)

Rules:

  • When MessageFormat = 'Html', messages are treated as HTML markup and passed through without modification.
  • When MessageFormat = 'Text', messages are treated as plain text.
  • No ScriptBlocks allowed (keep existing data-only validation).

B) Provider-side normalization for stable idempotency

In IdLE.Provider.ExchangeOnline, implement a normalization routine used for idempotency comparison.

Suggested approach:

  • Add a private helper (example name): Normalize-IdleExchangeOnlineAutoReplyMessage
  • Normalize differences that Exchange commonly introduces (this can happen for both 'Text' and 'Html' inputs, because Exchange may persist/return HTML):
    • line endings (\r\n vs \n)
    • surrounding <html>, <head>, <body> wrappers
    • benign whitespace differences
  • Compare normalized current vs desired messages when deciding whether a change is required.

Important constraints:

  • Do not attempt to sanitize HTML (that would be surprising and could break intended formatting).
  • Keep normalization deterministic and minimal (only address known canonicalization effects).

C) Documentation + examples

Update docs to make formatted messages discoverable and safe to use:

  • docs/reference/steps/step-mailbox-ensure-out-of-office.md

    • Describe MessageFormat
    • Provide a formatted message example (HTML)
    • Mention idempotency normalization behavior
  • docs/reference/providers/provider-exchangeonline.md

    • Add a short example snippet showing a formatted (HTML) internal/external message.
  • Add or update an example workflow under examples/workflows/templates/ that demonstrates a formatted OOF message (for example with a link to Service Desk).

D) Tests

Add tests that prevent regressions:

  1. Step unit tests (Mailbox module)

    • Validates MessageFormat accepted values
    • Validates ScriptBlocks rejected inside Config (existing rule)
  2. ExchangeOnline provider unit tests (mock adapter)

    • Ensure normalization prevents repeated changes:
      • Desired message is a plain HTML string
      • Current message returned by adapter is the same content but wrapped/normalized
      • Provider reports Changed = $false
  3. If docs are generated: regenerate step reference and ensure the step page contains the new inputs.

Alternatives Considered

  1. Document "HTML works" without changing code
    Rejected because idempotency drift would still cause noisy plans and repeated updates in practice.

  2. Add a separate step EnsureOutOfOfficeHtml
    Rejected because it multiplies step types; a single step with an explicit MessageFormat is clearer.

  3. Convert Markdown to HTML inside IdLE
    Rejected because it adds complexity and a new transformation layer. Users can provide HTML directly.

Impact

  • Does this affect existing workflows?
    No breaking changes intended. Default behavior remains MessageFormat = 'Text'.

  • Any backward compatibility concerns?
    None expected if the new key is optional and defaults are preserved.

Additional Context

Current OOF step forwards message strings and the ExchangeOnline adapter uses Set-MailboxAutoReplyConfiguration with -InternalMessage and -ExternalMessage.
The provider also performs idempotency checks by comparing current vs desired values, which can be affected by server-side canonicalization.

Goal: make formatted auto-replies a first-class, reliable scenario for Leaver/handover workflows.

Metadata

Metadata

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions