16156

Create a calendar item

Continuing the occasional look at Outlook automation its time to see how we create a calendar item

function new-calendaritem {            
param (            
            
 [string]$mailbox,            
             
 [datetime]$start,            
             
 [datetime]$end,            
             
 [string]$subject,            
             
 [string]$location,            
             
 [string]$body            
            
)            
$outlook = New-Object -ComObject Outlook.Application            
            
$folder = get-mailfolders |             
where {$_.Path -like "*calendar*" -and $_.Path -notlike "*birthday*" -and $_.Path -like "*$mailbox*"}            
            
$calendar = $outlook.Session.GetFolderFromID($folder.EntryID, $folder.StoreID)            
             
$entry = $calendar.Items.Add(1)            
$entry.Start = $start            
             
$entry.End = $end            
             
$entry.Subject = $subject            
             
$entry.Location = $location            
             
$entry.Body = $body             
             
$entry.Save()            
            
}


 



The appropriate calendar is identified – remember I have 4 to choose from. The Add method is used from the calendar items collection and the properties populated.



I always enter dates like this “14 September 2011 11:00” as it removes any problems with culture. In the UK this would be “14/9/2011 11:00” but when entering in this style I have to remember to use the US format “9/14/2011 11:00”



The mailbox parameter helps identify which calendar the entry goes

Outlook: removing calendar entries

We recently looked at dumping the Calendar entries

http://msmvps.com/blogs/richardsiddaway/archive/2011/08/23/outlook-viewing-calendar-entries.aspx

 

I usually leave entries to build up in the Calendar but a simple clean operation is to delete everything that occurred before a certain date

function remove-calendaritem {            
param (            
 [datetime]$date            
)            
$outlook = New-Object -ComObject Outlook.Application            
            
get-mailfolders |             
where {$_.Path -like "*calendar*" -and $_.Path -notlike "*birthday*"} |            
foreach {            
  $targetfolder = $outlook.Session.GetFolderFromID($_.EntryID, $_.StoreID)            
              
  $targetfolder.Items | foreach {            
    if ($_.StartTime -lt $date){$_.Delete()}            
  }             
}            
}


The date parameter defines the date for which we want to delete all earlier entries. Get the calendar folders and test the StartTime of each entry. If its before our date then delete it.

Outlook: Viewing Calendar Entries

We have seen how to view emails – this is how to view items in your calendar

function get-calendaritem {            
            
$outlook = New-Object -ComObject Outlook.Application            
            
get-mailfolders |             
where {$_.Path -like "*calendar*" -and $_.Path -notlike "*birthday*"} |            
foreach {            
  $targetfolder = $outlook.Session.GetFolderFromID($_.EntryID, $_.StoreID)            
              
  $targetfolder.Items | foreach {            
   New-Object -TypeName PSObject -Property @{            
    Folder = $targetfolder.FolderPath            
    StartTime = $_.Start            
    EndTime = $_.End            
    Organizer = $_.Organizer            
    Subject = $_.Subject            
    Location =$_.Location            
   }            
  }             
}            
}


Use the get-mailfolders function we developed earlier. Filter for the calendar folders. For each of them get the folder and strip the appropriate properties from the entry. Create an object and display

Outlook: sending emails

We’ve looked at examining the email folders and their contents, as well as cleaning out old emails.

Its time to look at sending emails. This function shows the skeleton of the process

function send-mailitem {            
param (            
            
 [string]$to,            
             
 [string]$from,            
             
 [string]$subject,            
             
 [string]$body            
            
)            
$outlook = New-Object -ComObject Outlook.Application            
            
$email = $outlook.CreateItem($types::olMailItem)            
            
$email.To = $to            
$email.subject = $subject            
$email.body = $body            
            
$email.SendUsingAccount = $outlook.Session.Accounts | where {$_.DisplayName -eq $from}            
$email.Send()            
}


Create a new mail item object. Set the To, subject and body



The choose the account from which to send the email – remember I have multiple hotmail accounts connected through Outlook. If you are using Exchange you may want to test using smtpaddress instead of DisplayName



We can then use the send method to fire off the email.



There are a number of things to do to tidy this up:



  1. Create a function to get the account
  2. Accept the To parameter from the pipeline to enable multiple recipients
  3. Check the email addresses using regex (oh joy)

Outlook: deleting mail items

As promised here is the function to delete mail items in a specific folder

function remove-mailitem {            
[CmdletBinding(SupportsShouldProcess=$true)]            
param (            
 [parameter(Mandatory=$true)]            
 [string]$mailfolder,            
              
 [datetime]$start,            
 [datetime]$finish            
)            
if ($start -and $finish){            
  if ($start -ge $finish){Throw "Finish $($finish) before Start $($start)"}            
}            
            
$outlook = New-Object -ComObject Outlook.Application            
            
$folders | where {$_.Path -like "*$mailfolder"} |            
foreach {            
$targetfolder = $outlook.Session.GetFolderFromID($_.EntryID, $_.StoreID)            
              
foreach ($item in $targetfolder.Items)  {            
 if ($start){if ($item.SentOn -lt $start){continue}}            
 if ($finish){if ($item.SentOn -gt $finish){continue}}            
             
  if ($psCmdlet.ShouldProcess("$($item.Subject) $($item.SentOn)", "deleting")) {            
    $item.Delete()            
  }            
              
}            
               
}            
}


If you’ve been following this series you will recognise how this works. The parameters are the mail folder and an optional start and finish date. A quick check to see if the dates are the right way round and we jump into the processing. The folders that match our input are selected and foreach of them we loop through the mail items.



The SentOn date is compared to the start and finish dates if they are defined. The item is skipped if it falls outside of those dates.



We can then delete the item. I’ve also added the –whatif parameter to the function by using   [CmdletBinding(SupportsShouldProcess=$true)] and



if ($psCmdlet.ShouldProcess("$($item.Subject) $($item.SentOn)", "deleting")) {
  $item.Delete()
}



This adds another safety level to the function

Outlook: Viewing mail items

Continuing our perambulation around Outlook when used with multiple hotmail accounts its time to look at the other folders and the mail items they contain. This post will show how to view the mail items and a future post will show how to delete items from a specific folder.

Viewing mail items cam be performed with the following function

function get-mailitem {            
param (            
 [parameter(Mandatory=$true)]            
 [string]$mailfolder,            
              
 [switch]$all            
)            
$outlook = New-Object -ComObject Outlook.Application            
            
$folders | where {$_.Path -like "*$mailfolder"} |            
foreach {            
  $targetfolder = $outlook.Session.GetFolderFromID($_.EntryID, $_.StoreID)            
              
  if ($all){            
   $targetfolder.Items             
  }            
  else {            
   $targetfolder.Items | sort  SentOn -desc | select SenderEmailAddress, Subject, SentOn            
  }            
}            
}


The function takes a mandatory string to identify the mail folder and we use the GetFolderFromID method to access the folder. If the –all switch is used we get a dump of the full object for each mail item otherwise a summary consisting of the sender’s address, date sent and subject is output.



If the –all switch is used we can use the PowerShell pipeline to perform further processing e.g.



get-mailitem –mailfolder Baen –all | where {$_.SentOn –lt [datetime]”1 January 2007”}

Clearing junk mail

Getting back to looking at working with Outlook we can adapt the function used to deleted the contents of the Deleted Items folder to work with the Junk mail folders

function clear-junkmail {            
            
$outlook = New-Object -ComObject Outlook.Application            
            
get-mailitemcount -junk            
            
$folders | where {$_.Path -like "*junk*"} |            
foreach {             
  $mailfolder = $outlook.Session.GetFolderFromID($_.EntryID, $_.StoreID)            
              
  if ($mailfolder.Items.Count -gt 0){            
    do {            
      foreach ($item in $mailfolder.Items){$item.Delete()}            
    } while ($mailfolder.Items.Count -gt 0)            
  }               
}            
get-mailitemcount -junk            
}


Very much the same as before but we are looking for folders that contain the work “junk”



It would be possible to combine this function and the clear-deletedmail function but I decided to keep them separate for simplicity

Outlook folder item count revisited

I started this series http://msmvps.com/blogs/richardsiddaway/archive/2011/07/30/outlook-connector-amp-mail-folder-item-count.aspx by looking at how we could enumerate the mail folders in Outlook 2010 when I had had four hotmail accounts open.  The function has been modified since then

function get-mailitemcount {            
param (            
 [parameter(ParameterSetName="All")]            
 [switch]$all,             
 [parameter(ParameterSetName="Deleted")]            
 [switch]$deleted,            
 [parameter(ParameterSetName="Junk")]            
 [switch]$junk            
)            
$outlook = New-Object -ComObject Outlook.Application            
foreach ($folder in $outlook.Session.Folders){            
              
  foreach($mailfolder in $folder.Folders ) {            
               
  if ($deleted) {if ($($mailfolder.Name) -notlike "Deleted*"){continue} }            
  if ($junk)  {if ($($mailfolder.Name) -notlike "Junk*"){continue} }            
               
    New-Object -TypeName PSObject -Property @{            
      Mailbox = $($folder.Name)            
      Folder = $($mailfolder.Name)            
      ItemCount = $($mailfolder.Items.Count)            
    } | select Mailbox, Folder, ItemCount            
  }             
}            
}


I use three parameters to determine if I want to look at the Junk or Deleted folders or if I’m  going to dump the information for all folders.  I’ve used parameter sets to make the three parameters mutually exclusive.



The same loops are used as before – the outer one loops through the mailboxes and the inner one through each folder in those mailboxes.  If the deleted or junk switches have been set any folder that doesn’t match the criteria is skipped.



An object is created to output the name of the mailbox, folder and number of items

Emptying the Deleted folders–version 2

The original version of this function only did one pass at deleting and had to iterate through all of the folders to find the Deleted Items folder.  This time we use the collection of folders we created using the get-mailfolders function to go directly to the Deleted Items folders

function clear-deletedmail {            
            
$outlook = New-Object -ComObject Outlook.Application            
            
get-mailitemcount -deleted            
            
$folders | where {$_.Path -like "*deleted*"} |            
foreach {             
  $mailfolder = $outlook.Session.GetFolderFromID($_.EntryID, $_.StoreID)            
              
  if ($mailfolder.Items.Count -gt 0){            
    do {            
      foreach ($item in $mailfolder.Items){$item.Delete()}            
    } while ($mailfolder.Items.Count -gt 0)            
  }               
}            
get-mailitemcount -deleted            
}


The function starts by creating an Outlook object. The get-mailitemcount function has been revised to provide just the deleted or junk folders (I’ll post about the revisions next)



The folders collection is filtered to select just the Deleted Items folders (I’m assuming the word deleted hasn’t been used in any other folder names).  Each of the Deleted Items folders is accessed using the GetFoderFromID function using the EntryID and StoreID saved in the objects in the folder. If the number of items in the folder is not zero we create a do loop to control the deletion. This will keep calling the foreach loop that performs the deletion until everything is deleted (remember our original function need several passes to delete all the items in the folder)



A final call to get-mailitemcount shows the position after all of the items are deleted.

Outlook folders

The functions we’ve seen so far have involved iterating through the whole set of Outlook folders. That’s a lot of folders (I have 4 email accounts with lost of folders). The trick is to do this just once and then use the GetFolderFromID method at the Outlook.Session level to access individual mailboxes

The problem is that this method uses the EntryID and the StoreID for the folder.  Examples are shown below

StoreID : 0000000038A1BB1005E5101AA1BB08002B2A56C200006D736E636F6E2E646C6C
0000000000000000E92FEB759650448683B87DE522AA494800433A5C55736572735C526963
686172645C417070446174615C4C6F63616C5C4D6963726F736F66745C4F75746C6F6F6B5C
726963686172645F73696464617761795F686F746D61696C2E6F737400

EntryID : 000000000A9D24A8D4E32445825D043ADB203A6F0100D9539C2261A6BB45B9DA
B62C7081B3C101002100FFFF0000

Path    : \\emailaddress@hotmail.com\Deleted Items

Now I for one don’t want to be typing in the EntryID never mind the StoreID – chances of getting that right range from zero to about … zero

What we can do convert all of our Outlook functions (the two so far and the others I’ve got planned) into a module. In the psm1 file I can put a line that says

$folders = get-mailfolders

That creates a collection of objects containing the path, storeid and entryid for all of the folders. We can then search through that collection much faster than the outlook folders.

We create the collection like this

function get-mailfolders {            
$outlookfolders = @()            
$outlook = New-Object -ComObject Outlook.Application            
foreach ($folder in $outlook.Session.Folders){            
              
  foreach($mailfolder in $folder.Folders ) {            
   $olkf = New-Object PSObject -Property @{            
    Path = $($mailfolder.FullFolderPath)            
    EntryID = $($mailfolder.EntryID)            
    StoreID = $($mailfolder.StoreID)            
   }            
               
   $outlookfolders += $olkf            
               
  }             
}            
$outlookfolders            
}


Loop through the folders as we’ve already seen and create an object that has the path, storeid and entryid. Add the object to the collection and output the collection at the end of the function.



We’ll see how to use this collection in the revised clear-deletedmail function