This code sample will save one or more selected messages to your My Documents folder as individual .msg files. The file name includes the received date and time. Spaces and invalid characters are replaced with underscores.
A variation of this macro that saves as a text file is at Save email message as text file. Included is a version that saves selected messages as one text file. For more information on saving to other formats, see How to Save Email in Windows File System.
See How to use the VBA Editor if you don't know how to use macros or the VBA Editor.
Updated December 17 2014: macro checks for message class and skips meetings and report/receipt messages. I also added character replacements for single quote and asterisk.
Option Explicit Public Sub SaveMessageAsMsg() Dim oMail As Outlook.MailItem Dim objItem As Object Dim sPath As String Dim dtDate As Date Dim sName As String Dim enviro As String enviro = CStr(Environ("USERPROFILE")) For Each objItem In ActiveExplorer.Selection If objItem.MessageClass = "IPM.Note" Then Set oMail = objItem sName = oMail.Subject ReplaceCharsForFileName sName, "-" dtDate = oMail.ReceivedTime sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _ vbUseSystem) & Format(dtDate, "-hhnnss", _ vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".msg" sPath = enviro & "\Documents\" Debug.Print sPath & sName oMail.SaveAs sPath & sName, olMSG End If Next End Sub Private Sub ReplaceCharsForFileName(sName As String, _ sChr As String _ ) sName = Replace(sName, "'", sChr) sName = Replace(sName, "*", sChr) sName = Replace(sName, "/", sChr) sName = Replace(sName, "\", sChr) sName = Replace(sName, ":", sChr) sName = Replace(sName, "?", sChr) sName = Replace(sName, Chr(34), sChr) sName = Replace(sName, "<", sChr) sName = Replace(sName, ">", sChr) sName = Replace(sName, "|", sChr) End Sub
Pick the Folder Location
To select the folder where you want to save the selected messages, you can use the BrowseForFolder function. You'll need to select the folder before you begin saving the messages. If you select it after the For Each loop, you'll need to select a folder for each message.
Don't forget to get the BrowseForFolder function.
Option Explicit Public Sub SaveMessageAsMsg() Dim oMail As Outlook.MailItem Dim objItem As Object Dim sPath As String Dim dtDate As Date Dim sName As String Dim enviro As String Dim strFolderpath As String enviro = CStr(Environ("USERPROFILE")) 'Defaults to Documents folder ' get the function at http://slipstick.me/u1a2d strFolderpath = BrowseForFolder(enviro & "\documents\") ' Cleanly exit if Cancel is clicked If StrFolderpath = "False" Then Cancel = True Exit Sub End If For Each objItem In ActiveExplorer.Selection If objItem.MessageClass = "IPM.Note" Then Set oMail = objItem sName = oMail.Subject ReplaceCharsForFileName sName, "-" dtDate = oMail.ReceivedTime sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _ vbUseSystem) & Format(dtDate, "-hhnnss", _ vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".msg" sPath = strFolderpath & "\" Debug.Print sPath & sName oMail.SaveAs sPath & sName, olMSG End If Next End Sub
Save messages as they are sent
This version of the macro will save messages to the user's My Documents folder as they are added to the Sent Items folder, using "Now" to create the time and date stamp. If the subject contains illegal filename characters, you'll need the ReplaceCharsForFileName sub above.
Private WithEvents objSentItems As Items Private Sub Application_Startup() Dim objSent As Outlook.MAPIFolder Set objNS = Application.GetNamespace("MAPI") Set objSentItems = objNS.GetDefaultFolder(olFolderSentMail).Items Set objNS = Nothing End Sub Private Sub objSentItems_ItemAdd(ByVal Item As Object) Dim sPath As String Dim dtDate As Date Dim sName As String Dim enviro As String enviro = CStr(Environ("USERPROFILE")) sName = Item.Subject ReplaceCharsForFileName sName, "-" dtDate = Item.ReceivedTime sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _ vbUseSystem) & Format(dtDate, "-hhnnss", _ vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".msg" sPath = enviro & "\Documents\" Debug.Print sPath & sName Item.SaveAs sPath & sName, olMSG End Sub
Use a Userform to display locations to choose from
This version of the macro uses a userform to display locations to choose from.
To use this macro, you need to put this line in a module, not in Thisoutlooksession.
Public lstNum As Long
This code goes into ThiOutlookSession:
Option Explicit Public WithEvents objSentItems As Items Public Sub Application_Startup() Dim objSent As Outlook.MAPIFolder Dim objNS As Object Set objNS = Application.GetNamespace("MAPI") Set objSentItems = objNS.GetDefaultFolder(olFolderSentMail).Items Set objNS = Nothing End Sub Public Sub objSentItems_ItemAdd(ByVal Item As Object) Dim dtDate As Date Dim sName As String Dim sPath As String UserForm1.Show Debug.Print lstNum Select Case lstNum Case -1 ' -1 is what you want to use if nothing is selected sPath = "C:\Users\slipstick\Documents\" Case 0 sPath = "C:\Users\slipstick\Documents\Email Attach\" Case 1 sPath = "C:\Users\slipstick\Documents\pics\" Case 2 sPath = "C:\Users\slipstick\Documents\Balsam Lake\" End Select sName = Item.Subject ReplaceCharsForFileName sName, "-" dtDate = Item.ReceivedTime sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _ vbUseSystem) & Format(dtDate, "-hhnnss", _ vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".msg" Debug.Print sPath & sName Item.SaveAs sPath & sName, olMSG End Sub Public Sub ReplaceCharsForFileName(sSubject As String, _ sChr As String _ ) sName = Replace(sName, "'", sChr) sName = Replace(sName, "*", sChr) sName = Replace(sName, "/", sChr) sName = Replace(sName, "\", sChr) sName = Replace(sName, ":", sChr) sName = Replace(sName, "?", sChr) sName = Replace(sName, Chr(34), sChr) sName = Replace(sName, "<", sChr) sName = Replace(sName, ">", sChr) sName = Replace(sName, "|", sChr) End Sub
This code goes into the UserForm. Name the OK button btnOK. See VBA UserForm sample: Select from a list of templates for step-by-step instructions to design the userform.
Private Sub UserForm_Initialize() With ListBox1 .AddItem "Email Attach" .AddItem "pics" .AddItem "Balsam Lake" End With End Sub Private Sub btnOK_Click() lstNum = ListBox1.ListIndex Unload Me End Sub
When you send a message, the userform comes up with the list of folder locations to choose from.
How to use the macros on this page
First: You need to have macro security set to low during testing. The macros will not work otherwise.
To check your macro security in Outlook 2010 and newer, go to File, Options, Trust Center and open Trust Center Settings, and change the Macro Settings. In Outlook 2007 and older, look at Tools, Macro Security.
After you test the macro and see that it works, you can either leave macro security set to low or sign the macro.
Some macros need to be in ThisOutlookSession, others go into a module or can be placed in either ThisOutlookSession or a module. The instructions are below.
Open the VBA Editor by pressing Alt+F11 on your keyboard.
To put the code in a module:
- Right click on Project1 and choose Insert > Module
- Copy and paste the macro into the new module.
To put the macro code in ThisOutlookSession:
- Expand Project1 and double click on ThisOutlookSession.
- Copy then paste the macro into ThisOutlookSession. (Click within the code, Select All using Ctrl+A, Ctrl+C to copy, Ctrl+V to paste.)
More information as well as screenshots are at How to use the VBA Editor
More Information
- How to Save Email in Windows File System
- Import Messages from File System into Outlook Folders
- OWA: Save Messages to My Documents
- Save a Message as HTML and Delete the (Annoying) Folder
- Save email message as text file
- Save Outlook Email as a PDF
- Saving All Messages to the Hard Drive Using VBA
To save all incoming messages as files as they arrive in your Inbox, see E-Mail: Save new items immediately as files (VBOffice.net)
Hi everybody,
How can I deleta an e-mail in Outlook after copying it to a disk?
How to remove an e-mail after it has been saved as an *.msg file?
Hello Diane,
Thanks for your sharing, it has been a of a great help for me in daily task now!
However, Due to the requirements of my job, I want to set the file name by the principle: items in content body email+year/month/day_number of ascending from 1..n.
For example, here is the body content email:
From: xxx@yyy.zzzz
Sent: 15 August, 2023 8:34 AM
To: pic@abc.com
Subject: Notice of change of e-invoice
" Dear: ABC Company (MST: 0345287134)
Invoice of Company with information:
- Invoice form symbol: 1
- Invoice symbol: C23TYY
- Invoice number: 10
- Date of establishment: August 14, 2023
- Seller of goods and providing services: XYZ CO., LTD (MST:2912857402) Has been replaced by invoice form symbol: 1, invoice symbol: C23TYY, invoice number: 12, date of making : 15/08/2023 In case you need more detailed information, please contact the seller of goods and provide services.
Sincerely thank you! "
With this email, i would like to save as msg file with the name:
0345287134_20230815-1
If have more email from this supplier, the name file will be:
0345287134_20230815-2
0345287134_20230815-3
.....
0345287134_20230815-n
Hope to have your continued support, thanks you!
Hi Diane,
I hope you are doing well.
I was wondering if you are still responding to comments from this article? This code has proven so valuable to me but I am having some issues trying to change the folder path to which I want the emails saved when running the code.
May I ask if you can could please offer some input? I want to change to a folder I've created inside my Documents folder but I can't get them there for some unknown reason. I'm very new to all of this so I'm not entirely sure as to how to incorporate other functions into the code if that is required (?). I'm using the default code (the first one in the article). I have a folder called 'OLAttachments' in my Documents folder but I've tried changing the path in the script to the full one that leads to that to no avail.
I'm at a standstill here and would be more than grateful for any and all help.
I wish you all the best!
Hi Diane
Been using this VBA for years and am now finding that my Office 365 which has just been updated by the company is now giving that error message,
"Cannot Open MSG File (Error: We can't open .msg. Its possible the file is already open, or you don't have permission)"..
The work around is to go into File Explorer and select the file properties and change it to Read-Only. This works, but a real pain to do it every time.
Here's a ref to the error.
https://answers.microsoft.com/en-us/outlook_com/forum/all/cannot-open-saved-msg-file/095ff296-5fd1-44fa-955c-61e4f4197430?page=1
Thought maybe there is a one liner I could add to the VBA that would automatically save the .msg file with read-only property. Do you know if that could be done? Then I'd just make the line in-active if Microsoft ever fixes this thing again. It took them 5 years to fix it the last time...
Thanks
This is really wonderful - thank you for your contribution!
Rather than run on selected messages, is there a way to loop through the entire contents of a PST file (including subfolders)? I'm trying to do some mass backups, and this would be incredibly useful.
Hi All,
I used this script with success but faced issues with path/filename length.
It would be nice that at least the name of the msg file would be shortened till the maximum length.
I'm not sure how to implement it so any help is appreciated.
This block sets the file name -
sName = Item.Subject
ReplaceCharsForFileName sName, "-"
dtDate = Item.ReceivedTime
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, "-hhnnss", _
vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".msg"
the first two lines use the subject and remove characters that are illegal in the file name. If you have a long subject, you can shorten it - this gets the first 20 characters of the subject.
sName = left(item.subject, 20)
This would remove illegal characters instead of replacing them
ReplaceCharsForFileName sName, ""
The next part is the received date - in 20211028-080822 format. The reason for using the full time is in the event there are two messages with the same subject and received minute.
You can shorten it to 2110280808 by removing 2 2's, the -, and the s's from the date format.
dtDate = Item.ReceivedTime
sName = Format(dtDate, "yymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, "hhnn", _
vbUseSystemDayOfWeek, vbUseSystem)
This line puts the two together - you can remove '& -' to use "2110280808subject-20-character"
& "-" & sName & ".msg"
Hello Diane,
Thanks for your script, it has been a of a great help for me for almost 2 years now. Which is fantastic.
However, last week I updated from MS 2010 to O365 and since then the first time Outlook lauches all the new e-mails that were received overnight (when outlook was closed) are not flagged as new items and not backed up. The scripts starts normally and save all the new messages after outlook is opened, but I miss the automatick backups on the ones received overnight.
I've been manually saving those few e-mails, but was wondering if you have had (or know about) any similar issue and knows how I can work around it.
Appreciate your time and Attention
What type off email account are you using? It shouldn't matter... and there should be no differences with the versions.