none
EWS/Powershell - Trigger script when specific email is received RRS feed

  • Question

  • I'm trying to build a script using Powershell and EWS to trigger a script after a specific email is received. We have emails generated on a daily basis and sent to a distribution when a new product build is available. When I receive that email, I manually execute a script that updates one of our servers with the latest product build.

    Lately, these updates have been pushing out almost 3 times a day, so I'm looking to automate this process through Powershell. Ideally, I would like the script to run as a scheduled task every 2-3 hours, and if it detects that this particular email has been received, it fires off the update script. 

    I've been using Glen's Exchange Dev Blog to build some of what I have now:

    $dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"
    [void][Reflection.Assembly]::LoadFile($dllpath)
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
    $windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
    $aceuser = [ADSI]$sidbind
    
    $service.AutodiscoverUrl($aceuser.mail.ToString())
    
    $svFldid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
    $SearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, "Update is available!");
    $SearchFolder = new-object Microsoft.Exchange.WebServices.Data.SearchFolder($service);
    $searchFolder.SearchParameters.RootFolderIds.Add([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot);
    $searchFolder.SearchParameters.Traversal = [Microsoft.Exchange.WebServices.Data.SearchFolderTraversal]::Deep;
    $searchFolder.SearchParameters.SearchFilter = $SearchFilter
    


    This searches the inbox to find a sub-string in the subject containing "Update Available!" but I'm not exactly sure where to go from here.

    Any help would be much appreciated!

    Thanks,

    Kevin

    Monday, September 19, 2011 5:24 PM

All replies

  • Hi,

    actually, you don't need to create a search folder. Just do a service.FindItems call using the search filter you have constructed. This will return a list of EmailMessages you can work with.

    Kind regards,
    Henning Krause

    Monday, September 19, 2011 8:25 PM
  • If you have 2010 I would also use AQS to query the content index rather then use a Searchfilter this can help if you are dealing with folders that have large item counts  eg

    $AqsString = "System.Subject:`"Update Available!`"" 
    $MailboxName = "user@domain.com"
    
    $dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"
    [void][Reflection.Assembly]::LoadFile($dllpath)
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
    $service.Credentials = New-Object System.Net.NetworkCredential("user@doma.com","password")
    
    $service.AutodiscoverUrl($MailboxName,{$true})
    
    "Checking : " + $MailboxName 
    $ibInbox = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
    $fiItems = $null
    $ItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
    do{
    	$fiItems = $service.findItems($ibInbox,$AqsString,$ItemView)
    	$ItemView.offset += $fiItems.Items.Count
    	foreach($Item in $fiItems.Items){
    		$Item.Subject
    	}
    }while($fiItems.MoreAvailable -eq $true)
    
    

    Cheers
    Glen

    Tuesday, September 20, 2011 5:11 AM
  • Hmm. I tried something similar, but it's not outputting any results. For testing purposes, I entered "FW: v1190  BRS (web) is available!" which is the actual subject copied from the email. I'm not able get any results from that. 

     

    $String = "System.Subject:`"FW: v1190  BRS (web) is available!`"" 
    $dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"
    [void][Reflection.Assembly]::LoadFile($dllpath)
    
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
    $windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
    $aceuser = [ADSI]$sidbind
    
    $service.AutodiscoverUrl($aceuser.mail.ToString())
    
    
    $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
    
    $iv = new-object Microsoft.Exchange.WebServices.Data.ItemView(1)
    $fiItems = $service.FindItems($folderid, $String, $iv)
    $ItemView.offset += $fiItems.Items.Count
    foreach ($Item in $fiItems.Items){
           $Item.Subject
    }
    



    Tuesday, September 20, 2011 1:45 PM
  • So with the variable $MailboxName are you actually putting anything in this you should put the primary SMTP address of the mailbox you want to access in this variable if your using the currently logged in User you could drop this or do something like

    $MailboxName = $aceuser.mail.ToString()

    Also this will only look at email in the users Inbox folder so if you have a rule that moves messages into another folder in the Mailbox you would need to include some code to first find the folderId of that mailbox folder so you can then issue a FindItems on that folder

    Cheers
    Glen

    Wednesday, September 21, 2011 4:35 AM
  • Ok. So I was able to build the script. Everything works fine except for one thing. When I try to run this script as a scheduled task, it does not execute. My schedule tasks settings are correct, so I'm not exactly sure why it's not executing. Below is the script

     

    $dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"
    [void][Reflection.Assembly]::LoadFile($dllpath)
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
    
    #Get the email address of the user running the function
    $windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
    $aceuser = [ADSI]$sidbind
    $service.AutodiscoverUrl($aceuser.mail.ToString())
    
    # Find the email message by subject string
    $String = "BRS (web) is available!"
    $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
    
    # Configure the amount of items to be viewed
    $iv = new-object Microsoft.Exchange.WebServices.Data.ItemView(1)
    
    # Find email messages based on the subject string
    $findItems = $service.FindItems($folderid, $String, $iv)
    
    # Create a persistant connection to the remote computer 
    $pass = convertto-securestring PASSWORD -asplaintext -force
    $servCred = new-object -typename System.Management.Automation.PSCredential -argumentlist USER ,$pass
    $s = new-pssession -computername SERVER -credential $servCred
    
    # If message containing $String has not been read yet, determine version number   
    foreach ($Item in $findItems.Items){
        if ($Item.IsRead -eq $FALSE){
                $Item.Subject
                $Item.DateTimeReceived
               
                $toString = $Item.Subject                                                       # $toString = BRS (web) is available!
                $emailVersion = $toString.ToString()                                            # $emailVersion = FW: v1190 BRS (web) is available!
                $emailVersion = $emailVersion.substring($emailVersion.indexof("v"))             # $emailVersion = v1190 BRS (web) is available!
                $emailVersion = $emailVersion.substring(0,$emailVersion.indexOf(" "))           # $emailVersion = v1190
    
                $sftpVersion = get-childitem U:\*.zip | sort-object LastWriteTime -descending | select -first 1 
                $sftpVersion = $sftpVersion.ToString()                                          # $sftpVersion = U:\v1190.zip
                $sftpVersion = $sftpVersion.substring($sftpVersion.indexof("v"))                # $sftpVersion = v1190.zip
                $sftpVersion = $sftpVersion.substring(0,$sftpVersion.indexOf("."))              # $sftpVersion = v1190
    
                if ($emailVersion -ne $sftpVersion){
                    invoke-command -session $s -scriptblock {C:\BRSetup\Update_now.ps1} -asjob
                    Start-Sleep -s 180
                    get-job | stop-job -passthru }
                
                if($emailVersion -eq $sftpVersion){
                     Write-Host "Versions are the same" -verbose
                    
                }
                
         $Item.IsRead = $TRUE 
         $item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)  
         }
    }
      
    


    Wednesday, September 21, 2011 7:24 PM
  • Its unlikely the script causing this but start with basics eg put some logging into to see if the script is running eg first line

    $File ="C:\temp\Debug.txt"
    Get-Date | Out-File $File

    Also read and check http://technet.microsoft.com/en-us/library/ee176949.aspx

    Eg it maybe things like signing in the profile the scheduled task is using etc

    Cheers
    Glen

    Thursday, September 22, 2011 5:33 AM