Dmitry Kostochko

HowTo: Get an attachment size in Outlook 2000 – 2010, part 1

The new Size property of the Attachment object was introduced in the Outlook 2007 Object Model. There exist at least two methods of getting the attachment size in older Outlook versions, that is in Outlook 2003, XP and 2000.

The first method is as follows: you store each attachment in a temporary file, then query the file size, and after that delete that temporary file. The other, and probably a smarter way, is getting the attachment size via the PR_ATTACH_SIZE Extended MAPI property. It is that second method that we are going to scrutinize today.

The DoGetAttachmentSize method is quite simple, the code below processes the Attachments collection:

Private Sub DoGetAttachmentSize(ByRef mail As Outlook._MailItem)
    Dim attachments As Outlook.Attachments = mail.Attachments
    If attachments IsNot Nothing Then
        Try
            If attachments.Count > 0 Then
                Dim Output As String = String.Empty
                For i As Integer = 1 To attachments.Count
                    Dim attach As Outlook.Attachment = attachments.Item(i)
                    If attach IsNot Nothing Then
                        Try
                            Dim size As Long = GetMAPIProp( _
                                attach.MAPIOBJECT, _
                                MAPI.PR_ATTACH_SIZE)
                            Output += "#" + i.ToString() + _
                             ": " + attach.FileName + _
                             " " + size.ToString() + _
                             Environment.NewLine
                        Finally
                            Marshal.ReleaseComObject(attach)
                        End Try
                    End If
                Next i
                If Output <> String.Empty Then MessageBox.Show(Output)
            End If
        Finally
            Marshal.ReleaseComObject(attachments)
        End Try
    End If
End Sub

In the GetMAPIProp method, you dig for the needed PR_ATTACH_SIZE property. Initialize Extended MAPI, query the right interface, get the SPropValue structure and receive the wanted value. Pay attention here to the two calls of QueryInterface. The point is that Outlook 2003, 2007 and Outlook 2010 return only the IMAPIProp interface, while Outlook 2000 and Outlook XP return the IAttach interface only. What kind of interface will be implemented in Outlook 2010 is unclear so far, that is why I am leaving the code as is,  with 2 QueryInterface calls:

Private Function GetMAPIProp( _
    ByVal oMAPIObject As Object, _
    ByVal uiPropertyTag As UInteger) 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)
        Dim guidMAPIProp As Guid = New Guid(MAPI.IID_IMAPIProp)
        Dim res = Marshal.QueryInterface(IUnk, guidMAPIProp, IProperty)
        If (res <> MAPI.S_OK) Then
            Dim guidMAPIAttach As Guid = New Guid(MAPI.IID_IAttachment)
            Marshal.QueryInterface(IUnk, guidMAPIAttach, IProperty)
            If (res <> MAPI.S_OK) Then Return 0
        End If
        Try
            MAPI.HrGetOneProp(IProperty, uiPropertyTag, pPropValue)
            If (pPropValue = IntPtr.Zero) Then Return 0
            Dim propValue As SPropValue
            propValue = _
                Marshal.PtrToStructure(pPropValue, propValue.GetType())
            result = propValue.Value And UInt32.MaxValue
        Catch ex As System.Exception
            Throw ex
        End Try
    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

Have a nice weekend. I hope the weather will finally get better here and I will go fishing to enjoy peace and tranquility, at last!

You may also be interested in:

How to develop an Outlook COM add-in step-by-step
Advanced features for Outlook toolbars, menus and ribbons

Available downloads:

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

2 Comments

  • Antonio NUZZO says:

    Hi, thanx for this useful code. (sorry for my english, I’m french). There is a function in Outlook 2010 that allows you to bulk resize all images attached into an email (File/Info/Resize large images when I send this messages).
    Do you know if that could be achieved through VBA code?
    Thanks in advance

  • Eugene Astafiev says:

    Hi Antonio,

    The Outlook Object Model doesn’t provide any property or method exactly for this. However, you can try to handle ItemSend event of the Application class and re-attach resized images programmatically.

Post a comment

Have any questions? Ask us right now!