nikhilbhr
nikhilbhr

Reputation: 101

find domain name using email address from Active Directory

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

Answers (1)

Gabriel Luci
Gabriel Luci

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

Related Questions