用Python将EML(MIME)转换为MSG

发布于 2025-02-03 17:52:00 字数 1365 浏览 3 评论 0原文

我正在尝试使用Python将EML文件转换为MSG(Outlook)文件。使用各种示例,我能够收集此代码,但是,它不起作用。它创建了一个味精文件,但是该文件是由Outlook无法读取的,并且大小比输入EML文件大两倍。我有点迷路了,有什么想法吗?

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()

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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉栀 2025-02-10 17:52:00

首先,尺寸并不重要,特别是如果您比较不同的文件格式。
其次,尝试在实用程序中打开MSG文件,例如 ssview (它显示了数据isTorage级)或 outlookspy (我是它的作者 - 单击OpenIMSGONISTG按钮) - 它将在MAPI级别显示MSG文件数据。

也许最重要的是,与Outlook 2016一样,接口仅在您的代码在Outlook.exe地址空间内运行(即您的代码是com/vsto addin或Outlook vba)。另外,您的代码永远不会检查iconvertersessessessessessesses :: mimetomapi返回成功返回代码。

如果使用 rexemption 是一个选项(我也是其作者),它允许将EML文件转换为MSG无需使用Outlook Converter即(在VB脚本中):

    set Session = CreateObject("Redemption.RDOSession")
    Session.MAPIOBJECT = Application.Session.MAPIOBJECT 'not required
    set Msg = Session.CreateMessageFromMsgFile("c:\temp\test.msg")
    Msg.Sent = true
    Msg.Import "c:\temp\test.eml", 1024 '1024 is olRfc822
    Msg.Save

Firstly, sizes don't matter, especially if you compare different file formats.
Secondly, try to open the MSG file in a utility like SSView (it shows the data on the IStorage level) or OutlookSpy (I am its author - click OpenIMsgOnIStg button) - it will show the MSG file data on the MAPI level.

Perhaps most importantly, as of Outlook 2016, IConverterSession interface only works if your code is running inside the outlook.exe address space (i.e. your code is a COM/VSTO addin or Outlook VBA). Also, your code never checks that IConverterSession::MIMEToMAPI returns a success return code.

If using Redemption is an option (I am also its author), it allows to convert an EML file to MSG without using Outlook converter as easily as (in VB script):

    set Session = CreateObject("Redemption.RDOSession")
    Session.MAPIOBJECT = Application.Session.MAPIOBJECT 'not required
    set Msg = Session.CreateMessageFromMsgFile("c:\temp\test.msg")
    Msg.Sent = true
    Msg.Import "c:\temp\test.eml", 1024 '1024 is olRfc822
    Msg.Save
ペ泪落弦音 2025-02-10 17:52:00

因此,在我从Outlook X86迁移到X64之后,它开始工作,我添加了以下注册表键:

[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}"

键是您可以在以下方面找到的键的副本:

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

工作代码:

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()

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文