Export or Strip Email Attachments in Outlook

AID: 3562
  • Status: Published

12367 points

  • Byalainbryden
  • TypeTips/Tricks
  • Posted on2010-08-12 at 10:08:33
Awards
  • Community Pick
  • Experts Exchange Approved
Intro

I've seen a few requests floating around for scripts that will export or strip attachments out of emails, and so far have never encountered any high quality implementations of this feature, so I created this method with a little flavor. Whether you just want an easy way to save all attachments somewhere on your computer, or you're doing a bulk reduction of your inbox size, this script should satisfy your needs.

All you need to do is select the emails you want to export or remove attachments from, and click your new "Export Attachments" button:
Step1.PNG
  • 14 KB
  • Export Attachments
Export Attachments


Specify your file path:
Step2.PNG
  • 47 KB
  • Specify File Path
Specify File Path


Choose whether or not you want to remove attachments from the original message(s):
Step3.PNG
  • 12 KB
  • Option to remove attachments or just export
Option to remove attachments or just export


(Don't worry about overwriting same-named files, I have you covered):
Overwrite.PNG
  • 10 KB
  • Prevents Unwanted Overwriting
Prevents Unwanted Overwriting


And presto! Your attachments have been saved to the desired location:
Step4.PNG
  • 52 KB
  • Attachments Exported
Attachments Exported


And if you chose to strip attachments, your emails will now be conveniently prepended with the files it used to contain, their size, and a link to the path where they were saved:
Step5.PNG
  • 24 KB
  • Attachments Stripped
Attachments Stripped




Here's how you make yourself an Export Attachments feature in Outlook

1

Insert a New Module

You're going to be making a VBA macro for going through messages and attachments. To do this, you need to open up the VBA project for your Outlook (by pressing Alt+F11). When it opens, your window will look similar to the one in the screen shot below. Then, right click your project on the left, and click Insert, Module, as shown:



2

Paste in the Macro Code

The hard work has all been done for you :)
The code below takes care of all the features describe above (and more). Just copy paste it into the window, and you're almost ready to go! The code to copy in is below:

Option Explicit

Public Sub ExportAttachments()
    Dim objOL As Outlook.Application
    Dim objMsg As Object
    Dim objAttachments As Outlook.Attachments
    Dim objSelection As Outlook.Selection
    Dim i As Long, lngCount As Long
    Dim filesRemoved As String, fName As String, strFolder As String, saveFolder As String, savePath As String
    Dim alterEmails As Boolean, overwrite As Boolean
    Dim result
    
    saveFolder = BrowseForFolder("Select the folder to save attachments to.")
    If saveFolder = vbNullString Then Exit Sub
    
    result = MsgBox("Do you want to remove attachments from selected file(s)? " & vbNewLine & _
    "(Clicking no will export attachments but leave the emails alone)", vbYesNo + vbQuestion)
    alterEmails = (result = vbYes)
    
    Set objOL = CreateObject("Outlook.Application")
    Set objSelection = objOL.ActiveExplorer.Selection
    
    For Each objMsg In objSelection
        If objMsg.Class = olMail Then
            Set objAttachments = objMsg.Attachments
            lngCount = objAttachments.Count
            If lngCount > 0 Then
                filesRemoved = ""
                For i = lngCount To 1 Step -1
                    fName = objAttachments.Item(i).FileName
                    savePath = saveFolder & "\" & fName
                    overwrite = False
                    While Dir(savePath) <> vbNullString And Not overwrite
                        Dim newFName As String
                        newFName = InputBox("The file '" & fName & _
                            "' already exists. Please enter a new file name, or just hit OK overwrite.", _
                            "Confirm File Name", fName)
                        If newFName = vbNullString Then GoTo skipfile
                        If newFName = fName Then overwrite = True Else fName = newFName
                        savePath = saveFolder & "\" & fName
                    Wend
                    
                    objAttachments.Item(i).SaveAsFile savePath
                    
                    If alterEmails Then
                        filesRemoved = filesRemoved & "<br>""" & objAttachments.Item(i).FileName & """ (" & _
                                                                formatSize(objAttachments.Item(i).size) & ") " & _
                            "<a href=""" & savePath & """>[Location Saved]</a>"
                        objAttachments.Item(i).Delete
                    End If
skipfile:
                Next i
                
                If alterEmails Then
                    filesRemoved = "<b>Attachments removed</b>: " & filesRemoved & "<br><br>"
                    
                    Dim objDoc As Object
                    Dim objInsp As Outlook.Inspector
                    Set objInsp = objMsg.GetInspector
                    Set objDoc = objInsp.WordEditor

                    objMsg.HTMLBody = filesRemoved + objMsg.HTMLBody
                    objMsg.Save
                End If
            End If
        End If
    Next
    
ExitSub:
    Set objAttachments = Nothing
    Set objMsg = Nothing
    Set objSelection = Nothing
    Set objOL = Nothing
End Sub

Function formatSize(size As Long) As String
    Dim val As Double, newVal As Double
    Dim unit As String
    
    val = size
    unit = "bytes"
    
    newVal = Round(val / 1024, 1)
    If newVal > 0 Then
        val = newVal
        unit = "KB"
    End If
    newVal = Round(val / 1024, 1)
    If newVal > 0 Then
        val = newVal
        unit = "MB"
    End If
    newVal = Round(val / 1024, 1)
    If newVal > 0 Then
        val = newVal
        unit = "GB"
    End If
    
    formatSize = val & " " & unit
End Function

'Function purpose:  To Browser for a user selected folder.
'If the "OpenAt" path is provided, open the browser at that directory
'NOTE:  If invalid, it will open at the Desktop level
Function BrowseForFolder(Optional Prompt As String, Optional OpenAt As Variant) As String
    Dim ShellApp As Object
    Set ShellApp = CreateObject("Shell.Application").BrowseForFolder(0, Prompt, 0, OpenAt)

    On Error Resume Next
    BrowseForFolder = ShellApp.self.Path
    On Error GoTo 0
    Set ShellApp = Nothing
     
    'Check for invalid or non-entries and send to the Invalid error handler if found
    'Valid selections can begin L: (where L is a letter) or \\ (as in \\servername\sharename.  All others are invalid
    Select Case Mid(BrowseForFolder, 2, 1)
        Case Is = ":": If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
        Case Is = "\": If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
        Case Else: GoTo Invalid
    End Select
     
    Exit Function
Invalid:
     'If it was determined that the selection was invalid, set to False
    BrowseForFolder = vbNullString
End Function

Function BrowseForFile(Optional Prompt As String, Optional OpenAt As Variant) As String
    Dim ShellApp As Object
    Set ShellApp = CreateObject("Shell.Application").BrowseForFolder(0, Prompt, 16 + 16384, OpenAt)
    
    On Error Resume Next
    BrowseForFile = ShellApp.self.Path
    On Error GoTo 0
    Set ShellApp = Nothing
     
    'Check for invalid or non-entries and send to the Invalid error handler if found
    'Valid selections can begin L: (where L is a letter) or \\ (as in \\servername\sharename.  All others are invalid
    Select Case Mid(BrowseForFolder, 2, 1)
        Case Is = ":": If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
        Case Is = "\": If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
        Case Else: GoTo Invalid
    End Select
     
    Exit Function
Invalid:
     'If it was determined that the selection was invalid, set to False
    BrowseForFile = vbNullString
End Function

                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:

Select allOpen in new window


When you've pasted it in, everything should look like this. The code is pretty straightforward, so those of you who like to dig in should be able to understand and customize it at will:

PastedCode.PNG
  • 82 KB
  • Code Pasted into VBA Project
Code Pasted into VBA Project



3

Add a Button for Your Macro

Now you can close down the Microsoft Visual Basic window. You've done the hard part. Next we want to add the macro to the toolbar so that you can use it conveniently. Right click on a blank area of the toolbar as shown, and click "Customize...". This will bring up the Outlook Customize Toolbars dialogue.



4

Drag your Macro Onto the Toolbar

You have to find your macro and drag it onto the Toolbar now. Switch to the "Commands" tab in the dialogue, and select "Macros" from the list on the left. You should see "ExportAttachments" macro there. Select it and drag it to wherever you want it on your toolbar:

AddButton.PNG
  • 33 KB
  • Add the Macro to the Toolbar
Add the Macro to the Toolbar



5

Rename the Button

You probably don't like the ugly name Outlook has given your button, so go ahead and rename it. To do this, click the "Rearrange Commands" button at the bottom of the dialogue we have open (I know - pretty unintuitive). A new dialogue will open. Click the "Toolbar" option button (instead of "Menu Bar") and find the new button you just created. When you find it, select it and click the "Modify Selection" button. Here, you can rename it to whatever you want. Here's an illustration:

RenameButton.PNG
  • 43 KB
  • Rename the Button
Rename the Button



If you want, you can give your button a shortcut by inserting an ampersand (&) in front of the letter you want to be the shortcut. Then when you press Alt+'That Letter', it will trigger the button. Careful, if you chose a letter that is already a shortcut (like E for the 'Edit' menu item) then you'll have to press Alt+E+E(again) to cycle through to your button.



6

Test it out!

Now test it out! Select one or more emails, click the button, and save out your attachments. Isn't that sharp?

Step1.PNG
  • 14 KB
  • Export Attachments
Export Attachments


Step5.PNG
  • 24 KB
  • Attachments Stripped
Attachments Stripped




A few extra notes

  • If you're about to overwrite a file, the dialogue pops up to confirm the overwrite or let you change the file name. If you keep changing the name to that of a file that already exists, it will keep prompting you  :)
  • The code puts a nicely formatted message at the top of your emails, including all the names of removed files, and their sizes, and even the path where they were saved (as a url). You can customize this message if you edit the code.
  • If you move the file after you've saved it, the link in the emails doesn't get updated (unless you do it manually), so be aware if you plan to make use of this feature to track down attachments in the future - save it where you want to store it!
  • If you click cancel in the initial folder chooser dialogue, the whole routine will end. If you click cancel when picking a new name for a file that already exists, it will just skip that file and leave it attached to the email.
  • If you want a button that will always strip attachments, or one that will always just save all attachments, but leave the email as is, you can easily modify this macro to not prompt you and always perform the desired action.
    For instance, replacing the lines
result = MsgBox("Do you want to remove attachments from selected file(s)? " & vbNewLine & _
    "(Clicking no will export attachments but leave the emails alone)", vbYesNo + vbQuestion)
alterEmails = (result = vbYes)

                                    
1:
2:
3:

Select allOpen in new window


with just
alterEmails = false

                                    
1:

Select allOpen in new window

will cause the macro to just save attachments but not strip them out.


One other thing you might want to consider is changing the icon of your button. I'm sure you've noticed that that nice icon on the first page doesn't appear on its own. I created that in the same place as I renamed the button. After clicking "Modify Selection", click "Modify button icon..." and you will get a window where you can specify your own icon. This is how I designed mine:
ButtonEditor.PNG
  • 15 KB
  • Design your own Button Icon
Design your own Button Icon



Enjoy, and if you found this article handy, let me know and click "Yes" at the top of the page!

--
Alain Bryden

PS: If you're curious about that 'Archive Message(s)' button on my toolbar, you can check out my article about it here: How to make an 'Archive' button in Outlook
Other articles by me.
    Asked On
    2010-08-12 at 10:08:33ID3562
    Tags

    Outlook

    ,

    Attachment

    ,

    Strip

    ,

    Archive

    ,

    Save

    ,

    Button

    ,

    Manage

    ,

    Email

    ,

    VBA

    ,

    Macro

    Topic

    Outlook Groupware Software

    Views
    6477

    Comments

    Expert Comment

    by: mwvisa1 on 2010-08-12 at 11:39:31ID: 18124

    Alain, brilliant!
    Look how much cooler my icon is, though.
    ExportAttachIcon.PNG
    • 2 KB
    • My Cooler Icon
    My Cooler Icon

    Seriously, as a testament to your article, having the icon image and at a decent size I was easily able to replicate even that detail in implementing this in my system.

    I love this Macro, very nicely done ...

    You have my Yes vote.

      Expert Comment

      by: Qlemo on 2010-08-12 at 14:16:31ID: 18134

      Good stuff! This article shows how you can do that replacing/removing thing with own code.

      I for myself use Outlook Attachment Remove Add-In (http://www.kopf.com.br/outlook/) for exact the same action. It never had any issues replacing the attachments with file system links, or removing them completely. It has some more options and is free. If you do not like to use own code, it is really worth a try.

      Expert Comment

      by: dcmathis on 2010-10-15 at 07:30:45ID: 20523

      This is just the tool that I'm looking for.  However, I'm getting a runtime error when trying to run the macro.  If it makes a difference, I'm using outlook 2010.  Specifically, the flagged line is line 62, "                    objMsg.HTMLBody = filesRemoved + objMsg.HTMLBody"  Any chance that this could be related to the version of Outlook?

      Sorry, I'm not a visual basic programmer, so I'm a little in the dark here.

      Thanks.

      Expert Comment

      by: dcmathis on 2010-10-15 at 07:54:41ID: 20524

      Oops.  I guess I should have been more specific.  When I run the macro, it strips the attachment and saves it where instructed, but then generates a Runtime error "5": Invalid procedure call or argument.  I wonder if the problem is the .HTMLBody part of the command, as this isn't defined anywhere in the macro.

      At any rate, when I close the email message I'm asked if I want to save the changes.  If I say no, then the attachment is left in the message.  If I say yes, then the attachment is NOT saved in the message, but neither are the comments that should be there, i. e. attachment name and where saved.

      Thoughts?

      Author Comment

      by: alainbryden on 2010-10-15 at 08:17:31ID: 20525

      Sorry, this is only guaranteed to work for Outlook 2003 and 2007. I would have expected it to work for 2010 as well, but Microsoft could have very well changed their object model to no longer support writing to the objMsg.HTMLBody property. This might also be disabled due to a security setting on your system so that viruses can't alter the content of emails before you send them out. Maybe if you post a question referring to this article an expert with Outlook 2010 can figure out whether or not this can be made to work.

      Cheers,
      Alain

      Expert Comment

      by: dcmathis on 2010-10-27 at 09:54:38ID: 20892

      Alain,  Sorry, my mistake.  It does work fine, as long as the email message is displayed as html.  If the message is displayed as plain text, then the file is exported just fine, but the note isn't inserted in the email message.
       Two more questions:  
      1.  How would I modify it to prompt for a filename in all situations, rather than just if the file already exists, or possibly utilize the default "Save As" dialog box?  
      2.  How would I modify it to actually display the path to to the saved attachment instead of the [Location Saved] text, perhaps while still having it be a clickable link?

      Thanks again for a great tool.

      Dow

      Author Comment

      by: alainbryden on 2010-10-27 at 10:59:10ID: 20893

      1. Unfortunately, Outlook does not have provide access to the nice Save As dialogue in VBA the way Excel does, which is why I used the folder selection solution I did. With work, one might be able to come up with a better solution.

      To always ask for a file name, Replace
      While Dir(savePath) <> vbNullString And Not overwrite
                                              
      1:
      

      Select allOpen in new window

      with just
      Do
                                              
      1:
      

      Select allOpen in new window

      and then at the end of the loop, replace
      Wend
                                              
      1:
      

      Select allOpen in new window

      with
      Loop While Dir(savePath) <> vbNullString And Not overwrite
                                              
      1:
      

      Select allOpen in new window



      2. Replace the following line with the one below it.
      "<a href=""" & savePath & """>[Location Saved]</a>"
                                              
      1:
      

      Select allOpen in new window

      "<a href=""" & savePath & """>" & savePath & "</a>"
                                              
      1:
      

      Select allOpen in new window



      Cheers,
      Alain

      Expert Comment

      by: dcmathis on 2010-10-27 at 15:03:56ID: 20898

      FANTABULOUS!!!!

      Thanks a million!

      Expert Comment

      by: thims on 2010-12-10 at 13:22:12ID: 21977

      Why so complex way? There are free tools that perform this and many more:
      http://www.outlookfreeware.com/en/products/attachments/

      Expert Comment

      by: BrianEsser on 2011-01-04 at 17:43:24ID: 22678

      Excellent! Thanks for your efforts - This was perfect for what I was looking for.
      I didn't have to register with another website and I learned some things in the process thanks to your HIGH quality work. You made it a cake walk and simplified the complexities completely as far as I'm concerned.

      What would be a good way to get you some points or recognition for your efforts?

      Cheers,
      Brian

      Author Comment

      by: alainbryden on 2011-01-04 at 20:53:30ID: 22683

      Just voting this article helpful gets me points, so I thank you for that and for the kind words of encouragement :)

      Alain

      Expert Comment

      by: Jofnn on 2011-02-01 at 03:51:17ID: 23361

      Fantastic Alain!

      Only one tweek I'd recommend, would be to have a variable read the "received date" so that it could be pumped into the filename... i.e. for easy filtering:  Turning the file name into something like

      (strRCVDATE)_(strEXPDATE)_(filename)

      Where strRCVDATE is when it was received... strEXPDATE is where it was exported

      Any ideas how to achieve this?

      Author Comment

      by: alainbryden on 2011-02-01 at 19:46:32ID: 23394

      You could get those strings by running the objMsg.ReceivedTime and Now() values through Format( value, "yyyy/mm/dd") - and then concatenating them with the file name.

      Hope that helps ./

      Author Comment

      by: alainbryden on 2011-03-14 at 09:28:30ID: 24703

      Some troubleshooting notes:

      After putting the macro into outlook, next time you close outlook, you should get a message:

      "Do you want to save the VBA project 'VbaProject.OTM'?"

      You should answer "Yes" so that the macro is available next time.


      It's possible that the next time you open Outlook - Outlook will detect the macro and disable it by default.

      If you go to Tools > Trust Center, and then click the tab called "Macro Security", you probably have "Warnings for signed macros; all unsigned macros are disabled" checked. Because this macro is unsigned (you made it yourself), outlook will disable it by default, so you will need to select "No security check for macros." This will allow the macro to work by default each time Outlook is restarted.

      Alain

      Expert Comment

      by: JGarza81 on 2011-04-13 at 09:32:21ID: 25745

      Hi Alain!

      I think this is great! I would like to make a small tweek to show that the file did have an attachment. I would like to be able to keep the attachment sign with the email so I know that e-mail had an attachment. Is there a way to creat a shortcut to the file and save that to the e-mail?

      Thanks!!
      Jerry

      Author Comment

      by: alainbryden on 2011-04-13 at 11:29:05ID: 25747

      Neat Idea.

      Hopefully it won't be too much trouble. Just use the short bit of code on this page to create your shortcut:
      http://www.vbforums.com/showthread.php?t=234891

      Next use
      objMsg.Attachments.Add filePath
                                              
      1:
      

      Select allOpen in new window

      after stripping attachments, but before you save the email back.

      Finally, delete the shortcut you created in a temporary location.

      Expert Comment

      by: JGarza81 on 2011-04-13 at 11:47:49ID: 25748

      Thanks Alain! I am going to play around with your idea and try and get it to work. I really like that. After some reasearch, another way to show the attachment sign is to make a blank text file to attach after the attachment as been stripped. Using your code bit, I set this up and it worked well. I would rather have what you have proposed, so I will play with that.

      temp = saveFolder & "\Attachments Removed.txt"
                              objAttachments.Add temp, olByValue, , "Attachments Removed"

      Now I am going to try and work on a way to get the attachments to save into SharePoint! Fun!

      Expert Comment

      by: LearnHow on 2011-04-29 at 13:51:49ID: 26128

      How can one included the email with the extracted attachment?

      Author Comment

      by: alainbryden on 2011-04-30 at 20:43:52ID: 26143

      Hey, you'll want to use objMsg.SaveAs to save the email itself out to file. You'll have to decide whether you want to do that before or after you've stripped attachments and added text to the original body of the email.

      Add your Comment

      Please Sign up or Log in to comment on this article.

      Join Experts Exchange Today

      Gain Access to all our Tech Resources

      Get personalized answers

      Ask unlimited questions

      Access Proven Solutions

      Search 3.2 million solutions

      Read In-Depth How-To Guides

      1000+ articles, demos, & tips

      Watch Step by Step Tutorials

      Learn direct from top tech pros

      And Much More!

      Your complete tech resource

      See Plans and Pricing

      30-day free trial. Register in 60 seconds.

      Loading Advertisement...

      Top Outlook Experts

      1. apache09

        663,644

        Sage

        2,168 points yesterday

        Profile
        Rank: Genius
      2. alanhardisty

        170,946

        Guru

        0 points yesterday

        Profile
        Rank: Genius
      3. demazter

        131,854

        Master

        0 points yesterday

        Profile
        Rank: Genius
      4. chris_bottomley

        109,375

        Master

        2,800 points yesterday

        Profile
        Rank: Genius
      5. thinkpads_user

        95,624

        Master

        750 points yesterday

        Profile
        Rank: Genius
      6. Rajkumar-MCITP

        89,780

        Master

        0 points yesterday

        Profile
        Rank: Guru
      7. l33tf0b

        83,091

        Master

        0 points yesterday

        Profile
        Rank: Wizard
      8. BlueDevilFan

        73,191

        Master

        50 points yesterday

        Profile
        Rank: Savant
      9. jjmck

        66,336

        Master

        0 points yesterday

        Profile
        Rank: Genius
      10. Neilsr

        61,466

        Master

        0 points yesterday

        Profile
        Rank: Genius
      11. amitkulshrestha

        61,377

        Master

        0 points yesterday

        Profile
        Rank: Genius
      12. jcimarron

        49,232

        0 points yesterday

        Profile
        Rank: Genius
      13. ve3ofa

        46,002

        0 points yesterday

        Profile
        Rank: Genius
      14. dlmille

        45,200

        0 points yesterday

        Profile
        Rank: Genius
      15. akicute555

        44,979

        10 points yesterday

        Profile
        Rank: Wizard
      16. Anuroopsundd

        44,529

        0 points yesterday

        Profile
        Rank: Sage
      17. HendrikWiese

        40,896

        2,000 points yesterday

        Profile
        Rank: Sage
      18. Exchange_Geek

        37,449

        0 points yesterday

        Profile
        Rank: Sage
      19. jordannet

        36,757

        0 points yesterday

        Profile
        Rank: Wizard
      20. acbrown2010

        34,652

        0 points yesterday

        Profile
        Rank: Genius
      21. diverseit

        34,600

        0 points yesterday

        Profile
        Rank: Guru
      22. WORKS2011

        32,775

        0 points yesterday

        Profile
        Rank: Guru
      23. e_aravind

        31,941

        0 points yesterday

        Profile
        Rank: Genius
      24. JBlond

        31,700

        0 points yesterday

        Profile
        Rank: Sage
      25. limjianan

        30,910

        0 points yesterday

        Profile
        Rank: Genius

      Hall Of Fame