Getting the SMTP Email Address of an Exchange Sender of a MailItem from Outlook in VB.NET VSTO

Standard

 image

Sometimes the easiest things in software development are the hardest things.  Particularly when it comes to VSTO development.

The Problem

You’d think that programmatically retrieving the sender’s SMTP email address from an email item in Outlook would be easy wouldn’t you?  It isn’t.

The “Address” property of the MailItem object is supposed to return the email address.   And it does if your email comes from an internet sender, such as a friendly Nigerian businessman.  If the email sender a user of Microsoft Exchange, you get a wierd X400 formatted email address.  Not very handy if you want the SMTP email address.

If you search for this information you’ll find solutions that usually involve obsolete components (CDO 1.21 – Unsupported by Microsoft) or 3rd party dlls (such as the excellent “Outlook Redemption”).   See the links section at the bottom of this article for a list of the good articles that discuss these techniques.

If you want your application to “remain pure” .NET however, there is no “cut and dried” solution.

The Solution

After much experimentation and agony my colleague Puji Arsana and myself have devised a solution that uses pure VSTO and VB.Net, without any 3rd party dependencies.

It seems to me that many people have already created this solution (and published parts of this), but so far noone has published a complete solution before.

So without further ado, here’s the VB.NET code to allow you to extract the SMTP email address, regardless of whether it’s an exchange or internet email.

Private Function GetSMTPEmailAddress(mailItem As MailItem) As String

    If mailItem.SenderAddressType = "EX" Then
         Return GetEmailAddressForExchangeServer(loItem.Name)
    Else
         Return mailItem.Address
    End If

End Function

Private Function GetEmailAddressForExchangeServer(ByVal emailName As String) As String
        Dim loDummyMsg As MailItem = moMailItem.Application.CreateItem(OlItemType.olMailItem)
        Dim loAddress As Recipient = loDummyMsg.Recipients.Add(emailName)

        loAddress.Resolve()
        Dim lsSmtpAddress As String = GetMAPIProperty(loAddress.AddressEntry.MAPIOBJECT, PR_SMTP_ADDRESS)
        Return lsSmtpAddress

End Function

#Region "MAPI Interface ID'S"
    ' The Interface ID's are used to retrieve the specific MAPI Interfaces from the IUnknown Object
    Private Const IID_IMAPISession As String = "00020300-0000-0000-C000-000000000046"
    Private Const IID_IMAPIProp As String = "00020303-0000-0000-C000-000000000046"
    Private Const IID_IMAPITable As String = "00020301-0000-0000-C000-000000000046"
    Private Const IID_IMAPIMsgStore As String = "00020306-0000-0000-C000-000000000046"
    Private Const IID_IMAPIFolder As String = "0002030C-0000-0000-C000-000000000046"
    Private Const IID_IMAPISpoolerService As String = "0002031E-0000-0000-C000-000000000046"
    Private Const IID_IMAPIStatus As String = "0002031E-0000-0000-C000-000000000046"
    Private Const IID_IMessage As String = "00020307-0000-0000-C000-000000000046"
    Private Const IID_IAddrBook As String = "00020309-0000-0000-C000-000000000046"
    Private Const IID_IProfSect As String = "00020304-0000-0000-C000-000000000046"
    Private Const IID_IMAPIContainer As String = "0002030B-0000-0000-C000-000000000046"
    Private Const IID_IABContainer As String = "0002030D-0000-0000-C000-000000000046"
    Private Const IID_IMsgServiceAdmin As String = "0002031D-0000-0000-C000-000000000046"
    Private Const IID_IProfAdmin As String = "0002031C-0000-0000-C000-000000000046"
    Private Const IID_IMailUser As String = "0002030A-0000-0000-C000-000000000046"
    Private Const IID_IDistList As String = "0002030E-0000-0000-C000-000000000046"
    Private Const IID_IAttachment As String = "00020308-0000-0000-C000-000000000046"
    Private Const IID_IMAPIControl As String = "0002031B-0000-0000-C000-000000000046"
    Private Const IID_IMAPILogonRemote As String = "00020346-0000-0000-C000-000000000046"
    Private Const IID_IMAPIForm As String = "00020327-0000-0000-C000-000000000046"
#End Region

#Region "MAPI Properties"

    ' MAPI Properties
    Public Const PR_TRANSPORT_MESSAGE_HEADERS As UInteger = 8192030
    Public Const PR_BODY As UInteger = 268435486
    Public Const PR_BODY_HTML As UInteger = 269680670
    Public Const PR_HTML As UInteger = 269680898
    Public Const PR_DISPLAY_NAME As UInteger = 805371934
    Public Const PR_SUBJECT As UInteger = 3604510
    Public Const PR_EMAIL_ADDRESS As UInteger = 805503006
    'public const uint PR_NEG_EMAIL_ADDRESS = -2146496482;
    Public Const PR_SMTP_ADDRESS As UInteger = 972947486
    Public Const PR_ADDRTYPE As UInteger = 805437470
#End Region

#Region "structure and variables "
    Private Structure SPropValue
        Public ulPropTag As UInteger
        Public dwAlignPad As UInteger
        Public Value As Long
    End Structure

    ' return codes
    Private Const S_OK As Integer = 0
#End Region

#Region "MAPI Functions"

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi, EntryPoint:="HrGetOneProp@12")> _
    Private Shared Sub HrGetOneProp(ByVal pmp As IntPtr, ByVal ulPropTag As UInteger, ByRef ppProp As IntPtr)
    End Sub

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi, EntryPoint:="HrSetOneProp@8")> _
    Private Shared Sub HrSetOneProp(ByVal pmp As IntPtr, ByVal pprop As IntPtr)
    End Sub

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi, EntryPoint:="MAPIFreeBuffer@4")> _
    Private Shared Sub MAPIFreeBuffer(ByVal lpBuffer As IntPtr)
    End Sub

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi)> _
    Private Shared Function MAPIInitialize(ByVal lpMapiInit As IntPtr) As Integer
    End Function

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi)> _
    Private Shared Sub MAPIUninitialize()
    End Sub

    ''' <summary>
    ''' Get a property from a passed MAPI object
    ''' </summary>
    ''' <param name="oMAPIObject"></param>
    ''' <param name="uiPropertyTag"></param>
    ''' <returns></returns>
    Private Shared Function GetMAPIProperty(ByVal oMAPIObject As Object, ByVal uiPropertyTag As UInteger) As String

        If oMAPIObject.Equals(Nothing) Then
            'No MAPI Object
            Return ""
        End If

        Dim sProperty As String = ""
        Dim pPropValue As IntPtr = IntPtr.Zero

        Dim IUnknown As IntPtr = IntPtr.Zero
        Dim IMAPIProperty As IntPtr = IntPtr.Zero

        Try

            ' initialize MAPI
            MAPIInitialize(IntPtr.Zero)

            ' get the unknown object.
            IUnknown = Marshal.GetIUnknownForObject(oMAPIObject)

            'get the property
            Dim guidIMAPIProp As New Guid(IID_IMAPIProp)
            If Marshal.QueryInterface(IUnknown, guidIMAPIProp, IMAPIProperty) <> S_OK Then
                'Failed to get IMAPIProperty
                Return ""
            End If

            Try

                ' get the field from the MAPI Property
                HrGetOneProp(IMAPIProperty, uiPropertyTag, pPropValue)
                ' Is the property actually there?
                If pPropValue = IntPtr.Zero Then
                    Return ""
                End If
                ' Get the value back
                Dim propValue As SPropValue = DirectCast(Marshal.PtrToStructure(pPropValue, GetType(SPropValue)), SPropValue)
                ' convert to string

                sProperty = Marshal.PtrToStringAnsi(New IntPtr(propValue.Value))
            Catch ex As System.Exception
                Throw ex
            End Try
        Finally
            ' CLEAN UP
            If pPropValue <> IntPtr.Zero Then
                MAPIFreeBuffer(pPropValue)
            End If

            If IMAPIProperty <> IntPtr.Zero Then
                Marshal.Release(IMAPIProperty)
            End If
            If IUnknown <> IntPtr.Zero Then
                Marshal.Release(IUnknown)
            End If

            MAPIUninitialize()
        End Try

        Return sProperty
    End Function
#End Region

How it Works

If the email is from exchange it translates the  email address into a “Recipient” object. 

Recipient objects expose “AddressEntry” objects, which in turn can be utilised by “ExtendedMAPI”.

The code then uses ExtendedMAPI which can “see” the property where the normal Outlook API cant.

Links

See http://www.outlookcode.com/d/code/getsenderaddy.htm#redemption and http://www.cdolive.com/cdo5.htm#EMailAddressOfSender for Redemption and CDO examples and http://groups.google.com/group/microsoft.public.outlook.program_vba/browse_frm/thread/4d4d5fece24a2a7/ad2fcbb691d5bf18 for a discussion of the property to use with Cached Exchange Mode in Outlook 2003 or later.

Share this post :

Advertisements

44 responses »

  1. I would try your code but I can’t find the property “AddressEntry” on a MailItem object. I’m working with c# and VSTO 2005 SE.

    David

  2. It seems to me that many people have already created this solution (and published parts of this), but so far noone has published a complete solution before.

    Can you please include all references used.

    Where does loItem come from?

    Thanks

  3. The loItem was a typing mistake, I’ve updated the original post.

    The references that come with a new addin project are sufficient. No additional references are required.

    Regards

    Julian

  4. I am new to the VB world. Are there any examples of this using VB as apposed to VB.NET.

    If it works, this will be the first example that has.

    Much appreciated.

    Julie

  5. Hi Julian

    Thanks for that originalidea!

    It helped me get the email address of both sender and recipient for an Outlook 2007 AddIn made in Visual Studio 2008.

    Keep up the good work!

    Cheers,
    Ole

  6. Hey there AnOriginalIdea, I was hoping you might be able to give us some ideas on how to implement the Cached Exchange Mode property parsing. The article to which you refer is good as a conceptual idea, but I must admit I have no idea how to modify your code to parse the multi-valued property.

    Hope you can give us some juicy tips! 🙂

    Mike

  7. I’m getting an error
    Type ‘DllImport’ is not defined for all the declarations in the MAPI Functions region.

    i.e.
    _
    Private Shared Sub HrGetOneProp(ByVal pmp As IntPtr, ByVal ulPropTag As UInteger, ByRef ppProp As IntPtr)
    End Sub

    What am I missing?

    I am also getting the error Name ‘Marshal’ is undefined in the GetMAPIProperty function.

  8. I’m having a couple issues. I’m really hoping I can get this to work with a Outlook 2007 add-in. I’m trying to get the SMTP address of a mail item that has been resolved by the GAL – and the MailItem.To is just giving me the name. Any help would be ABSOLUTELY WONDERFUL!!

    I’ve already included these imports:
    Imports System.Runtime.InteropServices
    Imports System.Runtime.InteropServices.Marshal
    Imports Microsoft.Office.Interop.Outlook

    This line:
    Dim loDummyMsg As MailItem = moMailItem.Application.CreateItem(OlItemType.olMailItem)
    says : moMailItem not declared

    This line:
    Return GetEmailAddressForExchangeServer(loItem.Name)
    says: loItem not declared. Should this be MailItem.Name?

    And yes. I’m a newbie. Should all these just be comments? Or should I be doing something specific with these?
    ”’
    ”’ Get a property from a passed MAPI object
    ”’
    ”’
    ”’
    ”’

    Please, any help would be a life saver!!

  9. here is some code lines that worked fine for me in outlook 2007… i hope it is useful for you..

    MsgBox fnGetSMTPAddress(“/o=CNPHJ/ou=CORP/cn=Recipients/cn=0008051”)

    Public Function fnGetSMTPAddress(ExchangeMailAddress As String) As String
    Dim objOutlook As Outlook.Application
    Dim objMailItem As Outlook.MailItem

    Set objOutlook = New Outlook.Application
    Set objMailItem = objOutlook.CreateItem(0)
    objMailItem.To = ExchangeMailAddress
    objMailItem.Recipients.ResolveAll
    fnGetSMTPAddress = objMailItem.Recipients.Item(1).AddressEntry.GetExchangeUser.PrimarySmtpAddress
    Set objMailItem = Nothing
    Set objOutlook = Nothing

    End Function

  10. It is working for me for the receiving mail items. Now I want to do the same trick to get the exchange mail address when sending a mail in outlook 2003.
    The command mailItem.SenderAddressType = “EX” is not working at that moment.

    How can this be done?

    Thanks in advance.

  11. I have it working for the receiving email.
    Now I want the same when sending an email. Is it possible to get the good email addresses from the receivers of that mail.
    The command mailItem.SenderAddressType is not set at that moment and so it is not equal “EX”.

    I hope someone has an solution.

    Thanks in advance.

  12. Guys, need help…. I tried to convert to c#…
    Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProperty) returns -2147467259
    and so the function returns empty string.
    Appreciate any help.

    //////// Program.cs////////////////

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Outlook = Microsoft.Office.Interop.Outlook;
    namespace testExchange
    {
    class Program
    {
    private const int PR_SMTP_ADDRESS = 972947486;
    static void Main(string[] args)
    {
    Outlook.Application oAC = new Microsoft.Office.Interop.Outlook.Application();
    Outlook.NameSpace oNS = oAC.GetNamespace(“MAPI”);
    //Outlook.NameSpace oNS = oAC.Session;

    //Outlook.AddressLists al = ac.Session.AddressLists;

    oNS.Logon(“”,””,false,true);

    Outlook.AddressLists oDLs = oNS.AddressLists;
    Outlook.AddressList oDL = oDLs[“Global Address List”];
    Outlook.AddressEntries oEntries = oDL.AddressEntries;
    int totalEntries = oEntries.Count;

    Console.WriteLine(“Total entries =” + totalEntries.ToString());

    for (int i = 1; i < 10; i++)
    {
    Console.WriteLine(oEntries[i].Name + “-” + oEntries[i].Type + “-” + oEntries[i].Address + “-” + oEntries[i].DisplayType);

    Outlook.MailItem oMI = (Outlook.MailItem) oAC.CreateItem(0);
    oMI.To = oEntries[i].Address;
    oMI.Recipients[1].Resolve();

    string emailAddress = Utils.GetMAPIProperty(oMI.Recipients[1].AddressEntry.MAPIOBJECT, PR_SMTP_ADDRESS);

    // empty string ?

    // In watch window, oMI.Recipients[1].AddressEntry.MAPIOBJECT’s Identity is null.Why??

    }

    oNS.Logoff();

    }
    }
    }

    //////// Utils.cs////////////////

    using System;
    using System.Runtime.InteropServices;
    namespace testExchange
    {
    public static class Utils
    {

    #region “MAPI Interface ID’S”
    // The Interface ID’s are used to retrieve the specific MAPI Interfaces from the IUnknown Object
    private const string IID_IMAPISession = “00020300-0000-0000-C000-000000000046”;
    private const string IID_IMAPIProp = “00020303-0000-0000-C000-000000000046”;
    private const string IID_IMAPITable = “00020301-0000-0000-C000-000000000046”;
    private const string IID_IMAPIMsgStore = “00020306-0000-0000-C000-000000000046”;
    private const string IID_IMAPIFolder = “0002030C-0000-0000-C000-000000000046”;
    private const string IID_IMAPISpoolerService = “0002031E-0000-0000-C000-000000000046”;
    private const string IID_IMAPIStatus = “0002031E-0000-0000-C000-000000000046”;
    private const string IID_IMessage = “00020307-0000-0000-C000-000000000046”;
    private const string IID_IAddrBook = “00020309-0000-0000-C000-000000000046”;
    private const string IID_IProfSect = “00020304-0000-0000-C000-000000000046”;
    private const string IID_IMAPIContainer = “0002030B-0000-0000-C000-000000000046”;
    private const string IID_IABContainer = “0002030D-0000-0000-C000-000000000046”;
    private const string IID_IMsgServiceAdmin = “0002031D-0000-0000-C000-000000000046”;
    private const string IID_IProfAdmin = “0002031C-0000-0000-C000-000000000046”;
    private const string IID_IMailUser = “0002030A-0000-0000-C000-000000000046”;
    private const string IID_IDistList = “0002030E-0000-0000-C000-000000000046”;
    private const string IID_IAttachment = “00020308-0000-0000-C000-000000000046”;
    private const string IID_IMAPIControl = “0002031B-0000-0000-C000-000000000046”;
    private const string IID_IMAPILogonRemote = “00020346-0000-0000-C000-000000000046”;
    private const string IID_IMAPIForm = “00020327-0000-0000-C000-000000000046”;
    #endregion

    #region “MAPI Properties”

    //MAPI Properties
    public const int PR_TRANSPORT_MESSAGE_HEADERS = 8192030;
    public const int PR_BODY = 268435486;
    public const int PR_BODY_HTML = 269680670;
    public const int PR_HTML = 269680898;
    public const int PR_DISPLAY_NAME = 805371934;
    public const int PR_SUBJECT = 3604510;
    public const int PR_EMAIL_ADDRESS = 805503006;
    //public const uint PR_NEG_EMAIL_ADDRESS = -2146496482;
    public const int PR_SMTP_ADDRESS = 972947486;
    public const int PR_ADDRTYPE = 805437470;
    #endregion

    #region “structure and variables ”
    private struct SPropValue
    {
    public int ulPropTag;
    public int dwAlignPad;
    public long Value;
    }

    // return codes
    private const int S_OK = 0;
    #endregion

    #region “MAPI Functions”

    [DllImport(“MAPI32.DLL”, CharSet=CharSet.Ansi, EntryPoint=”HrGetOneProp@12″)]
    private static extern void HrGetOneProp(IntPtr pmp , int ulPropTag , IntPtr ppProp);

    [DllImport(“MAPI32.DLL”, CharSet=CharSet.Ansi, EntryPoint=”HrSetOneProp@8″)]
    private static extern void HrSetOneProp(IntPtr pmp, IntPtr pprop);

    [DllImport(“MAPI32.DLL”, CharSet=CharSet.Ansi, EntryPoint=”MAPIFreeBuffer@4″)]
    private static extern void MAPIFreeBuffer(IntPtr lpBuffer);

    [DllImport(“MAPI32.DLL”, CharSet=CharSet.Ansi)]
    private static extern int MAPIInitialize(IntPtr lpMapiInit);

    [DllImport(“MAPI32.DLL”, CharSet=CharSet.Ansi)]
    private static extern void MAPIUninitialize();

    //
    // Get a property from a passed MAPI object
    //
    //
    //
    //

    public static string GetMAPIProperty(Object oMAPIObject , int uiPropertyTag )
    {
    if(oMAPIObject == null) return string.Empty;
    string sProperty = “”;
    IntPtr pPropValue = IntPtr.Zero;
    IntPtr IUnknown = IntPtr.Zero;
    IntPtr IMAPIProperty = IntPtr.Zero;

    try
    {
    //initialize MAPI
    MAPIInitialize(IntPtr.Zero);

    // get the unknown object.
    IUnknown = Marshal.GetIUnknownForObject(oMAPIObject) ;

    //get the property
    Guid guidIMAPIProp = new Guid (IID_IMAPIProp);

    if (Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProperty) != S_OK)
    // fails ??
    // Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProperty) returns -2147467259

    {
    //Failed to get IMAPIProperty
    return “”;
    }

    try
    {

    //get the field from the MAPI Property
    HrGetOneProp(IMAPIProperty, uiPropertyTag, pPropValue);
    //Is the property actually there?
    if(pPropValue == IntPtr.Zero) return “”;

    //Get the value back
    SPropValue propValue = (SPropValue)(Marshal.PtrToStructure(pPropValue, typeof(SPropValue)));// typeof(SPropValue));
    //convert to string

    sProperty = Marshal.PtrToStringAnsi(new IntPtr(propValue.Value));

    }

    catch(System.Exception ex)
    {
    throw ex;
    }

    }

    finally
    {

    // CLEAN UP
    if(pPropValue != IntPtr.Zero) MAPIFreeBuffer(pPropValue);
    if(IMAPIProperty != IntPtr.Zero) Marshal.Release(IMAPIProperty);
    if(IUnknown != IntPtr.Zero) Marshal.Release(IUnknown);
    MAPIUninitialize();

    }

    return sProperty;
    }

    #endregion

    }
    }

    • Hi, Jay

      I’ve just faced the same problem (can’t initialize an “IMAPIProperty”-prop, beeing at the same way with you …)
      Would you so kind to provide me an applicable solution for this task, if, of course, you got it yet ?

    • I’ve just faced the same problem. Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProperty) returns -2147467259. How did you fix it? I need your help. Thanks.

  13. Excellent post… thanks everyone.

    still have to try but these post have give me a lot of insight.

    Keep up the good work.

    Thanks for posting back, Juan P
    …exactly what i was looking for.

  14. Dear Anoriginalidea,

    You suggested this …..Session.CurrentUser.AddressEntry and I tried this …. Session.CurrentUser.Address ….. Its amazing I’ m able to solve my problem.

    Thanks Anoriginalidea.

    Thanks,
    Khajavali

  15. Jay,
    the fix to your C# code add the ‘ref’ to the third parameter:

    [DllImport(“MAPI32.DLL”, CharSet = CharSet.Ansi, EntryPoint = “HrGetOneProp@12”)]
    private static extern void HrGetOneProp(IntPtr pmp, int ulPropTag, ref IntPtr ppProp);

    • It doesn’t work. I have tried. Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProperty) returns -2147467259

  16. The call to GetMAPIProperty fails in Outlook 2010 64-bit with the following message:

    Unable to find an entry point named ‘HrGetOneProp@12’ in DLL ‘MAPI32.DLL’.

    Anyone knows how to fix this?

  17. Just want to add, that we just managed to get the cs code from Jay to work, so this i definately the solution for working with Outlook 2003 against an Exchange server 🙂

    • I used the code jay posted, but Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProperty) returns -2147467259. Could you share me the right code that would work.

      • I’m sorry, the code worked when I posted it. The error encountered is a COM error. This could be due to an incomplete Outlook install.
        I suggest you research the apis and try to understand what its doing.

      • The code written by VB.NET that you posted worked. I tried to convert it into C#.NET, but it doesn’t work.

  18. Hey:

    No need in VSTO 3.0 to bind to mapi dll to access MAPI properties. You can use .PropertyAccessor() on most VSTO objects. The logic stays the same otherwise.

  19. Hi there,

    I have tried in vein to get the smtp address from address books. This code looks promising. Has anyone done this in VB5 or 6. I tried to convert but am not skilled enough with syntax etc.

    Cheers.

  20. Check http://msdn.microsoft.com/en-us/library/ff184624

    How to: Get the SMTP Address of the Sender of a Mail Item (Office 2010)

    private string GetSenderSMTPAddress(Outlook.MailItem mail)
    {
    string PR_SMTP_ADDRESS =
    @”http://schemas.microsoft.com/mapi/proptag/0x39FE001E”;
    if (mail == null)
    {
    throw new ArgumentNullException();
    }
    if (mail.SenderEmailType == “EX”)
    {
    Outlook.AddressEntry sender =
    mail.Sender;
    if (sender != null)
    {
    //Now we have an AddressEntry representing the Sender
    if (sender.AddressEntryUserType ==
    Outlook.OlAddressEntryUserType.
    olExchangeUserAddressEntry
    || sender.AddressEntryUserType ==
    Outlook.OlAddressEntryUserType.
    olExchangeRemoteUserAddressEntry)
    {
    //Use the ExchangeUser object PrimarySMTPAddress
    Outlook.ExchangeUser exchUser =
    sender.GetExchangeUser();
    if (exchUser != null)
    {
    return exchUser.PrimarySmtpAddress;
    }
    else
    {
    return null;
    }
    }
    else
    {
    return sender.PropertyAccessor.GetProperty(
    PR_SMTP_ADDRESS) as string;
    }
    }
    else
    {
    return null;
    }
    }
    else
    {
    return mail.SenderEmailAddress;
    }
    }

  21. Functional solution for VB.Net 2010 using winforms and a button called button1
    using outlook 2003
    (mixed assembly from author and those who have commented previously)
    Thanks to all
    JB

    Imports System.Runtime.InteropServices
    Imports System.Runtime.InteropServices.Marshal
    Imports Microsoft.Office.Interop.Outlook
    Imports Microsoft.Office.Interop

    Public Class Form1

    #Region “MAPI Interface ID’S”
    ‘ The Interface ID’s are used to retrieve the specific MAPI Interfaces from the IUnknown Object
    Private Const IID_IMAPISession As String = “00020300-0000-0000-C000-000000000046”
    Private Const IID_IMAPIProp As String = “00020303-0000-0000-C000-000000000046”
    Private Const IID_IMAPITable As String = “00020301-0000-0000-C000-000000000046”
    Private Const IID_IMAPIMsgStore As String = “00020306-0000-0000-C000-000000000046”
    Private Const IID_IMAPIFolder As String = “0002030C-0000-0000-C000-000000000046”
    Private Const IID_IMAPISpoolerService As String = “0002031E-0000-0000-C000-000000000046”
    Private Const IID_IMAPIStatus As String = “0002031E-0000-0000-C000-000000000046”
    Private Const IID_IMessage As String = “00020307-0000-0000-C000-000000000046”
    Private Const IID_IAddrBook As String = “00020309-0000-0000-C000-000000000046”
    Private Const IID_IProfSect As String = “00020304-0000-0000-C000-000000000046”
    Private Const IID_IMAPIContainer As String = “0002030B-0000-0000-C000-000000000046”
    Private Const IID_IABContainer As String = “0002030D-0000-0000-C000-000000000046”
    Private Const IID_IMsgServiceAdmin As String = “0002031D-0000-0000-C000-000000000046”
    Private Const IID_IProfAdmin As String = “0002031C-0000-0000-C000-000000000046”
    Private Const IID_IMailUser As String = “0002030A-0000-0000-C000-000000000046”
    Private Const IID_IDistList As String = “0002030E-0000-0000-C000-000000000046”
    Private Const IID_IAttachment As String = “00020308-0000-0000-C000-000000000046”
    Private Const IID_IMAPIControl As String = “0002031B-0000-0000-C000-000000000046”
    Private Const IID_IMAPILogonRemote As String = “00020346-0000-0000-C000-000000000046”
    Private Const IID_IMAPIForm As String = “00020327-0000-0000-C000-000000000046”
    #End Region

    #Region “MAPI Properties”

    ‘ MAPI Properties
    Public Const PR_TRANSPORT_MESSAGE_HEADERS As UInteger = 8192030
    Public Const PR_BODY As UInteger = 268435486
    Public Const PR_BODY_HTML As UInteger = 269680670
    Public Const PR_HTML As UInteger = 269680898
    Public Const PR_DISPLAY_NAME As UInteger = 805371934
    Public Const PR_SUBJECT As UInteger = 3604510
    Public Const PR_EMAIL_ADDRESS As UInteger = 805503006
    Public Const PR_SMTP_ADDRESS As UInteger = 972947486
    Public Const PR_ADDRTYPE As UInteger = 805437470
    #End Region

    #Region “structure and variables ”
    Private Structure SPropValue
    Public ulPropTag As UInteger
    Public dwAlignPad As UInteger
    Public Value As Long
    End Structure

    ‘ return codes
    Private Const S_OK As Integer = 0
    #End Region

    #Region “MAPI Functions”

    _
    Private Shared Sub HrGetOneProp(ByVal pmp As IntPtr, ByVal ulPropTag As UInteger, ByRef ppProp As IntPtr)
    End Sub

    _
    Private Shared Sub HrSetOneProp(ByVal pmp As IntPtr, ByVal pprop As IntPtr)
    End Sub

    _
    Private Shared Sub MAPIFreeBuffer(ByVal lpBuffer As IntPtr)
    End Sub

    _
    Private Shared Function MAPIInitialize(ByVal lpMapiInit As IntPtr) As Integer
    End Function

    _
    Private Shared Sub MAPIUninitialize()
    End Sub

    ”’
    ”’ Get a property from a passed MAPI object
    ”’
    ”’
    ”’
    ”’
    Private Shared Function GetMAPIProperty(ByVal oMAPIObject As Object, ByVal uiPropertyTag As UInteger) As String

    If oMAPIObject.Equals(Nothing) Then
    ‘No MAPI Object
    Return “”
    End If

    Dim sProperty As String = “”
    Dim pPropValue As IntPtr = IntPtr.Zero

    Dim IUnknown As IntPtr = IntPtr.Zero
    Dim IMAPIProperty As IntPtr = IntPtr.Zero

    Try

    ‘ initialize MAPI
    MAPIInitialize(IntPtr.Zero)

    ‘ get the unknown object.
    IUnknown = Marshal.GetIUnknownForObject(oMAPIObject)

    ‘get the property
    Dim guidIMAPIProp As New Guid(IID_IMAPIProp)
    If Marshal.QueryInterface(IUnknown, guidIMAPIProp, IMAPIProperty) S_OK Then
    ‘Failed to get IMAPIProperty
    Return “”
    End If

    Try

    ‘ get the field from the MAPI Property
    HrGetOneProp(IMAPIProperty, uiPropertyTag, pPropValue)
    ‘ Is the property actually there?
    If pPropValue = IntPtr.Zero Then
    Return “”
    End If
    ‘ Get the value back
    Dim propValue As SPropValue = DirectCast(Marshal.PtrToStructure(pPropValue, GetType(SPropValue)), SPropValue)
    ‘ convert to string

    sProperty = Marshal.PtrToStringAnsi(New IntPtr(propValue.Value))
    Catch ex As System.Exception
    Throw ex
    End Try
    Finally
    ‘ CLEAN UP
    If pPropValue IntPtr.Zero Then
    MAPIFreeBuffer(pPropValue)
    End If

    If IMAPIProperty IntPtr.Zero Then
    Marshal.Release(IMAPIProperty)
    End If
    If IUnknown IntPtr.Zero Then
    Marshal.Release(IUnknown)
    End If

    MAPIUninitialize()
    End Try

    Return sProperty
    End Function
    #End Region

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    ‘modify string to suit your exchange
    MsgBox(fnGetSMTPAddress(“/O=ELLI/OU=ELLI/cn=Recipients/cn=03706”), MsgBoxStyle.OkOnly)

    End Sub

    Public Function fnGetSMTPAddress(ExchangeMailAddress As String) As String
    Dim objOutlook As Outlook.Application
    Dim objMailItem As Outlook.MailItem
    objOutlook = New Outlook.Application
    objMailItem = objOutlook.CreateItem(OlItemType.olMailItem)
    objMailItem.To = ExchangeMailAddress
    objMailItem.Recipients.ResolveAll()
    fnGetSMTPAddress = GetMAPIProperty(objMailItem.Recipients.Item(1).AddressEntry.MAPIOBJECT, PR_SMTP_ADDRESS)

    objMailItem = Nothing
    objOutlook = Nothing
    End Function

    End Class

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s