PSMimecast.psm1
<#
.SYNOPSIS This function will get information of a Mimecast account. .DESCRIPTION This function will get information of a Mimecast account including if the account is locked or disabled. This is equivalent to going to Administration -> Directories -> Internal Directories -> <domain> -> and picking a user in the web UI. .PARAMETER EmailAddress This parameter specifies the email address of the user you want get information about. .EXAMPLE PS C:\> Get-MimecastAccount -EmailAddress syrius.cleveland@example.com Name EmailAddress accountLocked AccountDisabled AllowSmtp AllowPop PasswordNeverExpires ForcePasswordChange ---- ------------ ------------- --------------- --------- -------- -------------------- ------------------- Syrius Cleveland syrius.cleveland@example.com False False False False False False In this example we get the account information for the user syrius.cleveland@example.com. We can see his account is not locked and not disabled. .INPUTS string EmailAddress .OUTPUTS spz.Mimecast.Account .NOTES This function actually calls the Update API call wihtout any changes to retrieve this information. #> function Get-MimecastAccount{ [cmdletbinding()] [Alias("Get-mcAccount")] param( [Parameter(Mandatory,ValueFromPipelineByPropertyName,ValueFromPipeline)] [Alias("User","Email")] [string]$EmailAddress ) Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/user/update-user" $url = $baseUrl + $apiCall } Process{ $headers = New-MimecastHeader -Uri $apiCall $postBody = @{ data = @(@{ emailAddress = $EmailAddress }) } $postBodyJson = $postBody | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBodyJson -Uri $url #Print the respons if ($response.data){ $response.data | ForEach-Object { $_ | Add-Member -TypeName "PSMimecast.Account" $_ } } else{ Write-Error "$($response.fail.errors.message)" } } } <# .SYNOPSIS This function retrieves the app info used to communicate with Mimecast's API that was previously stored using Set-MimecastAppInfo. .DESCRIPTION This function retrieves the app info used to communicate with Mimecast's API that was previously stored using Set-MimecastAppInfo. This information is stored in the following path, "$ENV:APPDATA\PSMimecast\AppInfo.xml". .EXAMPLE PS C:\> Get-MimecastAppInfo AppId AppKey ----- ------ XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX This example show the only way to use this function. The app info was successfully retrieved. Actual values have been redacted for this example. .INPUTS None .OUTPUTS PSCustomObject .NOTES App info must have been previously set using Set-MimecastAppInfo. #> function Get-MimecastAppInfo { [CmdletBinding()] [Alias("Get-mcAppInfo")] $Path = "$ENV:APPDATA\PSMimecast\AppInfo.xml" if (Test-Path -Path $Path){ $AppInfo = Import-Clixml -Path $Path [PSCustomObject]@{ AppId = $Appinfo.AppId AppKey = [pscredential]::new("API",(ConvertTo-SecureString -String $Appinfo.AppKey)).GetNetworkCredential().Password } } else{ Write-Error "No App Info has been set, use Set-MimecastAppInfo function to set this data" -ErrorAction Stop } } function Get-MimecastDateTime{ Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $form = New-Object Windows.Forms.Form -Property @{ StartPosition = [Windows.Forms.FormStartPosition]::CenterScreen Size = [drawing.size]::new(225,275) Text = 'Select a Date' Topmost = $true } $calendar = New-Object Windows.Forms.MonthCalendar -Property @{ Location = [drawing.size]::new(15,15) ShowTodayCircle = $false MaxSelectionCount = 1 } $form.Controls.Add($calendar) $TimePicker = New-Object System.Windows.Forms.DateTimePicker $TimePicker.Size = [Drawing.Size]::new(125,25) $TimePicker.Location = [Drawing.Size]::new(40,175) $TimePicker.ShowUpDown = $true $TimePicker.Format = [System.Windows.Forms.DateTimePickerFormat]::Time $form.Controls.Add($TimePicker) $okButton = New-Object Windows.Forms.Button -Property @{ Location = [drawing.size]::new(30,200) Size = [drawing.size]::new(75,23) Text = 'OK' DialogResult = [Windows.Forms.DialogResult]::OK } $form.AcceptButton = $okButton $form.Controls.Add($okButton) $cancelButton = New-Object Windows.Forms.Button -Property @{ Location = [drawing.size]::new(105,200) Size = New-Object Drawing.Size 75, 23 Text = 'Cancel' DialogResult = [Windows.Forms.DialogResult]::Cancel } $form.CancelButton = $cancelButton $form.Controls.Add($cancelButton) $result = $form.ShowDialog() if ($result -eq [Windows.Forms.DialogResult]::OK) { $date = $calendar.SelectionStart $time = $TimePicker.Value $SelectionDate = ([DateTime]::new($date.Year,$date.Month,$date.Day,$time.Hour,$time.Minute,0)).ToUniversalTime() $SelectionDate.ToString("yyyy-MM-ddTHH:mm:ss+0000") } } <# .SYNOPSIS This function returns the directory connections of Mimecast. .DESCRIPTION This function returns the directory connections of Mimecast. This function is equivalent to going to Administration -> Services -> Directory Synchronization in the web UI. .EXAMPLE PS C:\> Get-MimecastDirectoryConnection | Select-Object -First 1 enabled : True id : MTOKEN:XXXXXXXXXXXXXXXXXXXXXXX... description : description info : serverType : active_directory ldapSettings : @{hostname=example.example... status : ok lastSync : 12/29/2021 7:43:30 AM syncRunning : False domains : acknowledgeDisabledAccounts : True This example gets the directory connectors and grabs only the first one that is returned. Here we can see whether the connection sync is running and the last time it ran. .INPUTS None .OUTPUTS PSCustomObject .NOTES No notes to add. #> function Get-MimecastDirectoryConnection{ [CmdletBinding()] [Alias("Get-mcDirectoryConnection")] param() Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/directory/get-connection" $url = $baseUrl + $apiCall } Process{ $headers = New-MimecastHeader -Uri $apiCall #Create post body $postBody = @{data = @()} | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.data){ $response.data | ForEach-Object { $_.lastSync = [datetime]$_.lastSync $_ } } else{ Write-Error "$($response.fail.errors.message)" } } } <# .SYNOPSIS This function will get messages that are under moderatoin review to be rejected or released. .DESCRIPTION This function will get messages that are under moderatoin review to be rejected or released. This function is equivalent of going to Administration -> Message Center -> and selecting held reason category in the web UI. .PARAMETER reasonCode This parameter should return only messages that match the reasonCode supplied, however I think their API does not support this. .PARAMETER subject This parameter will return all held messages that have the subject field matching the string provided. .PARAMETER sender1 This parameter will return all held messages that have the sender field matching the string provided. The parameter uses sender1 since the variable sender is an automatic function and should not be used. .PARAMETER recipient This parameter will return all held messages that have the recipient field matching the string provided. .PARAMETER all This parameter will return all held messages that contain the provided string in any of the message's properties (subject, sender, recipeint, reasonCode). .PARAMETER admin This parameter determines the level of results to return. If false, only results for the currenlty authenticated user will be returned. If true, held messages for all recipients will be returned. The default value is false. The default value is True. .PARAMETER start This parameter will return all held messages that were receivied after the date and time provided. Use tab to launch the GUI to selecte a date and time. .PARAMETER end This parameter will return all held messages that were receivied before the date and time provided. Use tab to launch the GUI to selecte a date and time. .PARAMETER PageSize This parameter specifies how many held messages are return by each query. The default value is 50 and max value is 500. .EXAMPLE PS C:\> Get-mcHeldMessage -recipient syrius.cleveland From To subject route Held Reason HasAttachments DateReceived ---- -- ------- ----- ----------- -------------- ------------ Spiceworks Syrius Cleveland Need a new hobby for 2022? Check out ... INBOUND Agressive Spam Detection False 12/28/2021 7:57:50 PM This example gets all the held messages for receipient syrius.cleveland for the last 24 hours. .INPUTS None .OUTPUTS PSMimecast.HeldMessage .NOTES I do not believe the reasonCode parameter works, but I included since it is the documenation provided by Mimecast. #> function Get-MimecastHeldMessage { [cmdletbinding()] [Alias("Get-mcHeldMessage")] Param( [string]$reasonCode, [string]$subject, [Alias("Sender")] [string]$sender1, [string]$recipient, [string]$all, [bool]$admin = $true, [ArgumentCompleter({ param ($commandName,$parameterName,$wordToComplete,$commandAst,$fakeBoundParameters) Get-MimecastDateTime })] [string]$start = (Get-Date).AddDays(-1).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss+0000"), [ArgumentCompleter({ param ($commandName,$parameterName,$wordToComplete,$commandAst,$fakeBoundParameters) Get-MimecastDateTime })] [string]$end = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss+0000"), [ValidateRange(1,500)] [int]$PageSize = 50 ) Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/gateway/get-hold-message-list" $url = $baseUrl + $apiCall $searchBy = @{} $data = @{} $meta = @{ pagination = @{ pageSize = $PageSize } } $CommonParameters = [System.Management.Automation.Internal.CommonParameters].DeclaredProperties.Name $Parameters = $MyInvocation.MyCommand.Parameters.Keys | where {$_ -notin $CommonParameters} $SearchParam = @("all","subject","sender1","recipient","reason_code") $dataParam = @("admin","start","end") foreach ($param in $Parameters){ $value = (Get-Variable -Name $param).Value if (![String]::IsNullOrEmpty($value)){ if ($param -in $SearchParam){ $searchBy["fieldName"] = $param.TrimEnd('1') $searchBy["value"] = $value.ToString() } elseif ($param -in $dataParam){ $data[$param] = $value.ToString() } } } if ($searchBy.Keys -ne $null){ $data["searchBy"] = $searchBy } } #Begin Process{ $headers = New-MimecastHeader -Uri $apiCall #Create post body $postBody = @{ meta = $meta data = @($data) } | ConvertTo-Json -Depth 3 #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.fail){ Write-Error "$($response.fail.errors.message)" } else{ $message = $response.data foreach ($message in $response.data){ $message | Add-Member -Name ReleaseMessage -MemberType ScriptMethod -Value {New-HeldMessageReleaseAction -Id $this.Id} $message.dateReceived = [datetime]::Parse($message.dateReceived) $message | Add-Member -TypeName "PSMimecast.HeldMessage" $message } } } #Process } <# .SYNOPSIS This function will get the held message summary of all held messages broken up by Reason (or policy Info). .DESCRIPTION This function will get the held message summary of all held messages broken up by Reason (or policy Info). This function is equivalent of going to Administration -> Message Center in the web UI. .EXAMPLE PS C:\> Get-MimecastHeldMessageSummary policyInfo numberOfItems ---------- ------------- Agressive Spam Detection 7030 In this example we can see that there is 7,030 held messages under the Agressive Spam Detection policy and no held messages under any other policies. .INPUTS None .OUTPUTS PSCustomObject .NOTES No notes to add. #> function Get-MimecastHeldMessageSummary { [CmdletBinding()] [Alias("Get-mcHeldMessageSummary")] param() Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/gateway/get-hold-summary-list" $url = $baseUrl + $apiCall } Process{ $headers = New-MimecastHeader -Uri $apiCall #Create post body $postBody = @{data = @()} | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.data){ $response.data } else{ Write-Error "$($response.fail.errors.message)" } } } <# .SYNOPSIS This function will return the profile of a specified Mimecast user. .DESCRIPTION This function will return the profile of a specified Mimecast user. This function is equivalent to going to Administration -> Interal Directories -> <Domain> -> and selecting a user in the web UI. Some fields are missing like whether the account is locked or disabled, and Get-MimecastAccount should be used if these properties are needed. .PARAMETER EmailAddress This parameter specifies the email address of the user profile to return. .EXAMPLE PS C:\> Get-MimecastProfile -EmailAddress syrius.cleveland@example.com name : Syrius Cleveland emailAddress : syrius.cleveland@example.com links : {@{name=avatar; method=GET; uri=http://us-api.mimecast.com/... attributes : @{phoneNumber=} localPassword : True changePassword : True external : False editable : False role : Full Administrator companyName : Example Company serverTimeZone : America/New_York id : syrius.cleveland@example.com accountCode : XXXXXXX admin : True This example returns the profile of the user with the email address syrius.cleveland@example.com. .INPUTS string EmailAddress .OUTPUTS PSCustomObject .NOTES Some fields are missing like whether the account is locked or disabled, and Get-MimecastAccount should be used if these properties are needed. #> function Get-MimecastProfile { [cmdletbinding()] [Alias("Get-mcProfile")] Param( [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)] [string]$EmailAddress ) Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/user/get-profile" $url = $baseUrl + $apiCall } Process{ $headers = New-MimecastHeader -Uri $apiCall #Create post body $postBody = @{ data = @(@{ emailAddress = $emailAddress showAvatar = "False" }) } $postBody = $postBody | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.data){ $response.data } else{ Write-Error "$($response.fail.errors.message)" } } } function Get-MimecastRegion { [Alias("Get-mcRegion")] [CmdletBinding()] param() $Path = "$ENV:APPDATA\PSMimecast\Region.xml" if (Test-Path -Path $Path){ Import-Clixml -Path $Path } else{ throw "Region not set! Use New-MimecastAPIKeys or Set-MimecastRegion to set a region to use for API calls!" } } <# .SYNOPSIS This function will lock a Mimecast user account. .DESCRIPTION This function will lock a Mimecast user account. .PARAMETER EmailAddress This parameter specifies the emaill address of the account you want to lock. .EXAMPLE PS C:\> Lock-MimecastAccount -EmailAddress syrius.cleveland@example.com emailAddress : syrius.cleveland@example.com name : Syrius Cleveland forcePasswordChange : False passwordNeverExpires : False accountLocked : True accountDisabled : False allowSmtp : False allowPop : False This example locks the account with the email address syrius.cleveland@example.com. .INPUTS None .OUTPUTS PSCustomObject .NOTES This function uses the update-user API call to lock the user account. #> function Lock-MimecastAccount{ [cmdletbinding()] [Alias("Lock-mcAccount")] param( [Parameter(Mandatory)] $EmailAddress ) Begin{ $baseUrl = Get-mcBaseURL $uri = "/api/user/update-user" $url = $baseUrl + $uri } Process{ $headers = New-MimecastHeader -Uri $Uri $postBody = "{ ""data"": [ { ""accountLocked"": True, ""emailAddress"": ""$EmailAddress"" } ] }" #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the respons if ($response.data){ $response.data } else{ Write-Error "$($response.fail.errors.message)" } } } <# .SYNOPSIS This function is used to reject a currently held message. .DESCRIPTION This function is used to reject a currently held message. This function is equivalent to navigating to Administration -> Held Message -> Selecting a message and clicking the "reject" button in the web UI. .PARAMETER MessageId This parameter specifies the Id of the message that will be rejected. .PARAMETER message This parameter provides a message to be returned to the sender. .PARAMETER reasonType This parameter specifies the reason code for the message being rejected. Possible values are: MESSAGE CONTAINS UNDESIRABLE CONTENT, MESSAGE CONTAINS CONFIDENTIAL INFORMATION, REVIEWER DISAPPROVES OF CONTENT, INAPPROPRIATE COMMUNICATION, MESSAGE GOES AGAINST EMAIL POLICIES .PARAMETER notify This parameter indicates whether or not to Deliever a rejection notification to the sender. Default value is false. .EXAMPLE PS C:\> Get-MimecastHeldMessage -recipient syrius.cleveland | where policyinfo -eq "Agressive Spam Detection" | New-HeldMessageRejectAction -reasonType 'REVIEWER DISAPPROVES OF CONTENT' -nofify $true -message "Message was rejected due to spam." id reject -- ------ XXXXXXXXXXXXXXXXX.... True This example gets all held messages for syrius.cleveland and filters for only messages with the PolicyInfo equal to "Agressive Spam Detection". These held messages are then piped to New-HeldMessageRejectAction function to be rejected with a reason give and message for more information. An object is rertun to confirm this rejection was successful and provides the Id of the held message that was rejected. .INPUTS string MessageId .OUTPUTS PSCustomObject .NOTES You can provide an array of Ids to be rejected. #> function New-HeldMessageRejectAction{ [cmdletbinding()] [Alias("Invoke-mcRejectMessage")] Param( [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)] [Alias("Id")] [string[]]$MessageId, [string]$message, [ValidateSet("MESSAGE CONTAINS UNDESIRABLE CONTENT", "MESSAGE CONTAINS CONFIDENTIAL INFORMATION", "REVIEWER DISAPPROVES OF CONTENT", "INAPPROPRIATE COMMUNICATION", "MESSAGE GOES AGAINST EMAIL POLICIES")] [string]$reasonType, [bool]$nofify ) Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/gateway/hold-reject" $url = $baseUrl + $apiCall $SkipParamerters = @("MessageId") } Process{ $headers = New-MimecastHeader -Uri $apiCall $data = @{ids = $MessageId} $PSBoundParameters.Keys | where {$_ -notin $SkipParamerters} | foreach{ $data[$_] = $PSBoundParameters[$_] } $postBody = @{data = @($data)} | ConvertTo-Json -Depth 5 #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.fail){ Write-Error $response.fail.errors.message } else{ $response.data } } #Process } <# .SYNOPSIS This function can be used to release a currently held messages. .DESCRIPTION This function can be used to release a currently held messages. This function is equivalent to navigating to Administration -> Held Message -> Selecting a message and clicking the "release" button in the web UI. .PARAMETER MessageId This parameter specifies the Id of the message that will be released. .EXAMPLE PS C:\> Get-MimecastHeldMessage -recipient syrius.cleveland -start 2021-12-25T22:47:00+0000 | where {$_.from.displayableName -like "*example*"} | New-HeldMessageReleaseAction Id release -- ------- eNpVzF0Lgj7Y... True In tis example we get all held messages for syrius.cleveland strating 12/25/2021 and filter for only messages that came from example. These held messages are then piped to New-HeldMessageReleaseAction to be release. A return object confirms that the release was successful. .INPUTS string MessageId .OUTPUTS PSMimecast.ReleaseMessage .NOTES No notes to add. #> function New-HeldMessageReleaseAction{ [cmdletbinding()] [Alias("Invoke-mcReleaseMessage")] Param( [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)] [Alias("Id")] [string]$MessageId ) Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/gateway/hold-release" $url = $baseUrl + $apiCall } Process{ $headers = New-MimecastHeader -Uri $apiCall #Create post body $postBody = @{data = @(@{id = $MessageId})} | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.fail){ Write-Error $response.fail.errors.message } else{ $message = $response.data $message | Add-Member -TypeName "PSMimecast.ReleaseMessage" $message } } } <# .SYNOPSIS This function will create a new file (or overwrite an existing one) and store the API key that will used by other functions in this module to authenticate with the Mimecast API. .DESCRIPTION This function will create a new file (or overwrite an existing one) and store the API key that will used by other functions in this module to authenticate with the Mimecast API. .PARAMETER AppId This is the AppId string of the custome app integration you setup in the Mimecast web UI. .PARAMETER Credentials This parameter will use the credentials passed to it to authenticate with Mimecast. .PARAMETER AuthType This parameter specifies the authentication method to use with the provided credentials. If they are credentials to your AD account, then use "Basic-AD", otherwise setup a cloud password and use "Basic-Cloud". .EXAMPLE PS C:\> New-MimecastAPIKeys -AppId XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX -AuthType Basic-Cloud -Credentials (Get-Credential) This examples creates a new API key and stores it in file to be used by the rest of the module. Nothing is returned. .INPUTS None .OUTPUTS None .NOTES This function can be used to overwrite your existing API keys. You cannot use more than one API key with this module. #> function New-MimecastAPIKeys { [cmdletbinding()] Param( [Parameter(Mandatory)] $AppId, [Parameter(Mandatory)] [pscredential]$Credentials, [ValidateSet("Basic-Cloud","Basic-Ad")] $AuthType = "Basic-Cloud", [Parameter(Mandatory)] [ValidateSet("eu","de","us","ca","za","au","je")] [string]$Region ) Begin{ Set-MimecastRegion -Region $Region $baseUrl = Get-mcBaseURL $apiCall = "/api/login/login" $url = $baseUrl + $apiCall #Generate request header values $hdrDate = (Get-Date).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss UTC") $requestId = [guid]::NewGuid().guid } Process{ $EmailAddress = $Credentials.UserName $password = $Credentials.GetNetworkCredential().Password $headers = @{ "Authorization" = $authType + " " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($emailAddress + ":" + $password)); "x-mc-date" = $hdrDate; "x-mc-app-id" = $AppId; "x-mc-req-id" = $requestId; "Content-Type" = "application/json" } #Create post body $postBody = @{ data = @(@{ userName = $emailAddress }) } $postBody = $postBody | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.data.accesskey){ Set-MimecastAPIKeys -AccessKey $response.data.accesskey -SecretKey $response.data.secretKey -Email $EmailAddress -AuthType $AuthType } else{ Write-Error -Message "Unable to create keys: $($response.fail.errors.message)" } } #Process } <# .SYNOPSIS This function is used to initially setup the module by storing the appid and the appkey in an encrypted file to be used by other function. .DESCRIPTION This function is used to initially setup the module by storing the appid and the appkey in an encrypted file to be used by other function. The path to the file that is created is the following, "$ENV:APPDATA\PSMimecast\Keys.xml". You can find the values needed for the two paramters of this function by navigating to Administration -> Services -> API and Platform Integrations -> Your Application Integrations -> and selecting your app in the web UI. .PARAMETER AppId This parameter specifies the AppId of the custom app integration you created in the Mimecast portal. .PARAMETER AppKey This parameter specifies the AppKey of the custom app integration you created in the Mimecast portal. .EXAMPLE PS C:\> Set-MimecastAppInfo -AppId "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" -AppKey "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" This example sets the Mimecast App Info needed to use the rest of the functions in the module with redacted Id and Key. .INPUTS None .OUTPUTS None .NOTES You can find the values needed for the two paramters of this function by navigating to Administration -> Services -> API and Platform Integrations -> Your Application Integrations -> and selecting your app in the web UI. #> function Set-MimecastAppInfo { [cmdletbinding()] [Alias("Set-mcAppInfo")] Param( [Parameter(Mandatory)] [string]$AppId, [Parameter(Mandatory)] [string]$AppKey ) $Path = "$ENV:APPDATA\PSMimecast" if (!(Test-Path -Path $Path)){ New-Item -Path $Path -ItemType Directory -Force | Out-Null } $AppInfo = [PSCustomObject]@{ AppId = $AppId AppKey = (ConvertTo-SecureString $AppKey -AsPlainText -Force | ConvertFrom-SecureString) } $AppInfo | Export-Clixml -Path "$Path\AppInfo.xml" -Force } function Set-MimecastRegion { [Alias("Set-mcRegion")] [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateSet("eu","de","us","ca","za","au","je")] [string]$Region ) try{ $Path = "$ENV:APPDATA\PSMimecast" if (!(Test-Path -Path $Path)){ New-Item -Path $Path -ItemType Directory -Force | Out-Null } $RegionObject = @{ Region = $Region } $RegionObject | Export-Clixml -Path "$Path\Region.xml" -Force } catch{ $PSCmdlet.WriteError($_) } } <# .SYNOPSIS This function will initiate directory synchronization of all connected directories. .DESCRIPTION This function will initiate directory synchronization of all connected directories. This function is equivalent to navigating to Administration -> Services - Directory Synchronization -> and click "Sync Directory Data" in the web UI. .EXAMPLE PS C:\>Start-MimecastDirectorySync type syncStatus ---- ---------- ACTIVE_DIRECTORY started This example starts the directory synchronization process and the return object confirms that execution was successful. .INPUTS None .OUTPUTS PSCustomObject .NOTES This function may take some time to process, be patient when you call this function. #> function Start-MimecastDirectorySync{ [CmdletBinding()] [Alias("Start-mcDirectorySync")] param() Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/directory/execute-sync" $url = $baseUrl + $apiCall } Process{ $headers = New-MimecastHeader -Uri $apiCall #Create post body $postBody = @{data = @()} | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the respons if ($response.data){ $response.data } else{ Write-Error "$($response.fail.errors.message)" } } #Process } <# .SYNOPSIS This function unlocks a Mimecast account that is currently locked. .DESCRIPTION This function unlocks a Mimecast account that is currently locked. It does this by setting the property "accountLocked" to False. .PARAMETER EmailAddress This parameter specifies the email address of the Mimecast account you want to unlock. .EXAMPLE PS C:\> Unlock-MimecastAccount -EmailAddress syrius.cleveland@example.com emailAddress : syrius.cleveland@example.com name : Syrius Cleveland forcePasswordChange : False passwordNeverExpires : False accountLocked : False accountDisabled : False allowSmtp : False allowPop : False This example unlocks the Mimecast account with the email address of syrius.cleveland@example.com. The object of this account is returned and we can confirm the account is now unlocked by looking at the accountLocked property on this object. .INPUTS string EmailAddress .OUTPUTS PSCustomObject .NOTES General notes #> function Unlock-MimecastAccount{ [cmdletbinding()] [Alias("Unlock-mcAccount")] param( [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)] $EmailAddress ) Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/user/update-user" $url = $baseUrl + $apiCall } Process{ $headers = New-MimecastHeader -Uri $apiCall $postBody = @{ data = @(@{ accountLocked = "False" emailAddress = $EmailAddress }) } $postBody = $postBody | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.data){ $response.data } else{ Write-Error "$($response.fail.errors.message)" } } #Process } <# .SYNOPSIS This function will refresh an API keys access token if it has expired. .DESCRIPTION This function will refresh an API keys access token if it has expired. This function will automatically trigger if another function is called and the Mimecasat server returns a 418 error indicating the current access token has expired. .PARAMETER Password This parameter specifies the the password to use for the authentication process. It should be the same one initially used when creating the API keys. .EXAMPLE PS C:\> Update-MimecastExpiredAccessKey This example runs the command without the passowrd parameter. The user will be prompted to input a password since that parameter is mandatory. Once the password has been entered the function will try to create a new access token to use and store it in a secure file. .INPUTS None .OUTPUTS None .NOTES This function will automatically trigger if a function is called, but gets a 418 error indicating the current access token has expired. This re-authentication process was developed using the documenation in the link below. https://www.mimecast.com/developer/documentation/authentication-ui-apps/ #> function Update-MimecastExpiredAccessKey { param( [Parameter(Mandatory)] [SecureString]$Password ) Begin{ $baseUrl = Get-mcBaseURL $apiCall = "/api/login/login" $url = $baseUrl + $apiCall $Keys = Get-MimecastAPIKeys $Appinfo = Get-MimecastAppInfo $accessKey = $Keys.AccessKey $appId = $Appinfo.AppId $emailAddress = $keys.EmailAddress $authType = $Keys.AuthType } Process{ $hdrDate = (Get-Date).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss UTC") $requestId = [guid]::NewGuid().guid $cred = [pscredential]::new("Test",$Password) $pass = $cred.GetNetworkCredential().Password $headers = @{ "Authorization" = $authType + " " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($emailAddress + ":" + $pass)) "x-mc-date" = $hdrDate "x-mc-app-id" = $appId "x-mc-req-id" = $requestId "Content-Type" = "application/json" } #Create post body $postBody = @{ data = @(@{ userName = $emailAddress accessKey = $accessKey }) } $postBody = $postBody | ConvertTo-Json #Send Request $response = Invoke-MimecastAPI -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response if ($response.data){ $response.data } else{ Write-Error "$($response.fail.errors.message)" } } } function Get-mcBaseURL { [CmdletBinding()] param() try{ $region = (Get-MimecastRegion).Region return "https://$region-api.mimecast.com" } catch{ $PSCmdlet.WriteError($_) } } function Get-MimecastAPIKeys { $Path = "$ENV:APPDATA\PSMimecast\Keys.xml" if (Test-Path -Path $Path){ $SecretObject = Import-Clixml -Path $Path [PSCustomObject]@{ AccessKey = [pscredential]::new("API",(ConvertTo-SecureString -String $SecretObject.AccessKey)).GetNetworkCredential().Password SecretKey = [pscredential]::new("API",(ConvertTo-SecureString -String $SecretObject.SecretKey)).GetNetworkCredential().Password EmailAddress = $SecretObject.EmailAddress AuthType = $SecretObject.AuthType } } else{ Write-Error "Keys have not been set, use New-MimecastAPIKeys to set the keys" -ErrorAction Stop } } function Get-MimecastBaseURL { [cmdletbinding()] Param( $UserPrincipalName, $AppId ) Begin{ $baseUrl = "https://api.mimecast.com" $uri = "/api/login/discover-authentication" $url = $baseUrl + $uri } Process{ #Generate request header values $hdrDate = (Get-Date).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss UTC") $requestId = [guid]::NewGuid().guid #Create Headers $headers = @{ "x-mc-date" = $hdrDate; "x-mc-app-id" = $Appid; "x-mc-req-id" = $requestId; "Content-Type" = "application/json" } #Create post body $postBody = @{ data = @(@{ emailAddress = $UserPrincipalName }) } $postBody = $postBody | ConvertTo-Json #Send Request $response = Invoke-RestMethod -Method Post -Headers $headers -Body $postBody -Uri $url #Print the response $response } } function Invoke-MimecastAPI{ [cmdletbinding()] param( $Method, $Uri, $headers, $Body ) try{ Write-Information "Sending API Request to $uri" $response = Invoke-RestMethod @PSBoundParameters } catch [System.Net.WebException]{ Write-Information "A System.Net.WebException has occurred" if ($_.Exception.Message -like "*418*"){ Write-Warning "Your API Access has expired. Use Update-MimecastExpiredAccessKey to update your expired AccessKey" if ((Read-Host "Would you like to Update your API Access key (Y/N)?") -like "Y*"){ Update-MimecastExpiredAccessKey | Out-Null if ($?){ $response = Invoke-RestMethod @PSBoundParameters } } } elseif ($_.Exception.Message -like "*401*"){ $errorresponse = $_.ErrorDetails.message | ConvertFrom-Json $email = $errorresponse.fail.key.username $message = $errorresponse.fail.errors.message $ErrorRecord = [System.Management.Automation.ErrorRecord]::new( [System.Security.Authentication.InvalidCredentialException]::new($message), 'InvalidCredentialException', [System.Management.Automation.ErrorCategory]::AuthenticationError, ) throw $ErrorRecord } } catch{ Write-Information "An unknown error has occurred" $PSCmdlet.WriteError($_) } return $response } function New-MimecastHeader{ param( [string]$Uri ) $Keys = Get-MimecastAPIKeys $Appinfo = Get-MimecastAppInfo $accessKey = $Keys.AccessKey $secretKey = $Keys.SecretKey $appId = $Appinfo.AppId $appKey = $Appinfo.AppKey #Generate request header values $hdrDate = (Get-Date).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss UTC") $requestId = [guid]::NewGuid().guid #Create the HMAC SHA1 of the Base64 decoded secret key for the Authorization header $sha = New-Object System.Security.Cryptography.HMACSHA1 $sha.key = [Convert]::FromBase64String($secretKey) $sig = $sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($hdrDate + ":" + $requestId + ":" + $Uri + ":" + $appKey)) $sig = [Convert]::ToBase64String($sig) #Create Headers $headers = @{ "Authorization" = "MC $($accessKey): $sig" "x-mc-date" = $hdrDate "x-mc-app-id" = $appId "x-mc-req-id" = $requestId "Content-Type" = "application/json" } $headers } function Set-MimecastAPIKeys{ [cmdletbinding()] Param( [Parameter(Mandatory)] $AccessKey, [Parameter(Mandatory)] $SecretKey, $EmailAddress, $AuthType ) Begin{ $Path = "$ENV:APPDATA\PSMimecast" if (!(Test-Path -Path $Path)){ New-Item -Path $Path -ItemType Directory -Force | Out-Null } } #Begin Process{ $SecureAccessKey = ConvertTo-SecureString $AccessKey -AsPlainText -Force $SecureSecretKey = ConvertTo-SecureString $SecretKey -AsPlainText -Force $EncryptedAccessKey = ConvertFrom-SecureString -SecureString $SecureAccessKey $EncryptedSecureKey = ConvertFrom-SecureString -SecureString $SecureSecretKey $SecretObject = [PSCustomObject]@{ AccessKey = $EncryptedAccessKey SecretKey = $EncryptedSecureKey EmailAddress = $EmailAddress AuthType = $AuthType } $SecretObject | Export-Clixml -Path "$Path\Keys.xml" -Force } #Process } Export-ModuleMember -function Get-MimecastAccount, Get-MimecastAppInfo, Get-MimecastDateTime, Get-MimecastDirectoryConnection, Get-MimecastHeldMessage, Get-MimecastHeldMessageSummary, Get-MimecastProfile, Get-MimecastRegion, Lock-MimecastAccount, New-HeldMessageRejectAction, New-HeldMessageReleaseAction, New-MimecastAPIKeys, Set-MimecastAppInfo, Set-MimecastRegion, Start-MimecastDirectorySync, Unlock-MimecastAccount, Update-MimecastExpiredAccessKey |