Jump to content

Get eMails from Exchange inbox powershell to AutoIT?


Recommended Posts

After much searching I finally found a method to get eMails from an Exchange eMail account inbox.  I was hoping for AutoIT or vbscript but I couldn't find any that would read the inbox messages without using Outlook.

I needed this because I'm testing a web-form that generates an eMail sent to a shared mailbox "not what my current outlook is configured for".  so, I needed to connect to a different account, then get the inbox messages, and see if the auto-generated eMail message body contains what I submitted in the form.

 

I found a PowerShell script that was close and modified it to do just what I want, but I'd still like it to run in AutoIT but I'm not sure how to use the Microsoft.Exchange.WebServices.dll

Anybody have some ideas? 



#To Launch!
#	C:\Windows\System32> powershell -ExecutionPolicy ByPass		#This launches PowerShell and allows execution of .ps1 files
#	PS C:\Windows\System32> . "C:\Temp\eMail\getInbox.ps1"		#The period . in front of the .ps1 file forces PS to display results on-screen


# Where is the EWS .DLL file that you are using
# Get the installer from https://www.microsoft.com/en-us/download/details.aspx?id=42022
# We only need 2 dll's from the install and they can be stored anywhere:  "Microsoft.Exchange.WebServices.Auth.dll" & "Microsoft.Exchange.WebServices.dll"
	$EWSdll = "C:\Temp\eMail\Microsoft.Exchange.WebServices.dll"

# Where do you want the output text file to be saved
	$Output = "C:\Temp\eMails.txt"

# replace with your email address
	$email    = "MyemailAddress@work.net"

# only need to populate these if you're impersonating...
	$username = "myemail"
	$password = "Sup3rS3cre+"
	$domain   = "ad.work.net"

# load the assembly : point to the dll in the location you have the .dll file
	[void] [Reflection.Assembly]::LoadFile($EWSdll)

# set ref to exchange, first references 2007, 2nd is 2010 (default)
	#$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
	$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService

# use first option if you want to impersonate, otherwise, grab your own credentials with the 3rd one.  not sure what the 2nd one is for
	$s.Credentials = New-Object Net.NetworkCredential($username, $password, $domain)
	##$s.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
	#$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;

	# If you have a set number of items you want to get, use this and insert the # in the ()
	# $items = $inbox.FindItems(5)

	# If you want to retrieve all items (Server limit is usually at 1000) then use this line
	#	Details on the max returned by server:  https://blogs.msdn.microsoft.com/exchangedev/2010/03/12/throttling-policies-and-the-ewsfindcountlimit/
	$items = $inbox.FindItems($inbox.TotalCount)


# Put some counts at the top of the output
	Write-host "Total Inbox count: $($inbox.TotalCount)"
	Write-host "Unread count: $($inbox.UnreadCount)"

	#These two lines, write the output to the specified text file
	Add-Content $Output "Total Inbox count:  $($inbox.TotalCount)"
	Add-Content $Output "Unread count:  $($inbox.UnreadCount)"

	foreach ($item in $items.Items)
	{
	# load the property set to allow us to get to the body
	  $item.load($psPropertySet)

	  # Get the Body text as-is
	  $bod = $item.Body.Text

	#if you only want a short summary of the Body, then comment the above line and un-comment these 4 lines
	   # $bod = $item.Body.Text -replace '\s+', ' '
	   # $bodCutOff = (100,$bod.Length | Measure-Object -Minimum).Minimum
	   # $bod = $bod.Substring(0,$bodCutOff)
	   # $bod = "$bod..."


	  # output the results - first of all the From, Subject, References and Message ID
	  write-host "===================================================================="
	  Write-host "From:  $($item.From.Name)"
	  Write-host "Subject:  $($item.Subject)"
	  Write-host "Body:  $($bod)"
	  write-host "===================================================================="
	  ""

	  # Output the results to the specified Text file
	  Add-Content $Output ""
	  Add-Content $Output "===================================================================="
	  Add-Content $Output "From:  $($item.From.Name)"
	  Add-Content $Output "Subject:  $($item.Subject)"
	  Add-Content $Output "Body:",$($bod)
	  Add-Content $Output "===================================================================="
	  Add-Content $Output ""

	}




#see these URLs for more info
# EWS Stuff
# folder members: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.folder_members%28v=exchg.80%29.aspx
# exporting headers: https://www.allabout365.com/2010/10/export-email-headers-exchange-powershell/
# read emails with EWS: https://social.technet.microsoft.com/Forums/en-US/3fbf8348-2945-43aa-a0bc-f3b1d34da27c/read-emails-with-ews?forum=exchangesvrdevelopment

 

Thanks,

Mike

Link to post
Share on other sites

If you just want to call your powershell from AutoIt. you need to set your Dll full path to $EWSdll. 

 

Probably you could write a Cmdlets or function to to be easy pass parameter  to your powershell script using AutoIt.

Then you can call it using something like this in AutoIt

 

Local $sCommands = $sPSFullPath & ' -ExecutionPolicy ByPass import-module "' & $sPsScriptFullPath & '" ;Your-CmdLets -someparameter1 "'& $sparam1  &'" -someparameter2 "'& $sparam2 & '"'
Local $iPID = RunWait(@ComSpec & " /c " & $sCommands, "", @SW_SHOW)

Saludos

Link to post
Share on other sites

I think is a little complex convert to row AutoIt due seems to be it does not provide a COM accesible Object (Activex). You could probably could do it using  .NET Common Language Runtime (CLR) Framework. Probably a little easer Running C# or NET code through those libraries but It would be embebed code something like powershell. 

I think your actual code, using powershell is simple,easy and functional.


Saludos

Link to post
Share on other sites

I have updated the PowerShell script to accept parameters, but it's failing if the Paths contain spaces.  I have tried so many different ways and it keeps failing whenever I try to use a path with a space.

Any ideas on how to get this to work with spaces?

 

This works great!  PowerShell -ExecutionPolicy ByPass -command "C:\Temp\GetMail.ps1" -EWSdll 'C:\Temp\Microsoft.Exchange.WebServices.dll' -Output 'C:\Temp\eMails.txt' -email 'MyemailAddress@work.net' -username 'myemail' -password 'Sup3rS3cre+' -domain 'ad.work.net'

 

This fails with TONS of errors!  PowerShell -ExecutionPolicy ByPass -command "C:\Temp\eMail Test\GetMail.ps1" -EWSdll 'C:\Temp\eMail Test\Microsoft.Exchange.WebServices.dll' -Output 'C:\Temp\eMail Test\eMails.txt' -email 'MyemailAddress@work.net' -username 'myemail' -password 'Sup3rS3cre+' -domain 'ad.work.net'

 

 

param(
	[string]$EWSdll,
	[string]$Output,
	[string]$email,
	[string]$username,
	[string]$password,
	[string]$domain
	)

# load the assembly : point to the EWS dll
	[void] [Reflection.Assembly]::LoadFile($EWSdll)

# set ref to exchange, first references 2007, 2nd is 2010 (default)
	#$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
	$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService

# use first option if you want to impersonate, otherwise, grab your own credentials
	$s.Credentials = New-Object Net.NetworkCredential($username, $password, $domain)
	##$s.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
	#$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;

	# If you have a set number of items you want to get, use this and insert the # in the ()
	# $items = $inbox.FindItems(5)

	# If you want to retrieve all items (Server limit usually at 1000) then use this
	#	Details on the max returned by server:  https://blogs.msdn.microsoft.com/exchangedev/2010/03/12/throttling-policies-and-the-ewsfindcountlimit/
	 $items = $inbox.FindItems($inbox.TotalCount)

# output unread count
	Write-host "Total Inbox count: $($inbox.TotalCount)"
	Write-host "Unread count: $($inbox.UnreadCount)"

	#These two lines, write the output to the specified text file
	Add-Content $Output "Total Inbox count:  $($inbox.TotalCount)"
	Add-Content $Output "Unread count:  $($inbox.UnreadCount)"

	foreach ($item in $items.Items)
	{
	# load the property set to allow us to get to the body
	  $item.load($psPropertySet)

	  # Get the Body text as-is
	  $bod = $item.Body.Text

	#if you only want a short summary of the Body, then comment the above line and un-comment these 4 lines
	   # $bod = $item.Body.Text -replace '\s+', ' '
	   # $bodCutOff = (100,$bod.Length | Measure-Object -Minimum).Minimum
	   # $bod = $bod.Substring(0,$bodCutOff)
	   # $bod = "$bod..."


	  # output the results - first of all the From, Subject, References and Message ID
	  write-host "===================================================================="
	  Write-host "From:  $($item.From.Name)"
	  Write-host "Subject:  $($item.Subject)"
	  Write-host "Body:  ",$($bod)
	  write-host "===================================================================="
	  ""

	  # Output the results to the specified Text file
	  Add-Content $Output ""
	  Add-Content $Output "===================================================================="
	  Add-Content $Output "From:  $($item.From.Name)"
	  Add-Content $Output "Subject:  $($item.Subject)"
	  Add-Content $Output "Body:",$($bod)
	  Add-Content $Output "===================================================================="
	  Add-Content $Output ""

	}




#see these URLs for more info
# EWS Stuff
# folder members: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.folder_members%28v=exchg.80%29.aspx
# exporting headers: https://www.allabout365.com/2010/10/export-email-headers-exchange-powershell/
# read emails with EWS: https://social.technet.microsoft.com/Forums/en-US/3fbf8348-2945-43aa-a0bc-f3b1d34da27c/read-emails-with-ews?forum=exchangesvrdevelopment

 

Thanks,

Mike

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By DannyJ
      $sCommands1 = 'powershell.exe Get-ChildItem' $iPid = run($sCommands1   , @WorkingDir , @SW_SHOW , 0x2) $sOutput = ""  While 1     $sOutput &= StdoutRead($iPID)         If @error Then             ExitLoop         EndIf  WEnd ;~ msgbox(0, '' , $sOutput) ConsoleWrite("$sOutput") ConsoleWrite($sOutput) ConsoleWrite(@CRLF) $aOutput = stringsplit($sOutput ,@LF , 2) For $i=0 To  UBound($aOutput) - 1 Step 1     ConsoleWrite($aOutput[$i]) Next The script above reads the whole directory into a one dimensional array, but I need to work with the array, so I need to split the array into multiple dimensions.
      I have already read some forum answers here, and I have already tried these commands:
       
      Are there any way to use the $aOutput variable like in PowerShell:
      PowerShell:
      $a = Get-ChildItem $a.Mode I imagine this in AutoIt  $aOutput
      ConsoleWrite($aOutput[i].Mode) Or if I split this command into 2 dimension like:
      For $i To UBound($aOutput)-1 Step 1 ConsoleWrite($aOutput[$i][1]) ConsoleWrite($aOutput[$i][2]) Next  
    • By DannyJ
      If I try to run this script with   Get-ChildItem which means dir this script works perfectly, but If I try to run this command Get-RDUserSession, my script has the following error message:
      This command runs perfectly in PowerShell admin and I get back the values
      Get-RDUserSession -ConnectionBroker  broker.local | sort Username Or you can try this command as well
      Get-Command Get-RDUserSession If I run the above mentioned command this runs perfectly in PowerShell but not with AutoIt.
      Here is my script you can test the commands:
      #include<array.au3> $iPid = run('powershell Get-Command Get-RDUserSession'  , @WindowsDir , @SW_HIDE , 0x2) ;; This command not works in AutoIT you can test it in PowerShell but it won't work in Autoit ;$iPid = run('powershell Get-RDUserSession -ConnectionBroker  broker.local | sort Username'  , @WindowsDir , @SW_MAXIMIZE , 0x2) ; This command not works in AutoIT ;$iPid = run('powershell Get-ChildItem | sort Name'  , @WindowsDir , @SW_HIDE , 0x2) ; This runs perfectly $sOutput = ""  While 1     $sOutput &= StdoutRead($iPID)         If @error Then             ExitLoop         EndIf  WEnd ;~ msgbox(0, '' , $sOutput) $aOutput = stringsplit($sOutput , @LF , 2) _ArrayDisplay($aOutput)  
      That could be the solution of the problem if I could run, directly this PowerShell command window and Write to it and save it's values.
    • By DrLarch
      I'm trying to run this powershell command from Autoit and can't figure out how to pull it off:
      Get-ProvisionedAppxPackage -Online | Where-Object { $_.PackageName -match "xbox" } | ForEach-Object { Remove-ProvisionedAppxPackage -Online -AllUsers -PackageName $_.PackageName } I've been trying to run it many different ways including:
      $sCMD = 'Get-ProvisionedAppxPackage -Online | Where-Object { $_.PackageName -match "xbox" } | ForEach-Object { Remove-ProvisionedAppxPackage -Online -AllUsers -PackageName $_.PackageName }' RunWait(@comspec & ' /c powershell.exe -nologo -executionpolicy bypass -noprofile -Command "&' & $sCMD & '"') The problem is that it seems I'm missing something in how to escape or double the quotes. I've tried doubling the quotes in many different ways, but the end result always produces a syntax error in powershell. I could just run powershell first, then paste and run the command, then close the powershell window, but that's clunky. I'm trying to do it either via parameter (as above) or in one line like this:
      RunWait(@comspec & ' /c powershell.exe -nologo -executionpolicy bypass -noprofile -Command "&Get-ProvisionedAppxPackage -Online | Where-Object { $_.PackageName -match "xbox" } | ForEach-Object { Remove-ProvisionedAppxPackage -Online -AllUsers -PackageName $_.PackageName }"')  
    • By antonioj84
      any assistance how to incorporate this powershell command within autoit
       
      powershell.exe -nologo -executionpolicy bypass -WindowStyle hidden -noprofile -command "&Set-WinUserLanguageList -LanguageList fr-CA, en-CA -Force"
    • By Divane
      Hello everyone. I need to convert any string to 3-digit decimal. It is possible to convert through online tools. Is there any way to do this in AutoIt.

      For Example ;
      8cdb3 = DECIMAL 056 099 100 098 051

      Is it possible the conversion above by AutoIt? Thanks.
×
×
  • Create New...