I'm trying to get the e-mail adresses of all user's in our company domain.
99% work but sometimes there is y NullReferenceException in my Output.
Code:
string dom = "mydomain";
System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry("LDAP://" + dom); //domain, user, password
System.DirectoryServices.DirectorySearcher ds = new System.DirectoryServices.DirectorySearcher(entry);
ds.Filter = ("(objectClass=User)");
int count = 1;
foreach (System.DirectoryServices.SearchResult resEnt in ds.FindAll())
{
try
{
System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
String email = de.Properties["mail"].Value.ToString();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
There might be a NullReferenceException in the line
String email = de.Properties["mail"].Value.ToString();
If in the Properties["mail"] returns a null value or its Value property is null, then the attempt to call ToString() will lead to an exception.
This will help in this case (C# 6 syntax)
String email = de.Properties["mail"]?.Value?.ToString();
or
String email = null;
if (de.Properties["mail"] != null && de.Properties["mail"].Value != null)
{
email = de.Properties["mail"].Value.ToString();
}
Related
I am using active directory and want a list of all users, basically in dotnet core. But I am receiving an exception:
Search result reference received, and referral following is off
Below is my code.
LdapSearchResults lsc = lc.Search("DC = xyz, DC = local", LdapConnection.SCOPE_ONE , "(|(objectClass = person)(objectClass = user))", null, false);
Necromancing - just in case the links go dark.
To fix it in your application, set ReferralFollowing to true.
if you get the message
Search result reference received, and referral following is off
, add
Novell.Directory.Ldap.LdapSearchConstraints cons = lc.SearchConstraints;
cons.ReferralFollowing = true;
lc.Constraints = cons;
to your code.
Example:
public static void GetUsers()
{
System.Collections.Generic.List<ARSoft.Tools.Net.Dns.SrvRecord> lsLdap = GetLdap();
ARSoft.Tools.Net.Dns.SrvRecord ldap = lsLdap[0];
string[] attrs = new string[] { "cn", "distinguishedName", "sAMAccountName", "userPrincipalName", "displayName", "givenName", "sn", "mail", "mailNickname", "memberOf", "homeDirectory", "msExchUserCulture" };
// CN = Common Name
// OU = Organizational Unit
// DC = Domain Component
string searchBase = "DC=cor,DC=local";
string searchFilter = "(&(objectClass=user)(objectCategory=person))";
string ldapHost = MySamples.TestSettings.ldapHost;
int ldapPort = MySamples.TestSettings.ldapPort;//System.Convert.ToInt32(args[1]);
string loginDN = MySamples.TestSettings.loginDN; // args[2];
string password = MySamples.TestSettings.password; // args[3];
Novell.Directory.Ldap.LdapConnection lc = new Novell.Directory.Ldap.LdapConnection();
int ldapVersion = Novell.Directory.Ldap.LdapConnection.Ldap_V3;
try
{
// connect to the server
lc.Connect(ldap.Target.ToString(), ldap.Port);
// bind to the server
lc.Bind(ldapVersion, loginDN, password);
Novell.Directory.Ldap.LdapSearchConstraints cons = lc.SearchConstraints;
cons.ReferralFollowing = true;
lc.Constraints = cons;
// To enable referral following, use LDAPConstraints.setReferralFollowing passing TRUE to enable referrals, or FALSE(default) to disable referrals.
Novell.Directory.Ldap.LdapSearchResults lsc = lc.Search(searchBase,
Novell.Directory.Ldap.LdapConnection.SCOPE_SUB,
searchFilter,
attrs,
false,
(Novell.Directory.Ldap.LdapSearchConstraints)null);
while (lsc.HasMore())
{
Novell.Directory.Ldap.LdapEntry nextEntry = null;
try
{
nextEntry = lsc.Next();
}
catch (Novell.Directory.Ldap.LdapReferralException eR)
{
// https://stackoverflow.com/questions/46052873/ldap-referal-error
// The response you received means that the directory you are requesting does not contain the data you look for,
// but they are in another directory, and in the response there is the information about the "referral" directory
// on which you need to rebind to "redo" the search.This principle in LDAP are the referral.
// https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bp31k5d.html
// To enable referral following, use LDAPConstraints.setReferralFollowing passing TRUE to enable referrals, or FALSE (default) to disable referrals.
// are you sure your bind user meaning
// auth.impl.ldap.userid=CN=DotCMSUser,OU=Service Accounts,DC=mycompany,DC=intranet
// auth.impl.ldap.password = mypassword123
// has permissions to the user that is logging in and its groups?
System.Diagnostics.Debug.WriteLine(eR.LdapErrorMessage);
}
catch (Novell.Directory.Ldap.LdapException e)
{
// WARNING: Here catches only LDAP-Exception, no other types...
System.Console.WriteLine("Error: " + e.LdapErrorMessage);
// Exception is thrown, go for next entry
continue;
}
var atCN = nextEntry.getAttribute("cn");
var atUN = nextEntry.getAttribute("sAMAccountName");
var atDN = nextEntry.getAttribute("distinguishedName");
var atDIN = nextEntry.getAttribute("displayName");
if (atCN != null)
System.Console.WriteLine(atCN.StringValue);
if (atUN != null)
System.Console.WriteLine(atUN.StringValue);
if (atDN != null)
System.Console.WriteLine(atDN.StringValue);
if (atDIN != null)
System.Console.WriteLine(atDIN.StringValue);
System.Console.WriteLine("\n" + nextEntry.DN);
Novell.Directory.Ldap.LdapAttributeSet attributeSet = nextEntry.getAttributeSet();
System.Collections.IEnumerator ienum = attributeSet.GetEnumerator();
while (ienum.MoveNext())
{
Novell.Directory.Ldap.LdapAttribute attribute = (Novell.Directory.Ldap.LdapAttribute)ienum.Current;
string attributeName = attribute.Name;
string attributeVal = attribute.StringValue;
System.Console.WriteLine(attributeName + "value:" + attributeVal);
}
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
}
finally
{
// disconnect with the server
lc.Disconnect();
}
}
You have to activate the behaviour which will follow the referral returned by the directory.
The response you received means that the directory you are requesting does not contain the data you look for, but they are in another directory, and in the response there is the information about the "referral" directory on which you need to rebind to "redo" the search. This principle in LDAP are the referral.
I don't know how to do it in C#, but maybe have a look at :
https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bp31k5d.html
Please help me, I'm facing a fatal problem here. If someone could fix this, I swear I will treat u to a huge drink whenever u step into my country (Vietnam). Ok here's the problem: I'm coding a webservice for multi connection simultaneously from tablet (around 100 clients). It ran well but recently whenever high traffic occurs, my webservice seems to stuck somehow and I need to copy - override the published file of webservice in order for it to run again (restart website in IIS is no use) ...
This is my w/s code for handling the data:
public string Info_Handling(string id, string name, string strDetails)
{
string checkExist = "";
string str = "";
string str2 = "";
MLL_Customer _customerClient = new MLL_Customer();
MLL_CustomerCategory _categoryClient = new MLL_CustomerCategory();
MLL_Product _productClient = new MLL_Product();
MLL_SampleProduct _sampleClient = new MLL_SampleProduct();
if (_customerClient.CheckExistCustomer(id, name.ToUpper(), 2) == 1) // SID & NAME
{
checkExist = "EXIST";
}
using (SqlConnection connection = new SqlConnection(ConfigurationSettings.AppSettings["Main.ConnectionString"]))
{
connection.Open();
SqlTransaction trans = connection.BeginTransaction("XXX");
try
{
// ID Example: 11 means VIP - 12 means Normal - 13 means ples... jkg
// First - Insert Customer
string strCustomerCategory = _categoryClient.SelectCategoryByID(id).ToString();
if (!checkExist.Equals("EXIST"))
{
Customer businessObject = new Customer();
businessObject.ID = sid;
businessObject.Name = name.ToUpper();
businessObject.CategoryID = strCustomerCategory;
str = "" + _customerClient.Insert(businessObject, connection, trans);
}
// Second Insert Product spliting from a string Ex: "TV&Laptop&CD"
string[] productDetails = strDetails.Split(new char[] { '&' });
object obj3;
SampleProduct objSample;
Product objProduct;
for (int j = 0; j < productDetails.Length; j++)
{
if (_productClient.CheckExist(id, productDetails[j])) == null) // Check if customer already owns this product
{
// Get the properties of sample product.
objSample = _sampleClient.SelectSampleProduct(productDetails[j]);
objProduct = new Product();
objProduct.SID = sid;
objProduct.Testcode = objSample.TestCode;
objProduct.Category = objSample.Category;
objProduct.Unit = objSample.Unit;
objProduct.Price = objSample.Price;
if (_productClient.Insert(objProduct, connection, trans) != 0)
{
str2 = str2 + "&" + objProduct.Testcode;
// return the code of product in order to see which product has been inserted successfully
}
}
}
trans.Commit();
SqlConnection.ClearAllPools();
}
catch (Exception exception)
{
str = "0";
str2 = exception.Message + exception.Source;
try
{
trans.Rollback();
}
catch (Exception)
{
}
}
}
if (!str2.Equals(""))
{
return (str + "&" + id + str2);
}
return ("0&" + sid + str);
}
I modified the code but this is basically how i roll. Could anyone plz tell me some solution. Deeply thank u.
1 more thing about ClearAllPools() method: I know how it works but I dont even know why I need it. Without this, my data will be messed up terrible. CategoryID of one customer will be assigned for another customer sometimes. ???? How could it happened ?? HELP
Am doing a workflow cheching in which i have 2 values and the when the foreach condition is checked only one time it enters the loop and exits out without going to the next one.
public CustomBusinessServices InvokeWorkFlowPermissionBusinessRule(dynamic workFlowImplemented, out string serviceName, out int permissionId)
{
try
{
List<WorkflowEligibilityMapping> workFlowPermissionService = new List<WorkflowEligibilityMapping>();// to handle null values
int current_ControllerId = Convert.ToInt32(workFlowImplemented); //ControllerId
using (var db = new AdminDb())
{
//to select services against this controller
workFlowPermissionService = (from definition in db.WorkFlowDefinition.AsNoTracking()
join model in db.WorkFlowModel.AsNoTracking()
on definition.WorkFlowDefinitionId equals model.WorkFlowDefinitionId
join permission in db.WorkFlowPermission.AsNoTracking()
on model.WorkFlowDefinitionId equals permission.WorkFlowDefinitionId
where model.ControllerNameId.Equals(current_ControllerId)
select new WorkflowEligibilityMapping
{
Service = permission.Service,
WorkFlowPermissionId = permission.WorkFlowPermissionId
}).ToList();
}
int[] workFlowServiceDetails = workFlowPermissionService.Select(x => x.WorkFlowPermissionId).ToArray();
//to Login userId
var userId = Assyst.PanERP.Common.AppSession.Common.UserID;
/*******************Issue in foreach i think**************************************/
foreach (int workFlowServiceDetail in workFlowServiceDetails)
/*******workFlowServiceDetails have 2 valus********/
{
using (var db = new AdminDb())
{
string workFlowServiceDtl = (from perm in db.WorkFlowPermission.AsNoTracking()
where perm.WorkFlowPermissionId == workFlowServiceDetail
select perm.Service).FirstOrDefault();
//to select eligibility rules against this service
string eligibility = (from definition in db.WorkFlowDefinition.AsNoTracking()
join model in db.WorkFlowModel.AsNoTracking()
on definition.WorkFlowDefinitionId equals model.WorkFlowDefinitionId
join permission in db.WorkFlowPermission.AsNoTracking()
on model.WorkFlowDefinitionId equals permission.WorkFlowDefinitionId
where model.ControllerNameId.Equals(current_ControllerId) && permission.WorkFlowPermissionId == workFlowServiceDetail
select permission.EligibilityRule).FirstOrDefault();
if (eligibility == null)
{
string validationMessage = "";
validationMessage = "Please set eligibility for workflow permission";
serviceName = null;
permissionId = 0;
return new CustomBusinessServices() { strMessage = validationMessage };
}
string[] strTxt = workFlowServiceDtl.Split(';'); //split the service name by ';' and strore it in an array
string serviceUrl = string.Empty;
string workFlowServiceName = string.Empty;
string classpath = string.Empty;
workFlowServiceName = strTxt[0].ToString();
workFlowServiceName = workFlowServiceName.Replace(" ", "");//get the service name by removing empty blank space for the word
classpath = strTxt[1].ToString();
//Invoke REST based service (like Node.Js service)
if (strTxt.Length == 4)
{
serviceUrl = strTxt[3].ToString();
}
//Invoke c# based service
else
{
serviceUrl = string.Empty;
}
var userLists = PermissionCallMethod(classpath, workFlowServiceName, new[] { workFlowImplemented, eligibility }, serviceUrl);
if (userLists.UserList.Contains(userId))
{
serviceName = strTxt[0].ToString() + ";Assyst.PanERP.Common.WorkFlowNotificationServices;" + strTxt[2].ToString();
permissionId = workFlowServiceDetail;
return userLists;
}
}
}
serviceName = string.Empty;
permissionId = 0;
return null;
}
catch (Exception ex)
{
throw ex;
return null;
}
}
workFlowServiceDetails have 2 values and the workFlowServiceDetail takes the first one and checks for it.goes through the loop and mapes the role for the first one to the user list at the end and the without checking the for the second vale it moves out of the loop. Please help me to make the loop work for 2 values.Is it some problem in the return part...?
if (eligibility == null)
{
string validationMessage = "";
validationMessage = "Please set eligibility for workflow permission";
serviceName = null;
permissionId = 0;
return new CustomBusinessServices() { strMessage = validationMessage };
}
if (userLists.UserList.Contains(userId))
{
serviceName = strTxt[0].ToString() + ";Assyst.PanERP.Common.WorkFlowNotificationServices;" + strTxt[2].ToString();
permissionId = workFlowServiceDetail;
return userLists;
}
If any of the above if statements evaluates to true, your loop will exit without looping through the second item in your array. The reason for this is that you are in your first conditional check do the following:
return new CustomBusinessServices() { strMessage = validationMessage };
And in your second:
return userLists;
The return statement will exit your method, and therefore terminate the foreach as well.
Try building your object first, and after your loop has walked through each item, do a return statement returning your object.
I am a new web developer and in my company all the ASP.NET applications rely on a system that pulls down the user information from the SAP system and retrieve them as a XML document. This system has only one textbox for inserting the username to retrieve his information. An example of it:
If you insert the username: johnA
the system will provide you with the following information:
John
Arneson
Elli
and so on.
Then, in the ASP.NET web-based applications, we used to use three C# classes that does the connections with this system and helpes in getting the specific user information from that system.
Anyway, Now we want to replace that system with a new system that gets the user information from the Active Directory.
I put the following code in the server and it works well, so when the employee goes to this code in our server, he will see a page that shows all of his information. What I want to do right now is utilizing this in all our developed and the next new-developed web-based applications by putting a TextBox to put the username of the user and retrieve of all of his information from this system. So how to do that?
I am a beginner and I could not be able to find a way for doing this in Google or anywhere else.
My code of the class for accessing the Active Directory is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.DirectoryServices;
/// <summary>
/// Summary description for ActiveDirectory
/// </summary>
public class ActiveDirectory
{
public static string GetPersonData(string id, string datatype)
{
//return "x xx xxxx xxx xxx"; //comment this line.
//Faster performance through Active Directory
string property = datatype;
switch (property) //backwards compatibility
{
/* case "tel":
return FindProperty(id, Property.Tel);*/
case "name":
return FindProperty(id, Property.Name);
case "dept":
return FindProperty(id, Property.Dept);
case "line":
return FindProperty(id, Property.Line);
case "email":
return FindProperty(id, Property.Email);
case "id":
return FindProperty(id, Property.Name);
default:
return "";
}
}
//ACTIVE DIRECTORY OPTION.. FOR A BETTER PERFORMANCE
const string ID = "cn";
const string NAME = "displayName";
const string TEL = "telephoneNumber";
const string DEPT = "department";
const string LINE = "extensionAttribute3";
const string UNIT = "extensionAttribute10";
const string TITLE = "title";
const string FNAME = "givenName";
const string MNAME = "initials";
const string LNAME = "sn";
const string EMAIL = "mail";
const string AREA = "extensionAttribute3";
const string MANAGER = "manager";
const string ORGCODE = "extensionAttribute10";
const string DN = "distinguishedName";
public enum Property
{
Name, Tel, Dept, Line, Unit, Title, Fname, Mname, Lname, Email, Manager, OrgCode, DistinguishedName
}
public static DirectoryEntry GetDirectoryEntry()
{
using (((System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
{
DirectoryEntry de = new DirectoryEntry(); //DirectoryEntry class encapsulates a node or object in the AD hierarchy
de.Path = "LDAP://CompanyName.COM";
de.AuthenticationType = AuthenticationTypes.Delegation;
return de;
}
}
public static bool UserExists(string username)
{
DirectoryEntry de = GetDirectoryEntry();
DirectorySearcher deSearch = new DirectorySearcher(); //Directory Searcher: It will perform queries against the active directory hierarchy
deSearch.SearchRoot = de; //SearchRoot is used to specify where the search starts
deSearch.Filter = "(&(objectClass=user) (cn=" + username + "))"; //the search retrieves all objects.
// Create a SearchResultCollection object to hold a collection of SearchResults
// returned by the FindAll method.
SearchResultCollection results = deSearch.FindAll();
return results.Count > 0;
}
public static String FindName(String userAccount)
{
DirectoryEntry entry = GetDirectoryEntry();
String account = userAccount.Replace(#"Domain\", "");
try
{
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + account + ")";
search.PropertiesToLoad.Add("displayName");
SearchResult result = search.FindOne();
if (result != null)
{
return result.Properties["displayname"][0].ToString();
}
else
{
return "Unknown User";
}
}
catch (Exception ex)
{
string debug = ex.Message;
return debug;
}
}
public static String FindProperty(String userAccount, Property p)
{
string property = "";
//proceed with LDAP search.
switch (p)
{
case Property.Dept:
property = DEPT;
break;
case Property.Email:
property = EMAIL;
break;
case Property.Fname:
property = FNAME;
break;
case Property.Line:
property = LINE;
break;
case Property.Lname:
property = LNAME;
break;
case Property.Mname:
property = MNAME;
break;
case Property.Name:
property = NAME;
break;
case Property.Tel:
property = TEL;
break;
case Property.Title:
property = TITLE;
break;
case Property.Unit:
property = UNIT;
break;
case Property.Manager:
property = MANAGER;
break;
case Property.OrgCode:
property = ORGCODE;
break;
case Property.DistinguishedName:
property = DN;
break;
default:
return "";
}
DirectoryEntry entry = GetDirectoryEntry();
String account = userAccount.Replace(#"Domain\", "");
try
{
System.Text.Encoding enc = System.Text.Encoding.ASCII;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectCategory=user)(SAMAccountName=" + account + "))";
search.PropertiesToLoad.Add(property);
SearchResult result = search.FindOne();
search.Dispose();
entry.Close();
entry.Dispose();
if (result != null)
{
object value = result.Properties[property][0];
if (value is System.Byte[])
return enc.GetString((byte[])value);
else
return value.ToString();
}
else
{
return "-";
}
}
catch (Exception ex)
{
string debug = ex.Message;
return "debug";
}
}
public static List<string> FindChildren(string userAccount)
{
DirectoryEntry entry = GetDirectoryEntry();
String account = userAccount.Replace(#"Domain\", "");
string dn = FindProperty(userAccount, Property.DistinguishedName);
dn.Replace("*","\\2a");
dn.Replace("(", "\\28");
dn.Replace(")", "\\29");
dn.Replace("\\", "\\5c");
dn.Replace("NUL", "\\00");
dn.Replace("/", "\\2f");
string property = ID;
List<string> output = new List<string>();
try
{
System.Text.Encoding enc = System.Text.Encoding.ASCII;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectCategory=user)(manager=" + dn + "))";
search.PropertiesToLoad.Add(property);
SearchResultCollection results = search.FindAll();
search.Dispose();
entry.Close();
entry.Dispose();
if (results != null)
{
foreach (SearchResult result in results)
{
object value = result.Properties[property][0];
if (value is System.Byte[])
output.Add(enc.GetString((byte[])value));
else
output.Add(value.ToString());
}
}
}
catch (Exception ex)
{
throw ex;
}
return output;
}
public static string FindOrg(string orgcode, string property)
{
DirectoryEntry entry = GetDirectoryEntry();
try
{
System.Text.Encoding enc = System.Text.Encoding.ASCII;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectCategory=user)(" + ORGCODE + "=" + orgcode + "*))";
search.PropertiesToLoad.Add(property);
SearchResult result = search.FindOne();
search.Dispose();
entry.Close();
entry.Dispose();
if (result != null)
{
object value = result.Properties[property][0];
if (value is System.Byte[])
return enc.GetString((byte[])value);
else
return value.ToString();
}
else
{
return "-";
}
}
catch (Exception ex)
{
string debug = ex.Message;
return "debug";
}
}
}
UPDATE:
For your information, the above classes are on the server. Now, I am developing a new web-based application. And in this web-based application, I have a textbox that I will use to enter the username. So how I will be able to send this username to that system and retrieve the user information for it to this application? Could you please provide me with an example?
Ok understand now what you really need. The best way for this to be accomplish is by using asp.net webservices. What this means is that you must make some edits to your code that is currently running on your server.
Please look up Asp.net Web Services and check out these links: Microsoft Web Services weblink and Create and Use ASP.NET Web Service
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// do something here....
}
// find the group in question
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, "YourGroupNameHere");
// if found....
if (group != null)
{
// iterate over members
foreach (Principal p in group.GetMembers())
{
Console.WriteLine("{0}: {1}", p.StructuralObjectClass, p.DisplayName);
// do whatever you need to do to those members
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
And as "Nation" mentioned in his response, if you "hide" this behind a web service interface, then all sorts of applications can call into your code and get the information they need out of Active Directory!
I'm attempting to get the email address typed into the To field of a compose mail window.
I try to get the Address property of a Recipient, which according to VS, should give me the email.
I am instead receiving a string that looks like this:
"/c=US/a=att/p=Microsoft/o=Finance/ou=Purchasing/s=Furthur/g=Joe"
How can I get the email address in the recipient field?
My code so far:
List <string> emails = new List<string>();
if (thisMailItem.Recipients.Count > 0)
{
foreach (Recipient rec in thisMailItem.Recipients)
{
emails.Add(rec.Address);
}
}
return emails;
Can you try this ?
emails.Add(rec.AddressEntry.Address);
Reference link
EDIT:
I don't have the right environment to test so I'm just guessing all this, but how about
string email1Address = rec.AddressEntry.GetContact().Email1Address;
or .Email2Adress or .Email3Address
Also there is,
rec.AddressEntry.GetExchangeUser().Address
that you might want to try.
Try this
private string GetSMTPAddressForRecipients(Recipient recip)
{
const string PR_SMTP_ADDRESS =
"http://schemas.microsoft.com/mapi/proptag/0x39FE001E";
PropertyAccessor pa = recip.PropertyAccessor;
string smtpAddress = pa.GetProperty(PR_SMTP_ADDRESS).ToString();
return smtpAddress;
}
This is available on MSDN here
I have used the same way to get email addresses in my application and its working.
the AddressEntry also has an SMTPAddress property that exposes the primary smtp adress of the user.
I don't know if this helps or how accurate
it is, a sample
private string GetSmtp(Outlook.MailItem item)
{
try
{
if (item == null || item.Recipients == null || item.Recipients[1] == null) return "";
var outlook = new Outlook.Application();
var session = outlook.GetNamespace("MAPI");
session.Logon("", "", false, false);
var entryId = item.Recipients[1].EntryID;
string address = session.GetAddressEntryFromID(entryId).GetExchangeUser().PrimarySmtpAddress;
if (string.IsNullOrEmpty(address))
{
var rec = item.Recipients[1];
var contact = rec.AddressEntry.GetExchangeUser();
if (contact != null)
address = contact.PrimarySmtpAddress;
}
if (string.IsNullOrEmpty(address))
{
var rec = item.Recipients[1];
var contact = rec.AddressEntry.GetContact();
if (contact != null)
address = contact.Email1Address;
}
return address;
}
finally
{
}
}