Extend Edit Remote Mailbox (dev) with alias and GAL management#12
Open
SirTrek wants to merge 7 commits into
Open
Extend Edit Remote Mailbox (dev) with alias and GAL management#12SirTrek wants to merge 7 commits into
SirTrek wants to merge 7 commits into
Conversation
The existing editremotemailbox page (GET/POST) only edited DisplayName,
PrimarySmtpAddress-as-identity, Alias (mail nickname), and
RemoteRoutingAddress. It had no way to manage secondary SMTP proxy
addresses or GAL visibility.
Adds:
- An Email Addresses card listing all EmailAddresses proxy addresses,
with a modal to add a new alias (Set-RemoteMailbox -EmailAddresses
@{Add=...}) and a Remove button per alias (@{Remove=...})
- A Hidden from Address Lists card with a one-click toggle for
HiddenFromAddressListsEnabled
Both actions post back to /editremotemailbox with an Action field, and
the page re-renders with the mailbox's current state afterwards.
Factored the shared rendering logic (used by GET and by every POST
action) into Get-RemoteMailboxEditPage to avoid duplicating the
proxy-address/GAL-badge HTML building four times.
The whole request loop ran inside one try/finally with no catch, so any exception writing a response (e.g. the client closes the connection or navigates away before the write completes, surfacing as "The specified network name is no longer available") propagated out of the while loop and killed the entire listener for all users. Wraps each request's handling in its own try/catch so a single failed request is logged and the server keeps listening. Same issue and fix as on main; ported here since dev has the identical request loop.
Author
|
Update: this has now been tested against a live on-prem Exchange Management Tools install (Get-RemoteMailbox/Set-RemoteMailbox for viewing properties, adding/removing aliases, toggling HiddenFromAddressListsEnabled, and changing RemoteRoutingAddress) and works as expected. |
Adds a "Danger Zone" card to the Edit Remote Mailbox page with a type-to-confirm control (must type the mailbox's PrimarySmtpAddress before the Disable button enables) backed by a server-side check of the same confirmation text, since the client-side JS is trivially bypassable. Disable-RemoteMailbox strips the Exchange attributes from the AD object; it does not delete the Exchange Online mailbox itself. Since the mailbox no longer exists afterward, the POST handler redirects to the Remote Mailboxes list (via a new Get-RemoteMailboxListPage helper) instead of re-rendering an edit page for an identity that's gone. Local-only change, not opened as a PR upstream.
PowerShell's -eq/-ne string comparison is case-insensitive by default, but the JS confirm-text check used strict !== (case-sensitive, no trim). If the AD-stored PrimarySmtpAddress casing differed at all from what the user typed, or there was stray whitespace, the button stayed disabled even though the server-side check would have accepted it. Trim and lowercase both sides of the JS comparison so it matches the server's more forgiving behavior.
dev's feather-icons <script> tag has no version pinned, so it fetches whatever's latest on the CDN at page-load time. If that version's API shape changes, feather.replace() throws, and since it's the first statement in the shared inline <script> block, the uncaught exception stopped the type-to-confirm listener code right after it from ever running - the Disable button stayed permanently disabled regardless of the casing fix in the previous commit. Wrap it in try/catch so an icon-library hiccup can't take out unrelated functional JS again.
Adds web/table-tools.js, a small self-initializing script that finds every table.table on the page and: - inserts a search box above it that filters rows by substring match across the whole row's text - makes non-empty column headers clickable to sort rows by that column's text, toggling ascending/descending with a ▲/▼ indicator Wired into all five list pages (Remote Mailboxes, Distribution Groups, Contacts, Email Address Policies, Accepted Domains) via one added <script> tag each. Purely client-side against rows already rendered by the server - no new PowerShell routes, no data refetch, and it naturally handles distributiongroups.html's two tables since it operates on every matching table on the page independently.
Launch-ExchangeRecipientAdmin.bat self-elevates via UAC (the Exchange Management Tools assemblies require admin rights to load, which a plain double-clicked shortcut doesn't have by default) and resolves its own folder via %~dp0, so it works regardless of where this project is placed or which user runs it. Create-Shortcut.ps1 is a one-time setup script that creates a Desktop .lnk pointing at the .bat, using the repo's icon if present and falling back to the stock PowerShell icon otherwise (dev's asset rewrite removed images/favicon.ico, so that fallback is needed here). Both are fully dynamic (no hardcoded paths/usernames) - safe to publish, verified against the actual file contents before committing.
Author
|
Update: pushed several more commits since this was opened — disable-mailbox support, client-side search/sort on all list pages, and a desktop shortcut launcher, plus two small bug fixes found along the way. All tested against a live on-prem Exchange Management Tools install. Updated the PR description above to match. |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
devalready has aGET/POST /editremotemailboxpage (nice rewrite — CDN assets, full edit pages for every recipient type). It covers DisplayName, PrimarySmtpAddress-as-identity, Alias (mail nickname), and RemoteRoutingAddress, but had no way to manage secondary SMTP proxy addresses, GAL visibility, or disabling a mailbox, and had no search/sort on any of its list pages. This PR adds all of that on top ofdev's existing conventions (POST forms, CDN Bootstrap/feather, card layout):EmailAddressesproxy addresses (Primary vs Alias badge), an "Add alias" modal (Set-RemoteMailbox -EmailAddresses @{Add=...}), and a Remove button per alias (@{Remove=...})HiddenFromAddressListsEnabledDisable-RemoteMailbox) behind a type-to-confirm control (must type the mailbox'sPrimarySmtpAddressbefore the button enables), checked server-side too so it can't be bypassed client-side. Since the mailbox no longer exists afterward, it redirects to the Remote Mailboxes list (via a newGet-RemoteMailboxListPagehelper) instead of showing an edit page for a gone identity.web/table-tools.js(pure client-side against rows already rendered by the server — no new routes, no data refetch).Launch-ExchangeRecipientAdmin.bat(self-elevates via UAC, since the Exchange Management Tools assemblies need admin rights to load, which a plain double-clicked shortcut doesn't have) andCreate-Shortcut.ps1(one-time setup script that creates a Desktop shortcut, fully dynamic — no hardcoded paths/usernames).Both alias/hidden/disable actions POST back to
/editremotemailboxwith anActionfield and re-render with the mailbox's current state, so you see the result immediately instead of bouncing to the list (except disable, which necessarily goes to the list since the identity is gone). I factored the shared rendering intoGet-RemoteMailboxEditPage/Get-RemoteMailboxListPageto avoid duplicating the proxy-address/GAL-badge HTML across every action — the one deviation from the rest of the script's style (which inlines everything per-route);Also includes two small robustness fixes found while building/testing this:
try/finallywith nocatch, so a client dropping its connection mid-response (e.g. "the specified network name is no longer available") took down the entire listener for all users. Same fix as my other PR (Add Remote Mailbox properties/alias/GAL/routing-address management #11) —devhas the identical loop and bug.feather.replace()running first in the same<script>block; since dev's feather-icons<script>tag has no version pinned, an unrelated feather-icons API change on the CDN threw and silently blocked the confirm button from ever enabling. Wrapped it in try/catch so an icon-library hiccup can't take out unrelated functional JS again.Related: #11 adds the same alias/GAL/disable functionality against
main,