-
Notifications
You must be signed in to change notification settings - Fork 0
Add HTML message format support with stable idempotency for ExchangeOnline OOF #177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
f34e97f
Initial plan
Copilot 3be3eab
Add MessageFormat support and HTML normalization for OOF messages
Copilot 4676fed
Update documentation with HTML OOF message examples
Copilot 03087f7
Address code review feedback on normalization comments
Copilot 0167410
Add FromFile pattern for loading HTML messages from external files
Copilot 8d4bd39
Remove global FromFile pattern to fix backward compatibility issue
Copilot f5beacb
Apply suggestions from code review
blindzero dfc3e3e
Remove short-circuit checks to make idempotency checks truly independent
Copilot 02681aa
Make whitespace normalization more conservative to avoid false negatives
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
src/IdLE.Provider.ExchangeOnline/Private/Normalize-IdleExchangeOnlineAutoReplyMessage.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| function Normalize-IdleExchangeOnlineAutoReplyMessage { | ||
| <# | ||
| .SYNOPSIS | ||
| Normalizes Exchange Online auto-reply messages for stable idempotency comparison. | ||
|
|
||
| .DESCRIPTION | ||
| Exchange Online may introduce server-side canonicalization when storing automatic reply messages, | ||
| such as adding HTML/body wrappers, normalizing line endings, or adjusting whitespace. | ||
|
|
||
| This helper performs minimal, deterministic normalization to ensure that functionally equivalent | ||
| messages are recognized as identical during idempotency checks. | ||
|
|
||
| Normalization operations: | ||
| - Normalize line endings (CRLF to LF) | ||
| - Remove common HTML wrappers added by Exchange (<html>, <head>, <body>) | ||
| - Trim leading/trailing whitespace | ||
| - Normalize consecutive whitespace sequences in HTML (multiple spaces/tabs to single space) | ||
|
|
||
| This function does NOT sanitize or validate HTML. It only normalizes structural differences | ||
| introduced by server-side canonicalization. | ||
|
|
||
| .PARAMETER Message | ||
| The auto-reply message string to normalize (plain text or HTML). | ||
|
|
||
| .OUTPUTS | ||
| System.String - The normalized message string. | ||
|
|
||
| .EXAMPLE | ||
| $normalized = Normalize-IdleExchangeOnlineAutoReplyMessage -Message $currentMessage | ||
| if ($normalized -eq (Normalize-IdleExchangeOnlineAutoReplyMessage -Message $desiredMessage)) { | ||
| # Messages are functionally equivalent | ||
| } | ||
|
|
||
| .NOTES | ||
| This is a private helper function used by the ExchangeOnline provider for idempotency checks. | ||
| #> | ||
| [CmdletBinding()] | ||
| [OutputType([string])] | ||
| param( | ||
| [Parameter()] | ||
| [AllowEmptyString()] | ||
| [AllowNull()] | ||
| [string] $Message | ||
| ) | ||
|
|
||
| if ([string]::IsNullOrEmpty($Message)) { | ||
| return '' | ||
| } | ||
|
|
||
| # Start with the original message | ||
| $normalized = $Message | ||
|
|
||
| # 1. Normalize line endings: CRLF -> LF | ||
| $normalized = $normalized -replace "`r`n", "`n" | ||
| $normalized = $normalized -replace "`r", "`n" | ||
|
|
||
| # 2. Remove common HTML wrappers that Exchange may add | ||
| # Remove <!DOCTYPE ...> declarations | ||
| $normalized = $normalized -replace '(?i)<!DOCTYPE[^>]*>', '' | ||
|
|
||
| # Remove <html> opening and closing tags (with optional attributes) | ||
| $normalized = $normalized -replace '(?i)<html[^>]*>', '' | ||
| $normalized = $normalized -replace '(?i)</html>', '' | ||
|
|
||
| # Remove <head> wrapper tags while preserving their inner content | ||
| $normalized = $normalized -replace '(?is)<head[^>]*>\s*(.*?)\s*</head>', '$1' | ||
|
|
||
| # Remove <body> opening and closing tags (with optional attributes) | ||
| $normalized = $normalized -replace '(?i)<body[^>]*>', '' | ||
| $normalized = $normalized -replace '(?i)</body>', '' | ||
|
|
||
| # 3. Trim leading/trailing whitespace (including newlines) | ||
| $normalized = $normalized.Trim() | ||
|
|
||
| # 4. Normalize whitespace conservatively | ||
| # Only collapse truly excessive whitespace that Exchange commonly adds | ||
| # This is conservative to avoid making intentionally different messages compare equal | ||
| # NOTE: This normalization is ONLY used for idempotency comparison, not for modifying | ||
| # the actual message sent to Exchange. The original message formatting is preserved. | ||
|
|
||
| # Normalize 3+ consecutive spaces/tabs to 2 (preserves intentional double-spacing) | ||
| # This handles Exchange adding extra whitespace without collapsing intentional formatting | ||
| $normalized = $normalized -replace '[ \t]{3,}', ' ' | ||
|
|
||
| # 5. Normalize excessive empty lines (4+ consecutive newlines to 3) | ||
| # This is very conservative - only removes truly excessive blank lines | ||
| # Preserves intentional spacing while handling Exchange-added excessive gaps | ||
| $normalized = $normalized -replace '\n{4,}', "`n`n`n" | ||
|
|
||
| # 6. Final trim to remove any whitespace introduced by previous operations | ||
| $normalized = $normalized.Trim() | ||
|
|
||
| return $normalized | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.