How to Set VotingResponses in Outlook via Powershell - powershell

I am trying to issue approvals on mailbox items via Powershell but can't seem to find the right method to do so. Here is the code I have used thus far.
Add-type -assembly "Microsoft.Office.Interop.Outlook"
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$recipient = $namespace.CreateRecipient('othermailbox#example.local')
$recipient.Resolve();
$sharedFolder = $namespace.GetSharedDefaultFolder($recipient, $olFolders::olFolderInBox)
$sharedFolder.Items
The member objects from $sharedFolder. Items contain string properties around VotingOptions and VotingResporse but I don't see a method to perform an approved vote. Any help is appreciated as there are hundreds of items I need to bulk approve. Thanks.

Loop through the items, for each item read the VotingOptions property, call MailItem.Reply (returns the new item), set the VotingResponse property on the reply message, call Send.

This is the code I ended up going with based on Dmitiry's input.
Add-type -assembly "Microsoft.Office.Interop.Outlook"
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$recipient = $namespace.CreateRecipient('othermailbox#example.local')
$recipient.Resolve()
$sharedFolder = $namespace.GetSharedDefaultFolder($recipient, $olFolders::olFolderInBox)
$messages = $sharedFolder.Items | Where-Object { $_.subject -eq "Approval Required" }
foreach ($message in $messages)
{
$reply = $message.Reply()
$reply.VotingResponse = "Approve"
$reply.Send()
}

Related

ForEach loop not the same as printed in CLI?

When I type '
$Listboxcal= New-Object System.Windows.Forms.ListBox
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) -and $_.Start -le $(Get-Date).AddDays(1)} | select Start, Subject.
' the CLI prints perfectly the date/time/subject title
however when I add '
$Listboxcal= New-Object System.Windows.Forms.ListBox
$Listboxcal.Location = New-Object System.Drawing.Size(10,10)
$Listboxcal.Size = New-Object System.Drawing.Size(230,270)
$Listboxcal.Height = 150
[…]
ForEach ($calendars in $cItems) {[void]$Listboxcal.Items.Add($calendars)} '
I only get "#(Start=05/05/2019 11:30:00; Subject=}" printed. Ideally I would like Time start and Subject printed to list box. Any ideas?
Never explicitly filter items in your code - it is very inefficient. Always use Items.Find/FindNext or Items.Restrict, especially if you want to expand the recurrences.
See the example at https://learn.microsoft.com/en-us/office/vba/api/outlook.items.includerecurrences

Suppress output created by PowerShell New-Object

Suppress PowerShell output messages new outlook application object is created?
$outlook = New-Object -ComObject outlook.application
$outlookItem = $outlook.CreateItem("olMailItem")
I already tried using these approaches. They did not work:
$outlook = New-Object -ComObject outlook.application > $Null
$outlook = New-Object -ComObject outlook.application |Out-Null
($outlook = New-Object -ComObject outlook.application) |Out-Null
These are the output message that I don't want them on the screen:
Application : Microsoft.Office.Interop.Outlook.ApplicationClass
Class : 5
...
...
#boxdog, thanks for pointing it out.
After many break points, I noticed the output is produced by Attachments.Add() method. It is resolved using >$null.
$outlookItem.Attachments.Add("fileName.txt") > $null

How to Send email from Draft using Powershell?

I'm trying to automatically send all email saved, which are available in "Draft" using powershell.I've seen VBA can do, but powershell is the future. Sharing code will help other peer to tweak.
#Send all items in the "Drafts" folder that have a "To" address filled in.
#Setup Outlook
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -comobject Outlook.Application
$myOutlook = $Outlook.Application
$myNameSpace = $myOutlook.GetNamespace("MAPI")
$myFolders = $myNameSpace.Folders
#Set Draft Folder.
$myDraftsFolder = $myFolders("rsprebitz#idafoundation.org").Folders("Drafts")
#Loop through all Draft Items
$myDraftsFolder.Items|foreach-object {
#Check for "To" address and only send if "To" is filled in.
If ($_.To.trim().length -gt 0) {
#Send Item
$_.Send
}
}
try this
VWP.CS's answer was close but had to make a slight change to get it to work for me:
# Initialize components
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -comobject Outlook.Application
$namespace = $Outlook.GetNameSpace("MAPI")
# Set drafts folder
$myDraftsFolder = $namespace.Folders.Item('yourmailboxname').Folders.Item('Drafts')
# Loop through all Draft Items
$myDraftsFolder.Items | foreach-object {
# Check for "To" address and only send if "To" is filled in.
If ($_.To.trim().length -gt 0) {
#Send Item
Write-Verbose "Sending..." -Verbose
$_.Send()
}
}

List Senders from a Shared Mailbox Folder (Recursively)

I am trying to get a full list of senders to an specific shared mailbox i have access to (vía Outlook).
So far I am using this small but handy script to choose the selected folder as I have no idea on how to call as a parameter (Param) the folder I want to check:
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")
$Inbox = $namespace.pickfolder()
$Inbox.items | Select-Object -Property SenderName
After that I filter the output depending on the info I need (in this case, senders).
This forces me to choose the folder MANUALLy, I just want to set it as a parameter to the script.
How should I pass the specific folder as a parameter?.
Thanks in advance and best regards.
If I understood that correctly, you yould create a function where you pass the Inbox Name
function GetSenders
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$True)]
[string]$Inbox
)
Begin
{
Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
}
Process
{
"Your Script here - What should happen with the Inbox?"
}
End
{
Write-Host "Script has Finished"
}
}
When you load this Function, you can just write GetSenders -Inbox "InboxName"

Powershell with Word CheckSpelling and selected dictionary

I would like to spell check some strings using the Microsoft Word API in Powershell and a specific dictionary ("English (US)").
I use the following code to do the checking but it does not seem to take into account the dictionary I want. Any ideas what is wrong? Also, command "New-Object -COM Word.Dictionary" seems to fail.
$word = New-Object -COM Word.Application
$dictionary = New-Object -COM Word.Dictionary
foreach ($language in $word.Languages) {
if ($language.Name.Contains("English (US)")) {
$dictionary = $language.ActiveSpellingDictionary;
break;
}
}
Write-Host $dictionary.Name
$check = $word.CheckSpelling("Color", [ref]$null, [ref]$null, [ref]$dictionary)
if(!$check) {
Write-Host "Spelling Error!"
}
$word.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) | Out-Null
Remove-Variable word
The COMobject word.dictionary does not exist (at least not on my machine), here is what worked for me in the short test i did:
$dic = New-Object -COM Scripting.Dictionary #credits to MickyB
$w = New-Object -COM Word.Application
$w.Languages | % {if($_.Name -eq "English (US)"){$dic=$_.ActiveSpellingDictionary}}
$w.checkSpelling("Color", [ref]$null, [ref]$null, [ref]$dic)
Another possibility in addition to Paul's:
$dictionary = New-Object -COM Scripting.Dictionary
I was experiencing the same problem, that the Word.Application.checkSpelling() method seems to ignore any dictionary passed to it. I worked around the issue creating a Word document, defining a text range, changing the LanguageID of this range to the language I want to proof read against, and then inspecting detected spelling errors. Here is the code:
<#Function which helps to pick the language#>
function FindLanguage($language_name){
foreach($element in $Word.Languages){
if($element.Name -eq $language_name){
$element.Name
return $element
}
}
}
$Proofread_text = "The lazie frog jumpss over over the small dog."
$Word = New-Object -COM Word.Application
$Document = $Word.Documents.Add()
$Textrange = $Document.Range(0)
$english = FindLanguage("English (US)")
$Textrange.LanguageID = $english.ID
$Textrange.InsertAfter($Proofread_text)
<#Handle misspelled words here#>
foreach($spell_error in $textrange.SpellingErrors){
Write-Host $spell_error.Text
}
$Document.Close(0)
$Word.Quit()
The output will be:
>>lazie
>>jumpss
>>over
I found it helpful to disable the language autodetection in word before starting the script. Especially when you plan to switch the language.