如何从Active Directory获取用户的电子邮件地址?

29

我试图获取AD中用户的电子邮件地址,但没有成功。

String account = userAccount.Replace(@"Domain\", "");
DirectoryEntry entry = new DirectoryEntry();

try {
    DirectorySearcher search = new DirectorySearcher(entry);

    search.PropertiesToLoad.Add("mail");  // e-mail addressead

    SearchResult result = search.FindOne();
    if (result != null) {
        return result.Properties["mail"][0].ToString();
    } else {
        return "Unknown User";
    }
} catch (Exception ex) {
    return ex.Message;
}

有人能看到问题所在或指出正确的方向吗?

8个回答

48

免责声明:此代码并不搜索单一精确匹配,所以对于domain\j_doe,如果还存在类似命名的帐户,则可能返回domain\j_doe_from_external_department的电子邮件地址。如果这种行为不可取,则可以使用samAccountName过滤器代替下面使用的anr过滤器,或者对结果进行额外的过滤。

我已成功地使用了这个代码(其中 "account" 是用户登录名而不是域名(domain\account):

// get a DirectorySearcher object
DirectorySearcher search = new DirectorySearcher(entry);

// specify the search filter
search.Filter = "(&(objectClass=user)(anr=" + account + "))";

// specify which property values to return in the search
search.PropertiesToLoad.Add("givenName");   // first name
search.PropertiesToLoad.Add("sn");          // last name
search.PropertiesToLoad.Add("mail");        // smtp mail address

// perform the search
SearchResult result = search.FindOne();

3
是的,这对我也起作用了。是的,也需要调用语法...Response.Write(result.Properties["givenName"][0].ToString()); Response.Write("<br>"); Response.Write(result.Properties["sn"][0].ToString()); Response.Write("<br>"); Response.Write(result.Properties["mail"][0].ToString()); Response.Write("<br>"); Response.Write(FindName("gruberj")); - user95440
3
我不得不使用"(&(objectCategory=person)(objectClass=user)(anr=" + account + "))",因为当我只使用objectClass=user时,第一个结果是一台计算机。 - Matt
我刚刚把这个可以在我们域上运行的Gist放在了一起:https://gist.github.com/roufamatic/8442829 - roufamatic
4
上面查询语句中的“anr”代表“模糊名称解析”,因此进行模糊匹配。如果您想要精确匹配,请在代码中使用“sAMAccountName”而不是“anr”。 - Gareth
你可能也需要这个:与用户在AD中关联的所有属性列表 https://www.manageengine.com/products/ad-manager/help/csv-import-management/active-directory-ldap-attributes.html - George
显示剩余3条评论

27

你们工作太辛苦了:

// Look up the current user's email address
string eMail =  UserPrincipal.Current.EmailAddress;

3
UserPrincipal 是什么?它所在的命名空间和程序集是什么? - Kiquenet
3
很好,需要引用“System.DirectoryServices.AccountManagement”,并且不需要登录,因为当前已经登录。 - CooPzZ
3
你的帖子比原回答晚了8年,但是嘿,我现在正在寻找 - 所以我会选择1行而不是7行... - Ken
3
OP并没有询问如何找到当前用户的电子邮件地址,即使他们这样做了,也假定应用程序正在使用域身份验证。我翻译完毕。 - William
它在本地主机上运行正常,但一旦部署到IIS上就失败了!请注意此问题:https://dev59.com/Imgu5IYBdhLWcg3w3qx7 - DeveloperDan

3

这个怎么样?

public string GetEmailFromSamAccountName(string samAccountName, string domain="YOURCOMPANY")
{
   using (var principalContext = new PrincipalContext(ContextType.Domain, domain))
   {
      var userPrincipal = UserPrincipal.FindByIdentity(principalContext, samAccountName);
      return userPrincipal.EmailAddress;
   }
}

3
您可以尝试以下的GetUserEmail方法。如果您想要在MVC中查找已登录用户的电子邮件地址,则调用带有User.Identity.Name的GetUserEmail()函数即可。
using System.DirectoryServices;
using System.Linq;

public string GetUserEmail(string UserId)
    {

        var searcher = new DirectorySearcher("LDAP://" + UserId.Split('\\').First().ToLower())
        {
            Filter = "(&(ObjectClass=person)(sAMAccountName=" + UserId.Split('\\').Last().ToLower() + "))"
        };

        var result = searcher.FindOne();
        if (result == null)
            return string.Empty;

        return result.Properties["mail"][0].ToString();

    }

GetUserEmail(User.Identity.Name) //Get Logged in user email address

2

你忘记了一个过滤器。

在调用 FindOne 之前,请尝试添加以下内容:

search.Filter = String.Format("(sAMAccountName={0})", account);

在将值放入过滤器字符串之前,必须对其进行转义(参见http://tools.ietf.org/html/rfc4515#section-3 ff.)。 - Tomalak
我认为有更好的方法。您可以将搜索范围设置为 SearchScope.Base,这样搜索可能检索到的唯一对象就是您提供的根对象。我相信那时不需要任何显式过滤。 - Jonathan Gilbert

1
此外,您从哪里获取用户名(存储、用户输入、当前身份)?用户名可以轻松更改(重命名),但 SID/Windows 登录标识不会更改。因此,如果可能和/或需要设计方面的考虑,最好通过 SID 而不是 samaccountname 进行过滤/搜索...

1
你需要添加System.DirectoryServices.AccountManagement引用并在using语句中包含相同的引用。现在,您将可以访问当前用户的登录详细信息,如下所示,包括电子邮件地址。
string loginname = Environment.UserName;
string firstname = UserPrincipal.Current.GivenName;
string lastname = UserPrincipal.Current.Surname;
string name = UserPrincipal.Current.Name;
string eMail = UserPrincipal.Current.EmailAddress;

我认为他们并不是在询问当前用户 - 他们想要查找特定的用户 - - William

0

更新: 弗雷德里克解决了这个问题...

Jakob是对的。你需要过滤你的搜索。如果需要,你可以在那里做各种andor,但我认为sAMAccountName就足够了。你可能想启动ADSI工具(我认为它在资源包中),它让你像注册表一样遍历AD。它非常适合查看属性。然后找到一个用户,确定你想要的属性(在这种情况下是邮件)以及它的primary key是什么 - sAMAccountName是一个好选择,但你也可能想要过滤节点类型。

我用的是Mac,所以不能为你检查,但AD中的每个节点都有一个类型,你可以将其添加到你的过滤器中。我认为它看起来像这样:

((sAMAccountName=bob) & (type=User))

再次确认一下 - 我知道它不是type=user,但类似于那个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接