Jump to content
Sign in to follow this  
BigDaddyO

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


hmm... I guess I have to have a signature...

Share this post


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

Share this post


Link to post
Share on other sites

I was hoping to convert the whole thing into pure AutoIT, but for now, I'll look into trying to pass parameters into it as you suggested since I'll need to pass Credentials and such.

 

Thanks,

Mike


hmm... I guess I have to have a signature...

Share this post


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

Share this post


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


hmm... I guess I have to have a signature...

Share this post


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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By obiwanceleri
      Good evening! 
      I know this has been done to death in many programming languages and probably even in AutoIt. 
      But couldn't help myself and as a learning challenge I wrote "yet another converter" LOL
      I need your help to test it and show me "the error of my ways" but in a nutshell here's what it can do already (taken from my source file) :
      Converts all zip files recursively into a 7Zip file, with max compression REQUIRES AUTOIT Version 3.3.14.5 + Exact copy with attributes and folder structure + Extensive error checking, including files blocked by anti-virus (by file count) + Can stop process and restart later with the use of a log file + Can pause process (but in between compressing / extracting files) + Creates a .CSV file that can be used to check on compression ratios + Dynamic GUI that enables user to see console while 7zip is working + Gui can be stretched horizontally for long filenames + Up to 5 retries while transfering compressed files + Checks free space (at startup) to make sure you don't kill your OS LOL + Have converted 10,000+ files with no issues in file integrity. + Open to suggestions and program free to modify to your liking + Will eventually be fully modular and configurable (if there is interest for this) + Exit codes so you can have an idea where program went wrong (if it did) + Fully commented so users can tinker away. - Cannot save archive comments. - Not FULLY tested yet, do not use on .zip files that have no backups The program also has a very minimal GUI that can be stretched. Not a huge fan of million-button interfaces.
      I also assume some people running this program will have a 1024x768 monitor so the GUI is made accordingly.
      There is no way I am keeping this script for myself. If this is useful to anybody, feel free to use it and modify it. All I ask is you credit me (as I will credit those who contribute).
      Now here's the issues that are left to fix. Any help is greatly appreciated and I will add your name in the credits if you so wish.
      - For some reason while compression is under way, all my current explorer windows flicker; notably the cut-and-paste part. I can't seem to narrow it down. 
      - Also context menu is closed in explorer every time program compresses / extracts a new file
      - I've added support for retries if, for some reason, AutoIt can't move the converted file. This happened once after 5000-6000 conversions. Now that I've programmed the retries, the process is somewhat slower. It shouldn't affect speed though.  
      - After compressing 10,000+ files (Yes I have that many zip files! Think Mame) I've had a system meltdown. There's a leak somewhere. Am I supposed to close something and I'm not? I've added _IsPressed() lately so closing that .DLL is not the cause of this leak. 
      - Subtracting one array from another was a tricky thing to program (happens when user stops and restarts process), if you can think of a faster way I'm all in.
      Obviously if you find bugs or have suggestions, I'm all ears. 
      Changelog is included in the source file, including credits.
      PLEASE DON'T CONVERT ALL YOUR FILES YET. It's not fully tested (well I tested it but I need others to test too).
       
      Obiwanceleri
      Zip27z_102.au3
    • By Exit
      For my next project I would like to send files with "alternate data streams" by email in ZIP format.
      I can not use any external program like 7-Zip or WinRAR. (They would fit😥)
      Who knows how to create a ZIP file with "alternate data streams" included with the Powershell command "Compress-Archive"? 
      Here a test script:  (save as "ADSTester.cmd")
      @rem Try to create a zip file with alternate data streams (ADS) included @rem Housekeeping @cls @del ADSTester.zip >nul: @RD /S /Q Extracted >nul: @del ADSTester.txt >nul: @rem End of Housekeeping echo This is the ADSTester.txt file >ADSTester.txt echo This is the ADSTester.txt:Part1 file >ADSTester.txt:Part1 echo This is the ADSTester.txt:Part2 file >ADSTester.txt:Part2 dir /r ADSTester.txt @rem See the 3 files @rem **************************************************************** @rem **************************************************************** @rem Please alter the next lines to include the alternate data streams. powershell Compress-Archive -Path .\ADSTester.txt -Update -DestinationPath ADSTester.zip powershell Expand-Archive -Path ADSTester.zip -DestinationPath .\Extracted\ dir /r Extracted\ADSTester.txt @rem Only one file left :-( pause  
    • By ur
      Which Powershell command in the PowerCLI module for VMware ESX used to interact with UI apps?
       
      When I launch any exe/any exeutable using powercli on guest VM using powercli command.
      Invoke-VMScript, I am able to run them in the background but not in the foreground.
       
      i.e., UI apps are not launching but showing the background as running in the task manager.
       
      We need our UI Automation scripts to execute in the VM, but it is not working.
       
      We are able to do in virtualbox and hyper-v but not in vmware esx using powercli.
       
      Please suggest.
    • By ambad4u
      Hello and Good Day to All!
      I am trying to install .NET 3.5 on Windows 10 x64bit via autoit (via ShellExecuteWait + PowerShell).
      If I run this line, it will runs without issues:
      ShellExecuteWait('PowerShell.exe', '-executionpolicy Bypass -File "' & @ScriptDir & '\OJP83BU523.ps1' & '"') "OJP83BU523.ps1" contains: DISM /Online /Enable-Feature /FeatureName:NetFX3 /All /Source:D:\Sources\sxs /LimitAccess
      However, since I won't know in advance the drive letter of the "sources" folder, I created a script to generate a PowerShell Script to give a correct path for it.
      With the modified script below, PowerShell only blinks and nothing happens
      ShellExecuteWait('PowerShell.exe', '-executionpolicy Bypass -File "' & @ScriptDir & '\' & $filename & '"') or
      ShellExecuteWait('PowerShell.exe', '-executionpolicy Bypass -File "' & $filename & '"')  
      I wish I know the difference with "$filename" and "\OJP83BU523.ps1" usage, as for me, it should be the same.
      Attached is my entire autoit script.
      any help is appreciated!, many thanks in advance!
      test.au3
    • By JLogan3o13
      There are a number of posts on the forum regarding use of Selenium in AutoIt. I recently had a go at using the PowerShell Selenium module, and was amazed at how easy it is. Thought I would post an example here; if anyone is interested this could probably be incorporated into AutoIt code pretty easily. 
      Pre-Req - The true star of this script is the ChroPath extension, available for Edge, Chrome and FireFox. With it installed, you just click on the element, select Inspect, and then ChroPath generates the XPath to the element for you. Here is an example based on a simple form I created on one of my sites.
      $myForm = Start-SeChrome -StartURL "http://logancomputerser.com/Appointment.html" -Maximized $firstName = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_First']" $lastName = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_Last']" $address = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_Street1']" $city = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_City']" $zip = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_Zip']" $state = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//select[@id='formElement_State']" $phoneDay = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_DaytimePhone']" $phoneNight = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_EveningPhone']" $email = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_liamE']" $user = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_48564']" $pw = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='formElement_f403c']" $submit = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='wstForm_Contact_Submit']" $reset = Find-SeElement -Driver $myForm -Timeout 30 -XPath "//input[@id='wstForm_Contact_Reset']" Send-SeKeys -Element $firstName -Keys "Joe" Send-SeKeys -Element $lastName -Keys "Blow" Send-SeKeys -Element $address -Keys "111 S. Main St." Send-SeKeys -Element $city -Keys "AnyCity" Send-SeKeys -Element $zip -Keys "90210" Send-SeKeys -Element $state -Keys "CA" Send-SeKeys -Element $phoneDay -Keys "555.867.5309" Send-SeKeys -Element $phoneNight -Keys "555.888.1212" Send-SeKeys -Element $email -Keys "1Adam12@gmail.com" Send-SeKeys -Element $user -Keys "JBlow" Send-SeKeys -Element $pw -Keys "MyPassword" Start-Sleep 1 Invoke-SeClick -Element $submit Stop-SeDriver -Driver $myForm  
      As mentioned, this is just another way to skin the cat, but I found it a pretty fast way to initiate some easy testing in Selenium, and have used it a couple of times in projects now, both straight through PowerShell and wrapped in AutoIt.
×
×
  • Create New...