从Outlook使用通配符读取来自特定发件人的附件

时间:2017-02-14 13:56:45

标签: powershell outlook

我尝试从Outlook中提取与senderemailaddress属性的通配符匹配的附件。从下面的代码中可以看出,我尝试使用两个过滤器,但无济于事。

当我在代码中使用当前处于活动状态的未注释过滤器时,代码不会抛出任何错误,也不会下载与测试用例匹配的附件。但是,如果我激活注释过滤器并运行它,我会收到以下错误。

Exception calling "Restrict" with "1" argument(s): "Cannot parse condition. Error at
"like"."
At C:\Users\acer\Desktop\outlook.ps1:42 char:2
+  $filteredItems = $folder.items.Restrict($filter)
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ComMethodTargetInvocation

代码:

$filepath = "C:\folder\subfolder\subsubfolder\"
function downloadFiles {
    $filter = "[UnRead]=true AND [SenderEmailAddress] -match @example"
    #$filter = "[UnRead]=true AND [SenderEmailAddress] -like '*@example*'"

    Add-Type -Assembly "Microsoft.Office.Interop.Outlook" | Out-Null
    $olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]

    $outlook = New-Object -ComObject Outlook.Application 
    $namespace = $outlook.GetNameSpace("MAPI")

    $folder = $namespace.GetDefaultFolder($olFolders::olFolderInBox)

    #$folder.Items | select SenderEmailAddress

    $filteredItems = $folder.Items.Restrict($filter)

    foreach ($objMessage in $filteredItems) {
        $intCount = $objMessage.Attachments.Count

        if ($intCount -gt 0) {
            for ($i=1; $i -le $intCount; $i++) {
                $objMessage.Attachments.Item($i).SaveAsFile($filepath+$objMessage.Attachments.Item($i).FileName)
            }
        }
        $objMessage.Unread = $false
    }

    $outlook.Close
}

downloadFiles

Edit1:感谢大家的建议。 我能够通过使用unread = true过滤并从过滤邮件的属性中匹配senderemailaddress进行模式化。

添加修改后的代码:

$filepath = "C:\folder\subfolder\subsubfolder\"
    function downloadFiles {
        $filter="[UnRead]=true"
    $emailfilter = "*@xyz.co.in"
    $subjectfilter = "test file*"

    Add-Type -Assembly "Microsoft.Office.Interop.Outlook" | Out-Null
        $olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]

        $outlook = New-Object -ComObject Outlook.Application 
        $namespace = $outlook.GetNameSpace("MAPI")

        $folder = $namespace.GetDefaultFolder($olFolders::olFolderInBox)

        #$folder.Items | select SenderEmailAddress

        $filteredItems = $folder.Items.Restrict($filter)

        foreach ($objMessage in $filteredItems) {
            $subject = $objMessage.Subject
            $emailaddress = $objMessage.SenderEmailAddress

            if(($emailaddress -like $emailfilter) -and ($subject -like $subjectfilter)){
            $intCount = $objMessage.Attachments.Count

            if ($intCount -gt 0) {
                for ($i=1; $i -le $intCount; $i++) {
                    $objMessage.Attachments.Item($i).SaveAsFile($filepath+$objMessage.Attachments.Item($i).FileName)
                }
            }
            $objMessage.Unread = $false
          }

           else {continue}
       }
        $outlook.Close
    }

    downloadFiles

现在问题是安排这个脚本?当我在命令提示符下使用powershell路径运行此脚本时,它运行正常。但是,当我安排相同时,它没有完成。我可以在TaskManager中看到任务调度程序生成的outlook进程,并且必须手动终止进程以终止进程。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

提供商不允许在此方法的过滤器中使用Like。从MSDN article

开始
  

没有办法执行"包含"操作。例如,你   无法使用“查找”或“限制”来搜索具有特定项目的项目   主题字段中的单词。相反,您可以使用AdvancedSearch   方法,或者您可以遍历文件夹中的所有项目并使用   InStr函数在字段中执行搜索。

答案 1 :(得分:0)

我会使用EWS。保存必须允许以编程方式访问Outlook。

最简单的方法是从nuget下载。您可以通过首先下载nuget:

在PowerShell中执行此操作
$sourceNugetExe = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
$targetNugetExe = "D:\Program Files\nuget\nuget.exe" # chaneg path to suit
Invoke-WebRequest $sourceNugetExe -OutFile $targetNugetExe
Set-Alias nuget $targetNugetExe -Scope Global -Verbose

然后下载EWS nuget包:

Set-Location D:\Temp # change to suit
nuget install 'Microsoft.Exchange.WebServices'

现在你可以开始使用:)

# load the assembly
[void][Reflection.Assembly]::LoadFile("D:\Temp\Microsoft.Exchange.WebServices.2.2\lib\40\Microsoft.Exchange.WebServices.dll")

# set ref to exchange - may need to change the version
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)

# replace with your email address
$email = "your.email@domain.com"

# grab your own credentials
$s.UseDefaultCredentials = $true

# discover the url from your email address
$s.AutodiscoverUrl($email)

# get a handle to the inbox
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#create a property set (to let us access the body & other details not available from the FindItems call)
$psPropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text

$items = $inbox.FindItems(100) # change to suit

# loop through the emails - at this point, we don't have full info - we have to Load the email
# restrict on what we do know - if the email is read and if it has attachments
$items | where { !$_.IsRead -and $_.HasAttachments } | ForEach-Object {
  # load the email, so we can get to other properties, like attachments, sender, etc
  $_.Load()
  # does the sender match our wildcard?
  if ($_.Sender -like '*lmnopqr*') {
    # loop through all file attachments
    $_.Attachments | Where-Object { $_ -is [Microsoft.Exchange.WebServices.Data.FileAttachment] } | ForEach-Object {
      # save them (yes, Load = Save in this instance!)
      $_.Load("D:\Temp\$($_.Name)")
    }
  }
}

有关如何与EWS互动的更多信息,请参阅EWS link

另外,请参阅我的其他SO post,其中有关从哪里获取EWS程序集的过时,但确实有一些关于额外EWS方法/属性的有用信息。如果您没有使用自己的凭据(或运行PowerShell的流程没有Exchange帐户),它还会详细介绍如何使用备用凭据。