EWS.psm1

param (
    [string]$Mailbox = 'bartek.bielawski@live.com',
    [Microsoft.Exchange.WebServices.Data.ExchangeVersion]$Version = 'Exchange2010_SP1'
)

<#
    Still TODO:
    -- commment based help for functions
    -- about_ article to describe functionality
#>


$connections = @{}

function Connect-EWSService {
[OutputType('Microsoft.Exchange.WebServices.Data.ExchangeService')]
[CmdletBinding()]
param (
    
    # Mailbox that command will connect to.
    $Mailbox = $Script:Mailbox,

    # Version of exchange server that we will connect to.
    [Microsoft.Exchange.WebServices.Data.ExchangeVersion]
    $Version = $Script:Version,

    # Credentials that will be used to connect to mailbox.
    [Management.Automation.PSCredential]
    [Management.Automation.Credential()]
    $Credential = [Management.Automation.PSCredential]::Empty
)
    $exchangeService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService $Version
    if ($Credential -ne [Management.Automation.PSCredential]::Empty) {
        $exchangeService.UseDefaultCredentials = $false
        $exchangeService.Credentials = $Credential.GetNetworkCredential()   
    } else {
        $exchangeService.UseDefaultCredentials = $true
    }
    $exchangeService.AutodiscoverUrl($Mailbox)
    $Script:exchangeService = $exchangeService
    $Script:connections.Add(
        $exchangeService,
        $Mailbox
    )
    $exchangeService
}

function Get-EWSItem {
[OutputType('Microsoft.Exchange.WebServices.Data.Item')]
[CmdletBinding(
    DefaultParameterSetName = 'byId'
)]
param (

    # Filter that will be used to retrieve items.
    [Parameter(Position = 0)]
    [string]$Filter,

    # Id of folder that items will be retrieved from.
    [Parameter(
        ParameterSetName = 'byId',
        ValueFromPipelineByPropertyName = $true,
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.FolderId]$Id,

    #
    [Parameter(
        ParameterSetName = 'byName',
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]$Name,
    
    # Service object that will be used to retrieve items.
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService,

    [Microsoft.Exchange.WebServices.Data.BasePropertySet]$PropertySet,

    [ValidateRange(1,1000)]
    [Int]$PageSize = 100,

    [Int]$Limit
)

process {
    if (-not $Service) {
        return
    }

    switch ($PSCmdlet.ParameterSetName) {
        byId {
            $secondParameter = $Id
        }
        byName {
            $secondParameter = $Name
        }
    }
        
    $folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind(
        $Service,
        $secondParameter
    )

    if ($Limit -and $Limit -lt $PageSize) {
        $PageSize = $Limit
    }

    $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView $PageSize, 0
    do {
        $list = $Folder.FindItems($Filter,$view)
        if ($PropertySet -and $Lista.TotalCount) {
            $set = New-Object Microsoft.Exchange.WebServices.Data.PropertySet $PropertySet
            $Service.LoadPropertiesForItems(
                $list,
                $set
            ) | Out-Null
        }
        $list
        $view.Offset += $list.Items.Count
        if ($Widok.Offset -ge $Limit) {
            break
        }
    } while ($list.MoreAvailable)
}

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
    }
}

}

function Get-EWSFolder  {
[OutputType('Microsoft.Exchange.WebServices.Data.Folder')]
[CmdletBinding()]
param (
    [Parameter(
        Mandatory = $true
    )]
    [ValidateScript({
        $Root, $Rest = $_ -split '\\|/|:|\|'
        try { 
            [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]$Root 
            $true
        } catch {
            throw "Root folder must belong to collection of WellKnownFolderName: $_"
        }
    })]
    [string]$Path,
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService,
    [Microsoft.Exchange.WebServices.Data.Mailbox]$Mailbox
)

    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }

    if (-not $PSBoundParameters.ContainsKey('Mailbox')) {
        if (-not ($Mailbox = $connections[$Service])) {
            $Mailbox = $Script:Mailbox
        }
    }
    $name = [Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName
    $rootFolderName, $remaingPath = $Path -split '\\|/|:|\|'
    try {
        $rootFolder = New-Object Microsoft.Exchange.WebServices.Data.FolderId $rootFolderName, $Mailbox
    } catch {
        throw "Unexpected error occured: $_"
    }
    $root = [Microsoft.Exchange.WebServices.Data.Folder]::Bind(
        $Service,
        $rootFolder
    )

    foreach ($item in $remaingPath) {
        $filter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo -ArgumentList @(
            $name,
            $item
        )
        $lastItem = 
            New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring -ArgumentList @(
                $name,
                $item
            )
        try {
            $new = $root.FindFolders($filter,1).Folders[0]
            if ($new) {
                $root = $new
            } else {
                $view = New-Object Microsoft.Exchange.WebServices.Data.FolderView 10, 0
                do {
                    $list = $root.FindFolders($lastItem,$view)
                    $list
                    $view.Offset += $list.Items.Count
                } while ($list.MoreAvailable)

            }
        } catch {
            Write-Warning "Could not find subfolder: $item"
            $root
            return
        }
    }
    $root
}

function Get-EWSAttachment {
[OutputType('Microsoft.Exchange.WebServices.Data.FileAttachment')]
[CmdletBinding()]
param (
    [Parameter(
        ValueFromPipeline = $true
    )]
    [Microsoft.Exchange.WebServices.Data.Item[]]$Item,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $script:exchangeService

)

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
    }
}

process {
    if (-not $Service) {
        return
    }

    $Service.LoadPropertiesForItems(
        $Item,
        [Microsoft.Exchange.WebServices.Data.PropertySet]::FirstClassProperties
    ) | Out-Null

    foreach ($singleItem in $Item) {
        foreach ($attachment in $singleItem.Attachments) {
            $attachment
        }
    }
}

}

function Save-EWSAttachment {
[CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'Low'
)]
param (
    [string]$Path,
    [Parameter(
        ValueFromPipelineByPropertyName = $true,
        ValueFromPipeline = $true
    )]
    [Microsoft.Exchange.WebServices.Data.FileAttachment[]]$Attachment,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $script:exchangeService
)

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
    }
}

process {
    if (-not $Service) {
        return
    }

    foreach ($singleAttachment in $Attachment) {
        $fullPath = Join-Path -Path $Path -ChildPath $singleAttachment.Name
        if ($PSCmdlet.ShouldProcess(
                $singleAttachment.Name,
                "Save to $Path"
        )) { 
            $singleAttachment.Load(
                $fullPath
            )
        }
    }
}
}

function New-EWSMessage {
[OutputType('Microsoft.Exchange.WebServices.Data.EmailMessage')]
[CmdletBinding(
    DefaultParameterSetName = 'inline'
)]
param (
    [Parameter(
        Mandatory = $true
    )]
    [string[]]$To,
    [string[]]$Cc,
    [string[]]$Bcc,
    [Parameter(
        Mandatory = $true
    )]
    [string]$Subject,
    [Parameter(
        Mandatory = $true,
        ParameterSetName = 'inline'
    )]
    [string]$Body,
    [Microsoft.Exchange.WebServices.Data.BodyType]$BodyType = 'Text',
    [string[]]$Attachment,
    [Parameter(
        ValueFromPipeline = $true,
        Mandatory = $true,
        ParameterSetName = 'pipe'
    )]
    $InputObject,
    [Parameter(
        ParameterSetName = 'pipe'
    )]
    [switch]$IsHtml,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $script:exchangeService
)

begin {
    $data = New-Object Collections.ArrayList
}

process {
    if (-not $Service) {
        return
    }

    if ($InputObject) {
        $data.Add($InputObject) | Out-Null
    }
}

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }

    if ($data.Count) {
        if (! $IsHtml -and $BodyType -eq 'HTML') {
            $body = $data | ConvertTo-Html | Out-String
        } else {
            $body = $data | Out-String
        }
    }
    $message = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage $Service
    $message.Subject = $Subject
    $message.Body = $body
    $message.Body.BodyType = $BodyType
    foreach ($file in $Attachment) {
        $message.Attachments.AddFileAttachment($file) | Out-Null
    }
    foreach ($recipient in $To) {
        $message.ToRecipients.Add(
            $recipient    
        ) | Out-Null
    }
    foreach ($recipient in $Cc) {
        $message.CcRecipients.Add(
            $recipient
        ) | Out-Null
    }
    foreach ($recipient in $Bcc) {
        $message.BccRecipients.Add(
            $recipient
        ) | Out-Null
    }
    $message.SendAndSaveCopy()
    $message
}
}

function New-EWSAppointment {
[OutputType('Microsoft.Exchange.WebServices.Data.Appointment')]
[CmdletBinding(
    DefaultParameterSetName = 'inline'
)]
param (
    [string[]]$Required,
    [string[]]$Optional,
    [Parameter(
        Mandatory = $true
    )]
    [string]$Subject,
    [Parameter(
        Mandatory = $true,
        ParameterSetName = 'inline'
    )]
    [string]$Body,
    [Microsoft.Exchange.WebServices.Data.BodyType]$BodyType = 'Text',
    [string]$Location,
    [DateTime]$Start,
    [TimeSpan]$Duration,
    [string[]]$Attachment,
    [Parameter(
        ValueFromPipeline = $true,
        Mandatory = $true,
        ParameterSetName = 'pipe'
    )]
    $InputObject,
    [Parameter(
        ParameterSetName = 'pipe'
    )]
    [switch]$IsHtml,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $script:exchangeService
)

begin {
    $data = New-Object Collections.ArrayList
}

process {
    if ($InputObject) {
        $data.Add($InputObject) | Out-Null
    }
}

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }
    if ($data.Count) {
        if (! $IsHtml -and $BodyType -eq 'HTML') {
            $body = $data | ConvertTo-Html | Out-String
        } else {
            $body = $data | Out-String
        }
    }
    $appointment = New-Object Microsoft.Exchange.WebServices.Data.Appointment $Service -Property @{
        Subject = $Subject
        Body = $body
        Start = $Start
        End = $Start + $Duration
        Location = $Location
    }
    $appointment.Body.BodyType = $BodyType
    foreach ($file in $Attachment) {
        $appointment.Attachments.AddFileAttachment($file) | Out-Null
    }
    foreach ($attendee in $Required) {
        $appointment.RequiredAttendees.Add(
            $attendee
        ) | Out-Null
    }
    foreach ($attendee in $Optional) {
        $appointment.OptionalAttendees.Add(
            $attendee
        ) | Out-Null
    }
    if ($Required -or $Optional) {
        $method = [Microsoft.Exchange.WebServices.Data.SendInvitationsMode]::SendToAllAndSaveCopy
    } else {
        $method = [Microsoft.Exchange.WebServices.Data.SendInvitationsMode]::SendToNone
    }
    $appointment.Save($method)
    $appointment
}
}

function New-EWSContact {
[OutputType('Microsoft.Exchange.WebServices.Data.Contact')]
param (
    [string]$GivenName,
    [string]$Surname,
    [string]$MiddleName,
    [string]$Company,
    [ValidateScript({
        try {
            foreach ($key in $_.Keys) {
                [Microsoft.Exchange.WebServices.Data.PhoneNumberKey]$key 
            }
            $true
        } catch {
            throw "Error: $key - $_"
        }
    })]
    [hashtable]$Phone,
    [ValidateScript({
        foreach ($hash in $_) {
            foreach ($key in $hash.Keys) {
                if ('DisplayName','email' -notcontains $key) {
                    throw "Wrong key in e-mail hashtable: $key"
                }
            }
        }
        $true
    })]
    [hashtable[]]$Email,
    [ValidateScript({
        try {
            foreach ($key in $_.Keys) {
                [Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]$key 
            }
        } catch {
            throw "Error: $key - $_"
        }

        foreach ($hash in $_.Values) {
            foreach ($key in $hash.Keys) {
                if ('City','CountryOrRegion','PostalCode','State','Street' -notcontains $key) {
                    throw "Wrong key in physical address hashtable: $key"
                }
            }
        }
        $true
    })]
    [hashtable]$PhysicalAddress,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $script:ExchangeService
)
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }

    $contact = New-Object Microsoft.Exchange.WebServices.Data.Contact $Service -Property @{
        GivenName = $GivenName
        MiddleName = $MiddleName
        Surname = $Surname
        CompanyName = $Company
        FileAsMapping = [Microsoft.Exchange.WebServices.Data.FileAsMapping]::SurnameCommaGivenName
    }

    foreach ($key in $Phone.Keys) {
        $Contact.PhoneNumbers[$key] = $Phone.$key
    }

    $index = 1
    foreach ($hash in $Email) {
        if ($index -le 3) {
            if ($email = $hash.email) {
                if (! ($displayName = $hash.DisplayName)) {
                    $displayName = $hash.email
                }
                $contact.EmailAddresses["EmailAddress$index"] =
                    New-Object Microsoft.Exchange.WebServices.Data.EmailAddress -ArgumentList @(
                        $displayName
                        $email
                    )
                $index++
            }
        }
    }
    foreach ($key in $PhysicalAddress.Keys) {
        $contact.PhysicalAddresses[$key] = 
            New-Object Microsoft.Exchange.WebServices.Data.PhysicalAddressEntry -Property @{
                City = $PhysicalAddress[$key].City
                CountryOrRegion = $PhysicalAddress[$key].CountryOrRegion
                PostalCode = $PhysicalAddress[$key].PostalCode
                State = $PhysicalAddress[$key].State
                Street = $PhysicalAddress[$key].Street
            }
    }
    $contact.Save()
    $contact
}

function Remove-EWSFolder {
[CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'High'
)]
param (
    [Microsoft.Exchange.WebServices.Data.DeleteMode]$DeleteMode = 'MoveToDeletedItems',
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService,
    [Parameter(
        ValueFromPipeline = $true,
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.Folder]$Folder
)

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }
}

process {
    if (-not $Service) {
        return
    }
    if ($PSCmdlet.ShouldProcess(
        "Folder: $($Folder.DisplayName)",
        'Remove EWS Folder'
    )) {
        $Folder.Delete($DeleteMode)
    }

}
}

function Clear-EWSFolder {
[CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'High'
)]
param (
    [Microsoft.Exchange.WebServices.Data.DeleteMode]$DeleteMode = 'MoveToDeletedItems',
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService,
    [Parameter(
        ValueFromPipeline = $true,
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.Folder]$Folder,
    [switch]$IncludeSubfolders
)

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }
}

process {
    if (-not $Service) {
        return
    }
    if ($PSCmdlet.ShouldProcess(
        "Folder: $($Folder.DisplayName)",
        "Clear (empty) EWS Folder with$('out' * (-not $IncludeSubfolders)) subfolders"
    )) {
        $Folder.Empty($DeleteMode, $IncludeSubfolders)
    }

}
}

function Remove-EWSItem {
[CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'High'
)]
param (
    [Microsoft.Exchange.WebServices.Data.DeleteMode]$DeleteMode = 'MoveToDeletedItems',
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService,
    [Parameter(
        ValueFromPipeline = $true,
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.Item]$Item
)

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }
}

process {
    if (-not $Service) {
        return
    }
    if ($PSCmdlet.ShouldProcess(
        "Item: $($Item.Subject)",
        "Remove using $DeleteMode mode"
    )) {
        $Item.Delete($DeleteMode)
    }
}
}

function New-EWSFolder {
[OutputType('Microsoft.Exchange.WebServices.Data.Folder')]
[CmdletBinding(
    DefaultParameterSetName = 'byName'
)]
param (
    [Parameter(
        Mandatory = $true,
        ValueFromPipelineByPropertyName = $true
    )]
    [string]$DisplayName,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [ValidateSet(
        'Calendar',
        'Contacts',
        'Tasks',
        'Mail'
    )]
    [string]$FolderType = 'Mail',
    [Parameter(
        ParameterSetName = 'byId',
        ValueFromPipelineByPropertyName = $true,
        Mandatory = $true
    )]
    [Alias('Id')]
    [Microsoft.Exchange.WebServices.Data.FolderId]$ParentId,
    [Parameter(
        ParameterSetName = 'byName',
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]$ParentName,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService,
    [Microsoft.Exchange.WebServices.Data.Mailbox]$Mailbox

)

begin {
    $type = 'Microsoft.Exchange.WebServices.Data.{0}Folder' -f "$(
        if ($FolderType -ne 'Mail') {
            $FolderType
        }
    )"

}

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }
}

process {
    if (-not $Service) {
        return
    }

    if ($PSCmdlet.ParameterSetName -eq 'byName') {
        if (-not $PSBoundParameters.ContainsKey('Mailbox')) {
            if (-not ($Mailbox = $Connections[$Service])) {
                $Mailbox = $Script:Mailbox
            }
        }

        $folder = New-Object Microsoft.Exchange.WebServices.Data.FolderId $ParentName, $Mailbox
        $parentId = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service, $ParentName).Id
    }

    $newFolder = New-Object $Type $Service
    if ($FolderType -eq 'Mail') {
        $newFolder.FolderClass = 'IPF.Note'
    }
    $newFolder.DisplayName = $DisplayName
    $newFolder.Save($parentId)
    
    $name = [Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName
    $root = [Microsoft.Exchange.WebServices.Data.Folder]::Bind(
        $Service,
        $parentId
    )

    $filter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo -ArgumentList @(
        $name,
        $DisplayName
    )
    try {
        $root.FindFolders($filter,1).Folders[0]
    } catch {}
}
}

function Move-EWSItem {
[CmdletBinding(
    ConfirmImpact = 'Medium',
    SupportsShouldProcess = $true
)]
param (
    [ValidateScript({
        $root, $rest = $_ -split '\\|/|:|\|'
        try { 
            [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]$root 
            $true
        } catch {
            throw "Root folder must belong to WellKnownFolderName: $_"
        }
    })]
    [string]$DestinationPath,
    [Parameter(
        ValueFromPipeline = $true,
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.Item]$Item,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService

)

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }
}

begin {

    $Mailbox = $Connections[$Service]
    $name = [Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName
    $rootName, $remaingPath = $DestinationPath -split '\\|/|:|\|'
    try {
        $rootId = New-Object Microsoft.Exchange.WebServices.Data.FolderId $rootName, $Mailbox
    } catch {
        throw "Unexpected error occured: $_"
    }
    $root = [Microsoft.Exchange.WebServices.Data.Folder]::Bind(
        $Service,
        $rootId
    )

    foreach ($pathItem in $remaingPath) {
        $filter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo -ArgumentList @(
            $name,
            $pathItem
        )
        try {
            $new = $root.FindFolders($filter,1).Folders[0]
            if ($new) {
                $root = $new
            }
        } catch {
            Write-Warning "Could not find sub-folder: $pathItem"
            $root
            return
        }
    }
    $destination = $root
}

process {
    if (-not $Service) {
        return
    }

    if ($PSCmdlet.ShouldProcess(
            $Item.Subject,
            "Move to $DestinationPath"
    )) { 
        $Item.Move($destination.Id)
    }
}
}

function Move-EWSFolder {
[CmdletBinding(
    ConfirmImpact = 'Medium',
    SupportsShouldProcess = $true
)]
param (
    [ValidateScript({
        $root, $rest = $_ -split '\\|/|:|\|'
        try { 
            [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]$root 
            $true
        } catch {
            throw "Root folder must belong to collection of WellKnownFolderName: $_"
        }
    })]
    [string]$DestinationPath,
    [Parameter(
        ValueFromPipeline = $true,
        Mandatory = $true
    )]
    [Microsoft.Exchange.WebServices.Data.Folder]$Folder,
    [Parameter(
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Exchange.WebServices.Data.ExchangeService]$Service = $Script:exchangeService

)

end {
    if (-not $Service) {
        Write-Warning 'No connection defined. Use Connect-EWSService first!'
        return
    }
}

begin {

    $Mailbox = $Connections[$Service]
    $name = [Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName
    $rootName, $remaingPath = $DestinationPath -split '\\|/|:|\|'
    try {
        $rootId = New-Object Microsoft.Exchange.WebServices.Data.FolderId $rootName, $Mailbox
    } catch {
        throw "Unexpected error occured: $_"
    }
    $root = [Microsoft.Exchange.WebServices.Data.Folder]::Bind(
        $Service,
        $rootId
    )

    foreach ($pathItem in $remaingPath) {
        $filter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo -ArgumentList @(
            $name,
            $pathItem
        )
        try {
            $new = $root.FindFolders($filter,1).Folders[0]
            if ($new) {
                $root = $new
            }
        } catch {
            Write-Warning "Could not find sub-folder: $pathItem"
            $root
            return
        }
    }
    $destination = $root
}

process {
    if (-not $Service) {
        return
    }

    if ($PSCmdlet.ShouldProcess(
            $Folder.DisplayName,
            "Move to $DestinationPath"
    )) { 
        $Folder.Move($destination.Id)
    }
}
}

Export-ModuleMember -Function *-EWS*