Hey, Scripting Guy! Can I Share My Microsoft Outlook Calendar via E-Mail?

Hey, Scripting Guy! Can I Share My Microsoft Outlook Calendar via E-Mail?

  • Comments 5
  • Likes

Bookmark and Share

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I really like the ability to export my calendar into a shareable format with Microsoft Outlook. It is really cool, but can I accomplish this by using a Windows PowerShell script?

-- MB


 

Hey, Scripting Guy! AnswerHello MB,

Microsoft Scripting Guy Ed Wilson here. In 30 minutes, I have a Live Meeting with Karen, our TechNet Site manager, and Craig, the Scripting Editor. Because I do not want to get too involved in something and miss this very important meeting, I thought I would answer some of the e-mail that was sent to scripter@microsoft.com. Often, the e-mail is easy to answer, and those tend to be incorporated into a Quick-Hits Friday post. At other times, the answers are more involved, and I flag those until I have a bit more time to work on the solution.

MB, your e-mail was one that I have had flagged for quite some time. I am glad it was a rainy day in Charlotte, and I had the morning to work on your script. When the script worked perfectly the first time (which is often unusual), I was stoked! The Scripting Wife who was downstairs messing around on Facebook sent me an instant message that asked, “Are you ok?” Let us spare the superlatives and get down to the code. This script is cool. The complete EmailCalendar.ps1 script is seen here.

EmailCalendar.ps1

#Requires -version 2.0
Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
$olCalendarDetail = "Microsoft.Office.Interop.Outlook.olCalendarDetail" -as [type]
$olCalendarMailFormat = "Microsoft.Office.Interop.Outlook.olCalendarMailFormat" -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace  = $Outlook.GetNameSpace("mapi")
$folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar)
$CalendarSharing=$folder.GetCalendarExporter()
$CalendarSharing.CalendarDetail = $olCalendarDetail::olFreeBusyOnly
$CalendarSharing.startDate = Get-Date
$CalendarSharing.endDate = (Get-Date).addDays(7)
$CalendarSharing.RestrictToWorkingHours = $true
$CalendarSharing.IncludeAttachments = $false
$CalendarSharing.IncludePrivateDetails = $false
$MailItem = $CalendarSharing.ForwardAsICal($olCalendarMailFormat::olCalendarMailFormatDailySchedule)
$MailItem.Recipients.Add("Scripter@Microsoft.Com")
$MailItem.Send()

The first thing that is done in the EmailCalendar.ps1 script is to load the Microsoft.Office.Interop.Outlook interop assembly. To do this, use the Add-Type cmdlet. This was covered in detail in Monday’s Hey, Scripting Guy! post.

After the Outlook interop assembly is loaded, add a couple of enumerations. The three Outlook enumerations that are created are the OlDefaultFolders, OlCalendarDetail, and OlCalendarMailFormat. All three enumerations are documented on MSDN, and you can refer to those pages to see additional options for modifying the behavior of the script. For example, you might want to change the level of calendar detail by using a different enumeration value for OlCalendarDetail. Adding the Outlook interop assembly and the three type enumerations is seen here.

#Requires –Version 2.0
Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
$olCalendarDetail = "Microsoft.Office.Interop.Outlook.olCalendarDetail" -as [type]
$olCalendarMailFormat = "Microsoft.Office.Interop.Outlook.olCalendarMailFormat" -as [type]

Next, you need to create an instance of the Outlook.Application COM object. The Outlook.Application object is the main object that is used when scripting Microsoft Outlook. It provides a number of methods and properties that can be used in creating some powerful scripts. The Application object represents the entire Outlook application. After it is created, the Application object is stored in the $outlook variable:

$outlook = New-Object -ComObject outlook.application

Now that you have an instance of the Outlook Application object, you can use the GetNamespace method to return a NameSpace object. The only type of namespace that is permitted to be returned by the GetNameSpace method is “mapi.” The returned namespace object is stored in the $namespace variable, as seen here.

$namespace  = $Outlook.GetNameSpace("mapi")

The Namespace object contains the GetDefaultFolder method that accepts an OlDefaultFolders enumeration as its input value. The returned folder object is stored in the $folder variable.

$folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar)

When you have a folder object, you can call the GetCalendarExporter method, which does not accept any arguments. The returned CalendarSharing object is stored in the $CalendarSharing variable:

$CalendarSharing=$folder.GetCalendarExporter()

The CalendarSharing object has a number of properties that can be configured to control the way the Microsoft Outlook calendar is shared. Most of the properties are configured in the EmailCalendar.ps1 script. You may want to review the properties on MSDN if the script does not behave exactly as you would like it to behave.

The first property to configure is the CalendarDetail property. The CalendarDetail accepts an instance of the OlCalendarDetail enumeration. There are three options: Free and busy with the subject, free and busy only, or full details. The actual enumeration values are documented on MSDN. For the EmailCalendar.ps1 script, I decided to only share free and busy time and to not share the details or subjects of the meetings. This is seen here:

$CalendarSharing.CalendarDetail = $olCalendarDetail::olFreeBusyOnly

The next two properties to set on the CalendarSharing object are the startDate property and the endDate property. These two properties are expressed as datetime objects and are easily created using the Get-Date cmdlet. If you want to share a portion of the calendar from the past, use addDays with a negative value, as shown here:

PS C:\Users\ed.NWTRADERS> (get-date).adddays(-7)

Wednesday, November 25, 2009 3:31:46 PM

PS C:\Users\ed.NWTRADERS> (get-date).adddays(+7)

Wednesday, December 09, 2009 3:31:54 PM

For the EmailCalendar.ps1 script I decided to share the calendar appointments from the current date to seven days in the future. This is seen here.


$CalendarSharing.startDate = Get-Date
$CalendarSharing.endDate = (Get-Date).addDays(7)

The next three properties to configure are self explanatory. Do you want to restrict the calendar to working hours? Do you wish to include attachments? Do you want your calendar to include private details? Each of these properties accepts a Boolean $true or $false, as shown here.

$CalendarSharing.RestrictToWorkingHours = $true

$CalendarSharing.IncludeAttachments = $false

$CalendarSharing.IncludePrivateDetails = $false

Now you are ready to configure the e-mail message that will send the calendar to your designated recipient. To do this, use the ForwardAsICal method from the CalendarSharing object. If you did not want to send the calendar in an e-mail, you could also save the calendar as an iCalendar (.ics) file by using the SaveAsICal method. The ForwardAsIcal method requires an instance of an OlCalendarMailFormat enumeration value that will determine if the calendar will be configured as a daily schedule or an event schedule. For the EmailCalendar.ps1 script, I decided to create a daily schedule. Feel free to play with the format to see which meets your needs the best. To create an event schedule format, you would use this enumeration value:

$olCalendarMailFormat::olCalendarMailFormatEventList

The MailItem object that is created by using the ForwardAsICal method is stored in the $MailItem variable as shown here:

$MailItem = $CalendarSharing.ForwardAsICal($olCalendarMailFormat::olCalendarMailFormatDailySchedule)

There is only one thing that must be configured for the MailItem object: the recipient’s e-mail address. After you have used the Add method—from the Recipients collection that is returned by the Recipients property of the MailItem object—to add the recipient to the MailItem, call the Send method and your calendar will speed on its way to its destination. This is shown here:

$MailItem.Recipients.Add("Scripter@Microsoft.Com")

$MailItem.Send()

Your recipient will receive a really cool e-mail message, as seen here:

Image of e-mail message received by recipient

 

When your recipient opens the e-mail message, they will be able to see the details you selected when you exported the calendar. The details from our script are seen here:

Image of details of exported calendar

 

MB, that is all there is to sharing your Outlook Calendar via Windows PowerShell. This also concludes Microsoft Outlook Week on the TechNet Script Center. Join us tomorrow for Quick-Hits Friday.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • In case somebody else misses the obvious (as I did), one needs to install .NET Programmability Support for Outlook from the Office 2007 setup.  

    http://msdn.microsoft.com/en-us/library/bb646840.aspx

  • hi sir

    i m so soory:

    CLSID {0006F03A-0000-0000-C000-000000000046} error : 80080005.

    + $outlook = New-Object <<<<  -ComObject outlook.application

    my best regard

    arnold

  • Anyone able to do this with a sharepoint calendar attached to outlook?  It is a great script i just want to do this for that sharepoint calendar?  Any help would be great!

  • I have sharepoint working but hit a problem myself.  I walked the mapi namespace with pshscripts.blogspot.com/.../get-outlookfoldersps1.html

    I then used the folder names and replaced $folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar) with $folder = $namespace.Folders.Item("SharePoint Lists").Folders.Item("nameofcalendar")

    but for some reason the $CalendarSharing.endDate = (Get-Date).addDays(7) is not working so its dumbing the whole (massive) calendar!  any help?

  • Coul I use this script to export anybody's calendar? How would I open a given user's Mailbox to export the calendar with this script?

    Thanks a lot, Rosario