为什么这个正则表达式测试会给出相同正文文本的不同结果?

时间:2017-08-14 20:44:52

标签: regex outlook outlook-vba text-parsing

以下是相关代码,它根据我是使用TestLaunchURL启动它还是在传入消息到达时由Outlook传递给它的消息体的正则表达式测试给出不同的结果:

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 "Speech On.wav"

RetCode = Reg1.Test(olMail.Body)
MsgBox "The RetCode from Reg1.Test(olMail.Body) equals" + Str(RetCode)
' If the regular expression test for URLs in the message body finds one or more
If RetCode Then
       PlayTheSound "chimes.wav"
'      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
               PlayTheSound "tada.wav"
               If InStr(1, strURL, ".com") Then
                     PlayTheSound "TrainWhistle.wav"
'                    Activate that link to accept the job
                     RetCode = ShellExecute(0, "Open", strURL)
                     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

测试IF Reg1.Test(olMail.Body)在从传入消息的Outlook规则调用时始终返回0,并且当我使用调试器触发同一消息时始终返回-1 / strong>来自我的收件箱。

当代码被Outlook规则触发时,代码的行为几乎就像它有一个空消息体一样,而当我在我的收件箱中从完全相同的消息中启动消息体时,代码就像消息体一样。

我完全陷入困境,因为我无法理解,同一个身体的同一个消息如何能够提供两种不同的结果,具体取决于谁将消息传递给子程序。

其他调试信息: 由于问题似乎围绕着消息正文的价值,我添加了以下代码,同样也检查了HTMLBody:

If IsNull(olMail.Body) Then
     MsgBox "The message body is null!!"
Else
     MsgBox "BODY:  " + "|" + olMail.Body + "|"
End If

If IsNull(olMail.HTMLBody) Then
     MsgBox "The message HTMLbody is null!!"
Else
     MsgBox "BODY:  " + "|" + olMail.HTMLBody + "|"
End If

如果脚本由包含内容的邮件的Outlook规则触发,并且只有内容“http://britishtoolworks.com”,则当它到达时,这两个消息框是

[由于某种原因,我被禁止发布图片。这些在BODY和一些文本的两个管道字符之间绝对没有显示,但对于HTMLBody中的URL没有任何内容]

虽然这些是消息框,但如果我在之后通过TestLaunchURL触发脚本,那么同一消息就位于我的收件箱中:

[显示实际预期内容。我被禁止发布更多图片。]

如果有人能解释这种差异,请做。

1 个答案:

答案 0 :(得分:0)

这是最终有效的代码。很明显,olTail的.Body成员在某些幕后处理有时间发生之前是不可用的,如果你不等待很长时间,那么当你去测试使用它时它就不会存在。关注公共子OpenLinksMessage,这是问题发生的地方。

允许对olMail.Body进行预期处理的主要(且唯一)更改显然是添加了代码行: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 对其他问题的耐心和帮助,这些问题构成了这一问题的基础。他引导我找到解决方案。

附录: 另一位在别处帮助我的人提出了值得注意的事情,因为我认为她做对了。我通过IMAP访问使用Gmail下载我的邮件。似乎正在发生的事情是,一旦将标题信息填充到MailItem对象中,就会立即触发Outlook规则。该对象的其余成员,包括.Body,似乎在幕后异步填充。脚本中的处理速度与填充处理的速度可能会导致脚本被头信息触发并在Outlook本身填充之前访问.Body。有趣的是,当发生这种情况时,大部分时间直到找到此解决方案,.Body不被认为是NULL。 IsNull测试从未通过,但打印时的内容没有任何内容,因为在我用作分隔符的两个管道字符之间绝对没有。什么是“没有任何占用任何角色”,但也不是NULL?

显然,传递的整个MailItem不会通过“Is Nothing”测试,我不会考虑使用“Is Nothing”来测试对象的单个成员。

对于我自己,我认为这是错误的。在切换MailItem对象进行脚本处理之前,逻辑推定可以预先填充的该对象的所有成员将在切换之前由Outlook预先填充。它似乎没有发生这种情况,这是在我的机器上的Outlook 2010和另一个上的Outlook 2016。如果你得到一个尚未填充的成员,它应该始终具有NULL值,因为这应该是在填充过程发生之前所有内容都被初始化的内容。