calendar, exporting Outlook emails to CSV - powershell

My job is to export emails from Outlook default inbox folder to CSV file.
Here is the script:
cls
Function Get-OutlookInBox #getoutlookcontent
{
Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
$folder.items |
Select-Object -Property Subject, ReceivedTime, SenderName, to
}
write-host "select date greater or equal to and hit enter"
Function date1
#calendar
{
[void]
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object Windows.Forms.Form
$objForm.Text = "Select a Date"
$objForm.Size = New-Object Drawing.Size #(190,190)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({
if ($_.KeyCode -eq "Enter")
{
$global:dtmDate=$objCalendar.SelectionStart
$objForm.Close()
}
})
$objForm.Add_KeyDown({
if ($_.KeyCode -eq "Escape")
{
$objForm.Close()
}
})
$objCalendar = New-Object System.Windows.Forms.MonthCalendar
$objCalendar.ShowTodayCircle = $False
$objCalendar.MaxSelectionCount = 1
$objForm.Controls.Add($objCalendar)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
}
date1
$gt = (get-date).tostring() #getcurrent date
Get-OutlookInbox | #exporting
where { $_.ReceivedTime -gt [datetime] "$globa:dtmdate" -AND $_.ReceivedTime
-le
[datetime] "$gt" } | Export-Csv D:\Users\XXX\Desktop\test1.csv -
Encoding ASCII -NoTypeInformation -force
Parts of code are works perfectly fine separately.
I am able export emails when i am putting date in to code like that:
Get-OutlookInbox | #exporting
where { $_.ReceivedTime -gt [datetime] "8/21/2017" -AND $_.ReceivedTime
-le
[datetime] "8/24/2017" } | Export-Csv D:\Users\XXX\Desktop\test1.csv -
Encoding ASCII -NoTypeInformation -force
but while I am trying to put variable instead of exact values I am getting error msg Cannot convert value "" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
My question is how to convert variable in to datetime.
Second thing which I notice in this part of code
Get-OutlookInbox | #exporting
where { $_.ReceivedTime -gt [datetime] "8/21/2017" -AND $_.ReceivedTime
-le
[datetime] "8/24/2017" } | Export-Csv D:\Users\XXX\Desktop\test1.csv -
Encoding ASCII -NoTypeInformation -force
In that case operator -gt works perfectly fine for me even it shouldn't. Script exporting emails from date which I set not day after. But second part -le works like less than not less and equal. Which is confusing since I need to set date day+1. I have tried to put several comparison operators but result is always the same.

Related

Powershell script to display a list of users and respective permissions of a shared mailbox

I thought I'd post this here just in case I'm barking up the wrong tree. I'm looking to put together a Powershell script that can list all of the members of a shared mailbox and their respective permissions (Limited to "UserName", "Name", "Mailbox", "Full Access", "Send As", "SOBO"). My plan is for the script to ask for an email address and output to look something like this:
User Name Mailbox Full Access Send As SOBO Success
---- ---- ------- ----------- ------- ----- --------
ACB123 Smith, James Examplebox Yes Yes No Success
ABC213 Smith, Pete Examplebox Yes No Yes Success
I was surprised when I couldn't find anything online that is even similar to this.
My script, so far, grabs a list of users that have Full Access (well, it's supposed to, it seems to grab the lesser permissions too, but this actually serves my purpose). The script then strips the collected info down to usernames, then runs a for each to gather information to complete the table above. It runs an AD query for the display names as running Get-ADPermission is not an option.
I haven't got as far as to do the Send As and SoBo parts of the table because I can't get the table to be bigger than 4 columns before it turns into a list, instead of a table. I know there's the Format-Table command but I can't seem to integrate it into my current pscustomobject setup - which is currently set up to split successful queries from failed ones.
This is what I have so far, it's pretty dirty, but this is just my best guess to how something like this should work:
import-moduleactivedirectory
Install-ModuleExchangeOnlineManagement
Connect-ExchangeOnline-ShowBanner:$false
Clear-Host
$ErrorActionPreference='Stop'
$status=[System.Collections.Generic.List[pscustomobject]]::new()
$Entered_email=$Entered_email.trim()
$Collect_SendAs=Get-Mailbox$Entered_email-resultsizeunlimited|Get-RecipientPermission|where {($_.trustee -ne"NT AUTHORITY\SELF")} |where {($_.trustee -match"#")} |selectTrustee
$Collect_users=Get-Mailbox-Identity$Entered_email-ResultSize:Unlimited|Get-MailboxPermission|?{($_.IsInherited -eq$False) -and-not ($_.User -match"NT AUTHORITY")} #|select -ExpandProperty user
$status=foreach($Aliasin$Collect_users)
{
try
{
$User= ($Alias.User.Split("#")[0])
$Access=$Alias.AccessRights
$User_name=Get-ADUser-identity$User-propertiesDisplayName|select-expandpropertyDisplayName
# $Has_SendAs = ($Collect_SendAs.Split("#")[0])
# if ($User -like "*Has_SendAs*") {$User_SendAs = "yes"
# }else{$User_SendAs = "No"}
[pscustomobject]#{
User =$user
Name =$user_name.Split(',')[1..0]-join' '
Mailbox =$Entered_email
'Access Rights'=$Access.Trim("{","}")
'Has Send As'=$User_SendAs
Status ='SUCCESS'
}
}
catch
{
[pscustomobject]#{
User =$user
Status ='FAILED'
Message =$_.Exception.Message
}
}
}
$success,$failed=$status.Where({$_.Status -eq'SUCCESS'},'Split')
$success|selectUser,Name,Mailbox,'Access Rights','Has Send As'|Format-Table|Out-String|Write-Host-ForegroundColorGreen
$failed |selectUser,Message|Out-String|Write-Host-ForegroundColorRed
$SoBo=Get-Mailbox$Entered_email|select #{l='SendOnBehalfOf';e={$_.GrantSendOnBehalfTo -join"`n"}}
$Sobo_Output=$SoBo-replace"#{SendOnBehalfOf=",''-replace"}",''
If ($Sobo_Output-ge1) {
Write-Host"Users With Send on Belhalf Permissions"-ForegroundColorGreen
Write-Host"--------------------------------------"-ForegroundColorGreen
Write-Host$SoBo_Output-ForegroundColorGreen
Write-Host""
}else{
Write-Host"Users With Send on Belhalf Permissions"-ForegroundColorGreen
Write-Host"--------------------------------------"-ForegroundColorGreen
Write-Host"No users found with this permission level"-ForegroundColorGreen
Write-Host""
}
Disconnect-ExchangeOnline-Confirm:$false-InformationActionIgnore-ErrorActionSilentlyContinue
Pause
Any advice would be appreciated at this stage, I definitely could use help with the table, I could probably figure out how to add the Send As and SoBo searches, but if anyone knows some really efficient ones please let me know.
Thanks in advance.
UPDATED
I've amended the script above, because I couldn't figure out how toadd another message.
I've taken on board the changes suggested by #TheMadTechnician, and abandoned the idea of adding SoBo to the table as the SoBo users information is saved as some weird string of names and usernames, so I've rigged it so that this information pops out on a separate table below the access level table.
I've added line 10 ($Collect_SendAs), this is a line that can pull the email addresses (username#domain.com) of all users that have Send As access to the mailbox, I'm looking to get this integrated into the access level table and have made a few wrong turns trying to do this (lines 22-24 are my latest failed attempts to do this).
What I would like to do with the info collected in line 10 is to strip out the #domain part, then compare it with the usernames extracted in line 11, if there match, add a "yes" to the Send As column for the user, and if there is no match, add a "No".
If anyone can help with this, that would be amazing.
UPDATE
Think I've got it:
Import-Module ActiveDirectory
Install-Module ExchangeOnlineManagement
Connect-ExchangeOnline -ShowBanner:$false
Clear-Host
$ErrorActionPreference = 'Stop'
$status = [System.Collections.Generic.List[pscustomobject]]::new()
$Entered_email = Read-host "Enter a mailbox address"
$Entered_email = $Entered_email.trim()
$Collect_SendAs = Get-Mailbox $Entered_email -resultsize:unlimited | Get-RecipientPermission | where {($_.trustee -ne "NT AUTHORITY\SELF")} | where {($_.trustee -match "#")} | select -ExpandProperty Trustee
$Collect_users = Get-Mailbox -Identity $Entered_email -ResultSize:Unlimited | Get-MailboxPermission | ?{($_.IsInherited -eq $False) -and -not ($_.User -match "NT AUTHORITY")}
$status = foreach ($Alias in $Collect_users)
{
try
{
$User = ($Alias.User.Split("#")[0])
$User_name = Get-ADUser -identity $User -properties DisplayName | select -expandproperty DisplayName
if ($Collect_SendAs -match $User) {$User_SendAs = "yes"
}else{$User_SendAs = "No"}
$Access = $Alias.AccessRights
[pscustomobject]#{
User = $user
Name = $user_name.Split(',')[1..0]-join' '
Mailbox = $Entered_email
'Access Rights' = $Access.Trim("{","}")
'Has Send As' = $User_SendAs
Status = 'SUCCESS'
}
}
catch
{
[pscustomobject]#{
User = $user
Status = 'FAILED'
Message = $_.Exception.Message
}
}
}
$success, $failed = $status.Where({$_.Status -eq 'SUCCESS'},'Split')
$success | select User, Name, Mailbox,'Access Rights','Has Send As' | Format-Table | Out-String | Write-Host -ForegroundColor Green
$failed | select User, Message | Out-String | Write-Host -ForegroundColor Red
$SoBo = Get-Mailbox $Entered_email |select #{l='SendOnBehalfOf';e={$_.GrantSendOnBehalfTo -join"`n"}}
$Sobo_Output = $SoBo -replace "#{SendOnBehalfOf=",'' -replace"}",''
If ($Sobo_Output -ge 1) {
Write-Host "Users With Send on Behalf Permissions" -ForegroundColor Green
Write-Host "--------------------------------------" -ForegroundColor Green
Write-Host $SoBo_Output -ForegroundColor Green
Write-Host ""
}else{
Write-Host "Users With Send on Behalf Permissions" -ForegroundColor Green
Write-Host "--------------------------------------" -ForegroundColor Green
Write-Host "No users found with this permission level" -ForegroundColor Green
Write-Host ""
}
Disconnect-ExchangeOnline -Confirm:$false -InformationAction Ignore -ErrorAction SilentlyContinue
Pause
Thanks a lot to everyone who posted.
You are duplicating efforts a LOT with this. Line 9 would return you all the users that have access and the access they have, but you discard everything but the user's account name, and then later loop through those users and get their access one at a time. Here I keep that info, then use it inside the loop to reduce calls to Exchange to get perms again and again. I also changed a variable name since you re-used $User for different things which can be very confusing.
import-module activedirectory
Install-Module ExchangeOnlineManagement
Connect-ExchangeOnline -ShowBanner:$false
Clear-Host
$ErrorActionPreference='Stop'
$status=[System.Collections.Generic.List[pscustomobject]]::new()
$Entered_email = Read-host "Enter a mailbox address"
$Collect_users = Get-Mailbox -Identity $Entered_email -ResultSize:Unlimited|Get-MailboxPermission|?{($_.IsInherited -eq $False) -and -not ($_.User -match"NT AUTHORITY")} #|select -ExpandProperty user
$status=foreach($Alias in $Collect_users)
{
try
{
$User= ($Alias.User.Split("#")[0])
$Access=$Alias.AccessRights
if ($Access -like "*FullAccess*") {$Access_Result="yes"
}else{$Access_Result="No"}
$User_name = Get-ADUser -identity $User -properties DisplayName|select -expandproperty DisplayName
[pscustomobject]#{
User = $user
Name = $user_name
Mailbox = $Entered_email.Split("#")[0]
'Full Access'= $Access_Result
Status ='SUCCESS'
}
}
catch
{
[pscustomobject]#{
User = $user.user
Status ='FAILED'
Message = $_.Exception.Message
}
}
}
$success,$failed=$status.Where({$_.Status -eq'SUCCESS'},'Split')
$success|Out-String|Write-Host-ForegroundColorGreen
$failed |Out-String|Write-Host-ForegroundColorRed
Pause
I started making a "mailbox manager" gui last year and never got around to finishing it, but maybe there's some useful stuff you could pull from it. The last thing I was trying to add was who has access/sendas TO the selected account (bottom part of the gui), which isn't quite working...but the first part (see what accounts/sendas an account has permission for) is working.
The eventual idea was to add a "save" button in so you could check/uncheck the tickboxes as you'd like in the gui and it'd adjust the permissions.
#Init
$logpath = "C:\Scripts\Logs\MailboxPermissions.log"
#Create session on 365 Exchange server
if ((Get-PSSession).Computername -notmatch "outlook.office365.com"){Connect-365}#or: Connect-ExchangeOnline -ShowBanner:$false
$UPNs = Get-Mailbox -Identity * | select -ExpandProperty UserPrincipalName
$AccToDatasource = [System.Collections.ArrayList]::new()
$BS1 = [System.Windows.Forms.BindingSource]::new()
$BS1.DataSource = $AccToDatasource
$AccByDatasource = [System.Collections.ArrayList]::new()
$BS2 = [System.Windows.Forms.BindingSource]::new()
$BS2.DataSource = $AccByDatasource
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$get_permissions={
$AccToDatasource.Clear()
$AccByDatasource.Clear()
$user = $ComboBox1.Text
write-host "Checking $($user)"
Get-EXOMailboxPermission -Identity $user | ?{$_.User -ne "NT AUTHORITY\SELF"} | %{
$tablerow = New-Object psobject
$data = #{Email="$($_.User)";Inbox=1;SendAs=0}
$tablerow | Add-Member -NotePropertyMembers $data -TypeName tablerow
$AccToDatasource.Add($tablerow)
}
Get-EXORecipientPermission -Identity $user | ?{$_.Trustee -ne "NT AUTHORITY\SELF"} | %{
$indx = [array]::IndexOf($AccToDatasource.Email,$_.Trustee)
if($indx -ne -1){
$AccToDatasource[$indx].SendAs = 1
}else{
$tablerow = New-Object psobject
$data = #{Email="$($_.Trustee)";SendAs=1}
$tablerow | Add-Member -NotePropertyMembers $data -TypeName tablerow
$AccToDatasource.Add($tablerow)
}
}
$BS1.ResetBindings($true)
<##Attempt 1
Get-EXOMailbox -MailboxPlan "ExchangeOnlineEnterprise" -Properties UserPrincipalName | select -ExpandProperty UserPrincipalName | %{
Start-ThreadJob {
Get-EXOMailboxPermission -Identity $using:_ -User $using:user -ErrorAction SilentlyContinue
} | Wait-Job | Receive-Job | %{
$tablerow = New-Object psobject
$data = #{Email="$($_.Trustee)";Inbox=1;SendAs=0}
$tablerow | Add-Member -NotePropertyMembers $data -TypeName tablerow
$AccByDatasource.Add($tablerow)
}
}
$BS2.ResetBindings($true)
#>
#Attempt 2
Get-EXOMailbox -MailboxPlan "ExchangeOnlineEnterprise" -Properties UserPrincipalName | select -ExpandProperty UserPrincipalName | %{Start-ThreadJob {Get-EXOMailboxPermission -Identity $using:_ -User $using:user -ErrorAction SilentlyContinue}} | Wait-Job | Receive-Job | %{
$tablerow = New-Object psobject
$data = #{Email="$($_.Trustee)";Inbox=1;SendAs=0}
$tablerow | Add-Member -NotePropertyMembers $data -TypeName tablerow
$AccByDatasource.Add($tablerow)
}
$BS2.ResetBindings($true)
}
#Form Init
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = New-Object System.Drawing.Point(600,650)
$Form.text = "Mailbox Manager"
$Form.TopMost = $false
$ComboBox1 = New-Object system.Windows.Forms.ComboBox
$ComboBox1.width = 370
$ComboBox1.height = 30
$ComboBox1.location = New-Object System.Drawing.Point(137,25)
$ComboBox1.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$ComboBox1.Items.AddRange($UPNs)
$ComboBox1.AutoCompleteSource = "ListItems"
$ComboBox1.AutoCompleteMode = "SuggestAppend"
#$ComboBox1.add_SelectedIndexChanged({
# if ($ComboBox1.Text.Length -gt 10){
# get-permissions -user $ComboBox1.Text
# }
#})
$Label1 = New-Object system.Windows.Forms.Label
$Label1.text = "Select 365 User:"
$Label1.AutoSize = $true
$Label1.width = 25
$Label1.height = 30
$Label1.location = New-Object System.Drawing.Point(14,25)
$Label1.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$Label2 = New-Object system.Windows.Forms.Label
$Label2.text = "Has access to:"
$Label2.AutoSize = $true
$Label2.width = 25
$Label2.height = 30
$Label2.location = New-Object System.Drawing.Point(14,55)
$Label2.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$Label3 = New-Object system.Windows.Forms.Label
$Label3.text = "Accessible by:"
$Label3.AutoSize = $true
$Label3.width = 25
$Label3.height = 30
$Label3.location = New-Object System.Drawing.Point(14,358)
$Label3.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$DataGridView1 = New-Object system.Windows.Forms.DataGridView
$DataGridView1.text = "Emails"
$DataGridView1.width = 560
$DataGridView1.height = 250
$DataGridView1.AutoGenerateColumns = $false
$DataGridView1.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewTextBoxColumn -Property #{"Name"="Email"})) | Out-Null
$DataGridView1.Columns['Email'].DataPropertyName = "Email"
$DataGridView1.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewCheckBoxColumn -Property #{"Name"="Inbox"})) | Out-Null
$DataGridView1.Columns['Inbox'].DataPropertyName = "Inbox"
$DataGridView1.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewCheckBoxColumn -Property #{"Name"="SendAs"})) | Out-Null
$DataGridView1.Columns['SendAs'].DataPropertyName = "SendAs"
$DataGridView1.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewTextBoxColumn -Property #{"Name"="Start"})) | Out-Null
$DataGridView1.Columns['Start'].DataPropertyName = "Start"
$DataGridView1.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewTextBoxColumn -Property #{"Name"="End"})) | Out-Null
$DataGridView1.Columns['End'].DataPropertyName = "End"
$DataGridView1.ColumnHeadersVisible = $true
$DataGridView1.AutoSizeColumnsMode = 10
$DataGridView1.DataSource = $BS1
$DataGridView1.location = New-Object System.Drawing.Point(11,82)
$DataGridView1.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#e0dede")
$DataGridView1.add_DataError({write-host "hit error"})
$DataGridView2 = New-Object system.Windows.Forms.DataGridView
$DataGridView2.width = 560
$DataGridView2.height = 250
$DataGridView2.location = New-Object System.Drawing.Point(9,383)
$DataGridView2.AutoGenerateColumns = $false
$DataGridView2.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewTextBoxColumn -Property #{"Name"="Email"})) | Out-Null
$DataGridView2.Columns['Email'].DataPropertyName = "Email"
$DataGridView2.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewCheckBoxColumn -Property #{"Name"="Inbox"})) | Out-Null
$DataGridView2.Columns['Inbox'].DataPropertyName = "Inbox"
$DataGridView2.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewCheckBoxColumn -Property #{"Name"="SendAs"})) | Out-Null
$DataGridView2.Columns['SendAs'].DataPropertyName = "SendAs"
$DataGridView2.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewTextBoxColumn -Property #{"Name"="Start"})) | Out-Null
$DataGridView2.Columns['Start'].DataPropertyName = "Start"
$DataGridView2.Columns.Add((new-object -TypeName System.Windows.Forms.DataGridViewTextBoxColumn -Property #{"Name"="End"})) | Out-Null
$DataGridView2.Columns['End'].DataPropertyName = "End"
$DataGridView2.ColumnHeadersVisible = $true
$DataGridView2.AutoSizeColumnsMode = 10
$DataGridView2.DataSource = $BS2
$DataGridView2.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#e0dede")
$loadButton = New-Object system.Windows.Forms.Button
$loadButton.text = "Load"
$loadButton.width = 60
$loadButton.height = 30
$loadButton.location = New-Object System.Drawing.Point(509,25)
$loadButton.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$loadButton.Add_Click($get_permissions)
$saveButton = New-Object system.Windows.Forms.Button
$saveButton.text = "Save"
$saveButton.width = 60
$saveButton.height = 30
$saveButton.location = New-Object System.Drawing.Point(509,341)
$saveButton.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$Form.controls.AddRange(#($Label1,$Label2,$Label3,$ComboBox1,$DataGridView1,$DataGridView2,$saveButton, $loadButton))
[void]$Form.ShowDialog()

Downloading .xlsx attachment from Outlook of Specific Date using Powershell

I have the below script. This $Tests shows the list of .xlsx attachment of specific date but is not able to download and throws an error. Please find the below script.
Add-type -assembly "Microsoft.Office.Interop.Outlook"
$olDefaultFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = New-Object -comobject Outlook.Application
$mapi = $outlook.GetNameSpace(“MAPI”)
$inbox = $mapi.GetDefaultFolder(6)
$FilePath= "c:\temp\Test\"
$subfolder = $inbox.Folders | Where-Object {$_.Name -eq “Test”}
$mail=$subfolder.Items |Select-Object -Property "ReceivedTime",#{name="Attachments";expression={$_.Attachments|%{$_.DisplayName}}} | Where-Object{$_.attachments -match ".xlsx" -and ($_.receivedtime -match "9/15/2020")} | Select-Object "attachments"
$Test = $mail.attachments
foreach ($out in $test) {$_.attachments|foreach {
Write-Host $_.filename
$Filename = $_.filename
If ($out.Contains("xlsx")) {
$_.saveasfile((Join-Path $FilePath "$out")) }}}
I am able to filter the .xlsx Attachments with Specific Date. But after this, I don't know how to save/download them.
Working with com objects can be rather frustrating in powershell. I recommend you get extremely familiar with Get-Member. You really have to interrogate each object. I've simplified your script as well as tested thoroughly. It will download each matching attachment (name) from each match email (received date)
Add-type -assembly "Microsoft.Office.Interop.Outlook"
$olDefaultFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = New-Object -comobject Outlook.Application
$mapi = $outlook.GetNameSpace(“MAPI”)
$inbox = $mapi.GetDefaultFolder(6)
$FilePath= "c:\temp\Test\"
$subfolder.Items | Where-Object {$_.receivedtime -match "9/20/2020" -and $($_.attachments).filename -match '.xlsx'} | foreach {
$filename = $($_.attachments | where filename -match '.xlsx').filename
foreach($file in $filename)
{
Write-Host Downloading $file to $filepath -ForegroundColor green
$outpath = join-path $filepath $file
$($_.attachments).saveasfile($outpath)
}
}
You may use this for more of an "in-line" approach.
Add-type -assembly "Microsoft.Office.Interop.Outlook"
$olDefaultFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = New-Object -comobject Outlook.Application
$mapi = $outlook.GetNameSpace(“MAPI”)
$inbox = $mapi.GetDefaultFolder(6)
$FilePath= "c:\temp\Test\"
$subfolder.Items | Where-Object {$_.receivedtime -match "9/20/2020" -and $($_.attachments).filename -match '.xlsx'} | foreach {
foreach($attachment in $($_.attachments | where filename -match '.xlsx'))
{
Write-Host Downloading $attachment.filename to $filepath -ForegroundColor green
$attachment.SaveAsFile((join-path $FilePath $attachment.filename))
}
}

How to get outlook recurring meeting items in powershell

I am using below script to pull outlook calendar items and it works for events that occur once. It fails for recurring meeting invites as the start date on it would be when the invite was sent and not the occurrence start time. Also, i dont see any variable referencing the occurrence end date, so cant dynamically lookup for the occurrence. Any suggestions on how to get that?
Function Get-OutlookCalendar {
Add-type -assembly “Microsoft.Office.Interop.Outlook” | out-null
$olFolders = “Microsoft.Office.Interop.Outlook.OlDefaultFolders” -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace(“MAPI”)
$folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar)
$folder.items |
Select-Object -Property start,RequiredAttendees, Subject, IsRecurring, Organizer,ConversationID,RecurrenceState,OptionalAttendees,Body
}
$start_date=(Get-date).AddDays(-2) |Get-Date -Format 'MM/dd/yyyy'
$end_date=Get-Date -Format 'MM/dd/yyyy'
Get-OutlookCalendar| where-object { $_.start -gt [datetime]$start_date -and $_.start -le [datetime]$end_date } | sort-object start
You can try below switch:
switch ($item.IsRecurring)
{
$false {
if ($item.start -ge $dt -and $item.start -lt ($dt).AddDays(1))
{
$item | Select-Object -Property Subject, Start, Duration, Location, RequiredAttendees
}
}
$true {
try {
$rec=$item.GetRecurrencePattern()
$recitem=$rec.GetOccurrence($dt.ToString("yyyy-MM-dd") + " " + $item.Start.ToString("HH:mm"))
$recitem | Select-Object -Property Subject, Start, Duration, Location, RequiredAttendees, IsRecurring
}
catch {}
finally {}
}
}

Display duration of outlook appointment?

I am unable to display the duration of each appointment in my list box. I'm trying to print in the listbox 11:30; (60) B/H or 11:30-12:30; B/H, however unsure of how to do this, please may someone help?
I have tried $Duration and $._Duration, putting them between "[...]Start.ToString('HH:mm'), $_.Subject } " 'HH:mm' and $_. subject however these haven't been successful
#listbox for calendar entry
$Listboxcal= New-Object System.Windows.Forms.ListBox
$Listboxcal.Location = New-Object System.Drawing.Size(10,55)
$Listboxcal.Size = New-Object System.Drawing.Size(80,270)
$Listboxcal.Height = 150
add-type -assembly “Microsoft.Office.Interop.Outlook” | out-null
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace(“MAPI”)
# https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.outlook.oldefaultfolders?view=outlook-pia
# Calendar = olFolderCalendar = 9
$calendar = $namespace.GetDefaultFolder(9)
# get today's calendar items!
$cItems = $calendar.Items | Where-Object {$_.Start -ge $(Get-Date $StrCaldate) -and $_.Start -le $(Get-Date $StrCaldate).AddDays(1)} |Sort-Object -Property Start | foreach { "{0}; {1}" -f $_.Start.ToString('HH:mm'), $_.Subject }
ForEach ($calendars in $cItems) {[void]$Listboxcal.Items.Add($calendars)}
The calendar appointments have a duration property. You just need to add that to the $cItems variable
$cItems = $calendar.Items | Where-Object {$_.Start -ge $(Get-Date $StrCaldate) -and $_.Start -le $(Get-Date $StrCaldate).AddDays(1)} |Sort-Object -Property Start | foreach { "{0}; ({1}) {2}" -f $_.Start.ToString('HH:mm'), $_.Duration, $_.Subject }
When I run this on my own calendar, I get the following:
16:30; (60) Appointment 1
18:30; (120) Appointment 2
It is working for me with the Duration property:
$calendar.Items | Select -First 1 | %{ $_.StartUTC.Tostring("hh:mm") `
+ "; (" + $_.Duration + ") " + $_.Subject}

replace text with a textbox input using variable

In my script I have a textbox- the user inserts text in it and than I want to change the text in a file (which the script creates earlier) to what the user inserted in the textbox.
The problem: it does deletes the part I wanted to be changed in the file- but it doesn`t write the text of the user instead. I also tried to locate the variable in the if loop- and it did changed the text like i wanted, but when I run the script again it wrote the old text in the disabled textbox.
my script is kinda long so I wont post all of it, but here are the importent parts. Thanks for the help!
#This creates a checkbox called dsp.z
$objDspCheckbox = New-Object System.Windows.Forms.Checkbox
$objDspCheckbox.Location = New-Object System.Drawing.Size(20,40)
$objDspCheckbox.Size = New-Object System.Drawing.Size(150,20)
$objDspCheckbox.Text = "dsp.z"
$objDspCheckbox.TabIndex = 0
$objForm.Controls.Add($objDspCheckbox)
#This creates the TextBox1 and put it on disable
$objTextBox1 = New-Object System.Windows.Forms.TextBox
$objTextBox1.Location = New-Object System.Drawing.Size(450,40)
$objTextBox1.Size = New-Object System.Drawing.Size(140,150)
$objTextBox1.TabIndex = 3
$objTextBox1.text = $text1
$objTextBox1.Enabled = $false
$objForm.Controls.Add($objTextBox1)
#This creates a checkbox for textbox1
$objDsp2Checkbox = New-Object System.Windows.Forms.Checkbox
$objDsp2Checkbox.Location = New-Object System.Drawing.Size(430,40)
$objDsp2Checkbox.Size = New-Object System.Drawing.Size(150,20)
$objDsp2Checkbox.TabIndex = 0
$objForm.Controls.Add($objDsp2Checkbox)
#Enables the textbox when user check the box:
#textbox1
$objDsp2Checkbox_OnClick = {
if ($objDsp2Checkbox.Checked -eq $true)
{
$objTextBox1.Enabled = $true
}
elseif ($objDsp2Checkbox.Checked -eq $false)
{
$objTextBox1.Enabled = $false
}
}
$objDsp2Checkbox.Add_Click($objDsp2Checkbox_OnClick)
#variables
$text1=$objTextBox1.Text
#This creates the ok and cancle buttons:
#ok Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(220,155)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click(
{
if (($objDspCheckbox.Checked -eq $true) -and ($objDsp2Checkbox.Checked -eq $true))
{
New-Item $path -itemtype file -name Dsp.json -value "old" ;((Get-Content "c:\users\$env:USERNAME\documents\Json\dsp.json") -replace 'old', $text1 | out-file "c:\users\$env:USERNAME\documents\Json\dsp.json") ;$objForm.close()
}
Try to Change This Line (specifly the $text1) to $objTextBox1.Text :
New-Item $path -itemtype file -name Dsp.json -value "old" ;
((Get-Content "c:\users\$env:USERNAME\documents\Json\dsp.json") -replace 'old', $text1 |
Out-file "c:\users\$env:USERNAME\documents\Json\dsp.json") ;$objForm.close()
To:
New-Item $path -itemtype file -name Dsp.json -value "old" ;
((Get-Content "c:\users\$env:USERNAME\documents\Json\dsp.json") -replace 'old', $objTextBox1.Text |
Out-file "c:\users\$env:USERNAME\documents\Json\dsp.json") ;$objForm.close()
I'm not sure if it's the case but if you just need to save the textbox text to file there's an easier approach :
$objTextBox1.Text | Out-file "c:\users\$env:USERNAME\documents\Json\dsp.json")