Get recipient's email address

  • Thread starter Thread starter Mark B
  • Start date Start date
M

Mark B

VSTO, OL2007, C#

From our Add-in, most of the time mail.Recipients[1].Address works to return
the recipients email address as say (e-mail address removed)

However, I noticed the following was returned for mail.Recipients[1].Address
this morning from one site instead of an email address:

/O=COMPANY1/OU=FIRST ADMINISTRATIVE GROUP/CN=RECIPIENTS/CN=SMITH

I assume it has got something to do with the user being on exchange? Is
there anyway to simply get the email address?
 
Yes, that's an Exchange DN type address (an Exchange Distinguished Name).

If the recipient is in the GAL or a contact item you can use this type of
code to get at the SMTP address:

string recipSMTP =
mail.Recipients[1].AddressEntry.GetExchangeUser.PrimarySmtpAddress;

Otherwise you need to access some MAPI properties using PropertyAccessor.
Which property to access depends on whether or not cached Exchange mode is
being used or not. If a direct connection is used you can get the
Recipient.AddressEntry.PropertyAccessor object and use the PR_SMTP_ADDRESS
property tag with it, if cached mode is used you would need to use the
PR_EMS_AB_PROXY_ADDRESSES property tag.

const int PR_SMTP_ADDRESS = 0x39FE001E;
const int PR_EMS_AB_PROXY_ADDRESSES = 0x800F101E;

For use with PropertyAccessor you would use a DASL property tag, which would
look like this:

"http://schemas.microsoft.com/mapi/proptag/" + PR_SMTP_ADDRESS.ToString();
// or the other tag
 
I haven't got Exchange here to test it out on so if you can see anything
wrong with the following code I'd be grateful for any corrections:


namespace MyApp1.GetRecipientEmailAddress
{
class cGetRecipientEmailAddress
{
const int PR_SMTP_ADDRESS = 0x39FE001E;
const int PR_EMS_AB_PROXY_ADDRESSES = (int) 0x800F101E;

/// <summary>
/// Get recipient email address in (e-mail address removed) format even if on
Exchange.
/// </summary>
/// <returns></returns>
public string
mGetEmailAddress(Microsoft.Office.Interop.Outlook.Recipients objRecipients)
{

//See if normal email address
if (objRecipients[1].Address.Contains("@"))
{
return objRecipients[1].Address;
}

//See if Exchange user has email address
string strExchangeSMTPEmailAddress
=objRecipients[1].AddressEntry.GetExchangeUser().PrimarySmtpAddress;
if (strExchangeSMTPEmailAddress.Contains("@"))
{
return strExchangeSMTPEmailAddress;
}

//Access MAPI property
string
strMAPIEmailAddress=objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"+
PR_SMTP_ADDRESS.ToString()) as string;
if (strMAPIEmailAddress.Contains("@"))
{
return strMAPIEmailAddress;
}

//Access MAPI property (proxy)
string strMAPIEmailAddressProxy =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_EMS_AB_PROXY_ADDRESSES.ToString()) as string;
if (strMAPIEmailAddressProxy.Contains("@"))
{
return strMAPIEmailAddressProxy;
}

//Return null
return null;
}
}
}



Ken Slovak - said:
Yes, that's an Exchange DN type address (an Exchange Distinguished Name).

If the recipient is in the GAL or a contact item you can use this type of
code to get at the SMTP address:

string recipSMTP =
mail.Recipients[1].AddressEntry.GetExchangeUser.PrimarySmtpAddress;

Otherwise you need to access some MAPI properties using PropertyAccessor.
Which property to access depends on whether or not cached Exchange mode is
being used or not. If a direct connection is used you can get the
Recipient.AddressEntry.PropertyAccessor object and use the PR_SMTP_ADDRESS
property tag with it, if cached mode is used you would need to use the
PR_EMS_AB_PROXY_ADDRESSES property tag.

const int PR_SMTP_ADDRESS = 0x39FE001E;
const int PR_EMS_AB_PROXY_ADDRESSES = 0x800F101E;

For use with PropertyAccessor you would use a DASL property tag, which
would look like this:

"http://schemas.microsoft.com/mapi/proptag/" + PR_SMTP_ADDRESS.ToString();
// or the other tag




Mark B said:
VSTO, OL2007, C#

From our Add-in, most of the time mail.Recipients[1].Address works to
return the recipients email address as say (e-mail address removed)

However, I noticed the following was returned for
mail.Recipients[1].Address this morning from one site instead of an email
address:

/O=COMPANY1/OU=FIRST ADMINISTRATIVE GROUP/CN=RECIPIENTS/CN=SMITH

I assume it has got something to do with the user being on exchange? Is
there anyway to simply get the email address?
 
I'd probably check for "cn=" rather than "@", but "@" will probably work.

You need to use PR_SMTP_ADDRESS when it's not cached mode and use
PR_EMS_AB_PROXY_ADDRESSES when it is. You can check that using
ExchangeConnectionMode and interpreting the result as a member of the
OlExchangeConnectionMode enum. If it's one f the cached settings you use
PR_EMS_AB_PROXY_ADDRESSES. Some of them indicate you won't get a result
(disconnected or offline).

PR_EMS_AB_PROXY_ADDRESSES is what's known as a PR_MV_STRING8 property, it's
an array of strings. There may be 1 or more entries there but you have to
get the results of reading the property as a string array and parse the
array. A result with a capitalized "SMTP:" is the default SMTP address, any
with "smtp:" are alternates.

In addition, I'm not sure if PR_EMS_AB_PROXY_ADDRESSES will compile with the
declaration as it is. You might have to use this construct for the
declaration:

const int PR_EMS_AB_PROXY_ADDRESSES = unchecked((int)0x800F101E);

One tip, if you plan to do a lot with things like DASL and MAPI property
tags you might want to get a MAPI viewer. MFCMAPI is a free one from MS, I
personally use OutlookSpy (www.dimastr.com). A viewer will show the
properties of items, folders, stores, etc. and will show the prop tags for
you.

Another tip is what I said earlier. Avoid concatenated dot operators. They
create internal objects that you cannot explicitly release, which can lead
to memory leaks and other problems. Instead of something like
mail.Recipients[1].Address, use an explicit Recipients collection and an
explicit Recipient object. That way you can release the objects as needed
and when in loops avoid the 256 RPC channel errors. You also always declare
COM objects outside of loops for the same reason: only 1 object created and
you can explicitly release it as needed.




Mark B said:
I haven't got Exchange here to test it out on so if you can see anything
wrong with the following code I'd be grateful for any corrections:


namespace MyApp1.GetRecipientEmailAddress
{
class cGetRecipientEmailAddress
{
const int PR_SMTP_ADDRESS = 0x39FE001E;
const int PR_EMS_AB_PROXY_ADDRESSES = (int) 0x800F101E;

/// <summary>
/// Get recipient email address in (e-mail address removed) format even if on
Exchange.
/// </summary>
/// <returns></returns>
public string
mGetEmailAddress(Microsoft.Office.Interop.Outlook.Recipients
objRecipients)
{

//See if normal email address
if (objRecipients[1].Address.Contains("@"))
{
return objRecipients[1].Address;
}

//See if Exchange user has email address
string strExchangeSMTPEmailAddress
=objRecipients[1].AddressEntry.GetExchangeUser().PrimarySmtpAddress;
if (strExchangeSMTPEmailAddress.Contains("@"))
{
return strExchangeSMTPEmailAddress;
}

//Access MAPI property
string
strMAPIEmailAddress=objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"+
PR_SMTP_ADDRESS.ToString()) as string;
if (strMAPIEmailAddress.Contains("@"))
{
return strMAPIEmailAddress;
}

//Access MAPI property (proxy)
string strMAPIEmailAddressProxy =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_EMS_AB_PROXY_ADDRESSES.ToString()) as string;
if (strMAPIEmailAddressProxy.Contains("@"))
{
return strMAPIEmailAddressProxy;
}

//Return null
return null;
}
}
}
 
Hopefully the code below will work. I tried to remove all dot concatenation
but think you might be referring to my earlier code.

using Outlook=Microsoft.Office.Interop.Outlook;

namespace MYAPP.GetRecipientEmailAddress
{
class cGetRecipientEmailAddress
{
const int PR_SMTP_ADDRESS = 0x39FE001E;
const int PR_EMS_AB_PROXY_ADDRESSES = unchecked((int)0x800F101E);

/// <summary>
/// Get recipient email address in (e-mail address removed) format even if on
Exchange.
/// </summary>
/// <returns></returns>
public string mGetEmailAddress(Outlook.Recipients objRecipients)
{

//See if normal email address
if (objRecipients[1].Address.Contains("@"))
{
return objRecipients[1].Address;
}

//See if Exchange user is in GAL or contact item and has email
address
string strExchangeSMTPEmailAddress = "";
try
{
strExchangeSMTPEmailAddress =
objRecipients[1].AddressEntry.GetExchangeUser().PrimarySmtpAddress;
}
catch { }

if (strExchangeSMTPEmailAddress.Contains("@"))
{
return strExchangeSMTPEmailAddress;
}

//Not in GAL, try to access MAPI property
switch (fIsInExchangeCachedMode())
{
case false: //Direct Mode
{
string strMAPIEmailAddress = "";
try
{
strMAPIEmailAddress =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_SMTP_ADDRESS.ToString()) as string;
}
catch { }

if (strMAPIEmailAddress.Contains("@"))
{
return strMAPIEmailAddress;
}
break;
}

case true: //Cached Mode
{
//Access MAPI property (proxy)
string[] strMAPIEmailAddressProxy = null;

try
{
strMAPIEmailAddressProxy =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_EMS_AB_PROXY_ADDRESSES.ToString()) as string[];
foreach (string strItem in
strMAPIEmailAddressProxy)
{
if (strItem.Contains("SMTP:") &&
strItem.Contains("@"))
{
strItem.Replace("SMTP:", "");
strItem.Trim();
return strItem;
}
}
}
catch { }
break;
}
}
return null;
}


/// <summary>
/// Returns True if in Exchange Cached Mode
/// </summary>
/// <returns></returns>
public bool fIsInExchangeCachedMode()
{
switch
(Globals.ThisAddIn.Application.Session.ExchangeConnectionMode)
{
case
Outlook.OlExchangeConnectionMode.olCachedConnectedDrizzle: { return true;}
case Outlook.OlExchangeConnectionMode.olCachedConnectedFull:
{ return true;}
case
Outlook.OlExchangeConnectionMode.olCachedConnectedHeaders: { return true;}
case Outlook.OlExchangeConnectionMode.olCachedDisconnected:
{ return true;}
case Outlook.OlExchangeConnectionMode.olCachedOffline: {
return true;}
case Outlook.OlExchangeConnectionMode.olNoExchange: {
break; }
case Outlook.OlExchangeConnectionMode.olOffline: { break; }
case Outlook.OlExchangeConnectionMode.olOnline:{ break; }
}
return false;
}
}
}
 
Hi:

I guess the answer is sitting next to this post. Buy a Redemption
component.It saves me a lot of time.

Cheers,

Danny
 
Did you have a question, or are you showing your solution for the problem?




Mark B said:
Hopefully the code below will work. I tried to remove all dot
concatenation but think you might be referring to my earlier code.

using Outlook=Microsoft.Office.Interop.Outlook;

namespace MYAPP.GetRecipientEmailAddress
{
class cGetRecipientEmailAddress
{
const int PR_SMTP_ADDRESS = 0x39FE001E;
const int PR_EMS_AB_PROXY_ADDRESSES = unchecked((int)0x800F101E);

/// <summary>
/// Get recipient email address in (e-mail address removed) format even if on
Exchange.
/// </summary>
/// <returns></returns>
public string mGetEmailAddress(Outlook.Recipients objRecipients)
{

//See if normal email address
if (objRecipients[1].Address.Contains("@"))
{
return objRecipients[1].Address;
}

//See if Exchange user is in GAL or contact item and has email
address
string strExchangeSMTPEmailAddress = "";
try
{
strExchangeSMTPEmailAddress =
objRecipients[1].AddressEntry.GetExchangeUser().PrimarySmtpAddress;
}
catch { }

if (strExchangeSMTPEmailAddress.Contains("@"))
{
return strExchangeSMTPEmailAddress;
}

//Not in GAL, try to access MAPI property
switch (fIsInExchangeCachedMode())
{
case false: //Direct Mode
{
string strMAPIEmailAddress = "";
try
{
strMAPIEmailAddress =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_SMTP_ADDRESS.ToString()) as string;
}
catch { }

if (strMAPIEmailAddress.Contains("@"))
{
return strMAPIEmailAddress;
}
break;
}

case true: //Cached Mode
{
//Access MAPI property (proxy)
string[] strMAPIEmailAddressProxy = null;

try
{
strMAPIEmailAddressProxy =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_EMS_AB_PROXY_ADDRESSES.ToString()) as string[];
foreach (string strItem in
strMAPIEmailAddressProxy)
{
if (strItem.Contains("SMTP:") &&
strItem.Contains("@"))
{
strItem.Replace("SMTP:", "");
strItem.Trim();
return strItem;
}
}
}
catch { }
break;
}
}
return null;
}


/// <summary>
/// Returns True if in Exchange Cached Mode
/// </summary>
/// <returns></returns>
public bool fIsInExchangeCachedMode()
{
switch
(Globals.ThisAddIn.Application.Session.ExchangeConnectionMode)
{
case
Outlook.OlExchangeConnectionMode.olCachedConnectedDrizzle: { return true;}
case
Outlook.OlExchangeConnectionMode.olCachedConnectedFull: { return true;}
case
Outlook.OlExchangeConnectionMode.olCachedConnectedHeaders: { return true;}
case Outlook.OlExchangeConnectionMode.olCachedDisconnected:
{ return true;}
case Outlook.OlExchangeConnectionMode.olCachedOffline: {
return true;}
case Outlook.OlExchangeConnectionMode.olNoExchange: {
break; }
case Outlook.OlExchangeConnectionMode.olOffline: { break; }
case Outlook.OlExchangeConnectionMode.olOnline:{ break; }
}
return false;
}
}
}
 
Apologies. I was just showing it in case anyone saw something wrong with it
since my testing here is a bit limited since I don't have Exchange.

My assumption with this particular block of code here is that the format of
the string elements in PR_EMS_AB_PROXY_ADDRESSES is:

"SMTP:[email protected]"
"smtp:[email protected]"

since I extract the SMTP: bit. If that's not the case please let me know.


case true: //Cached Mode
{
//Access MAPI property (proxy)
string[] strMAPIEmailAddressProxy = null;

try
{
strMAPIEmailAddressProxy =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_EMS_AB_PROXY_ADDRESSES.ToString()) as string[];
foreach (string strItem in
strMAPIEmailAddressProxy)
{
if (strItem.Contains("SMTP:") &&
strItem.Contains("@"))
{
strItem.Replace("SMTP:", "");
strItem.Trim();
return strItem;
}
}
}
catch { }
break;





Ken Slovak - said:
Did you have a question, or are you showing your solution for the problem?




Mark B said:
Hopefully the code below will work. I tried to remove all dot
concatenation but think you might be referring to my earlier code.

using Outlook=Microsoft.Office.Interop.Outlook;

namespace MYAPP.GetRecipientEmailAddress
{
class cGetRecipientEmailAddress
{
const int PR_SMTP_ADDRESS = 0x39FE001E;
const int PR_EMS_AB_PROXY_ADDRESSES = unchecked((int)0x800F101E);

/// <summary>
/// Get recipient email address in (e-mail address removed) format even if on
Exchange.
/// </summary>
/// <returns></returns>
public string mGetEmailAddress(Outlook.Recipients objRecipients)
{

//See if normal email address
if (objRecipients[1].Address.Contains("@"))
{
return objRecipients[1].Address;
}

//See if Exchange user is in GAL or contact item and has email
address
string strExchangeSMTPEmailAddress = "";
try
{
strExchangeSMTPEmailAddress =
objRecipients[1].AddressEntry.GetExchangeUser().PrimarySmtpAddress;
}
catch { }

if (strExchangeSMTPEmailAddress.Contains("@"))
{
return strExchangeSMTPEmailAddress;
}

//Not in GAL, try to access MAPI property
switch (fIsInExchangeCachedMode())
{
case false: //Direct Mode
{
string strMAPIEmailAddress = "";
try
{
strMAPIEmailAddress =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_SMTP_ADDRESS.ToString()) as string;
}
catch { }

if (strMAPIEmailAddress.Contains("@"))
{
return strMAPIEmailAddress;
}
break;
}

case true: //Cached Mode
{
//Access MAPI property (proxy)
string[] strMAPIEmailAddressProxy = null;

try
{
strMAPIEmailAddressProxy =
objRecipients[1].AddressEntry.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/"
+ PR_EMS_AB_PROXY_ADDRESSES.ToString()) as string[];
foreach (string strItem in
strMAPIEmailAddressProxy)
{
if (strItem.Contains("SMTP:") &&
strItem.Contains("@"))
{
strItem.Replace("SMTP:", "");
strItem.Trim();
return strItem;
}
}
}
catch { }
break;
}
}
return null;
}


/// <summary>
/// Returns True if in Exchange Cached Mode
/// </summary>
/// <returns></returns>
public bool fIsInExchangeCachedMode()
{
switch
(Globals.ThisAddIn.Application.Session.ExchangeConnectionMode)
{
case
Outlook.OlExchangeConnectionMode.olCachedConnectedDrizzle: { return
true;}
case
Outlook.OlExchangeConnectionMode.olCachedConnectedFull: { return true;}
case
Outlook.OlExchangeConnectionMode.olCachedConnectedHeaders: { return
true;}
case
Outlook.OlExchangeConnectionMode.olCachedDisconnected: { return true;}
case Outlook.OlExchangeConnectionMode.olCachedOffline: {
return true;}
case Outlook.OlExchangeConnectionMode.olNoExchange: {
break; }
case Outlook.OlExchangeConnectionMode.olOffline: {
break; }
case Outlook.OlExchangeConnectionMode.olOnline:{ break; }
}
return false;
}
}
}
 
Hi,
Great thread. I am having same issue but I am working with Outlook 2003.
It seems like AddressEntry for Outlook 2003, doesn't have GetExchangeUser and PropertyAccessor.

In this case, how to apply this solution?
Any help is appreciated.

-Regards
Rakib
 
Back
Top