【问题标题】:Issue on def OnForward(self, disp, item): in python using win32.comdef OnForward(self, disp, item) 上的问题:在 python 中使用 win32.com
【发布时间】:2022-01-19 19:34:09
【问题描述】:

我在 stackoverflow 上找到了下面的代码,链接如下:Python Outlook win32 event trigger when email is opened

我正在尝试使用此代码并添加“def OnForward(self, disp, item):”以在我转发的电子邮件上添加签名。但是前锋不好用。我会尝试解释一下,每次我点击转发时,它都会在新窗口中弹出电子邮件,但也会出现在主 Outlook 窗口中,然后“def OnRead(self):”也停止工作!我不知道是否正确表达自己,但任何帮助将不胜感激

outlook main Window

import win32com.client
import pythoncom

#Handler for Application Object
class Application_Handler(object):
    def OnItemLoad(self, item):
        print('Application::OnItemLoad')

        #Only want to work with MailItems 
        if( item.Class == win32com.client.constants.olMail ): 
            #Get a Dispatch interface to the item
            cli = win32com.client.Dispatch(item)
            #Set up a handler
            handler = win32com.client.WithEvents(cli,MailItem_Handler)
            #Store the MailItem's Dispatch interface for use later
            handler.setDisp(cli)
 
#Handler for MailItem object
class MailItem_Handler(object):
    def setDisp(self,disp):
        self._disp = disp

    def OnOpen(self,item):
        print('MailItem::OnOpen')
    
    def OnRead(self):
        print('MailItem::OnRead')
        subj = self._disp.Subject
        print('Subject:',subj)
        body = self._disp.Body
        print('Body:',body)
    def OnClose(self, item):
        return
        print('---------------MailItem::OnClose-------------------')
        print('-----------------------------------------------------')

    def OnForward(self, disp, item):
        print('---------------MailItem::OnForward-------------------')

        newMail = self._disp.Forward()
        newMail.HTMLBody = self._disp.HTMLBody + 'teste'
        newMail.Display()

        print('-----------------------------------------------------')

outlook = win32com.client.DispatchWithEvents("Outlook.Application", Application_Handler)
#Message loop
pythoncom.PumpMessages()

【问题讨论】:

  • 您有正确的 OnForward 签名吗?这是参考:docs.microsoft.com/en-us/office/vba/api/… 参数是 OnForward(self,item,bCancel)。
  • 我更正了上面引用的链接,因为我在 OnOpen 签名上出错了。

标签: python outlook outlook-addin win32com win32ole


【解决方案1】:

每次我点击转发时,它都会在新窗口中弹出电子邮件,但也会出现在主 Outlook 窗口中

Forward 事件处理程序中,您可以找到以下代码:

newMail = self._disp.Forward()
newMail.HTMLBody = self._disp.HTMLBody + 'teste'
newMail.Display()

当相应的事件被触发时,它会一次又一次地调用Forward。因此,Forward 方法会触发 Forward 事件。

Forward 事件在用户选择项目的 Forward 操作或为项目调用 Forward 方法时触发。因此,无需在事件处理程序中重新调用它。这是对Forward 方法的反应。被转发的新项目作为参数传递给事件处理程序。

def OnForward(self, disp, item):
        print('---------------MailItem::OnForward-------------------')

        newMail = item
        newMail.HTMLBody = self._disp.HTMLBody + 'teste'
        
        newMail.Display()

        print('-----------------------------------------------------')

【讨论】:

  • 我认为 OnForward 的签名是错误的。见上面的评论。第二个参数是新项目,第三个是允许取消操作的布尔值。
  • 签名在那里没有任何关键作用。如果签名不正确,则可能不会触发该事件。或者代码失去了取消默认操作的能力。如果事件过程将cancel 参数设置为true,则转发操作未完成且不显示新项目。所以,事实并非如此。
  • 答案集上的代码newMail = item。如果事件如果将 (IDispatch*, bool) 作为参数传递,则将 MailItem 引用设置为 bool。我还没有尝试过,但这看起来可能会导致问题?在 win32com 中,只检查参数的数量,而不是它们的类型(毕竟这是 Python),因此处理程序很可能会被调用(因为参数的数量是正确的)。如果我错了这个代码:Message='bool' object has no attribute 'HTMLBody',这是我所期望的。
  • Forward 事件处理程序接受一个被转发的项目和一个布尔值。因此,无需在事件处理程序中调用Forward
  • 我建议您尝试修改后的代码,看看自己会发生什么。
【解决方案2】:

编辑:正如@EugeneAstafiev 非常正确地指出的那样,对Forward() 的调用是不必要的,并且会重复Outlook 正在执行的操作。也无需拨打Display()

然而,虽然事件的签名是正确的,因为它需要两个参数,但隐含类型是错误的。第一个参数(在self 之后)是指向新项目的调度指针,第二个是允许处理程序取消事件的标志。

应该是:

def OnForward(self,newItem,bCancel):
    newItem.HTMLBody = self._disp.HTMLBody + 'teste'

只要事件处理程序未将 bCancel 设置为 True,就会显示 newItem。直到用户单击发送按钮或调用 Send() 方法后,才会真正发送 newItem。

MailItem 及其事件的引用是here

顺便说一句,在我的测试中设置bCancel=True 没有效果,并且该项目始终显示。我的猜测是win32com 没有正确处理 [in,out] 引用参数。

【讨论】:

  • 签名在那里没有任何关键作用。如果签名不正确,则可能不会触发该事件。或者代码失去了取消默认操作的能力。如果事件过程将 cancel 参数设置为 true,则转发操作未完成并且不显示新项目。所以,事实并非如此。
  • @EugeneAstafiev 我的答案中的代码运行(至少在我的测试中),并在显示之前将“teste”添加到邮件正文中。但是,bool 参数似乎被忽略了:即使我设置 bCancel=True,消息仍然显示:可能 [in,out] 参数的语法不正确。 bCancel 肯定会作为布尔值到达函数,设置为 False。
  • 问题与声明无关。
  • 嗨@DS_London,我尝试使用你的代码。我复制的部分效果很好,但在转发事件中我遇到了一些问题。我正在寻找的是,当我点击转发、回复或全部回复时,在发送之前打开一个带有 HTML 邮件正文签名的新窗口(我想在发送电子邮件之前查看签名)。我已经在 VBA 上编写了类似这样的脚本,它运行良好,但我认为 python 更健壮。在看到你的代码后,我试图联系你,但我没有找到联系你:)
  • @MárioJorgeRocha 也许添加您在 VBA 中所做的工作。通常该代码可以直接移植到 win32com 和 Python,因为 Outlook 对象模型是相同的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 2023-03-03
  • 2014-06-11
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
相关资源
最近更新 更多