对多封电子邮件执行一次批处理脚本

Posted

技术标签:

【中文标题】对多封电子邮件执行一次批处理脚本【英文标题】:Execute batch script once for multiple emails 【发布时间】:2016-03-09 22:05:07 【问题描述】:

我收到了多封电子邮件(每天我收到 3 封电子邮件,用于 3 个类别的订单)。邮件主题格式为:

订单摘要 - [类别] - [日期]”。

其中[类别] 可以是Category 1Category 2Category 3[Date] 是电子邮件的发送日期,格式为 DD/MM/YYYY。

我有一个规则设置来搜索“订单”,然后调用下面的代码。

我想在保存所有电子邮件附件后运行Complete.bat,我只想调用一次。

我已尝试通过创建另一个名为 saveAttachtoDisk_CATEGORY1(itm) 的子程序来实现此目的,该子程序仅在主题中找到“Category 1”时才被调用。然后它会保存附件,但也会搜索主题中的类别 1 并搜索昨天的日期。

我想要一个不依赖于日期的更好的解决方案。全局变量可以在我将变量设置为 1 然后运行Complete.bat 被发送,然后在将来如果变量 = 1 则不要运行Complete.bat。不确定将这个变量放在哪里(全局变量?)因为两个子模块似乎都放错了位置并引用它。

这两个模块都保存在 Microsoft Outlook VBA 的“模块”部分下。

Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
    Dim objAtt As Outlook.Attachment
    Dim SaveFolder As String
    SaveFolder = "D:\Orders\"
    For Each objAtt In itm.Attachments
         objAtt.SaveAsFile SaveFolder & "\" & objAtt.DisplayName
         objAtt.Delete
    Next
    itm.Save
End Sub

其他模块:

Public Sub saveAttachtoDisk_CATEGORY1(itm As Outlook.MailItem)
    Dim objAtt As Outlook.Attachment
    Dim SaveFolder As String
    SaveFolder = "D:\Orders\"
    For Each objAtt In itm.Attachments
        objAtt.SaveAsFile SaveFolder & "\" & objAtt.DisplayName
        objAtt.Delete
    Next
    itm.Save
    If InStr(1, itm.Subject, "ORDERS EXTRACT - Category 1 -" & Format(Date, "dd/mm/yyyy")) Then
        Shell "D:\Orders\Complete.bat"
    End If
End Sub

【问题讨论】:

我会在程序结束时调用SetTimer,超时时间为1秒,并用SaveSetting保存它的ID,并在程序开始时加载它并清除超时ID .因此,如果每个项目的保存时间少于 1 秒,则只有最后一个项目的超时不会被清除,并且您的计时器回调函数将被调用,您将在其中调用您的批处理文件。 "我想在保存所有电子邮件附件后运行 'Complete.bat',我只想调用一次。"每封邮件一次,还是每天一次?目前还不清楚你真正的问题是什么。你能详细说明一下吗? 潜在的问题是会有相同的附件名称。您应该在文件名前加上/附加接收日期代码 - 还是让它更独特?由于您从邮件项目中删除了附件,因此您没有任何追溯,我们不知道 Complete.bat 做了什么。还在“类别 1”上找到并寻找昨天的一个,然后呢? @Tim OP 等待明天在今天的三封邮件上运行批处理文件。问题是如何知道何时收到所有三封邮件并立即运行“在所有电子邮件附件都已保存并且我只想调用一次之后。” 当 OP 不在这里(?)来解决任何澄清请求时,有点难以“回答”这个问题。 【参考方案1】:

假设

OP 每天将收到三封电子邮件(尽管那是 可在代码中自定义) 主题总是以“ORDERS EXTRACT -”开头,没有其他 电子邮件将以该代码开头 OP 希望在收到 第三个 ORDERS EXTRACT 电子邮件。 OP aready 有一个规则设置为在收到 订单摘要电子邮件。此规则可以更改为运行 CategorySaveAndComplete OP 正在使用 Outlook 2013 或更高版本

建议的解决方案

下面的代码将保存每个订单提取电子邮件的附件,然后检查是否已收到所有三个。我选择不使用 .Find 和 .FindNext,因为这些方法不能使用通配符,因此需要对类别名称进行硬编码。我也选择不使用 .Restrict,因为我们只搜索三个项目。

也就是说,使用 .Find 和 .Restrict 的解决方案同样有效,并且在某些条件下(例如用户的收件箱中始终有许多项目)会比以下解决方案更好。

请注意,Orders Extract 电子邮件的预期计数、要匹配的主题字符串以及要检查的先前日期都可以通过常量设置。我实施了前一个日期检查,以防 OP 也想检查前一天。

Option Explicit

Public Const C_ExpectedOrderCount As Integer = 3 'Set number of expected emails for categories
Public Const C_SubjectFormat As String = "ORDERS EXTRACT - *"
Public Const C_PrevDatesToCheck As Integer = 0 'If the Outlook app may not be open every day, set this to the number of prior days the script should also check.

Public Sub CategorySaveAndComplete(itm As Outlook.MailItem)

    'Do not take any action if this is not an ORDERS EXTRACT email.
    If itm.Subject Like C_SubjectFormat Then

        Dim objAtt As Outlook.Attachment
        Dim SaveFolder As String
        SaveFolder = "D:\Orders\"
        For Each objAtt In itm.Attachments
            objAtt.SaveAsFile SaveFolder & "\" & objAtt.DisplayName
            objAtt.Delete
        Next
        itm.Save

        'Check all emails in Inbox for ORDERS EXTRACT - * - DATE
        Dim Item As Object
        Dim objNS As Outlook.NameSpace
        Set objNS = GetNamespace("MAPI")
        Dim olFolder As Outlook.MAPIFolder
        Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
        Dim iLoop As Integer
        Dim iCount As Integer
        Dim DateCheck As Date

        For iLoop = 0 To C_PrevDatesToCheck
            'Reset DateCheck and iCount if we are looping through days
            DateCheck = DateSerial(Year(Date), Month(Date), Day(Date)) - iLoop
            iCount = 0
            'Loop through mail items
            For Each Item In olFolder.Items
                If Item.Class = 43 Then
                    'This is an email. Check if it matches our criteria.
                    If Item.Subject Like C_SubjectFormat And CDate(CLng(Item.ReceivedTime)) = DateCheck Then iCount = iCount + 1
                End If
            Next
            'If we have met the expected targets, then run the batch file.
            If iCount = C_ExpectedOrderCount Then
                'We have exactly the expected number of items. Run the batch file.
                Shell "D:\Orders\Complete.bat"
            ElseIf iCount > C_ExpectedOrderCount Then
                'More items than expected. Check if user is OK with running batch file; if so, run it now.
                If MsgBox("More order extracts than expected were received. Expected " & _
                C_ExpectedOrderCount & "; received " & iCount & " for " & Format(DateCheck, "mmm d, yy") & _
                ". Would you like to run the Complete.bat file now?", vbYesNo) = vbYes Then Shell "D:\Orders\Complete.bat"
            End If
        Next iLoop
    End If
End Sub

【讨论】:

以上是关于对多封电子邮件执行一次批处理脚本的主要内容,如果未能解决你的问题,请参考以下文章

这是在Laravel中一次发送多封邮件的好方法吗?

在 Rails 中验证多封电子邮件和处理错误的最佳方法是啥?

自动化批处理文件和PowerShell脚本执行

windows怎么定时执行脚本

使用 PHP 脚本处理传入的电子邮件

如何在cakephp中一次发送多封电子邮件