@@ -197,7 +197,7 @@ const Page = () => {
197197 const aliasApiConfig = {
198198 type : "POST" ,
199199 url : "/api/EditUserAliases" ,
200- relatedQueryKeys : `ListUsers-${ userId } ` ,
200+ relatedQueryKeys : [ `ListUsers-${ userId } ` , `Mailbox- ${ userId } ` ] ,
201201 confirmText : "Add the specified proxy addresses to this user?" ,
202202 customDataformatter : ( row , action , formData ) => {
203203 return {
@@ -1259,8 +1259,8 @@ const Page = () => {
12591259 } ,
12601260 confirmText : "Are you sure you want to make this the primary proxy address?" ,
12611261 multiPost : false ,
1262- relatedQueryKeys : `ListUsers-${ userId } ` ,
1263- condition : ( row ) => row && row . Type !== "Primary ",
1262+ relatedQueryKeys : [ `ListUsers-${ userId } ` , `Mailbox- ${ userId } ` ] ,
1263+ condition : ( row ) => row && row . Type === "Alias ",
12641264 } ,
12651265 {
12661266 label : "Remove Proxy Address" ,
@@ -1274,28 +1274,73 @@ const Page = () => {
12741274 } ,
12751275 confirmText : "Are you sure you want to remove this proxy address?" ,
12761276 multiPost : false ,
1277- relatedQueryKeys : `ListUsers-${ userId } ` ,
1278- condition : ( row ) => row && row . Type !== "Primary ",
1277+ relatedQueryKeys : [ `ListUsers-${ userId } ` , `Mailbox- ${ userId } ` ] ,
1278+ condition : ( row ) => row && row . Type === "Alias ",
12791279 } ,
12801280 ] ;
12811281
1282+ // Merge Entra ID proxyAddresses (fast, primary source) with the mailbox EmailAddresses
1283+ // from Exchange so forward-sync drift between the two directories is visible.
1284+ const graphProxyAddresses = ( graphUserRequest . data ?. [ 0 ] ?. proxyAddresses || [ ] ) . filter (
1285+ ( address ) => typeof address === "string" ,
1286+ ) ;
1287+ // Mailbox serializes as an array with one element
1288+ const mailboxDetails = [ ] . concat ( userRequest . data ?. [ 0 ] ?. Mailbox || [ ] ) [ 0 ] ;
1289+ const exchangeProxyAddresses = [ ]
1290+ . concat ( mailboxDetails ?. EmailAddresses || [ ] )
1291+ . filter ( ( address ) => typeof address === "string" ) ;
1292+ // Only assess sync when Exchange returned addresses; a mailbox always has at least a primary
1293+ const exchangeAddressesLoaded = userRequest . isSuccess && exchangeProxyAddresses . length > 0 ;
1294+ const proxyAddressType = ( address ) =>
1295+ address . startsWith ( "SMTP:" ) ? "Primary" : address . startsWith ( "smtp:" ) ? "Alias" : address . split ( ":" ) [ 0 ] ;
1296+ const proxyAddressRows = ( ( ) => {
1297+ const rows = new Map ( ) ;
1298+ graphProxyAddresses . forEach ( ( address ) => {
1299+ rows . set ( address . toLowerCase ( ) , { Address : address , inGraph : true , inExchange : false } ) ;
1300+ } ) ;
1301+ exchangeProxyAddresses . forEach ( ( address ) => {
1302+ const existing = rows . get ( address . toLowerCase ( ) ) ;
1303+ if ( existing ) {
1304+ existing . inExchange = true ;
1305+ } else {
1306+ rows . set ( address . toLowerCase ( ) , { Address : address , inGraph : false , inExchange : true } ) ;
1307+ }
1308+ } ) ;
1309+ return [ ...rows . values ( ) ] . map ( ( row ) => ( {
1310+ Address : row . Address ,
1311+ Type : proxyAddressType ( row . Address ) ,
1312+ Source : ! exchangeAddressesLoaded
1313+ ? "Checking"
1314+ : row . inGraph && row . inExchange
1315+ ? "Entra ID & Exchange"
1316+ : row . inGraph
1317+ ? "Entra ID only"
1318+ : "Exchange only" ,
1319+ } ) ) ;
1320+ } ) ( ) ;
1321+ const mismatchedAddresses = exchangeAddressesLoaded
1322+ ? proxyAddressRows . filter ( ( row ) => row . Source !== "Entra ID & Exchange" )
1323+ : [ ] ;
1324+
12821325 const proxyAddressesCard = [
12831326 {
12841327 id : 1 ,
12851328 cardLabelBox : {
12861329 cardLabelBoxHeader : graphUserRequest . isFetching ? (
12871330 < CircularProgress size = "25px" color = "inherit" />
1288- ) : graphUserRequest . data ?. [ 0 ] ?. proxyAddresses ?. length > 1 ? (
1331+ ) : mismatchedAddresses . length === 0 && graphUserRequest . data ?. [ 0 ] ?. proxyAddresses ?. length > 1 ? (
12891332 < Check />
12901333 ) : (
12911334 < Error />
12921335 ) ,
12931336 } ,
12941337 text : "Proxy Addresses" ,
12951338 subtext :
1296- graphUserRequest . data ?. [ 0 ] ?. proxyAddresses ?. length > 1
1297- ? "Proxy addresses are configured for this user"
1298- : "No proxy addresses configured for this user" ,
1339+ mismatchedAddresses . length > 0
1340+ ? `${ mismatchedAddresses . length } address(es) only exist in one of Entra ID or Exchange - Microsoft may still be propagating recent changes`
1341+ : graphUserRequest . data ?. [ 0 ] ?. proxyAddresses ?. length > 1
1342+ ? "Proxy addresses are configured for this user"
1343+ : "No proxy addresses configured for this user" ,
12991344 statusColor : "green.main" ,
13001345 cardLabelBoxActions : (
13011346 < Button
@@ -1311,14 +1356,13 @@ const Page = () => {
13111356 table : {
13121357 title : "Proxy Addresses" ,
13131358 hideTitle : true ,
1314- data :
1315- graphUserRequest . data ?. [ 0 ] ?. proxyAddresses ?. map ( ( address ) => ( {
1316- Address : address ,
1317- Type : typeof address === "string" && address . startsWith ( "SMTP:" ) ? "Primary" : "Alias" ,
1318- } ) ) || [ ] ,
1319- refreshFunction : ( ) => graphUserRequest . refetch ( ) ,
1359+ data : proxyAddressRows ,
1360+ refreshFunction : ( ) => {
1361+ graphUserRequest . refetch ( ) ;
1362+ userRequest . refetch ( ) ;
1363+ } ,
13201364 isFetching : graphUserRequest . isFetching ,
1321- simpleColumns : [ "Address" , "Type" ] ,
1365+ simpleColumns : [ "Address" , "Type" , "Source" ] ,
13221366 actions : proxyAddressActions ,
13231367 offCanvas : {
13241368 children : ( data ) => {
@@ -1335,6 +1379,10 @@ const Page = () => {
13351379 label : "Type" ,
13361380 value : data . Type ,
13371381 } ,
1382+ {
1383+ label : "Source" ,
1384+ value : data . Source ,
1385+ } ,
13381386 ] }
13391387 actionItems = { proxyAddressActions }
13401388 />
0 commit comments