首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >VBA RegEx在MS中抓取反弹邮件

VBA RegEx在MS中抓取反弹邮件
EN

Stack Overflow用户
提问于 2014-08-22 13:10:26
回答 3查看 2.8K关注 0票数 0

我试图扩展一些Outlook电子邮件删除VBA代码的功能。我定期收到回弹电子邮件,并希望通过将上述电子邮件地址导出到MS来跟踪这些邮件(以供删除)。

代码在某种程度上是有效的。我只能刮第一个电子邮件地址在一个典型的回弹通知电子邮件使用RegEx。我为公司工作的邮件服务器将来自同一个域的电子邮件聚合成一个通知电子邮件。因此,我得到多个通知电子邮件,其中包含多个反弹的电子邮件。

如何让RegEx循环通过整个通知电子邮件来收集所有的电子邮件地址?我现在有点卡住了,因为--诚然--我对RegEx不太了解,并且“采用”了这段代码的大部分.

谢谢你的帮助,斯塔克溢出!

代码语言:javascript
运行
复制
Sub Extract_Invalid_To_Excel()

Dim olApp As Outlook.Application
Dim olExp As Outlook.Explorer
Dim olFolder As Outlook.MAPIFolder
Dim obj As Object
Dim stremBody As String
Dim stremSubject As String
Dim i As Long
Dim x As Long
Dim count As Long
Dim RegEx As Object
Set RegEx = CreateObject("VBScript.RegExp")
Dim xlApp As Object 'Excel.Application
Dim xlwkbk As Object 'Excel.Workbook
Dim xlwksht As Object 'Excel.Worksheet
Dim xlRng As Object 'Excel.Range

Set olApp = Outlook.Application
Set olExp = olApp.ActiveExplorer

Set olFolder = olExp.CurrentFolder

'Open Excel
Set xlApp = GetExcelApp
xlApp.Visible = True
If xlApp Is Nothing Then GoTo ExitProc

Set xlwkbk = xlApp.Workbooks.Add
Set xlwksht = xlwkbk.Sheets(1)
Set xlRng = xlwksht.Range("A1")
xlRng.Value = "Bounced email addresses"

'Set count of email objects
count = olFolder.Items.count

'counter for excel sheet
i = 0
'counter for emails
x = 1

For Each obj In olFolder.Items '**Loops through selected Outlook folder**
    xlApp.StatusBar = x & " of " & count & " emails completed"
    stremBody = obj.Body
    stremSubject = obj.Subject

    If checkEmail(stremBody) = True Then '**Checks email for keywords in email
        'MsgBox ("finding email: " & stremBody)

        '**RegEx to find email addresses within message body
        With RegEx
            .Pattern = "\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b"
            .IgnoreCase = True
            .MultiLine = True
            .Global = False
            Set olMatches = .Execute(stremBody) 'Executes RegEx function

            'Loop through RegEx matches
            For Each match In olMatches
                xlwksht.Cells(i + 2, 1).Value = match
                i = i + 1
            Next match
        End With
        'TODO: move or mark the email that had the address extracted
    Else
        '**To view the items that aren't being parsed uncomment the following line
        'MsgBox (stremBody)
    End If

    x = x + 1
Next obj
xlApp.ScreenUpdating = True
MsgBox ("Invalid Email addresses are done being extracted")

ExitProc:
Set xlRng = Nothing
Set xlwksht = Nothing
Set xlwkbk = Nothing
Set xlApp = Nothing
Set emItm = Nothing
Set olFolder = Nothing
Set olNS = Nothing
Set olApp = Nothing
End Sub

Function GetExcelApp() As Object
' always create new instance
On Error Resume Next
Set GetExcelApp = CreateObject("Excel.Application")
On Error GoTo 0
End Function

Function checkEmail(ByVal Body As String) As Boolean
    Dim keywords(3) As String
    keywords(0) = "recipient's e-mail address was not found"
    keywords(1) = "error occurred while trying to deliver this message"
    keywords(2) = "message wasn't delivered"

    'Default value
    checkEmail = False
     For Each word In keywords
        If InStr(1, Body, word, vbTextCompare) > 1 Then
            checkEmail = True
            Exit For
        End If
     Next word
End Function

提供更多细节。我会收到数百封包含以下文字的电子邮件:

代码语言:javascript
运行
复制
Delivery has failed to these recipients or distribution lists:

John.Doe@abc.com
The recipient's e-mail address was not found in the recipient's e-mail system. Microsoft Exchange will not try to redeliver this message for you. Please check the e-mail address and try resending this message, or provide the following diagnostic text to your system administrator.

Morgan.Freedman@abc.com
The recipient's e-mail address was not found in the recipient's e-mail system. Microsoft Exchange will not try to redeliver this message for you. Please check the e-mail address and try resending this message, or provide the following diagnostic text to your system administrator.

Michael.Jordan@abc.com
The recipient's e-mail address was not found in the recipient's e-mail system. Microsoft Exchange will not try to redeliver this message for you. Please check the e-mail address and try resending this message, or provide the following diagnostic text to your system administrator.

上面的代码能够获取电子邮件正文文本中的第一个电子邮件地址(即John.Doe@abc.com),但是看不到其他两个电子邮件地址.

其余的代码运行得完美无缺。它将找到的电子邮件地址导出到Excel中。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-08-22 14:55:48

虽然RegEx函数仍然是新的,但我盲目地稍微修改了代码。

我将RegEx.Global布尔值更改为True,此代码将完美无缺地工作。

代码语言:javascript
运行
复制
With RegEx
   yadda yadda yadda
   .Global = True
End With

不管怎样,谢谢你。希望这对其他人有帮助!

票数 0
EN

Stack Overflow用户

发布于 2018-09-21 07:09:51

我收到多达200个反弹的电子邮件通知,其中每一个大型电子邮件分发。通过不断的联系,这很容易,因为该工具处理所有反弹的地址和代码到一个很好的文件。有了Outlook,我就只能靠自己了,但出于其他原因,我更喜欢这样做。因此,我想出了一个过程和VBA宏来完成任务。首先,我把所有的电子邮件,我希望处理到一个文件夹,并让它选择。使用Outlook 2010,我转到文件-> OPTIONS ->高级->导出。然后选择导出到文件 (Next),然后选择最后一个选项TAB分隔值(Windows)。然后选择名称和文件夹位置来存储一个合并了文件夹中所有电子邮件的单一TXT文件。将文件打开到Msft并运行以下VBA宏:

代码语言:javascript
运行
复制
Sub Bounced_Email_Harvester()
'
' Bounced-Email Text-Process Macro
'
Dim flag As Boolean
' DocLen is to maintain Document length in characters
Dim DocLen As Long
' Try to speed up Word by suspending unnecessary tasks
ActiveDocument.ActiveWindow.View.Draft = True
Options.Pagination = False
Options.CheckGrammarAsYouType = False
Options.CheckSpellingAsYouType = False
Application.ScreenUpdating = False
' Remove extraneous bracket characters < & >
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = ">>>"
        .Replacement.Text = "###"
        .Forward = True
        .Wrap = wdFindContinue
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    With Selection.Find
        .Text = "<<<"
        .Replacement.Text = "VVV"
        .Forward = True
        .Wrap = wdFindContinue
    End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.WholeStory
DocLen = Len(Selection)
Application.DisplayStatusBar = True
Selection.HomeKey Unit:=wdStory
' CORE OF MACRO IS WITHIN THIS LOOP
Do While DocLen > 800
    ' Selects text until next @ sign is reached - locating email addresses
    flag = True
    While flag = True
        Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
        DocLen = DocLen - 1
        If Strings.Right(Selection.Range.Text, 1) = "@" Or DocLen < 2 Then flag = False
        Wend
    flag = True
    Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend
    DocLen = DocLen + 1
    While flag = True
        Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend
        DocLen = DocLen + 1
    'Locate the Beginning of email seeking demarkations (brackets, space, tab, paragraph)
        If Strings.Right(Selection.Range.Text, 1) = "<" Or Strings.Right(Selection.Range.Text, 1) = "[" Or Strings.Right(Selection.Range.Text, 1) = "(" Or Strings.Right(Selection.Range.Text, 1) = " " _
        Or Strings.Right(Selection.Range.Text, 1) = Chr$(9) Or Strings.Right(Selection.Range.Text, 1) = Chr$(13) Or DocLen < 2 Then flag = False
    Wend
    Selection.TypeParagraph
    flag = True
    While flag = True
        Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
        DocLen = DocLen - 1
'Locate the End of email seeking demarkations (brackets, space, tab, paragraph)
        If Strings.Right(Selection.Range.Text, 1) = ">" Or Strings.Right(Selection.Range.Text, 1) = "]" Or Strings.Right(Selection.Range.Text, 1) = ")" Or Strings.Right(Selection.Range.Text, 1) = " " _
        Or Strings.Right(Selection.Range.Text, 1) = Chr$(9) Or Strings.Right(Selection.Range.Text, 1) = Chr$(13) Or DocLen < 2 Then flag = False
    Wend
    Selection.Collapse Direction:=wdCollapseEnd
    Selection.Previous(Unit:=wdCharacter, Count:=1).Select
    DocLen = DocLen + 1
    Selection.TypeParagraph
Loop
' END OF CORE MACRO LOOP
Selection.Collapse Direction:=wdCollapseEnd
    Selection.Previous(Unit:=wdCharacter, Count:=1).Select
    Selection.TypeParagraph
' Major work done - now some pesky house cleaning....
Selection.Find.ClearFormatting
With Selection.Find
    .Text = "mailto:"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
With Selection.Find
    .Text = ":550^p"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
With Selection.Find
    .Text = "<^p"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
    With Selection.Find
    .Text = ";^p"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
With Selection.Find
    .Text = "...^p"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
With Selection.Find
    .Text = ".^p"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.Execute Replace:=wdReplaceAll
    With Selection.Find
    .Text = "^p^p"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.Execute Replace:=wdReplaceAll
MsgBox ("Count: " & DocLen)
End Sub

可能会有10到15分钟的口碑传开,似乎被关起来了。我点击另一个应用程序,有时看任务管理器,以确认它仍然工作的基础上的性能监视器。早上开始后我去煮咖啡。它最终将以提供一个无意义的数字的msg框结束。点击它就可以走了。现在已经完成了,您将有一长列段落分隔的电子邮件地址。它似乎能够可靠地提取100%以上的电子邮件;例如,一些邮件服务器响应电子邮件域的派生,例如@us.att.com和@att.com,或者针对同一用户的@jpmogan.com和@jpchase.com。

复制整个过程,然后放到Excel列中。从这里开始,对列表进行排序并删除最明显的部分,所有的前20%都是以数字开头的电子邮件地址,以信封、标头、邮件、邮局、SMTP、X-发件人和大量重复发送电子邮件地址开始的电子邮件地址。然后在上面运行一个枢轴表以消除所有的重复。您现在有您的电子邮件列表导入到您的dB标记为弹出的电子邮件地址。在单词宏完成后的整个后处理只需要10到15分钟。我可能花了比需要更多的时间,因为无效的电子邮件地址将被我的dB链接忽略。

宏不提取弹跳代码,因此您不知道它是软弹跳(邮箱已满)或硬弹跳(未找到收件人)。在将它们放入文件夹之前,您可以尝试识别它们,或者您可以采取一种策略,在永久删除之前,需要在一段时间内进行两次反弹。你说了算。

我应该注意,我不是一个VBA程序员。40年前,我在一台商品电脑上学习了基本语言,有时还会接触到一些Msft访问功能。我使用VBA for Word的大部分经验仅限于记录宏,然后使用自动生成的代码自动执行一些重复任务。知道自己在做什么的人很可能会大大改进我的代码,但这对我来说是一个很大的节省时间。

票数 2
EN

Stack Overflow用户

发布于 2015-06-01 02:50:28

经过多次狩猎,我想出了以下的功能。一些正文文本仍然包含无效字符(不知道为什么),但总的来说,它是90%的正确。此函数解析传递的Outlook项集合,并将所有唯一的电子邮件地址(在ReportItem的正文中找到)添加到字符串列表中,该字符串列表被写入后面的“立即”窗口。

代码语言:javascript
运行
复制
Private Sub ListEmailAddresses(outlookItems As Outlook.Items)
  Dim folder As Outlook.MAPIFolder = Nothing
  Try
    Dim emailAddresses As New List(Of String)
    If TypeOf outlookItems.Parent Is Outlook.MAPIFolder Then
      folder = CType(outlookItems.Parent, Outlook.MAPIFolder)
    End If
    For i = 1 To outlookItems.Count
      Dim objItem As Object = outlookItems(i)
      Try
        If TypeOf objItem Is Outlook.ReportItem Then
          Dim rpt As Outlook.ReportItem = TryCast(objItem, Outlook.ReportItem)
          Dim temp() As Byte = System.Text.Encoding.Unicode.GetBytes(rpt.Body.ToArray())
          Dim sb As New System.Text.StringBuilder
          For z As Integer = 0 To temp.Length - 1
            sb.Append(Chr(temp(z)))
          Next
          Dim rptBody As String = sb.ToString
          Dim mc As MatchCollection = Regex.Matches(rptBody, _
                     "([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})")
          Dim results(mc.Count - 1) As String
          For x As Integer = 0 To results.Length - 1
            Dim emailAddr As String = ValueIfNull(mc(x).Value, "").ToLower
            If Not String.IsNullOrWhiteSpace(emailAddr) Then
              If Not emailAddresses.Contains(emailAddr) Then
                emailAddresses.Add(emailAddr)
              End If
            End If
          Next
        End If
      Catch ex As Exception
        ' Do Something if you care.
      Finally
        Marshal.ReleaseComObject(objItem)
      End Try
    Next
    emailAddresses.Sort()
    Debug.WriteLine(emailAddresses.ToSeparatedString(Environment.NewLine))
  Catch ex As Exception
    ' Do Something if you care.
  Finally
    If folder IsNot Nothing Then Marshal.ReleaseComObject(folder)
  End Try
End Sub
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25447867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档