Conversation
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
blindzero
left a comment
There was a problem hiding this comment.
@copilot Grundsätzlich schon o.k. Gerade für die Template Definition wäre es gut, externe Dateien nutzen zu können um nicht alles in der Workflow Definition selbst angeben zu müssen (wird schnell recht lang).
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Ich habe die Unterstützung für externe Template-Dateien hinzugefügt. Sie können jetzt Beispiel: Config = @{
Mode = 'Enabled'
MessageFormat = 'Html'
InternalMessage = @{ FromFile = './templates/oof-internal.html' }
ExternalMessage = @{ FromFile = './templates/oof-external.html' }
}Features:
Commit: 0167410 Siehe auch das neue Beispiel-Workflow |
blindzero
left a comment
There was a problem hiding this comment.
@copilot is it ensured that the external template file is also supporting the template substitution for dynamic content insert
Yes, template substitution for dynamic content is fully supported within external files. How it works:
Example file ( <p>Contact <a href="mailto:{{Request.DesiredState.Manager.Mail}}">{{Request.DesiredState.Manager.DisplayName}}</a></p>At planning time, placeholders are replaced with actual values from the request (e.g., 'jmanager@contoso.com' and 'Jane Manager'). This is validated by the test "resolves template placeholders within loaded file content" in |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01674108c9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Adds first-class support for HTML-formatted Exchange Online Out of Office (OOF) messages in IdLE, addressing idempotency drift caused by Exchange server-side canonicalization, and introduces a @{ FromFile = '...' } workflow template pattern for loading message bodies from external files during planning.
Changes:
- Extended the OOF step contract with optional
With.Config.MessageFormat(Text/Html) and validation. - Implemented ExchangeOnline provider message normalization for idempotent comparisons and updated idempotency check flow.
- Added
FromFilesupport to template resolution plus tests, docs, and example workflows/templates.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/fixtures/templates/oof-internal.html | Adds HTML template fixture for FromFile/template-resolution tests. |
| tests/fixtures/templates/oof-external.html | Adds HTML template fixture for FromFile/template-resolution tests. |
| tests/Steps/Invoke-IdleStepMailboxOutOfOfficeEnsure.Tests.ps1 | Adds unit tests for MessageFormat validation. |
| tests/Providers/ExchangeOnlineProvider.Tests.ps1 | Adds idempotency tests for HTML wrapper + line-ending normalization and direct tests for the normalization helper. |
| tests/Core/Resolve-IdleWorkflowTemplates.Tests.ps1 | Adds unit tests for the new @{ FromFile = '...' } pattern (path templating + content templating + errors). |
| src/IdLE.Steps.Mailbox/Public/Invoke-IdleStepMailboxOutOfOfficeEnsure.ps1 | Documents and validates With.Config.MessageFormat. |
| src/IdLE.Provider.ExchangeOnline/Public/New-IdleExchangeOnlineProvider.ps1 | Uses message normalization in idempotency comparisons for OOF messages. |
| src/IdLE.Provider.ExchangeOnline/Private/Normalize-IdleExchangeOnlineAutoReplyMessage.ps1 | Introduces normalization helper for stable message comparisons. |
| src/IdLE.Core/Private/Resolve-IdleWorkflowTemplates.ps1 | Implements FromFile template pattern (UTF-8 read during planning + placeholder substitution). |
| examples/workflows/templates/templates/oof-leaver-internal.html | Adds example internal HTML template file. |
| examples/workflows/templates/templates/oof-leaver-external.html | Adds example external HTML template file. |
| examples/workflows/templates/exo-leaver-mailbox-offboarding.psd1 | Updates example workflow to use inline HTML messages. |
| examples/workflows/templates/exo-leaver-mailbox-offboarding-external-templates.psd1 | Adds example workflow using FromFile to load external HTML templates. |
| docs/reference/steps/step-mailbox-ensure-out-of-office.md | Regenerated step reference to include MessageFormat. |
| docs/reference/providers/provider-exchangeonline.md | Adds provider documentation and examples for HTML OOF and FromFile. |
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Applied the suggested changes from the review thread (commit dfc3e3e): Removed short-circuit checks in the idempotency logic - all configuration properties (Mode, InternalMessage, ExternalMessage, ExternalAudience, Start/End dates) are now checked independently. Previously, the Impact: This ensures that all fields are properly evaluated for drift detection, which aligns with the PR description's claim of "independent checks" and fixes the issue where ExternalAudience changes could be masked by earlier checks. All 27 provider tests still pass with this change. |
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Implementation Plan for HTML OOF Message Support
Summary
Successfully implemented support for formatted HTML auto-reply messages in ExchangeOnline Out of Office (OOF) configuration with stable idempotency.
Core features:
MessageFormatparameter ('Text' | 'Html') with data-only validationArchitecture improvements:
Original prompt
This section details on the original issue you should resolve
<issue_title>ExchangeOnline OOF support formatted HTML auto-reply messages with stable idempotency</issue_title>
<issue_description>## 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.EnsureOutOfOfficecurrently acceptsConfig.InternalMessageandConfig.ExternalMessageas plain strings and forwards them to the Exchange Online provider, which usesSet-MailboxAutoReplyConfiguration.Two practical gaps remain:
No explicit support contract for formatted messages
Users cannot tell from IdLE docs/contracts whether HTML is allowed and what the expectations are.
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 = $trueon 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
-InternalMessageand-ExternalMessagevalues 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.Configfor message format and semantics:MessageFormat:'Text' | 'Html'(optional, default:'Text')InternalMessage: string (optional)ExternalMessage: string (optional)Rules:
MessageFormat = 'Html', messages are treated as HTML markup and passed through without modification.MessageFormat = 'Text', messages are treated as plain text.B) Provider-side normalization for stable idempotency
In
IdLE.Provider.ExchangeOnline, implement a normalization routine used for idempotency comparison.Suggested approach:
Normalize-IdleExchangeOnlineAutoReplyMessage\r\nvs\n)<html>,<head>,<body>wrappersImportant constraints:
C) Documentation + examples
Update docs to make formatted messages discoverable and safe to use:
docs/reference/steps/step-mailbox-ensure-out-of-office.mdMessageFormatdocs/reference/providers/provider-exchangeonline.mdAdd 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:
Step unit tests (Mailbox module)
MessageFormataccepted valuesConfig(existing rule)ExchangeOnline provider unit tests (mock adapter)
Changed = $falseIf docs are generated: regenerate step reference and ensure the step page contains the new inputs.
Alternatives Considered
Document "HTML works" without changing code
Rejected because idempotency drift would still cause noisy plans and repeated updates in practice.
Add a separate step
EnsureOutOfOfficeHtmlRejected because it multiplies step types; a single step with an explicit
MessageFormatis clearer.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 ...
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.