使用通配符从Outlook中读取来自特定发件人的附件 [英] Read attachments from Outlook which are from a particular sender using wildcards

查看:162
本文介绍了使用通配符从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进程,并且必须手动终止该进程以终止该进程.有什么想法吗?

解决方案

我将使用 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链接. /p>

另外,请参阅我的其他 SO帖子,该帖子对于从何处获取EWS组件已经过时了,但确实有关额外的EWS方法/属性,有一些有用的信息.如果您不使用自己的凭据(或者运行PowerShell的进程没有Exchange帐户),它还包含有关如何使用备用凭据的详细信息.

I have trying to extract attachments from Outlook which are matching the wildcard of senderemailaddress attribute. As can be seen in the below code, I was trying out with two filters but to no avail.

When I use uncommented filter currently active in the code, the code doesn't throw any errors nor does it download the attachments matching the test case. However if I activate the commented filter and run it, I get the following error.

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

Code:

$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 : Thanks everyone for the suggestions. I was able to do it by filtering with unread = true and pattern matching the senderemailaddress from the properties of the filtered mails.

Adding the modified code:

$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

Now the problem is scheduling this script? When I run this script using the powershell path in command prompt it's working fine. But when I schedule the same it's not completing. I could see the outlook process generated by the task scheduer in TaskManager and have to manually kill the process to terminate the same. Any ideas?

解决方案

I'd use EWS. Saves having to allow programmatic access to Outlook.

Easiest way is to download from nuget. You can do this in PowerShell by first downloading nuget:

$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

Then download the EWS nuget package:

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

Now you can start using :)

# 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)")
    }
  }
}

See the EWS link for more info on how to interact with EWS.

Also, see my other SO post which is out of date for where to get the EWS assembly from, but does have some useful info on extra EWS methods/properties. It also has details on how to use alternative credentials, if you're not using your own (or the process runing PowerShell doesn't have an Exchange account).

这篇关于使用通配符从Outlook中读取来自特定发件人的附件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆