【问题标题】:Outlook "Run Script" rule not triggering VBA script for incoming messagesOutlook“运行脚本”规则未触发传入邮件的 VBA 脚本
【发布时间】:2017-08-13 15:23:39
【问题描述】:

我正在根据另一位成员的建议创建这个新主题。有关事情如何到达这一点的更多历史记录,请参阅this question

我有这个 VBA 脚本,我知道它可以工作如果它被触发。如果我使用 TestLaunch 子例程,并且我的收件箱中已经有一条符合规则标准的消息(当然,它没有被规则启动),它会激活我希望它完美激活的链接。如果在创建规则时我说将其应用于收件箱中的所有现有邮件,那么它可以完美运行。但是,在需要它的地方,当新消息到达时它不需要。

我知道脚本没有被触发,因为如果我有这样的规则:

Outlook "New Message" rule that has "play sound" enabled

将“播放声音”作为其中的一部分,当消息从两个指定发件人中的任何一个到达时,声音总是会播放,因此触发了规则。我已经从规则中删除了声音播放部分,并将其集成到 VBA 代码中以用于测试目的:

Option Explicit

Private Declare Function ShellExecute _
  Lib "shell32.dll" Alias "ShellExecuteA" ( _
  ByVal hWnd As Long, _
  ByVal Operation As String, _
  ByVal Filename As String, _
  Optional ByVal Parameters As String, _
  Optional ByVal Directory As String, _
  Optional ByVal WindowStyle As Long = vbMinimizedFocus _
  ) As Long

Private Declare Function sndPlaySound32 _
    Lib "winmm.dll" _
    Alias "sndPlaySoundA" ( _
        ByVal lpszSoundName As String, _
        ByVal uFlags As Long) As Long

Sub PlayTheSound(ByVal WhatSound As String)
    If Dir(WhatSound, vbNormal) = "" Then
        ' WhatSound is not a file. Get the file named by
        ' WhatSound from the Windows\Media directory.
        WhatSound = Environ("SystemRoot") & "\Media\" & WhatSound
        If InStr(1, WhatSound, ".") = 0 Then
            ' if WhatSound does not have a .wav extension,
            ' add one.
            WhatSound = WhatSound & ".wav"
        End If
        If Dir(WhatSound, vbNormal) = vbNullString Then
            Beep            ' Can't find the file. Do a simple Beep.
            Exit Sub
        End If
    Else
        ' WhatSound is a file. Use it.
    End If

    sndPlaySound32 WhatSound, 0&    ' Finally, play the sound.
End Sub

Public Sub OpenLinksMessage(olMail As Outlook.MailItem)

 Dim Reg1 As RegExp
 Dim AllMatches As MatchCollection
 Dim M As Match
 Dim strURL As String
 Dim RetCode As Long

Set Reg1 = New RegExp

With Reg1
 .Pattern = "(https?[:]//([0-9a-z=\?:/\.&-^!#$;_])*)"
 .Global = True
 .IgnoreCase = True
End With

PlayTheSound "chimes.wav"

' If the regular expression test for URLs in the message body finds one or more
If Reg1.test(olMail.Body) Then

'      Use the RegEx to return all instances that match it to the AllMatches group
       Set AllMatches = Reg1.Execute(olMail.Body)
       For Each M In AllMatches
               strURL = M.SubMatches(0)
'              Don't activate any URLs that are for unsubscribing; skip them
               If InStr(1, strURL, "unsubscribe") Then GoTo NextURL
'              If the URL ends with a > from being enclosed in darts, strip that > off
               If Right(strURL, 1) = ">" Then strURL = Left(strURL, Len(strURL) - 1)
'              The URL to activate to accept must contain both of the substrings in the IF statement
               If InStr(1, strURL, ".com") Then
                     PlayTheSound "TrainWhistle.wav"
'                    Activate that link to accept the job
                     RetCode = ShellExecute(0, "Open", "http://nytimes.com")
                     Set Reg1 = Nothing
                     Exit Sub
               End If

NextURL:
   Next

End If

Set Reg1 = Nothing

End Sub

Private Sub TestLaunchURL()
    Dim currItem As MailItem
    Set currItem = ActiveExplorer.Selection(1)
    OpenLinksMessage currItem
End Sub

如果 VBA 脚本在所有情况下都被触发,它应该播放“chimes.wav”,如果我的实际链接激活处理发生,则播放“TrainWhistle.wav”。当新邮件到达时,两者都不会发生,但如果 Outlook 规则中有一个“播放声音”应该运行这个脚本,那么声音就会被播放。

目前我有宏的信任中心设置以允许所有宏,因为 Outlook 对在测试过程早期使用 selfcert.exe 的签名感到不安。我真的希望能够再次提升宏保护,而不是在这一切完成后将它们留在“全部运行”。

但是,首先,我一生无法弄清楚为什么这个脚本可以通过调试器完美运行,或者如果应用于现有邮件,但不会由应用于现有邮件的相同 Outlook 规则触发实际的新消息到达。在我正在开发此脚本的 Outlook 2010 和 Outlook 2016 下,在我正在部署它的朋友的计算机上也是如此。

任何有关解决此问题的指导将不胜感激。

【问题讨论】:

  • 从这个问题和之前问题中表达的想法来看,您可能不知道规则向导中有一个“运行脚本”选项,您可以在其中选择 OpenLinksMessage。
  • 呃,没有。从我对文本和标题中规则的扩展讨论中,我认为这并不完全明显。问题在于,规则中的“运行脚本”实际上并不是在运行脚本,即使消息符合应该导致它运行的规则标准。让我们不要进入我给出的显示“运行脚本”的规则的屏幕截图。
  • 其他运行脚本代码是否适用于传入消息?像 MsgBox oMail.SenderEmailAddress 这样简单的东西作为唯一的代码行。对所有传入邮件运行,规则中没有地址条件。
  • 我创建了一个公共子例程,它按照您的指示执行简单的消息框,并将其设置在一个没有过滤条件的规则中,并应用于每个传入的消息。它确实运行了,我弹出了消息框。
  • 那么最后一步就是用这个 Msgbox 代码替换规则中的 OpenLinksMessage 以确认地址条件是有效的。

标签: vba outlook system-calls text-parsing eventtrigger


【解决方案1】:

这是最终有效的代码。很明显,olMail 的 .Body 成员在某种幕后处理有时间发生之前是不可用的,如果你等待的时间不够长,当你去测试使用它时它就不会在那里。关注 Public Sub OpenLinksMessage

显然,允许该处理发生的主要变化是添加了以下代码行:Set InspectMail = olMail.GetInspector.CurrentItem。此 set 语句运行所需的时间允许 .Body 在 Outlook 规则传入的 olMail 参数上可用。有趣的是,如果您在 set 语句之后立即显示 InspectMail.Body,它会显示为空,就像 olMail.Body 过去一样。

Option Explicit

Private Declare Function ShellExecute _
  Lib "shell32.dll" Alias "ShellExecuteA" ( _
  ByVal hWnd As Long, _
  ByVal Operation As String, _
  ByVal Filename As String, _
  Optional ByVal Parameters As String, _
  Optional ByVal Directory As String, _
  Optional ByVal WindowStyle As Long = vbMinimizedFocus _
  ) As Long



Public Sub OpenLinksMessage(olMail As Outlook.MailItem)

 Dim InspectMail As Outlook.MailItem
 Dim Reg1 As RegExp
 Dim AllMatches As MatchCollection
 Dim M As Match
 Dim strURL As String
 Dim SnaggedBody As String
 Dim RetCode As Long

' The purpose of the following Set statement is strictly to "burn time" so that the .Body member of
' olMail is available by the time it is needed below.  Without this statement the .Body is consistently
' showing up as empty.  What's interesting is if you use MsgBox to display InspectMail.Body immediately after
' this Set statement it shows as empty.
Set InspectMail = olMail.GetInspector.CurrentItem

Set Reg1 = New RegExp

With Reg1
 .Pattern = "(https?[:]//([0-9a-z=\?:/\.&-^!#$;_])*)"
 .Global = True
 .IgnoreCase = True
End With

RetCode = Reg1.Test(olMail.Body)
' If the regular expression test for URLs in the message body finds one or more
If RetCode Then
'      Use the RegEx to return all instances that match it to the AllMatches group
       Set AllMatches = Reg1.Execute(olMail.Body)
       For Each M In AllMatches
               strURL = M.SubMatches(0)
'              Don't activate any URLs that are for unsubscribing; skip them
               If InStr(1, strURL, "unsubscribe") Then GoTo NextURL
'              If the URL ends with a > from being enclosed in darts, strip that > off
               If Right(strURL, 1) = ">" Then strURL = Left(strURL, Len(strURL) - 1)
'              The URL to activate to accept must contain both of the substrings in the IF statement
               If InStr(1, strURL, ".com") Then
'                    Activate that link to accept the job
                     RetCode = ShellExecute(0, "Open", strURL)
                     Set InspectMail = Nothing
                     Set Reg1 = Nothing
                     Set AllMatches = Nothing
                     Set M = Nothing
                     Exit Sub
               End If

NextURL:
   Next

End If

Set InspectMail = Nothing
Set Reg1 = Nothing
Set AllMatches = Nothing
Set M = Nothing

End Sub

特别感谢 niton 的耐心和帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 2011-02-17
    • 2014-09-05
    • 1970-01-01
    • 2015-08-20
    • 2016-06-28
    相关资源
    最近更新 更多