Skip to content

Instantly share code, notes, and snippets.

@mavaddat
Last active July 2, 2024 11:11
Show Gist options
  • Save mavaddat/1487f812ad4024b18991a602d9a4ff7f to your computer and use it in GitHub Desktop.
Save mavaddat/1487f812ad4024b18991a602d9a4ff7f to your computer and use it in GitHub Desktop.
Drizin's EML importer for Outlook Desktop

Importing EML files (or Outlook Express DBX) into Outlook 2010

25 Mar 2011

There are some documented ways of exporting Outlook Express emails to Outlook 2010. One major problem with this migration, is that you need to have both Outlook Express and Outlook 2010 installed on the same machine. If you have installed Outlook 2010 on a fresh Windows installation it could even be impossible to do, since Outlook Express cannot be installed on x64 Operating Systems.

If you don’t have both on the same machine, the alternative proposed solution is to import your EBX mailboxes from Outlook Express to Windows Live Mail first, and then exporting from Windows Live Mail to Outlook 2010.

Having been through that, I can tell you that this method is a pain in the ass. First of all, I noticed that many emails from Outlook Express were not being copied to Windows Live Mail. Next, I realized that even the emails which were appearing in Windows Live Mail could not be exported to Outlook 2010, failing with a MAPI error, and as far as I researched there is no fix available for 64-bit systems.

Having said that, I found this Portable Outlook Express Message Extractor, a nice freeware utility which could export EML files from Outlook Express. According to my tests, all emails have been exported, which proved to be better than Windows Live Mail importing.

After having exported EML files, all of them grouped in windows folders which mimic the same folder names of Outlook Express, I needed to found something to import those emails to Outlook.

I found some shareware programs that are supposed to import EML files into Outlook 2010, but I was very surprised that Outlook doesn’t have this as native feature.

Instead of buying the shareware, I decided to create my own VBA macro for that, since I have large VBA programming background. To my surprise, although Outlook can open EML files, there is no way to do it programatically only with VBA. So I created this VBA macro which loops through some folder, and opens each EML file by using SHELL EXEC. It may take a few milliseconds until Outlook opens the EML file, so the VBA waits until something is open in ActiveInspector. Finally, this email is copied into some chosen folder, and (in case of success) the original EML file is deleted.

This macro crashes sometimes, but you can restart the macro at any time, and it will restart from where it previously crashed (remember, all successfully imported EML files are deleted). If it keeps crashing after restart, then probably there is a problem with the next EML file which is about to be imported. In this case you can just delete the problematic EML.

PS: Sometimes you can open the EML yourself, without crashing Outlook, but according to my tests, everytime that a EML file was crashing Outlook it was something unimportant, like read receipts.

'----------------------------------------------------
' Code by Ricardo Drizin (contact info at http://www.drizin.com.br) @Drizin
'----------------------------------------------------
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Option Explicit
'---------------------------------------------------------------------
' This method closes ActiveInspectors if any.
' All importing is based on the assumption that the EML
' is opened by shell and we can refer to it through the ActiveInspector
'---------------------------------------------------------------------
Function CloseOpenInspectors() As Boolean
Dim app As Outlook.Application: Set app = CreateObject("Outlook.Application")
Dim insp As Outlook.Inspector
Dim count As Integer
count = 0
repeat:
count = count + 1
Set insp = app.ActiveInspector
If TypeName(insp) = "Nothing" Then
CloseOpenInspectors = True
Exit Function
End If
If TypeName(insp.CurrentItem) = "Nothing" Then
CloseOpenInspectors = True
Exit Function
End If
If (count > 100) Then
MsgBox "Error. Could not close ActiveInspector. "
CloseOpenInspectors = False
End If
insp.Close (olDiscard)
GoTo repeat
End Function
'---------------------------------------------------------------------
' This method allows user to choose a Root Folder in Outlook
' All EML files will be imported under this folder
'---------------------------------------------------------------------
Function GetRootFolder() As Outlook.folder
Dim app As Outlook.Application: Set app = CreateObject("Outlook.Application")
Dim NS As Outlook.NameSpace: Set NS = app.GetNamespace("MAPI")
Dim fold As Outlook.folder
Set fold = NS.PickFolder
'MsgBox fold.Name
Set GetRootFolder = fold
End Function
'---------------------------------------------------------------------
' Creates a child folder in Outlook, under root folder.
'---------------------------------------------------------------------
Function GetChildFolder(parentFolder As Outlook.folder, name As String)
On Error Resume Next
Dim fold2 As Outlook.folder
Set fold2 = parentFolder.folders.Item(name)
If Err.Number Then
On Error GoTo 0
Set fold2 = parentFolder.folders.Add(name)
End If
On Error GoTo 0
'MsgBox fold2.Name
Set GetChildFolder = fold2
End Function
'---------------------------------------------------------------------
' Imports the EML open in the current ActiveInspector
' into the given folder
'---------------------------------------------------------------------
Sub ImportOpenItem(targetFolder As Outlook.folder)
Static appInspectorsCount As Long
Dim app As Outlook.Application: Set app = CreateObject("Outlook.Application")
Dim insp As Outlook.Inspector: Set insp = app.ActiveInspector
Dim retries As Integer
retries = 0
While TypeName(insp) = "Nothing" ' READING PANE should be visible, or else it will not work.
'MsgWaitObj (1000)
Sleep (50)
DoEvents
Sleep (50)
Set insp = app.ActiveInspector
retries = retries + 1
'If retries > 100 Then
' Stop
'End If
Wend
If TypeName(insp) = "Nothing" Then
MsgBox "Error! Could not find open inspector for importing email."
Exit Sub
End If
Dim m As Object, m2 As Object, m3 As Object
Set m = insp.CurrentItem
'MsgBox m.Subject
Set m2 = m.Copy
Set m3 = m2.Move(targetFolder)
m3.Save
Set m = Nothing
Set m2 = Nothing
Set m3 = Nothing
insp.Close (olDiscard)
Set insp = Nothing
If appInspectorsCount = 0 And app.Inspectors.count <> 0 Then
Debug.Print "app.Inspectors.Count: "; app.Inspectors.count
appInspectorsCount = app.Inspectors.count
End If
If app.Inspectors.count > appInspectorsCount Then
Debug.Print "app.Inspectors.Count: "; app.Inspectors.count
Stop
appInspectorsCount = 0
End If
End Sub
'---------------------------------------------------------------------
' Scans a given folder for *.EML files and import them
' into the given folder.
' Each EML file will be deleted after importing.
'---------------------------------------------------------------------
Sub ImportEMLFromFolder(targetFolder As Outlook.folder, emlFolder As String)
If Right(emlFolder, 1) <> "\" Then emlFolder = emlFolder & "\"
Dim firstImport As Boolean: firstImport = True
Dim file As String
Dim count As Integer: count = 0
'MsgBox fold.Items.count
'Exit Sub
file = Dir(emlFolder & "*.eml")
repeat:
If file = "" Then
'MsgBox "Finished importing EML files. Total = " & count
Debug.Print "Finished importing EML files. Total = " & count
Exit Sub
End If
count = count + 1
Debug.Print "Importing... " & file & " - " & emlFolder
Shell ("explorer """ & emlFolder & file & """")
'If firstImport Then Stop
firstImport = False
Sleep (50)
On Error GoTo nextfile
Call ImportOpenItem(targetFolder)
Call Kill(emlFolder & file)
nextfile:
On Error GoTo 0
Sleep (50)
file = Dir()
GoTo repeat
End Sub
'---------------------------------------------------------------------
' Main method.
' User chooses an Outlook root Folder, and a Windows Explorer root folder.
' All EML files inside this folder and in immediate subfolders will be imported.
'---------------------------------------------------------------------
Sub ImportAllEMLSubfolders()
If Not CloseOpenInspectors Then
MsgBox "Open Inspectors cannot be closed!. Try restarting Outlook"
Exit Sub
End If
MsgBox "Choose a root folder for importing "
Dim rootOutlookFolder As Outlook.folder
Set rootOutlookFolder = GetRootFolder()
If rootOutlookFolder Is Nothing Then Exit Sub
Dim rootWindowsFolder As String
rootWindowsFolder = "D:\OutlookExpress-EMLs-folder"
rootWindowsFolder = InputBox("Choose a windows folder where you have your EML files", , rootWindowsFolder)
If IsNull(rootWindowsFolder) Or IsEmpty(rootWindowsFolder) Or rootWindowsFolder = "" Then Exit Sub
If Right(rootWindowsFolder, 1) <> "\" Then rootWindowsFolder = rootWindowsFolder & "\"
Dim subFolders As New Collection
Dim subFolder As String
subFolder = Dir(rootWindowsFolder, vbDirectory)
repeat:
If subFolder = "." Or subFolder = ".." Then GoTo nextdir
If (GetAttr(rootWindowsFolder & subFolder) And vbDirectory) = 0 Then GoTo nextdir
subFolders.Add (subFolder)
nextdir:
subFolder = Dir()
If subFolder <> "" Then GoTo repeat
Dim outlookFolder As Outlook.folder
' Importing main folder
Call ImportEMLFromFolder(rootOutlookFolder, rootWindowsFolder)
' Importing subfolders
While subFolders.count
subFolder = subFolders.Item(1)
subFolders.Remove (1)
Set outlookFolder = GetChildFolder(rootOutlookFolder, subFolder)
Debug.Print "Importing " & rootWindowsFolder & subFolder & " into Outlook folder " & outlookFolder.name & "..."
Call ImportEMLFromFolder(outlookFolder, rootWindowsFolder & subFolder)
Wend
Debug.Print "Finished"
End Sub

How to Run VBA Code in Your Outlook

At times you may wish to utilize VBA code in Outlook to achieve more functions. Yet, you do not know how to run VBA code in your Outlook. Thus, this article will expose the detailed steps to you.

Thereinafter, we will take Outlook 2010 version as an example and show you the elaborate steps, ranging from modifying macro security settings to running VBA code. Now, read on to get them.

Step 1: Enable “Developer” Tab

  1. First of all, after launching Outlook, access “File” menu. Access File Menu
  2. Then, in “File” menu, select and click on “Options”. Select Options in File Menu
  3. Next, in the popup “Outlook Options” window, switch to “Customize Ribbon”.
  4. Later, on the right side, you can find out and enable the “Developer” tab. Enable the “Developer” Tab
  5. Lastly, click “OK”.

Step 2: Check Macro Security Settings

  1. After returning to Outlook main window, you can access “Developer” ribbon.
  2. Then, click on the “Macro Security” button. Open Macro Security
  3. In the subsequent screen, you should select “Notifications for all macros” and hit “OK” button. Change Macro Security

Step 3: Access Outlook VBA Editor

To run VBA code, you have to access the VBA editor firstly, which can be achieved by the following 2 means:

  1. In Outlook, under the “Developer” tab, click on the “Visual Basic” button. Access VBA Editor by "Visual Basic" Button
  2. Or you can directly press “Alt + F11” key buttons.

Step 4: Add VBA Code

  1. In VBA editor, namely “Microsoft Visual Basic for Applications” window, you need to expand the “Microsoft Outlook Objects” folder on left side
  2. Then, double click on the “ThisOutlookSession” project to open it. Open “ThisOutlookSession” Project
  3. Subsequently, you can copy and paste your VBA code into the white editing pane of this project. Paste VBA Code
  4. Optionally, you can copy the VBA code into a module.
  • Click “Insert” button in the menu bar.
  • Choose “Module” from the drop down list. Insert New Module
  • Then, a new module will display. Now you can copy code into the module as usual. New Module

Note: In general, you can paste the code into either “ThisOutlookSession” or a module. But, the VBA code involving events, like “Application_Start”, must be put in “ThisOutlookSession”.

Step 5: Run VBA Code

After adding the macro, you can run it. In the macro window, you can press “F5” key button or click on the “Run” button in the toolbar.Run VBA Code

Note: For the VBA code involving events, like “Application_Start”, you ought to restart your outlook to activate it.

Optional Step: Add Macro to Quick Access Toolbar or Ribbon

If you would like to run macro in the main Outlook window instead of in the VBA editor, you can add the macro to Quick Access Toolbar or ribbon.

Add Macro to Quick Access Toolbar

  1. First off, access “Outlook Options” by following the operations shown in Step 1, in which you can shift to “Quick Access Toolbar” tab.
  2. Next, select “Macros” from the “Choose commands from”.
  3. Then, in the macro list, choose a macro.
  4. After that, click “Add >>” button in center.
  5. Finally, click “OK”. Add Macro to Quick Access Toolbar
  6. Since then, to run this macro, you can simply click the macro button in Quick Access Toolbar. Run Macro through Quick Access Toolbar

Add Macro to Ribbon

  1. At first, go to “File” menu and click “Options”.
  2. In the subsequent “Outlook Options” window, turn to “Customize Ribbon”.
  3. Then, on the right side, click “New Group” button. Create New Group in Ribbon
  4. Next, click “Rename” button.
  5. In the popup dialog box, specify a name and icon for the new group, such as “Smart Move” in my instance, and click “OK”. Rename New Group
  6. Later, on the left side, select “Macros” from the drop-down list of “Choose Commands from”.
  7. After that, in the macro list, select the macro you want.
  8. Then, click “Add >>” button in center to add this macro to the custom group. Add Macro to New Group
  9. Next, click “Rename” button.
  10. In the new dialog box, change the name of this macro and assign an icon to it. Rename the Macro Button
  11. Ultimately, click a series of “OK” until getting back to Outlook main window.
  12. Now, you will see the new macro button in ribbon, as shown in the following screenshot. New Macro Button in Ribbon

Author Introduction:

Shirley Zhang is a data recovery expert in DataNumen, Inc., which is the world leader in data recovery technologies, including mdf recovery and outlook repair software products. For more information visit www.datanumen.com

@mavaddat
Copy link
Author

mavaddat commented Nov 4, 2021

image I have this error, when try to run it.

In what context are you running the script? The script requires the Outlook namespace, so it should be run in Outlook VBA editor. I have added a how-to for you to make sure you're in the right environment.

@Valiante
Copy link

Just wanted to add another comment thanking you for both taking the time to create and post this. I'm using a modified version without the subfolder functionality, as I just wanted it all in a single Archive, but you'd done 99% of the work for me which is never a bad thing!

Thanks again.

@jazzgrewal
Copy link

Great script very helpful. It is the best alternative to pay for any tool online.

@mavaddat
Copy link
Author

Great script very helpful. It is the best alternative to pay for any tool online.

Good question! Let us know what you find.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment