Hello, I am tying to get the email address of a user under Active Directory using ASP.Net.
I'm quite new to the AD side of things, but I have had a fair amount of experience with asp.net. Could someone please help me contruct my LDAP path string. Here's what I have so far...
DirectoryEntry entry = new DirectoryEntry(
"LDAP://192.168.109.4/OU=People,DC=dev,DC=com",
"dev\\user",
"password", AuthenticationTypes.Secure);
My domain is "Dev" and my username is "macumberm" and im not going to tell you my password ;)
But when I put in these correct detials, I get the error:
A referral was returned from the server
what does this mean?
What id the OU?
How do I find out what to put in each parameter in the path string, OU, DC etc...
DirectoryEntry root = new DirectoryEntry("LDAP://RootDSE");
using (root)
{
Console.WriteLine(root.Properties["defaultNamingContext"][0].ToString());
}
This should tell you what the base DN you should be using is (when you run it in the domain of course). Then you can construct the AdsPath from there. Once you have this value, you can find your user account for example. Just read the first post in this
forum about common patterns and use the filter "(sAMAccountName=user)". It will tell you what the correct DN is for that user when you inspect the .Path property from either a SearchResult or a DirectoryEntry.
Have you tried running this locally from a machine joined to the domain and with your domain credentials? You see the way that all code runs is with the identity of the process that starts it. If you run the code on a machine that is not joined to the domain
or with a local account, it has no idea how to contact the domain.
If you tried running this with ASPNET, it would be a local account. The Locator service (which is contacted when using RootDSE), has no idea which domain (if any) to contact if it is contacted using a non-domain account.
If you cannot run this code locally on a domain machine (with a domain account), then you need to give it some more hints to tell it which domain you are looking for:
"LDAP://mydomain.com/RootDSE"
Of course, if you already knew your domain, I would not have given you this code since we can construct the proper DN string exactly when it is known.
using (entry)
{
if (entry.Properties.Contains("mail"))
{
foreach (object o in entry.Properties["mail"])
{
//iterate through each value in the 'mail' attribute as a string
str += o.ToString();
}
}
}
}
catch(Exception ex)
{
str = ex.Message;
}
but I get "There is no such object on the server"
I need to be able to read a users email given their username...
Well, the error tells me that you really do not have an OU called People (at least on that particular server). Are you using ADAM? Is that IP address pointing to a domain controller or your local computer?
Once you get that particular issue pointing to a non-existant object fixed (try using an LDAP browser to find this OU and get the string exactly), we can address the other issue that will trip you up: OU's don't have email addresses.
You are binding to a container that holds other objects and you are looking for an email address on the container. Instead, you should bind to the container, search for the objects that have email addresses you are interested in, and then iterate the email
addresses.
So, you have 3 steps:
1. Bind to your container - you are almost there, but you need to address this first.
2. Search for your objects - you can read the first post in the forum called "Common Patterns" to show how to do this.
3. Iterate through the email addresses - you are close, but it will change slightly from
what is ADAM? i dont know what you are refering to here, so probably not.
the IP is pointing to a domain controller, not my local machine.
Ill try to get the proper string then we'll go on to the next steps that you mentioned. Ill have a read of that thread you mentioned aswell.
Thanks for the help so far, I appreciate it greatly.
I got it working!! thanks so much for the help. I was having alot of trouble with the actual LDAP string to being with. But here is my code for getting the email of a user:
string mail = "";
try
{
DirectoryEntry entry = new DirectoryEntry("LDAP://192.168.109.4/CN=Users,DC=dev,DC=local");
DirectoryEntries entries = entry.Children;
foreach (DirectoryEntry members in entries)
{
if (members.Name.IndexOf("Some User Name") >= 0)
{
if (members.Properties.Contains("mail"))
{
foreach (object obj in members.Properties["mail"])
{
mail = obj.ToString();
}
}
}
}
}
catch(Exception ex)
{
str = ex.Message;
}
You can do this a lot more simply if you skip searching a particular OU and use an LDAP filter instead. A new DirectoryEntry with no arguments to the constructor is equivalent to DC=dev,DC=local authenticated with the current Windows user to the current
domain. This also has the benefit of generating a lot less traffic by having the AD do the search for you and return only the matching result.
string emailAddress = null;
using (DirectoryEntry searchRoot = new DirectoryEntry())
using (DirectorySearcher userSearcher = new DirectorySearcher(searchRoot, @"(&(objectCategory=Person)(objectClass=user)(mail=*)(sAMAccountName=username))", new string[] { "cn", "sAMAccountName", "displayName", "givenName", "sn", "mail" }))
{
SearchResult user = userSearcher.FindOne();
if (user != null)
{
emailAddress = user.Properties["mail"][0].ToString());
}
}
I've also included some other properties of interest that it might be desirable to either search on instead of sAMAccountName or use with your code in the string array that specifies properties to retrieve. A property name does not have to appear in the properties to retrieve to be able to use it in the LDAP filter string.
If you do have to authenticate with a particular user or use a specific OU, it gets slightly more complicated.
private static string GetNearestDomainController()
{
string nearestDomainController = null;
using (Domain computerDomain = Domain.GetComputerDomain())
using (DomainController currentDomainController = computerDomain.FindDomainController())
{
nearestDomainController = currentDomainController.Name;
}
return nearestDomainController;
}
string emailAddress = null;
using (DirectoryEntry searchRoot = new DirectoryEntry("LDAP://" + GetNearestDomainController() + "/OU=People,DC=dev,DC=local"), username, password)
using (DirectorySearcher userSearcher = new DirectorySearcher(searchRoot, @"(&(objectCategory=Person)(objectClass=user)(mail=*)(sAMAccountName=username))", new string[] { "cn", "sAMAccountName", "displayName", "givenName", "sn", "mail" }))
{
SearchResult user = userSearcher.FindOne();
if (user != null)
{
emailAddress = user.Properties["mail"][0].ToString();
}
}
Obviously, if your computer isn't bound to the domain, GetComputerDomain won't work and you'll have to specify an LDAP host manually.
Also, if you're taking a parameter to use in the LDAP filter string from user input, it's wise to make sure that any characters special to LDAP are properly escaped. Here's an extension to the string class that makes it easy.
using System;
using System.Text.RegularExpressions;
/// <summary>
///
/// </summary>
public static class LdapFilterEscapeStringExtension
{
private static Regex escapeFilter = new Regex(@"([\," + Regex.Escape("\\#+<>;\"=(*)") + "])", RegexOptions.Compiled);
private static Regex unescapeFilter = new Regex(@"\\([\," + Regex.Escape(" \\#+<>;\"=(*)") + "])", RegexOptions.Compiled);
/// <summary>
/// Escapes special characters in a string to be used within an LDAP filter.
/// </summary>
/// <param name="inputString">The input string.</param>
/// <returns></returns>
public static string EscapeLdapFilterValue(this string inputString)
{
string escaped = inputString;
if (!string.IsNullOrEmpty(inputString))
{
escaped = escapeFilter.Replace(inputString, @"\$1");
if (inputString.StartsWith(" "))
{
escaped = @"\" + escaped;
}
if (inputString.EndsWith(" "))
{
escaped = escaped.Substring(0, escaped.Length - 1) + @"\ ";
}
}
return escaped;
}
/// <summary>
/// Unescapes special characters in a string to be used within an LDAP filter.
/// </summary>
/// <param name="inputString">The input string.</param>
/// <returns></returns>
public static string UnescapeLdapFilterValue(this string inputString)
{
string unescaped = inputString;
if (!string.IsNullOrEmpty(inputString))
{
unescaped = unescapeFilter.Replace(inputString, "$1");
}
return unescaped;
}
}
Member
42 Points
91 Posts
Constructing LDAP path string
Dec 11, 2005 05:46 PM|kram|LINK
I'm quite new to the AD side of things, but I have had a fair amount of experience with asp.net. Could someone please help me contruct my LDAP path string. Here's what I have so far...
DirectoryEntry entry = new DirectoryEntry(
"LDAP://192.168.109.4/OU=People,DC=dev,DC=com",
"dev\\user",
"password", AuthenticationTypes.Secure);
My domain is "Dev" and my username is "macumberm" and im not going to tell you my password ;)
But when I put in these correct detials, I get the error:
A referral was returned from the server
what does this mean?
What id the OU?
How do I find out what to put in each parameter in the path string, OU, DC etc...
any help would be gretly appreciated
Kram
Member
135 Points
1801 Posts
Re: Constructing LDAP path string
Dec 12, 2005 05:30 PM|dunnry|LINK
Try this:
DirectoryEntry root = new DirectoryEntry("LDAP://RootDSE");
using (root)
{
Console.WriteLine(root.Properties["defaultNamingContext"][0].ToString());
}
This should tell you what the base DN you should be using is (when you run it in the domain of course). Then you can construct the AdsPath from there. Once you have this value, you can find your user account for example. Just read the first post in this forum about common patterns and use the filter "(sAMAccountName=user)". It will tell you what the correct DN is for that user when you inspect the .Path property from either a SearchResult or a DirectoryEntry.
Weblog
The Book
LDAP Programming Help
Member
42 Points
91 Posts
Re: Constructing LDAP path string
Dec 12, 2005 07:28 PM|kram|LINK
Im getting this error:
The specified domain either does not exist or could not be contacted
What can that mean? I thought if i ran your code it would be smart enought to know the domain it is on...
Do I have to modify your code?
Thank you for your help
Member
135 Points
1801 Posts
Re: Constructing LDAP path string
Dec 13, 2005 09:11 AM|dunnry|LINK
If you tried running this with ASPNET, it would be a local account. The Locator service (which is contacted when using RootDSE), has no idea which domain (if any) to contact if it is contacted using a non-domain account.
If you cannot run this code locally on a domain machine (with a domain account), then you need to give it some more hints to tell it which domain you are looking for:
"LDAP://mydomain.com/RootDSE"
Of course, if you already knew your domain, I would not have given you this code since we can construct the proper DN string exactly when it is known.
Weblog
The Book
LDAP Programming Help
Member
42 Points
91 Posts
Re: Constructing LDAP path string
Dec 13, 2005 04:55 PM|kram|LINK
But I ran the code anyways, and what it gave me I wouldnt have told you correctly by the looks of things:
"DC=DEV,DC=local"
Is what it returned.
Member
135 Points
1801 Posts
Re: Constructing LDAP path string
Dec 14, 2005 09:52 AM|dunnry|LINK
Yep, those shifty AD admins do this a lot. So, are you set then?
Weblog
The Book
LDAP Programming Help
Member
42 Points
91 Posts
Re: Constructing LDAP path string
Dec 14, 2005 05:03 PM|kram|LINK
String str = "";
try
{
DirectoryEntry entry = new DirectoryEntry(
"LDAP://192.168.109.4/OU=People,DC=dev,DC=local",
"dev\\username",
"password", AuthenticationTypes.Secure);
using (entry)
{
if (entry.Properties.Contains("mail"))
{
foreach (object o in entry.Properties["mail"])
{
//iterate through each value in the 'mail' attribute as a string
str += o.ToString();
}
}
}
}
catch(Exception ex)
{
str = ex.Message;
}
but I get "There is no such object on the server"
I need to be able to read a users email given their username...
Member
135 Points
1801 Posts
Re: Constructing LDAP path string
Dec 15, 2005 09:54 AM|dunnry|LINK
Once you get that particular issue pointing to a non-existant object fixed (try using an LDAP browser to find this OU and get the string exactly), we can address the other issue that will trip you up: OU's don't have email addresses.
You are binding to a container that holds other objects and you are looking for an email address on the container. Instead, you should bind to the container, search for the objects that have email addresses you are interested in, and then iterate the email addresses.
So, you have 3 steps:
1. Bind to your container - you are almost there, but you need to address this first.
2. Search for your objects - you can read the first post in the forum called "Common Patterns" to show how to do this.
3. Iterate through the email addresses - you are close, but it will change slightly from
Weblog
The Book
LDAP Programming Help
Member
42 Points
91 Posts
Re: Constructing LDAP path string
Dec 15, 2005 04:50 PM|kram|LINK
what is ADAM? i dont know what you are refering to here, so probably not.
the IP is pointing to a domain controller, not my local machine.
Ill try to get the proper string then we'll go on to the next steps that you mentioned. Ill have a read of that thread you mentioned aswell.
Thanks for the help so far, I appreciate it greatly.
Member
42 Points
91 Posts
Re: Constructing LDAP path string
Dec 15, 2005 05:56 PM|kram|LINK
string mail = "";
try
{
DirectoryEntry entry = new DirectoryEntry("LDAP://192.168.109.4/CN=Users,DC=dev,DC=local");
DirectoryEntries entries = entry.Children;
foreach (DirectoryEntry members in entries)
{
if (members.Name.IndexOf("Some User Name") >= 0)
{
if (members.Properties.Contains("mail"))
{
foreach (object obj in members.Properties["mail"])
{
mail = obj.ToString();
}
}
}
}
}
catch(Exception ex)
{
str = ex.Message;
}
None
0 Points
1 Post
Re: Constructing LDAP path string
Jan 09, 2013 12:05 PM|JamieSee|LINK
You can do this a lot more simply if you skip searching a particular OU and use an LDAP filter instead. A new DirectoryEntry with no arguments to the constructor is equivalent to DC=dev,DC=local authenticated with the current Windows user to the current domain. This also has the benefit of generating a lot less traffic by having the AD do the search for you and return only the matching result.
I've also included some other properties of interest that it might be desirable to either search on instead of sAMAccountName or use with your code in the string array that specifies properties to retrieve. A property name does not have to appear in the properties to retrieve to be able to use it in the LDAP filter string.
If you do have to authenticate with a particular user or use a specific OU, it gets slightly more complicated.
Obviously, if your computer isn't bound to the domain, GetComputerDomain won't work and you'll have to specify an LDAP host manually.
Also, if you're taking a parameter to use in the LDAP filter string from user input, it's wise to make sure that any characters special to LDAP are properly escaped. Here's an extension to the string class that makes it easy.