AdhocAdam / smletsexchangeconnector

SMLets PowerShell based Exchange Connector for controlling Microsoft System Center Service Manager 2016+
https://adhocadam.github.io/smletsexchangeconnector/
GNU General Public License v3.0
29 stars 19 forks source link

Get-SCSMUserByEmailAddress cannot find mail addresses with a dash #403

Closed alexaxb closed 2 years ago

alexaxb commented 2 years ago

If mail address contains a dash, the address won't be found in SCSM. Example: Get-SCSMObject -Class $notificationClass -Filter "TargetAddress -eq 'scott-jimmy.clarskon@contoso.com'" won't return anything. But: Get-SCSMObject -Class $notificationClass -Filter "TargetAddress -eq scott-jimmy.clarskon@contoso.com" will work.

AdhocAdam commented 2 years ago

I get results with and without the single quotes for the example you provided.

Is there a specific email in your environment that isn't matching? You don't need to paste it here, I'm just trying to understand how I could repro this.

alexaxb commented 2 years ago

Weird.. There are several emails in the environment that cause this, and I've run into this in the past as well. For me, the only thing that always works is without quotes. One observation: I could get one of the emails working by escaping the dash (Get-SCSMObject -Class $notificationClass -Filter "TargetAddress -eq 'scott--jimmy.clarskon@contoso.com'"). But that only worked for one of them.. Could it be something with language locale that makes a difference..seems far fetched, but who knows.. :)

AdhocAdam commented 2 years ago

I'll keep looking into the email thing.

Could you move the recent commit you made into its own pull request/branch? That one seems pretty straightforward and I wouldn't want this one to hold it up.

AdhocAdam commented 2 years ago

OOOOOOOOOOOOOOOOOHHHHHHHHHHHHH I THINK I GOT IT!!!!!

Like I said, per the example you gave above I can't repro this. I create the user (New-CMDBUser), I successfully get the user (Get-SCSMUserByEmailAddress). So the first thing I did, was run the command by itself just like you have but with the -Verbose switch:

#With single quotes
$notificationClass = Get-SCSMClass -name "System.Notification.Endpoint$"
Get-SCSMObject -Class $notificationClass -Filter "TargetAddress -eq 'Scott-Jimmy.Clarskon@contoso.com'" -Verbose
VERBOSE: Checking SMDefaultSession...
VERBOSE: Checking SMDefaultComputer...
VERBOSE: Connect using ComputerName 'localhost'
VERBOSE: Original Filter: TargetAddress -eq 'Scott-Jimmy.Clarskon@contoso.com'
VERBOSE: Fixed Filter: TargetAddress = 'Scott-Jimmy.Clarskon@contoso.com'
VERBOSE: Using TargetAddress = 'Scott-Jimmy.Clarskon@contoso.com' as criteria
VERBOSE: look for instance properties first
VERBOSE: now look for generic properties

Nothing really stands out as problematic here because I return the user despite it being in single quotes. So what I did next is remove the single quotes as you've suggested here in the pull request and to my surprise, I got something different.

#Without single quotes
$notificationClass = Get-SCSMClass -name "System.Notification.Endpoint$"
Get-SCSMObject -Class $notificationClass -Filter "TargetAddress -eq Scott-Jimmy.Clarskon@contoso.com" -Verbose
VERBOSE: Checking SMDefaultSession...
VERBOSE: Checking SMDefaultComputer...
VERBOSE: Connect using ComputerName 'localhost'
VERBOSE: Original Filter: TargetAddress -eq Scott-Jimmy.Clarskon@contoso.com
VERBOSE: Fixed Filter: TargetAddress = Scott-Jimmy.Clarskon@contoso.com
VERBOSE: ConvertFilterToCriteriaString: TargetAddress -eq Scott-Jimmy.Clarskon@contoso.com
VERBOSE: SubFilter => TargetAddress -eq Scott-Jimmy.Clarskon@contoso.com
VERBOSE: <Criteria xmlns='http://Microsoft.EnterpriseManagement.Core.Criteria/'><Reference Id='System.Notifications.Library' Version='10.19.1035.0' PublicKeyToken='31bf3856ad364e35' Alias='myMP' 
/><Expression><SimpleExpression><ValueExpressionLeft><Property>$Target/Property[Type='myMP!System.Notification.Endpoint']/TargetAddress$</Property></ValueExpressionLeft><Operator>Equal</Operator><ValueExpressionRight><Value
>Scott-Jimmy.Clarskon@contoso.com</Value></ValueExpressionRight></SimpleExpression></Expression></Criteria>
VERBOSE: look for instance properties first
VERBOSE: now look for generic properties

Again, I still return the user but this looks/feels way more right than the first. Granted, it doesn't get me any closer to understanding why it currently works both ways for me or why it sometimes doesn't work for you. The only difference is seeing the criteria getting built out by SMLets and that the Original Filter line no longer contains single quotes.

Now I don't have any users in my lab that have dashes in their email, so I decided to script the creation of a bunch of users in Active Directory based off my current ones by flipping their first/last names and using a - instead of a .

The AD connector syncs them in and then I looped through all of them with the Get-SCSMUserByEmailAddress function and that's where things got interesting. Because I had a single user that could not be found and in this case it was "Brockmire-Leigh@contoso.com" Even crazier, I clearly see the user in SCSM along with their associated Notification Channel. No typos, not an issue of casing, just nothing standing out. This is a perfect 1 to 1 match and yet the function isn't working. So I went back to the beginning above and tried just the command by itself:

But I realized I was missing the -Verbose switch throughout this new round of testing. So I flipped it on and behold...

#With single quotes
VERBOSE: Checking SMDefaultSession...
VERBOSE: Checking SMDefaultComputer...
VERBOSE: Connect using ComputerName 'localhost'
VERBOSE: Original Filter: TargetAddress -eq 'Brockmire-Leigh@contoso.com'
VERBOSE: Fixed Filter: TargetAddress = 'Brockmire<=igh@contoso.com'
VERBOSE: Using TargetAddress = 'Brockmire<=igh@contoso.com' as criteria
VERBOSE: look for instance properties first
VERBOSE: now look for generic properties

The surname/lastname contains "-Le" aka Less than or Equal To! In which case just like PowerShell, single quotes force a literal value to be taken, but in this case translates into <=. It goes without saying this user is definitley not found. I remove the single quotes...

#Without single quotes
VERBOSE: Checking SMDefaultSession...
VERBOSE: Checking SMDefaultComputer...
VERBOSE: Connect using ComputerName 'localhost'
VERBOSE: Original Filter: TargetAddress -eq Brockmire-Leigh@contoso.com
VERBOSE: Fixed Filter: TargetAddress = Brockmire<=igh@contoso.com
VERBOSE: ConvertFilterToCriteriaString: TargetAddress -eq Brockmire-Leigh@contoso.com
VERBOSE: SubFilter => TargetAddress -eq Brockmire-Leigh@contoso.com
VERBOSE: <Criteria xmlns='http://Microsoft.EnterpriseManagement.Core.Criteria/'><Reference Id='System.Notifications.Library' Version='10.19.1035.0' PublicKeyToken='31bf3856ad364e35' Alias='myMP' 
/><Expression><SimpleExpression><ValueExpressionLeft><Property>$Target/Property[Type='myMP!System.Notification.Endpoint']/TargetAddress$</Property></ValueExpressionLeft><Operator>Equal</Operator><ValueExpressionRight><Value
>Brockmire-Leigh@contoso.com</Value></ValueExpressionRight></SimpleExpression></Expression></Criteria>
VERBOSE: look for instance properties first
VERBOSE: now look for generic properties

SMLets performs the conversion to a comparison operator, but then saves itself with the ConvertFilterToCriteriaString step and a single user is now returned.

SO WITH ALLLLLLLL OF THAT SAID... by chance are any of the emails you've had issues with ever have a surname/last name that begins with -Le, -Ge, or some other comparison operator?

alexaxb commented 2 years ago

Well done! You have done a thorough investigation mister.. :) I checked the latest email that I hade problem with (cause it was the one I could remember..) and....YES! It contains an "-and" so it matches your theory.

AdhocAdam commented 2 years ago

yes01

Most excellent. So in that case, undo the $workItem change in this Pull Request so its just the fix for the single quote issue. Then let's get this included with #401!