Dustins-PowerShell-Module.psm1
<#
=========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2020 v5.7.174 Created on: 4/25/2020 12:02 Created by: Dustin Rhodes Organization: Perficient Filename: Dustins-PowerShell-Module.psm1 ------------------------------------------------------------------------- Module Name: Dustins-PowerShell-Module =========================================================================== #> function Write-HelloWorld { Write-Host "Hello World" } function Invoke-Menu { [CmdletBinding()] param( [Parameter(Position = 0,Mandatory = $true,HelpMessage = "Enter your menu text")] [ValidateNotNullOrEmpty()] [string]$Menu, [Parameter(Mandatory = $false)] [string]$MenuColor, [Parameter(Mandatory = $false,HelpMessage = "Optional menu title text")] [ValidateNotNullOrEmpty()] [string]$Title, [Parameter(Mandatory = $false)] [string]$TitleColor, [Parameter(Mandatory = $false,HelpMessage = "Optional response text to display below menu")] [string]$Response, [Parameter(Mandatory = $false)] [string]$ResponseColor, [Parameter(Mandatory = $false)] [Alias("cls")] [switch]$ClearScreen ) if ($ClearScreen) { Clear-Host } if ($Title) { if ($TitleColor) { Write-Host "$Title `n" -ForegroundColor $TitleColor } else { Write-Host "$Title `n" } } if ($MenuColor) { Write-Host "$Menu `n" -ForegroundColor $MenuColor } else { Write-Host "$Menu `n" } if ($Response) { if ($ResponseColor) { Write-Host "$Response `n" -ForegroundColor $ResponseColor } else { Write-Host "$Response `n" -ForegroundColor Magenta } } Read-Host -Prompt "SELECTION" } function Write-Log { [CmdletBinding()] param( [Parameter(Mandatory = $true,ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias("LogContent")] [string]$Message, [Parameter(Mandatory = $false)] [Alias("LogPath")] [string]$Path = $defaultLogFile, [Parameter(Mandatory = $false)] [ValidateSet("Error","Warning","Info")] [string]$Level = "Info", [Parameter(Mandatory = $false)] [switch]$NoClobber ) begin { # Set VerbosePreference to Continue so that verbose messages are displayed. $VerbosePreference = "Continue" } process { # If the file already exists and NoClobber was specified, do not write to the log. if ((Test-Path $Path) -and $NoClobber) { Write-Error "Log file $Path already exists, and you specified NoClobber. Either delete the file or specify a different name." return } # If attempting to write to a log file in a folder/path that doesn't exist create the file including the path. elseif (!(Test-Path $Path)) { Write-Verbose "Creating $Path." $NewLogFile = New-Item $Path -Force -ItemType File } else { # Nothing to see here yet. } # Format Date for our Log File $FormattedDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" # Write message to error, warning, or verbose pipeline and specify $LevelText switch ($Level) { "Error" { Write-Error $Message $LevelText = "ERROR:" } "Warning" { Write-Warning $Message $LevelText = "WARNING:" } "Info" { Write-Verbose $Message $LevelText = "INFO:" } } # Write log entry to $Path "$FormattedDate $LevelText $Message" | Out-File -FilePath $Path -Append } end { } } function Get-FileName () { [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Title, [Parameter(Mandatory = $false)] [string]$InitialDirectory, [Parameter(Mandatory = $false)] [string]$Filter ) $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog if ($Filter -or $InitialDirectory) { $OpenFileDialog.Title = $Title $OpenFileDialog.InitialDirectory = $InitialDirectory $OpenFileDialog.Filter = "All Files (*.$Filter*)| *.$Filter*" } else { $OpenFileDialog.Title = $Title $OpenFileDialog.Filter = "All files (*.*)| *.*" } $Result = $OpenFileDialog.ShowDialog() if ($Result -eq "OK") { $OpenFileDialog.FileName } else { $null } } function New-PSStoredCredential { <# .SYNOPSIS New-PSStoredCredential - Create a new stored credential .DESCRIPTION This function will save a new stored credential to a .cred file. .EXAMPLE New-PSStoredCredential .NOTES Written by: Dustin Rhodes #> if (!(Test-Path $KeyPath)) { Write-Warning "The `$KeyPath variable has not been set. Consider adding `$KeyPath to your PowerShell profile to avoid this prompt." $Path = Read-Host -Prompt "Enter a path for stored credentials" $global:KeyPath = $Path if (!(Test-Path $KeyPath)) { try { New-Item -ItemType Directory -Path $KeyPath -ErrorAction Stop | Out-Null } catch { throw $_.Exception.Message } } } $Credential = Get-Credential -Message "Enter Credentials" $Credential.Password | ConvertFrom-SecureString | Out-File "$($KeyPath)\$($Credential.Username).cred" -Force } function Get-PSStoredCredential { <# .SYNOPSIS Get-PSStoredCredential - Retrieve or list stored credentials .DESCRIPTION This function can be used to list available credentials on the computer, or to retrieve a credential for use in a script or command. .PARAMETER UserName Get the stored credential for the username .PARAMETER List List the stored credentials on the computer .EXAMPLE Get-PSStoredCredential -List .EXAMPLE $credential = Get-PSStoredCredential -UserName admin@tenant.onmicrosoft.com .EXAMPLE Get-PSStoredCredential -List .NOTES Written by: Dustin Rhodes #> param( [Parameter(Mandatory = $false,ParameterSetName = "Get")] [string]$UserName, [Parameter(Mandatory = $false,ParameterSetName = "List")] [switch]$List ) if (!(Test-Path $KeyPath)) { Write-Warning "The `$KeyPath variable has not been set. Consider adding `$KeyPath to your PowerShell profile to avoid this prompt." $Path = Read-Host -Prompt "Enter a path for stored credentials" $global:KeyPath = $Path } if ($List) { try { $CredentialList = @(Get-ChildItem -Path $KeyPath -Filter *.cred -ErrorAction Stop) foreach ($Cred in $CredentialList) { Write-Host "Username: $($Cred.BaseName)" } } catch { Write-Warning $_.Exception.Message } } if ($UserName) { if (Test-Path "$($KeyPath)\$($Username).cred") { $PwdSecureString = Get-Content "$($KeyPath)\$($Username).cred" | ConvertTo-SecureString $Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$PwdSecureString } else { throw "Unable to locate a credential for $UserName" } return $Credential } } function Set-PSWindowTitle { <# .Synopsis Updates PowerShell window title #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [Alias("String")] [string]$Text, [Parameter(Mandatory = $false)] [switch]$Update, [Parameter(Mandatory = $false)] [switch]$Replace ) begin { } process { if ($null -ne $Text) { if ($Update) { $Host.UI.RawUI.WindowTitle += $Text } elseif ($Replace) { $Host.UI.RawUI.WindowTitle = $Text } else { if ($Host.UI.RawUI.WindowTitle -match "(Administrator)") { $Host.UI.RawUI.WindowTitle = "$($env:USERNAME) (Administrator)" } else { $Host.UI.RawUI.WindowTitle = $env:USERNAME } } } } end { } } function Set-O365PSWindowTitle { <# .Synopsis Updates PowerShell window title to reflect connected O365 services #> $o365ServiceConnectionStatus = Get-O365ServiceConnectionStatus -Service AzureAD,ExchangeOnline,MSOnline,SecurityAndCompliance,SharePointOnline,SkypeForBusinessOnline foreach ($service in $o365ServiceConnectionStatus) { if ($service.Connected) { if ($Host.UI.RawUI.WindowTitle -match "Connected To:") { Set-PSWindowTitle -Text " / $($service.Service)" -Update } else { Set-PSWindowTitle -Text " - Connected To: $($service.Service)" -Update } } } } function Remove-InvalidPSSession { <# .Synopsis Remove broken and closed sessions #> begin { $psBroken = Get-PSSession | Where-Object { $_.State -like "*Broken*" } $psClosed = Get-PSSession | Where-Object { $_.State -like "*Closed*" } } process { if ($psBroken.Count -gt 0) { for ($i = 0; $i -lt $psBroken.Count; $i++) { Remove-PSSession -Session $psBroken[$i] } } if ($psClosed.Count -gt 0) { for ($i = 0; $i -lt $psClosed.Count; $i++) { Remove-PSSession -Session $psClosed[$i] } } } end { } } function Remove-DuplicatePSSession { <# .Synopsis Remove duplicate PowerShell sessions #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet("ExchangeOnline","SecurityAndCompliance","SkypeForBusinessOnline")] [string[]]$Service ) begin { } process { foreach ($item in $PSBoundParameters.Service) { Write-Verbose "Checking connection status of $item" switch ($item) { "ExchangeOnline" { $psEXO = Get-PSSession | Where-Object { ($_.ComputerName -eq "outlook.office365.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") } | Sort-Object Id -Descending if ($psEXO.Count -gt 1) { for ($i = 1; $i -lt $psEXO.Count; $i++) { Remove-PSSession -Session $psEXO[$i] } } } "SecurityAndCompliance" { $psSCC = Get-PSSession | Where-Object { ($_.ComputerName -like "*.ps.compliance.protection.outlook.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") } | Sort-Object Id -Descending if ($psSCC.Count -gt 1) { for ($i = 1; $i -lt $psSCC.Count; $i++) { Remove-PSSession -Session $psSCC[$i] } } } "SkypeForBusinessOnline" { $psSfBO = Get-PSSession | Where-Object { ($_.ComputerName -like "*.online.lync.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") } | Sort-Object Id -Descending if ($psSfBO.Count -gt 1) { for ($i = 1; $i -lt $psSfBO.Count; $i++) { Remove-PSSession -Session $psSfBO[$i] } } } } } } end { } } function Get-O365ServiceConnectionStatus { <# .Synopsis Gets connection status to Office 365 services #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet("AzureAD","ExchangeOnline","MSOnline","SecurityAndCompliance","SharePointOnline","SkypeForBusinessOnline")] [string[]]$Service ) begin { $serviceStatus = @() } process { foreach ($item in $PSBoundParameters.Service) { Write-Verbose "Checking connection status of $item" switch ($item) { "AzureAD" { try { $azureADSessionInfo = Get-AzureADCurrentSessionInfo -ErrorAction "SilentlyContinue" } catch { } if ($null -ne $azureADSessionInfo) { Write-Verbose "Connected to $item" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $true Details = $azureADSessionInfo } } else { Write-Verbose "Not connected to $item" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $false Details = $azureADSessionInfo } } } "ExchangeOnline" { try { $exoPSSession = Get-PSSession | Where-Object { ($_.ComputerName -eq "outlook.office365.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") } | Select-Object -Last 1 } catch { } if ($null -ne $exoPSSession) { Write-Verbose "Connected to $item" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $true Details = $exoPSSession } } else { Write-Verbose "Not connected to $item" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $false Details = $exoPSSession } } } "MSOnline" { try { $MSOnlineDomain = Get-MsolDomain -ErrorAction "SilentlyContinue" | Where-Object { $_.IsInitial -eq $true } } catch { } if ($null -ne $MSOnlineDomain) { Write-Verbose "Connected to $item" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $true Details = $MSOnlineDomain } } else { Write-Verbose "Not connected to $item" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $false Details = $MSOnlineDomain } } } "SecurityAndCompliance" { try { $SCCPSSession = Get-PSSession | Where-Object { ($_.ComputerName -like "*.ps.compliance.protection.outlook.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") } | Select-Object -Last 1 } catch { } if ($null -ne $SCCPSSession) { Write-Verbose "Connected to Security and Compliance Center" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $true Details = $SCCPSSession } } else { Write-Verbose "Not connected to Security and Compliance Center" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $false Details = $SCCPSSession } } } "SharePointOnline" { try { $SPOTenant = Get-SPOTenant } catch { } if ($null -ne $SPOTenant) { Write-Verbose "Connected to SharePoint Online" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $true Details = $SPOTenant } } else { Write-Verbose "Not connected to SharePoint Online" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $false Details = $SPOTenant } } } "SkypeForBusinessOnline" { try { $SfBOPSSession = Get-PSSession | Where-Object { ($_.ComputerName -like "*.online.lync.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") } | Select-Object -Last 1 } catch { } if ($null -ne $SfBOPSSession) { Write-Verbose "Connected to SkypeForBusinessOnline" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $true Details = $SfBOPSSession } } else { Write-Verbose "Not connected to SkypeForBusinessOnline" $serviceStatus += [pscustomobject]@{ Service = $item Connected = $false Details = $SfBOPSSession } } } } } $serviceStatus } end { } } function Connect-Office365 { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateSet('AzureAD','ExchangeOnline','MSOnline','MSTeams','SecurityAndCompliance','SharePointOnline','SkypeForBusinessOnline')] [string[]]$Service, [Parameter(Mandatory = $false)] [Alias('SPOrgName')] [string]$SharePointOrganizationName, [Parameter(ParameterSetName = 'Credential', Mandatory = $false)] [pscredential]$Credential, [Parameter(ParameterSetName = 'StoredCreds', Mandatory = $false)] [switch]$UseStoredCredential, [Parameter(ParameterSetName = 'StoredCreds', Mandatory = $false)] [string]$UserName, [Parameter(ParameterSetName = 'MFA', Mandatory = $false)] [switch]$MFA, [Parameter(Mandatory = $false)] [string]$Prefix ) begin { #remove invalid PowerShell sessions Remove-InvalidPSSession #check for existing globally defined credentials if ($UseStoredCredential) { Write-Verbose "Using stored credentials" $Credential = Get-PSStoredCredential -UserName $UserName Write-Verbose "Using stored credentials for $($Credential.UserName)" Set-PSWindowTitle Set-PSWindowTitle -Update -Text " - $($Credential.UserName)" } elseif ((!$MFA) -and ($null -ne $global:Credential)) { $credentialSelection = Read-Host "Credentials found for $($global:Credential.UserName). Use existing credentials? (Y*/N)" switch ($credentialSelection) { "Y" { Write-Verbose "Using existing credentials ($($global:Credential.UserName))" $Credential = $global:Credential Set-PSWindowTitle Set-PSWindowTitle -Update -Text " - $($Credential.UserName)" } "N" { Write-Verbose "Getting credentials" $Credential = Get-Credential -Message "Enter Office 365 Credentials" Write-Verbose "Using credentials for $($Credential.UserName)" Set-PSWindowTitle Set-PSWindowTitle -Update -Text " - $($Credential.UserName)" } default { Write-Verbose "Using existing credentials ($($global:Credential.UserName))" $Credential = $global:Credential Set-PSWindowTitle Set-PSWindowTitle -Update -Text " - $($Credential.UserName)" } } } elseif (!$MFA) { Write-Verbose "Getting credentials" $Credential = Get-Credential -Message "Enter Office 365 Credentials" Write-Verbose "Using credentials for $($Credential.UserName)" Set-PSWindowTitle Set-PSWindowTitle -Update -Text " - $($Credential.UserName)" } #Get-Module options $GetModuleSplat = @{ ListAvailable = $true Verbose = $false } } process { foreach ($item in $PsBoundParameters.Service) { Write-Verbose "Attempting connection to $item" switch ($item) { "AzureAD" { #check for AzureAD modules if ($null -eq ((Get-Module @GetModuleSplat -Name "AzureAD") -or (Get-Module @GetModuleSplat -Name "AzureADPreview"))) { Write-Error "AzureAD Module could not be located" continue } else { #get AzureAD connection status $azureADStatus = Get-O365ServiceConnectionStatus -Service AzureAD if ($azureADStatus.Connected) { Write-Verbose "Already connected to $item. Skipping..." } else { #connect to AzureAD using MFA Write-Verbose "Connecting to $item" if ($MFA -eq $true) { Write-Verbose "Connecting to $item using MFA" $azureADConnection = Connect-AzureAD if ($null -ne $azureADConnection) { Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } else { #connect to AzureAD using credentials Write-Verbose "Connecting to $item using credentials" $azureADConnection = Connect-AzureAD -Credential $Credential if ($null -ne $azureADConnection) { Write-Verbose "Connected to $item as $($Credential.Username)" } else { Write-Error "Unable to connect to $item using credentials" } } } } continue } "ExchangeOnline" { #remove duplicate ExchangeOnline sessions Remove-DuplicatePSSession -Service ExchangeOnline #get ExchangeOnline connection status $EXOStatus = Get-O365ServiceConnectionStatus -Service ExchangeOnline if ($EXOStatus.Connected) { Write-Verbose "Already connected to $item. Skipping..." } else { #connect to ExchangeOnline using MFA Write-Verbose "Connecting to $item" if ($MFA -eq $true) { $getChildItemSplat = @{ Path = "$Env:LOCALAPPDATA\Apps\2.0\*\CreateExoPSSession.ps1" Recurse = $true ErrorAction = 'SilentlyContinue' Verbose = $false } $EXOMFAModule = (Get-ChildItem @getChildItemSplat | Select-Object -ExpandProperty Target -First 1) #check for Exchange Online MFA module if ($null -eq $EXOMFAModule) { Write-Error "The Exchange Online MFA Module could not be located" continue } else { Write-Verbose "Importing Exchange Online MFA Module" .$EXOMFAModule Write-Verbose "Connecting to $item using MFA" $WarningPreference = "SilentlyContinue" Connect-EXOPSSession $WarningPreference = "Continue" $global:EXOPSSession = (Get-PSSession | Where-Object { ($_.ConfigurationName -eq "Microsoft.Exchange") -and ($_.ComputerName -eq "outlook.office365.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") })[0] if ($null -ne $EXOPSSession) { if ($Prefix -ne "") { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking -Prefix $Prefix } else { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking } Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } } else { #connect to ExchangeOnline using credentials $EXOPSSessionSplat = @{ ConfigurationName = "Microsoft.Exchange" ConnectionUri = "https://outlook.office365.com/powershell-liveid/" Authentication = "Basic" Credential = $Credential AllowRedirection = $true } Write-Verbose "Connecting to $item using credentials" $global:EXOPSSession = New-PSSession @EXOPSSessionSplat $null = Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking if ($null -ne $EXOPSSession) { if ($Prefix -ne "") { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking -Prefix $Prefix } else { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking } Write-Verbose "Connected to $item as $($Credential.UserName)" } else { Write-Error "Unable to connect to $item using credentials" } } } continue } "MSOnline" { #check for MSOnline module if ($null -eq (Get-Module @GetModuleSplat -Name "MSOnline")) { Write-Error "MSOnline Module could not be located" continue } else { #get MSOnline connection status $MSOnlineStatus = Get-O365ServiceConnectionStatus -Service MSOnline if ($MSOnlineStatus.Connected) { Write-Verbose "Already connected to $item. Skipping..." } else { Write-Verbose "Connecting to $item" if ($MFA -eq $true) { #connect to MSOnline using MFA Write-Verbose "Connecting to $item using MFA" Connect-MsolService $MSOnlineStatus = Get-O365ServiceConnectionStatus -Service MSOnline if ($MSOnlineStatus.Connected) { Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } else { #connect to MSOnline using credentials Write-Verbose "Connecting to $item using credentials" Connect-MsolService -Credential $Credential $MSOnlineStatus = Get-O365ServiceConnectionStatus -Service MSOnline if ($MSOnlineStatus.Connected) { Write-Verbose "Connected to $item as $($Credential.UserName)" } else { Write-Error "Unable to connect to $item using credentials" } } } } continue } "MSTeams" { if ($null -eq (Get-Module @GetModuleSplat -Name "MicrosoftTeams")) { Write-Error "MicrosoftTeams Module could not be located" } else { Write-Verbose "Connecting to $item using MFA" if ($MFA -eq $true) { $MSTeamsStatus = Connect-MicrosoftTeams if ($null -ne ($MSTeamsStatus)) { Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } else { $MSTeamsStatus = Connect-MicrosoftTeams -Credential $Credential if ($null -ne ($MSTeamsStatus)) { Write-Verbose "Connected to $item using credentials" } else { Write-Error "Unable to connect to $item using MFA" } } } continue } "SecurityAndCompliance" { #remove duplicate SecurityAndCompliance sessions Remove-DuplicatePSSession -Service SecurityAndCompliance #get SecurityAndCompliance connection status $SCCStatus = Get-O365ServiceConnectionStatus -Service SecurityAndCompliance if ($SCCStatus.Connected) { Write-Verbose "Already connected to $item. Skipping..." } else { #connect to SecurityAndCompliance using MFA Write-Verbose "Connecting to $item" if ($MFA -eq $true) { $getChildItemSplat = @{ Path = "$Env:LOCALAPPDATA\Apps\2.0\*\CreateExoPSSession.ps1" Recurse = $true ErrorAction = 'SilentlyContinue' Verbose = $false } $EXOMFAModule = (Get-ChildItem @getChildItemSplat | Select-Object -ExpandProperty Target -First 1) #check for Exchange Online MFA module if ($null -eq $EXOMFAModule) { Write-Error "The Exchange Online MFA Module could not be located" continue } else { Write-Verbose "Importing Exchange Online MFA Module" .$EXOMFAModule Write-Verbose "Connecting to $item using MFA" $WarningPreference = "SilentlyContinue" Connect-IPPSSession $WarningPreference = "Continue" $global:SCCPSSession = (Get-PSSession | Where-Object { ($_.ConfigurationName -eq "Microsoft.Exchange") -and ($_.ComputerName -like "*.ps.compliance.protection.outlook.com") -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") })[0] if ($null -ne $SCCPSSession) { if ($Prefix -ne "") { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking -Prefix $Prefix } else { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking } Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } } else { #connect to SecurityAndCompliance using credentials $SCCPSSessionSplat = @{ ConfigurationName = "Microsoft.Exchange" ConnectionUri = "https://ps.compliance.protection.outlook.com/powershell-liveid/" Authentication = "Basic" Credential = $Credential AllowRedirection = $true WarningAction = "SilentlyContinue" } Write-Verbose "Connecting to $item using credentials" $global:SCCPSSession = New-PSSession @SCCPSSessionSplat $null = Import-PSSession $SCCPSSession -AllowClobber -DisableNameChecking if ($null -ne $SCCPSSession) { if ($Prefix -ne "") { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking -Prefix $Prefix } else { Import-Module -Global -AsCustomObject (Import-PSSession $EXOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking } Write-Verbose "Connected to $item as $($Credential.UserName)" } else { Write-Error "Unable to connect to $item using credentials" } } } continue } "SharePointOnline" { #check for SharePointOnline module if ($null -eq (Get-Module @GetModuleSplat -Name Microsoft.Online.SharePoint.PowerShell)) { Write-Error "Microsoft.Online.SharePoint.PowerShell Module could not be located" continue } if (-not ($PSBoundParameters.ContainsKey("SharePointOrganizationName"))) { Write-Error "Please provide a valid SharePoint organization name with the -SharePointOrganizationName parameter." continue } $SharePointUrl = "https://{0}-admin.sharepoint.com" -f $SharePointOrganizationName Write-Verbose "Connecting to $item at $SharePointUrl" #get SharePointOnline connection status $SPOStatus = Get-O365ServiceConnectionStatus -Service SharePointOnline if ($SPOStatus.Connected) { Write-Verbose "Already connected to $item. Skipping..." } else { #connect to SharePointOnline using MFA Write-Verbose "Connecting to $item" if ($MFA -eq $true) { Write-Verbose "Connecting to $item using MFA" Connect-SPOService -Url $SharePointURL $SPOStatus = Get-O365ServiceConnectionStatus -Service SharePointOnline if ($SPOStatus.Connected) { Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } else { #connect to SharePointOnline using credentials Write-Verbose "Connecting to $item using credentials" Connect-SPOService -Url $SharePointURL -Credential $Credential $SPOStatus = Get-O365ServiceConnectionStatus -Service SharePointOnline if ($SPOStatus.Connected) { Write-Verbose "Connected to $item as $($Credential.UserName)" } else { Write-Error "Unable to connect to $item using credentials" } } } continue } "SkypeForBusinessOnline" { #check for SkypeOnlineConnector module if ($null -eq (Get-Module @GetModuleSplat -Name "SkypeOnlineConnector")) { Write-Error "SkypeOnlineConnector Module could not be located" } else { #remove duplicate SkypeForBusinessOnline sessions Remove-DuplicatePSSession -Service SkypeForBusinessOnline #get SkypeForBusinessOnline connection status $SfBOStatus = Get-O365ServiceConnectionStatus -Service SkypeForBusinessOnline if ($SfBOStatus.Connected) { Write-Verbose "Already connected to $item. Skipping..." } else { Write-Verbose "Connecting to $item" if ($MFA -eq $true) { #connect to SkypeForBusinessOnline using MFA Write-Verbose "Connecting to $item using MFA" $global:SfBOPSSession = New-CsOnlineSession if ($null -ne $SfBOPSSession) { Import-Module -Global -AsCustomObject (Import-PSSession $SfBOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } else { #connect to SkypeForBusinessOnline using credentials Write-Verbose "Connecting to $item using credentials" $global:SfBOPSSession = New-CsOnlineSession -Credential $Credential if ($null -ne $SfBOPSSession) { Import-Module -Global -AsCustomObject (Import-PSSession $SfBOPSSession -AllowClobber -DisableNameChecking) -DisableNameChecking Write-Verbose "Connected to $item using MFA" } else { Write-Error "Unable to connect to $item using MFA" } } } } continue } Default { } } } } end { Set-O365PSWindowTitle } } function Connect-ExchangeServer () { param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty][string]$ComputerName, [Parameter(Mandatory = $true)] [pscredential]$Credential ) $exchangeUri = "http://$ComputerName/PowerShell" #check for existing sessions $activeSessions = Get-PSSession | Where-Object { ($_.ComputerName -eq $ComputerName) -and ($_.State -eq "Opened") -and ($_.Availability -eq "Available") } if (!$activeSessions) { $exopSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $exchangeUri -Authentication Kerberos -Credential $Credential Import-PSSession $exopSession -AllowClobber -DisableNameChecking Write-Host "Connected to $ComputerName" } elseif ($activeSessions) { $activeSessions Write-Host "Already connected to $computerName" -ForegroundColor Yellow } } function Connect-EWS { param( [Parameter(Position = 0,Mandatory = $true)] [string]$MailboxName, [Parameter(Position = 1,Mandatory = $true)] [pscredential]$Credential ) begin { #Load Managed API dll #CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT $EWSDLL = (($(Get-ItemProperty -Path Registry::$(Get-ChildItem -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services' | Sort-Object Name -Descending | Select-Object -First 1 -ExpandProperty Name)). 'Install Directory') + "Microsoft.Exchange.WebServices.dll") if (Test-Path $EWSDLL) { Import-Module $EWSDLL } else { Write-Host "$(Get-Date -format yyyyMMddHHmmss): This script requires the EWS Managed API 1.2 or later. Please download and install the current version of the EWS Managed API from http://go.microsoft.com/fwlink/?LinkId=255472" -ForegroundColor Red -BackgroundColor Black return } #Set Exchange Version (2013 works for EXO) $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1 ## Create Exchange Service Object $Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService ($ExchangeVersion) #Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials #Credentials Option 1 using UPN for the windows Account #$psCred = Get-Credential $EWSCredential = New-Object System.Net.NetworkCredential ($Credential.UserName.ToString(),$Credential.GetNetworkCredential().Password.ToString()) $Service.Credentials = $EWSCredential #Credentials Option 2 #service.UseDefaultCredentials = $true #$service.TraceEnabled = $true #Choose to ignore any SSL Warning issues caused by Self Signed Certificates #HANDLE SSL #Create a compilation environment $Provider = New-Object Microsoft.CSharp.CSharpCodeProvider $Compiler = $Provider.CreateCompiler() $Params = New-Object System.CodeDom.Compiler.CompilerParameters $Params.GenerateExecutable = $False $Params.GenerateInMemory = $True $Params.IncludeDebugInformation = $False $Params.ReferencedAssemblies.Add("System.DLL") | Out-Null $TASource = @" namespace Local.ToolkitExtensions.Net.CertificatePolicy{ public class TrustAll : System.Net.ICertificatePolicy { public TrustAll() { } public bool CheckValidationResult(System.Net.ServicePoint sp, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem) { return true; } } } "@ $TAResults = $Provider.CompileAssemblyFromSource($Params,$TASource) $TAAssembly = $TAResults.CompiledAssembly #We now create an instance of the TrustAll and attach it to the ServicePointManager $TrustAll = $TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll") [System.Net.ServicePointManager]::CertificatePolicy = $TrustAll #Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use #CAS URL Option 1 Autodiscover #$service.AutodiscoverUrl($MailboxName, { $true }) #Write-host ("Using CAS Server : " + $Service.url) #CAS URL Option 2 Hardcoded #$uri=[system.URI] "https://casservername/ews/exchange.asmx" $URI = [system.URI]"https://outlook.office365.com/EWS/Exchange.asmx" $Service.Url = $URI ## Optional section for Exchange Impersonation $Service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress,$MailboxName) if (!$Service.Url) { throw "Error connecting to EWS" } else { return $Service } } } function Get-EWSFolderFromPath { param( [Parameter(Mandatory = $true)] [string]$FolderPath, [Parameter(Mandatory = $true)] [string]$MailboxName, [Parameter(Mandatory = $true)] [Microsoft.Exchange.WebServices.Data.ExchangeService]$EWSService, [Parameter(Mandatory = $false)] [Microsoft.Exchange.WebServices.Data.PropertySet]$PropertySet ) process { ## Find and Bind to Folder based on Path #Define the path to search should be seperated with \ #Bind to the MSGFolder Root $folderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId ([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName) $tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($EWSService,$folderId) #Split the Search path into an array $fldArray = $FolderPath.Split("\") #Loop through the Split Array and do a Search for each level of folder for ($lint = 1; $lint -lt $fldArray.Length; $lint++) { #Perform search based on the displayname of each folder level $fvFolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView (1) if (![string]::IsNullOrEmpty($PropertySet)) { $fvFolderView.PropertySet = $PropertySet } $SfSearchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo ([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$fldArray[$lint]) $findFolderResults = $EWSService.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView) if ($findFolderResults.TotalCount -gt 0) { foreach ($folder in $findFolderResults.Folders) { $tfTargetFolder = $folder } } else { Write-Host ("Error Folder Not Found check path and try again") $tfTargetFolder = $null break } } if ($tfTargetFolder -ne $null) { return [Microsoft.Exchange.WebServices.Data.Folder]$tfTargetFolder } else { throw ("Folder Not found") } } } function Create-NewEWSFolder { param( [Parameter(Mandatory = $true)] [Microsoft.Exchange.WebServices.Data.ExchangeService]$EWSService, [Parameter(Mandatory = $true)] [pscredential]$Credential, [Parameter(Mandatory = $true)] [string]$MailboxName, [Parameter(Mandatory = $true)] [string]$NewFolderName, [Parameter(Mandatory = $false)] [Microsoft.Exchange.WebServices.Data.Folder]$ParentFolder, [Parameter(Mandatory = $false)] [string]$FolderClass, [Parameter(Mandatory = $false,ParameterSetName = "Retention")] [string]$RetentionTag, [Parameter(Mandatory = $false,ParameterSetName = "Retention")] [int]$RetentionPeriodValue, [Parameter(Mandatory = $false,ParameterSetName = "Retention",HelpMessage = "This is usually 129 (Re-Scan)")] [int]$RetentionFlagsValue ) begin { $Error.Clear() $service = $EWSService $newFolder = New-Object Microsoft.Exchange.WebServices.Data.Folder ($service) $newFolder.DisplayName = $NewFolderName #bind to retention tag properties $policyTag = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition (0x3019,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Binary); $retentionFlags = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition (0x301D,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer); $retentionPeriod = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition (0x301A,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer); #determine which retention tag to apply to the current folder if ($RetentionTag) { $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress,$MailboxName); $tag = ($service.GetUserRetentionPolicyTags().RetentionPolicyTags | Where-Object { $_.DisplayName -eq $RetentionTag }) $newFolder.SetExtendedProperty($retentionFlags,$RetentionFlagsValue) $newFolder.SetExtendedProperty($retentionPeriod,$RetentionPeriodValue) try { $newFolder.PolicyTag = New-Object Microsoft.Exchange.WebServices.Data.PolicyTag ($true,$tag.RetentionId) $Error.Clear() } catch { Write-Host "`t Could not apply $RetentionTag retention tag to: " -ForegroundColor Red -NoNewline; Write-Host $NewFolderName -ForegroundColor Green `r Write-Host "`t" -NoNewline; Write-Host $error[0] -ForegroundColor Red -BackgroundColor Black `r`n $Error.Clear() } } #check folder class if (([string]::IsNullOrEmpty($FolderClass))) { $newFolder.FolderClass = "IPF.Note" } else { $newFolder.FolderClass = $FolderClass } #set $ParentFolder to $null and check $ParentFolder $ewsParentFolder = $null if (([string]::IsNullOrEmpty($ParentFolder))) { #bind to the MsgFolderRoot folder $folderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId ([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName) $ewsParentFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderId) } else { $ewsParentFolder = $ParentFolder } Write-Host "Processing folder: $NewFolderName" -ForegroundColor Cyan Write-Host "Folder doesn't exist: $NewFolderName. Creating it now..." -ForegroundColor Yellow $newFolder.Save($ewsParentFolder.Id) } } function Apply-RetentionPolicy { param( [Parameter(Mandatory = $true)] [Microsoft.Exchange.WebServices.Data.ExchangeService]$EWSService, [Parameter(Mandatory = $true)] [pscredential]$Credential, [Parameter(Mandatory = $true)] [string]$MailboxName, [Parameter(Mandatory = $true,ParameterSetName = "Retention")] [string]$FolderName, [Parameter(Mandatory = $true,ParameterSetName = "Retention")] [string]$RetentionTag, [Parameter(Mandatory = $true,ParameterSetName = "Retention")] [int]$RetentionPeriodValue, [Parameter(Mandatory = $true,ParameterSetName = "Retention")] [int]$RetentionFlagsValue ) begin { $service = $EWSService # Bind to retention tag properties $policyTag = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition (0x3019,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Binary); $retentionFlags = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition (0x301D,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer); $retentionPeriod = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition (0x301A,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer); $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress,$MailboxName); $folderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId ([Microsoft.Exchange.Webservices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName) $ewsParentFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderId) $folderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView (1000) $folderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep $foundFolders = $ewsParentFolder.FindFolders($folderView) $permanentFolderFoundId = $foundFolders | Where-Object { $_.DisplayName -eq $FolderName } $tag = ($service.GetUserRetentionPolicyTags().RetentionPolicyTags | Where-Object { $_.DisplayName -eq $RetentionTag }).RetentionId $tagByteArray = ([guid]$tag.GUID).ToByteArray() Write-Host -ForegroundColor Yellow "Found $FolderName in mailbox $MailboxName. Setting $RetentionTag retention policy now." #never delete assign tag $oFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$permanentFolderFoundId.Id) $oFolder.SetExtendedProperty($retentionFlags,$RetentionFlagsValue) $oFolder.SetExtendedProperty($retentionPeriod,$RetentionPeriodValue) $oFolder.SetExtendedProperty($policyTag,$tagByteArray) $oFolder.Update() Write-Host -ForegroundColor Green "Finished setting $RetentionTag on $FolderName in mailbox $MailboxName" } } ######################################################################################## function Connect-ExchangeOnPremises { param( [Parameter(Mandatory,HelpMessage = "http://<ServerFQDN>/powershell")] [System.String]$ConnectionUri, [Alias("RunAs")] [pscredential][System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) try { $Splatting = @{ ConnectionUri = $ConnectionUri ConfigurationName = "Microsoft.Exchange" } if ($PSBoundParameters["Credential"]) { $Splatting.Credential = $Credential } Import-PSSession -Session (New-PSSession @Splatting) } catch { $PSCmdlet.ThrowTerminatingError($_) } } function Send-Email { <# .SYNOPSIS This function allows you to send email .DESCRIPTION This function allows you to send email using the NET Class System.Net.Mail .PARAMETER To A description of the To parameter. .PARAMETER From A description of the From parameter. .PARAMETER FromDisplayName Specifies the DisplayName to show for the FROM parameter .PARAMETER SenderAddress A description of the SenderAddress parameter. .PARAMETER SenderDisplayName Specifies the DisplayName of the Sender .PARAMETER CC A description of the CC parameter. .PARAMETER BCC A description of the BCC parameter. .PARAMETER ReplyToList Specifies the email address(es) that will be use when the recipient(s) reply to the email. .PARAMETER Subject Specifies the subject of the email. .PARAMETER Body Specifies the body of the email. .PARAMETER BodyIsHTML Specifies that the text format of the body is HTML. Default is Plain Text. .PARAMETER Priority Specifies the priority of the message. Default is Normal. .PARAMETER Encoding Specifies the text encoding of the title and the body. .PARAMETER Attachment Specifies if an attachement must be added to the function .PARAMETER Credential Specifies the credential to use, default will use the current credential. .PARAMETER SMTPServer Specifies if the SMTP Server IP or FQDN to use .PARAMETER Port Specifies if the SMTP Server Port to use. Default is 25. .PARAMETER EnableSSL Specifies if the email must be sent using SSL. .PARAMETER DeliveryNotificationOptions Specifies the delivey notification options. https://msdn.microsoft.com/en-us/library/system.net.mail.deliverynotificationoptions.aspx .PARAMETER EmailCC Specifies the Carbon Copy recipient .PARAMETER EmailBCC Specifies the Blind Carbon Copy recipient .PARAMETER EmailTo Specifies the recipient of the email .PARAMETER EmailFrom Specifies the sender of the email .PARAMETER Sender Specifies the Sender Email address. Sender is the Address of the actual sender acting on behalf of the author listed in the From parameter. .EXAMPLE Send-email ` -EmailTo "fxcat@contoso.com" ` -EmailFrom "powershell@contoso.com" ` -SMTPServer "smtp.sendgrid.net" ` -Subject "Test Email" ` -Body "Test Email" This will send an email using the current credential of the current logged user .EXAMPLE $Cred = [System.Net.NetworkCredential](Get-Credential -Credential testuser) Send-email ` -EmailTo "fxcat@contoso.com" ` -EmailFrom "powershell@contoso.com" ` -Credential $cred -SMTPServer "smtp.sendgrid.net" ` -Subject "Test Email" ` -Body "Test Email" This will send an email using the credentials specified in the $Cred variable .EXAMPLE Send-email ` -EmailTo "fxcat@contoso.com","SomeoneElse@contoso.com" ` -EmailFrom "powershell@contoso.com" ` -SMTPServer "smtp.sendgrid.net" ` -Subject "Test Email" ` -Body "Test Email" This will send an email using the current credential of the current logged user to two fxcat@contoso.com and SomeoneElse@contoso.com .NOTES .LINK #> [CmdletBinding(DefaultParameterSetName = 'Main')] param( [Parameter(ParameterSetName = 'Main',Mandatory = $true)] [Alias('EmailTo')] [String[]]$To, [Parameter(ParameterSetName = 'Main',Mandatory = $true)] [Alias('EmailFrom','FromAddress')] [string]$From, [Parameter(ParameterSetName = 'Main')] [ValidateNotNullOrEmpty()] [string]$FromDisplayName, [Parameter(ParameterSetName = 'Main')] [Alias('EmailCC')] [string]$CC, [Parameter(ParameterSetName = 'Main')] [Alias('EmailBCC')] [System.String]$BCC, [Parameter(ParameterSetName = 'Main')] [ValidateNotNullOrEmpty()] [Alias('ReplyTo')] [System.String[]]$ReplyToList, [Parameter(ParameterSetName = 'Main')] [System.String]$Subject = "Email from PowerShell", [Parameter(ParameterSetName = 'Main')] [System.String]$Body = "Hello World", [Parameter(ParameterSetName = 'Main')] [switch]$BodyIsHTML = $false, [Parameter(ParameterSetName = 'Main')] [ValidateNotNullOrEmpty()] [System.Net.Mail.MailPriority]$Priority = "Normal", [Parameter(ParameterSetName = 'Main')] [ValidateSet("Default","ASCII","Unicode","UTF7","UTF8","UTF32")] [System.String]$Encoding = "Default", [Parameter(ParameterSetName = 'Main')] [System.String]$Attachment, [Parameter(ParameterSetName = 'Main')] [pscredential][System.Net.NetworkCredential]$Credential, [Parameter(ParameterSetName = 'Main',Mandatory = $true)] #verify that the host is reachable [ValidateScript({ Test-Connection -ComputerName $_ -Count 1 -Quiet })] [Alias("Server")] [string]$SMTPServer, [Parameter(ParameterSetName = 'Main')] [ValidateRange(1,65535)] [Alias("SMTPServerPort")] [int]$Port = 25, [Parameter(ParameterSetName = 'Main')] [switch]$EnableSSL, [Parameter(ParameterSetName = 'Main')] [ValidateNotNullOrEmpty()] [Alias('EmailSender','Sender')] [string]$SenderAddress, [Parameter(ParameterSetName = 'Main')] [ValidateNotNullOrEmpty()] [System.String]$SenderDisplayName, [Parameter(ParameterSetName = 'Main')] [ValidateNotNullOrEmpty()] [Alias('DeliveryOptions')] [System.Net.Mail.DeliveryNotificationOptions]$DeliveryNotificationOptions ) process { try { $SMTPMessage = New-Object -TypeName System.Net.Mail.MailMessage $SMTPMessage.From = $From foreach ($ToAddress in $To) { $SMTPMessage.To.Add($ToAddress) } $SMTPMessage.Body = $Body $SMTPMessage.IsBodyHtml = $BodyIsHTML $SMTPMessage.Subject = $Subject $SMTPMessage.BodyEncoding = $([System.Text.Encoding]::$Encoding) $SMTPMessage.SubjectEncoding = $([System.Text.Encoding]::$Encoding) $SMTPMessage.Priority = $Priority $SMTPMessage.Sender = $SenderAddress if ($PSBoundParameters['SenderDisplayName']) { $SMTPMessage.Sender.DisplayName = $SenderDisplayName } if ($PSBoundParameters['FromDisplayName']) { $SMTPMessage.From.DisplayName = $FromDisplayName } if ($PSBoundParameters['CC']) { $SMTPMessage.CC.Add($CC) } if ($PSBoundParameters['BCC']) { $SMTPMessage.BCC.Add($BCC) } if ($PSBoundParameters['ReplyToList']) { foreach ($ReplyTo in $ReplyToList) { $SMTPMessage.ReplyToList.Add($ReplyTo) } } if ($PSBoundParameters['attachment']) { $SMTPattachment = New-Object -TypeName System.Net.Mail.Attachment ($attachment) $SMTPMessage.Attachments.Add($SMTPattachment) } if ($PSBoundParameters['DeliveryNotificationOptions']) { $SMTPMessage.DeliveryNotificationOptions = $DeliveryNotificationOptions } $SMTPClient = New-Object -TypeName Net.Mail.SmtpClient $SMTPClient.Host = $SmtpServer $SMTPClient.Port = $Port if ($PSBoundParameters['EnableSSL']) { $SMTPClient.EnableSsl = $true } if ($PSBoundParameters['Credential']) { $SMTPClient.Credentials = $Credential } if (-not $PSBoundParameters['Credential']) { # Use the current logged user credential $SMTPClient.UseDefaultCredentials = $true } $SMTPClient.Send($SMTPMessage) } catch { $PSCmdlet.ThrowTerminatingError($_) } } end { Remove-Variable -Name SMTPClient -ErrorAction SilentlyContinue Remove-Variable -Name Password -ErrorAction SilentlyContinue } } function Get-ConsoleColor { <# .SYNOPSIS Get all available console colors .DESCRIPTION Get all available console colors. A preview how they look (foreground and background) can be displayed with the parameter "-Preview". .EXAMPLE Get-ConsoleColor ConsoleColor ------------ Black DarkBlue DarkGreen DarkCyan DarkRed DarkMagenta DarkYellow Gray DarkGray Blue Green Cyan Red Magenta Yellow White .LINK #> [CmdletBinding()] param ( ) begin { } process { $Colors = [Enum]::GetValues([ConsoleColor]) foreach ($Color in $Colors) { [pscustomobject] @{ ConsoleColor = $Color } } } end { } } |