Reputation: 101
I am in org where person can have multiple email address for example
if user alias = alias1 he will have for sure one email address as [email protected] at the same time he might have other email address [email protected]
Also my org has multiple active directory domain like NorthAmerica, EASTASIA, etc.
I want to find to which active directory domain the user belongs. Using below code I am able to figure out domain for all emails of type [email protected] but for other types of email the code is unable to find record in active directory.
string[] emails = new string[]{"[email protected]", "[email protected]"};
string[] DOMAINS = new string[] { "DOMAIN1", "DOMAIN2"};
PrincipalContext[] contexts = new PrincipalContext[DOMAINS.Length];
for (int i=0; i<DOMAINS.Length; i++)
{
contexts[i] = new PrincipalContext(ContextType.Domain, DOMAINS[i]);
}
foreach (string email in emails)
{
string myDomain = "Not found";
for(int i=0; i<DOMAINS.Length; i++)
{
UserPrincipal yourUser = UserPrincipal.FindByIdentity(contexts[i], email);
if (yourUser != null)
{
myDomain = DOMAINS[i];'
break;
}
}
Console.WriteLine(email + " " + myDomain);
}
for [email protected] i was able to find the active directory domain but not for the other case
Upvotes: 0
Views: 991
Reputation: 40858
UserPrincipal.FindByIdentity()
cannot actually search by email address. It can only search by one of the identifier types in the IdentityType
. In your case, it's probably matching by UserPrincipalName
, which is why you find results sometimes, but not all.
For this, I would use DirectorySearcher
directly, which is what UserPrincipal.FindByIdentity()
uses behind the scenes anyway, but you have more control over how you search.
You would have to search by the proxyAddresses
attribute. All of the user's email addresses will be there, prefixed by smtp:
(the primary address is uppercase SMTP:
). That would look something like this:
string[] emails = new string[]{"[email protected]", "[email protected]"};
string[] DOMAINS = new string[] { "DOMAIN1", "DOMAIN2"};
foreach (string email in emails)
{
string myDomain = "Not found";
for(int i=0; i<DOMAINS.Length; i++)
{
var searcher = new DirectorySearcher {
SearchRoot = new DirectoryEntry($"LDAP://{DOMAINS[i]}"),
Filter = $"(&(objectClass=user)(objectCategory=person)(proxyAddresses=smtp:{email}))",
PropertiesToLoad = { "cn" } //just put something so it doesn't return everything
};
if (searcher.FindOne() != null)
{
myDomain = DOMAINS[i];
break;
}
}
Console.WriteLine(email + " " + myDomain);
}
If all of the domains that you're searching are all in the same AD forest, then you can save time by querying the Global Catalog once, and not make separate queries on each domain. The Global Catalog stores data for all the domains in the forest. You target a Global Catalog by using GC://
instead of LDAP://
.
Then you can ask for the user's msDS-PrincipalName
attribute, which will be the username in DOMAIN\username
format, so you can pull the domain name from that. For example:
string[] emails = new string[]{"[email protected]", "[email protected]"};
foreach (string email in emails)
{
string myDomain = "Not found";
var searcher = new DirectorySearcher {
SearchRoot = new DirectoryEntry("GC://example.com"),
Filter = $"(&(objectClass=user)(objectCategory=person)(proxyAddresses=smtp:{email}))",
PropertiesToLoad = { "msDS-PrincipalName" }
};
var found = searcher.FindOne();
if (found != null)
{
var mdDsPrincipalName = (string) found.Properties["msDS-PrincipalName"][0];
myDomain = mdDsPrincipalName.Substring(0, mdDsPrincipalName.IndexOf("\\"));
}
Console.WriteLine(email + " " + myDomain);
}
Just replace example.com
with the name of any of your domains (doesn't matter which).
Upvotes: 1