Dmitry Kostochko

HowTo: Get an attachment size in Outlook 2000 – 2007, part 2

In the previous sample, which is part 1 of this short series, I showed how to get the PR_ATTACH_SIZE Extended MAPI property that returns the size of an Attachment object. To be more precise, it returns the size of the attached file plus the size of some internal info.

In most cases that makeweight does not matter at all since it is very small (about 100-200 bytes), but sometimes it may be excess. In order to get the exact size of the attached file, you need to use the PR_ATTACH_DATA_BIN binary property:

Private Function GetAttachSizeMAPI(ByVal oMAPIObject As Object) As Long
 
    If (oMAPIObject Is Nothing) Then Return 0
 
    Dim result As String = 0
    Dim pPropValue As IntPtr = IntPtr.Zero
    Dim IUnk As IntPtr = IntPtr.Zero
    Dim IProperty As IntPtr = IntPtr.Zero
    Try
        MAPI.MAPIInitialize(IntPtr.Zero)
        IUnk = Marshal.GetIUnknownForObject(oMAPIObject)
        ' Outlook 2003 and 2007 ( IMAPIProp )
        Dim res = Marshal.QueryInterface(IUnk, MAPI.guidMAPIProp, IProperty)
        If res = MAPI.S_OK Then
            Dim oMapiProp As Object = Marshal.GetObjectForIUnknown(IProperty)
            Dim iMapiProp As IMAPIProp = TryCast(oMapiProp, IMAPIProp)
            If iMapiProp IsNot Nothing Then
                Try
                    Dim stream As ComTypes.IStream
                    Dim IStream As IntPtr = IntPtr.Zero
                    iMapiProp.OpenProperty( _
                        MAPI.PR_ATTACH_DATA_BIN, _
                        MAPI.guidIStream, 0, 0, _
                        IStream)
                    If IStream <> IntPtr.Zero Then
                        Try
                            stream = TryCast( _
                                Marshal.GetObjectForIUnknown(IStream), _
                                ComTypes.IStream)
                            If stream IsNot Nothing Then
                                Try
                                    Dim stat As ComTypes.STATSTG = Nothing
                                    stream.Stat(stat, STATFLAG.STATFLAG_NONAME)
                                    result = stat.cbSize
                                    Return result
                                Finally
                                    Marshal.ReleaseComObject(stream)
                                End Try
                            End If
                        Finally
                            Marshal.Release(IStream)
                        End Try
                    End If
                Finally
                    Marshal.ReleaseComObject(oMapiProp)
                End Try
            End If
        End If
        ' Outlook 2000 and XP ( IAttach )
        res = Marshal.QueryInterface(IUnk, MAPI.guidMAPIAttach, IProperty)
        If res = MAPI.S_OK Then
            Dim oMapiProp As Object = Marshal.GetObjectForIUnknown(IProperty)
            Dim iMapiProp As IAttach = TryCast(oMapiProp, IAttach)
            If iMapiProp IsNot Nothing Then
                Try
                    Dim stream As ComTypes.IStream
                    Dim IStream As IntPtr = IntPtr.Zero
                    iMapiProp.OpenProperty( _
                        MAPI.PR_ATTACH_DATA_BIN, _
                        MAPI.guidIStream, 0, 0, _
                        IStream)
                    If IStream <> IntPtr.Zero Then
                        Try
                            stream = TryCast( _
                                Marshal.GetObjectForIUnknown(IStream), _
                                ComTypes.IStream)
                            If stream IsNot Nothing Then
                                Try
                                    Dim stat As ComTypes.STATSTG = Nothing
                                    stream.Stat(stat, STATFLAG.STATFLAG_NONAME)
                                    result = stat.cbSize
                                    Return result
                                Finally
                                    Marshal.ReleaseComObject(stream)
                                End Try
                            End If
                        Finally
                            Marshal.Release(IStream)
                        End Try
                    End If
                Finally
                    Marshal.ReleaseComObject(oMapiProp)
                End Try
            End If
        End If
    Finally
        If (pPropValue <> IntPtr.Zero) Then
            MAPI.MAPIFreeBuffer(pPropValue)
        End If
        If (IProperty <> IntPtr.Zero) Then
            Marshal.Release(IProperty)
        End If
        If (IUnk <> IntPtr.Zero) Then
            Marshal.Release(IUnk)
        End If
    End Try
    Return result
End Function

Personal thanks to François-Denis for his contribution to the PR_ATTACH_SIZE vs. PR_ATTACH_DATA_BIN properties discussion on our forum.

You may also be interested in:

How to program an Outlook COM add-in: ribbon tabs, command bars, task panes
Advanced features for Outlook plug-in development
How to develop custom Outlook forms

Available downloads:

This sample add-in was developed using Add-in Express 2009 for Microsoft Office and .net
C# sample Outlook add-in project for VS 2005
VB.NET sample Outlook add-in project for VS 2005

4 Comments

  • Adil Abdullah says:

    Title: OOM : How to retrieve Outlook attachments ( Reference, Value, Embedded and OLE) using VBA?

    WebSite: https://blogs.msdn.com/b/deva/archive/2009/04/29/oom-how-to-retrieve-outlook-attachments-reference-value-embedded-and-ole-using-vba.aspx

    Comments: Why Add-in-Express is failed to Get the Attachment Size in the Outlook Mail-Items. However the above mentioned Procedure is get the file size.

    I am using Outlook 2007 and Outlook 2010.

  • Dmitry Kostochko (Add-in Express Team) says:

    Hi Adil,

    In case of Outlook 2007 and 2010, you can use the Size property to get an attachment size. This blog post shows how to get an attachment size in all Outlook versions, from 2000 to 2010. As you know, the Size property was introduced in the Outlook 2007 Object Model.

  • Yet another anonymous victim of the Microsoft Deproductivity Department says:

    The code shown is incomplete. It ends with
    “Marshal.GetObjectForIUnknown(IStream), _
    ComTypes.IStrea”

    Also I cannot search the page with Control-F in Chrome. So I can’t search for .Size

    I’d love to work from the source. I won’t download anything but source.

  • Andrei Smolin (Add-in Express Team) says:

    Hello the victim,

    We look into the issue. I suggest that you download the “VB.NET sample Outlook add-in for VS 2005” download: it contains the complete source code. In a minute, I’ll rename the download to “VB.NET sample Outlook add-in project for VS 2005”.

Post a comment

Have any questions? Ask us right now!