Search code examples
pythonmimewin32commapimsg

Converting EML (MIME) to MSG with python


I'm trying to convert EML file to MSG (Outlook) file using python. Using various examples I was able to gather this code, but well, it doesn't work. It creates a msg file but the file is unreadable by Outlook and the size is two times bigger than the input eml file. I'm a little bit lost, any ideas?

from win32com.mapi import mapi
from win32com.mapi import mapitags
import win32com.client
import pythoncom
from win32com import storagecon

import ctypes
import platform
import winreg
import uuid 
import sys
import os

mapi.MAPIInitialize((mapi.MAPI_INIT_VERSION, mapi.MAPI_MULTITHREAD_NOTIFICATIONS))

IconvOLE = ctypes.OleDLL(r'C:\Program Files (x86)\Microsoft Office\root\Office16\OUTLMIME.DLL')
clsid_class = uuid.UUID(str(mapi.CLSID_IConverterSession)).bytes_le
iclassfactory = uuid.UUID(str(pythoncom.IID_IClassFactory)).bytes_le
com_classfactory = ctypes.c_long(0)
IconvOLE.DllGetClassObject(clsid_class, iclassfactory, ctypes.byref(com_classfactory))
MyFactory = pythoncom.ObjectFromAddress(com_classfactory.value, pythoncom.IID_IClassFactory)
cs =  MyFactory.CreateInstance (None, str(mapi.IID_IConverterSession))

eml = mapi.OpenStreamOnFileW(r"C:\test.eml")

stg = pythoncom.StgCreateDocfile(r"C:\test.msg",
    storagecon.STGM_CREATE | storagecon.STGM_READWRITE | storagecon.STGM_TRANSACTED)

msg = mapi.OpenIMsgOnIStg(0, None, stg, None, 0, mapi.MAPI_UNICODE)

cs.MIMEToMAPI(eml, msg, win32com.mapi.mapi.CCSF_SMTP | win32com.mapi.mapi.CCSF_INCLUDE_BCC)

msg.SaveChanges(0)

mapi.MAPIUninitialize()

Solution

  • So it started to work after I have moved from Outlook x86 to x64, and I added the following registry keys:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{4E3A7680-B77A-11D0-9DA5-00C04FD65685}]
    @="CLSID_IConverterSession"
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{4E3A7680-B77A-11D0-9DA5-00C04FD65685}\InprocServer32]
    @="C:\\Program Files\\Microsoft Office\\root\\Office16\\OUTLMIME.DLL"
    "ThreadingModel"="Both"
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{9EADBD1A-447B-4240-A9DD-73FE7C53A981}]
    @="CLSID_IMimeMessage"
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{9EADBD1A-447B-4240-A9DD-73FE7C53A981}\InprocServer32]
    @="C:\\Program Files\\Microsoft Office\\root\\Office16\\OUTLMIME.DLL"
    "ThreadingModel"="Both"
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{9EADBD1A-447B-4240-A9DD-73FE7C53A981}\Typelib]
    @="{9EADBD25-447B-4240-A9DD-73FE7C53A981}"
    

    Keys are copies of the keys that you can find in:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\CLSID
    

    Working code:

    mapi.MAPIInitialize((mapi.MAPI_INIT_VERSION, mapi.MAPI_MULTITHREAD_NOTIFICATIONS))
    
    
    inf = mapi.OpenStreamOnFile(r"C:\Users\xxx\raw.eml")
    
    stg = pythoncom.StgCreateDocfile(r"C:\Users\xxx\raw.msg",
        storagecon.STGM_CREATE | storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE | storagecon.STGM_TRANSACTED)
    
    msg = mapi.OpenIMsgOnIStg(0, None, stg, None, 0, mapi.MAPI_UNICODE)
    
    cs = pythoncom.CoCreateInstance(mapi.CLSID_IConverterSession, None, pythoncom.CLSCTX_INPROC_SERVER, mapi.IID_IConverterSession)
    
    
    cs.MIMEToMAPI(inf, msg, 0)
    
    msg.SaveChanges(0)
    
    mapi.MAPIUninitialize()