Public/SEPPmailAPI-User.ps1

<#
.SYNOPSIS
    Retrieves a single SEPPmail user by email address.
 
.DESCRIPTION
    This cmdlet returns the full property set of one existing SEPPmail user,
    identified by the user's email address (REST path 'user/{email}').
 
    Optionally, usage statistics for the user can be included with the
    -statistics switch. Umlauts and special characters in the returned object
    are converted from the API's ISO-8859-1 representation back to native
    PowerShell strings.
 
.PARAMETER eMail
    The email address of the user to retrieve. Mandatory, case-insensitive and
    accepted from the pipeline (by value or by property name).
 
.PARAMETER statistics
    If set, the returned user object also contains usage statistics data.
 
.PARAMETER SMAHost
    SEPPmail API hostname. Defaults to the configured value.
 
.PARAMETER SMAPort
    SEPPmail API port. Defaults to the configured value.
 
.PARAMETER SMAVersion
    SEPPmail API version. Defaults to the configured value.
 
.PARAMETER SMACred
    API credentials (PSCredential). Defaults to the configured value.
 
.PARAMETER SMASkipCertCheck
    Skip SSL certificate validation. Use only in test environments.
 
.INPUTS
    System.String
        You can pipe an email address to this cmdlet.
 
.OUTPUTS
    System.Management.Automation.PSCustomObject
        Returns the user object with all its properties.
 
.NOTES
    - Requires an active SEPPmail API session (New-SMAConfiguration).
 
.LINK
    Find-SMAUser
 
.LINK
    New-SMAUser
 
.LINK
    Set-SMAUser
 
.LINK
    Remove-SMAUser
 
.EXAMPLE
    PS C:\> Get-SMAUser -eMail 'm.musterfrau@contoso.com'
 
    Returns the user object for the given email address.
 
.EXAMPLE
    PS C:\> Get-SMAUser -eMail 'm.musterfrau@contoso.com' -statistics
 
    Returns the user object including usage statistics.
 
.EXAMPLE
    PS C:\> 'm.musterfrau@contoso.com' | Get-SMAUser
 
    Retrieves the user via pipeline input.
 
.EXAMPLE
    PS C:\> Find-SMAUser -partialMatch 'contoso' | Get-SMAUser
 
    Finds users by a partial match and retrieves the full object for each match.
#>

function Get-SMAUser
{
    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        SupportsShouldProcess = $false,
        ConfirmImpact = 'Low'
    )]
    param (
        #region REST-API path and query parameters
        [Parameter(
            ParameterSetName = 'Default',
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            Position = 0, 
            HelpMessage = 'Email address'
        )]
        [ValidateNotNullOrEmpty()]
        [ValidatePattern('^\S+@\S+$')]
        [string]$email,

        [Parameter(
            ParameterSetName = 'Default',
            Mandatory = $false,
            HelpMessage = 'Include statistics data'
        )]
        [switch]$statistics,
        #endregion

        #region SMA host parameters
        [Parameter(
            Mandatory = $false
            )]
        [String]$SMAHost = $Script:activeCfg.SMAHost,

        [Parameter(
            Mandatory = $false
            )]
        [int]$SMAPort = $Script:activeCfg.SMAPort,

        [Parameter(
            Mandatory = $false
            )]
        [String]$SMAVersion = $Script:activeCfg.SMAPIVersion,

        [Parameter(
            Mandatory=$false
            )]
            [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred,

        [Parameter(
            Mandatory=$false
            )]
        [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck
        #endregion
    )

    begin {
        if (! (verifyVars -VarList $Script:requiredVarList))
        {
            Throw($missingVarsMessage);
        }
        $smaParams=@{
            Host=$SMAHost;
            Port=$SMAPort;
            Version=$SMAVersion;
        }
    }
    process {
        Write-Verbose "Creating URL path"
        $uriPath = "{0}/{1}" -f 'user', $eMail.ToLower()

        Write-Verbose "Building full request uri"
        if ($statistics) {
            $boundParam = @{
                statistics = $statistics
            }
        }
        $uri = New-SMAQueryString -uriPath $uriPath -qParam $boundParam @smaParams
        
        Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod"
        $invokeParam = @{
            Uri         = $uri 
            Method      = 'GET'
            Cred        =  $SMACred
            SkipCertCheck = $SMASkipCertCheck
        }

        Write-Verbose "Call Invoke-SMARestMethod $uri" 
        $UserRaw = Invoke-SMARestMethod @invokeParam

        Write-Verbose 'Filter data and return as PSObject'
        $GetUser = $UserRaw.Psobject.properties.value

        Write-Verbose 'Converting Umlauts from ISO-8859-1'
        $user = ConvertFrom-SMAPIFormat -inputObject $Getuser

        # Userobject
        if ($User) {
            return $User
        }
        else {
            Write-Information 'Nothing to return'
        }
    }
    end {}
}

<#
.SYNOPSIS
    Finds locally existing users by email address, name, uid or a partial match.
 
.DESCRIPTION
    This cmdlet lets you quickly find users in the SEPPmail database by various
    properties. It offers four mutually exclusive search variants (parameter sets):
 
    1. By name - use -name with a part of the user's display name.
    2. By uid - use -uid with an EXACT match of the uid.
    3. By email - use -email with an EXACT match of the email address.
    4. By partialMatch - use -partialMatch to match name, uid or email partially.
 
    Without a search parameter all users are returned. The result can be further
    narrowed down with -customer, -limit, -active, -activeWithinDays and
    -customerAssignment, which can be combined with any of the search variants.
 
.PARAMETER email
    Exact email address to search for (parameter set 'email').
 
.PARAMETER partialMatch
    A partial string matched against name, uid or email (parameter set 'partialMatch').
 
.PARAMETER name
    A part of the user's display name to search for (parameter set 'name').
 
.PARAMETER uid
    The exact uid of the user to search for (parameter set 'uid').
 
.PARAMETER customer
    For MSPs and multi-customer environments: limit the query to a specific customer.
 
.PARAMETER limit
    Limit the output to <n> objects. 0 (default) returns all matching users.
 
.PARAMETER active
    Limit the output to active ($true) or inactive ($false) users.
 
.PARAMETER activeWithinDays
    Limit the output to users who have sent emails within the given number of days (1-20000).
 
.PARAMETER customerAssignment
    Limit the output to users assigned to a customer either 'explicit'
    (deliberately assigned) or 'implicit' (e.g. the [default] customer).
 
.PARAMETER SMAHost
    SEPPmail API hostname. Defaults to the configured value.
 
.PARAMETER SMAPort
    SEPPmail API port. Defaults to the configured value.
 
.PARAMETER SMAVersion
    SEPPmail API version. Defaults to the configured value.
 
.PARAMETER SMACred
    API credentials (PSCredential). Defaults to the configured value.
 
.PARAMETER SMASkipCertCheck
    Skip SSL certificate validation. Use only in test environments.
 
.OUTPUTS
    System.Management.Automation.PSCustomObject
        Returns one or more user objects with their details.
 
.NOTES
    - Requires an active SEPPmail API session (New-SMAConfiguration).
 
.LINK
    Get-SMAUser
 
.LINK
    New-SMAUser
 
.LINK
    Set-SMAUser
 
.LINK
    Remove-SMAUser
 
.EXAMPLE
    PS C:\> Find-SMAUser
    Emits all users and their details.
 
.EXAMPLE
    PS C:\> Find-SMAUser -email 'john.doe@fabrikam.eu'
    Emits the specific user with this exact email address.
 
.EXAMPLE
    PS C:\> Find-SMAUser -name 'john'
    Emits all users with 'john' in their display name.
 
.EXAMPLE
    PS C:\> Find-SMAUser -partialMatch 'fabrikam'
    Emits all users with 'fabrikam' in either name, uid or email.
 
.EXAMPLE
    PS C:\> Find-SMAUser -partialMatch 'Doe'
    Emits all users with 'Doe' in either name, uid or email,
    i.e. name 'John Doe' with email 'john@fabrikam.eu'.
 
.EXAMPLE
    PS C:\> Find-SMAUser -uid 'john'
    Emits the specific user with the exact uid 'john'.
 
.EXAMPLE
    PS C:\> Find-SMAUser -customer 'Contoso'
    Emits all users of a particular customer.
 
.EXAMPLE
    PS C:\> Find-SMAUser -limit 5
    Emits all users but stops output at 5 objects.
 
.EXAMPLE
    PS C:\> Find-SMAUser -active:$false
    Emits only inactive users.
 
.EXAMPLE
    PS C:\> Find-SMAUser -activeWithinDays 14
    Emits only users which have sent emails within the last 14 days.
 
.EXAMPLE
    PS C:\> Find-SMAUser -partialMatch 'tailspintoys.com' -activeWithinDays 14 -customer 'tailspintoys' -limit 50
    Use a combination of parameters to pre-filter the output as much as possible.
 
.EXAMPLE
    PS C:\> Find-SMAUser -customerAssignment implicit
    Shows users which are assigned to a customer - mostly the [default] customer -
    implicitly, so with no deliberate action.
 
.EXAMPLE
    PS C:\> Find-SMAUser -customerAssignment explicit
    Shows users which are explicitly assigned to a customer - a created, managed customer account.
#>

function Find-SMAUser
{
    [CmdletBinding(DefaultParameterSetName = 'Default')]
    [OutputType([PSCustomObject[]])]

    param (
        #region Define the 4 parametersets and the uniqe params in it
        # -list is hardcoded to $false as its used in the Find-SMAUSer cmdlet
        [Parameter(
            ParameterSetName = 'email',
            Mandatory        = $true,
            Position         = 0,
            HelpMessage      = 'Find users by their e-Mail address'
            )]
        [string]$email,

        [Parameter(
            ParameterSetName = 'partialMatch',
            Mandatory        = $true,
            Position         = 0,
            HelpMessage      = 'Find users by a partial match of their e-Mail address'
            )]
        [string]$partialMatch = ' ',

        [Parameter(
            ParameterSetName = 'name',
            Mandatory        = $true,
            Position         = 0,
            HelpMessage      = 'Find users by their display name (parts of the name allowed)'
            )]
        [string]$name,

        [Parameter(
            ParameterSetName = 'uid',
            Mandatory        = $true,
            Position         = 0,
            HelpMessage      = 'Find users by their exact uid' 
            )]
        [string]$uid,
        #endregion

        #region common API params for all parametersets
        [Parameter(
            Mandatory   = $false,
            HelpMessage = 'For MSP´s and multi-customer environments, limit query for a specific customer'
            )]
        [Parameter(ParameterSetName = 'default')]
        [Parameter(ParameterSetName = 'partialMatch')]
        [Parameter(ParameterSetName = 'name')]
        [Parameter(ParameterSetName = 'uid')]
        [Parameter(ParameterSetName = 'email')]
        [string]$customer,

        [Parameter(
            Mandatory   = $false,
            HelpMessage = 'limit output to <n> objects' 
            )]
        [Parameter(ParameterSetName = 'default')]
        [Parameter(ParameterSetName = 'partialMatch')]
        [Parameter(ParameterSetName = 'name')]
        [Parameter(ParameterSetName = 'uid')]
        [Parameter(ParameterSetName = 'email')]
        [ValidateRange(0, [int]::MaxValue)]
        [int]$limit = 0,

        [Parameter(
            Mandatory   = $false,
            HelpMessage = 'limit output to active or inactive objects' 
            )]
        [Parameter(ParameterSetName = 'default')]
        [Parameter(ParameterSetName = 'partialMatch')]
        [Parameter(ParameterSetName = 'name')]
        [Parameter(ParameterSetName = 'uid')]
        [Parameter(ParameterSetName = 'email')]
        [bool]$active,

        [Parameter(
            Mandatory   = $false,
            HelpMessage = 'limit output to users which have sent e-mails within a certain timeframe (days)'
            )]
        [Parameter(ParameterSetName = 'default')]
        [Parameter(ParameterSetName = 'partialMatch')]
        [Parameter(ParameterSetName = 'name')]
        [Parameter(ParameterSetName = 'uid')]
        [Parameter(ParameterSetName = 'email')]
        [ValidateRange(1, 20000)] 
        [int]$activeWithinDays,

        [Parameter(
            Mandatory   = $false,
            HelpMessage = 'limit output to users who have been explicite or implicit assigned to a customer'
            )]
        [Parameter(ParameterSetName = 'default')]
        [Parameter(ParameterSetName = 'partialMatch')]
        [Parameter(ParameterSetName = 'name')]
        [Parameter(ParameterSetName = 'uid')]
        [Parameter(ParameterSetName = 'email')]
        [ValidateSet('explicit','implicit')]
        [string]$customerAssignment,

        #endregion

        #region SMAParameters
        [Parameter(Mandatory = $false)]
        [String]$SMAHost = $Script:activeCfg.SMAHost,

        [Parameter(Mandatory = $false)]
        [int]$SMAPort = $Script:activeCfg.SMAPort,

        [Parameter(Mandatory = $false)]
        [String]$SMAVersion = $Script:activeCfg.SMAPIVersion,

        [Parameter(Mandatory=$false)]
        [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred,

        [Parameter(Mandatory=$false)]
        [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck
        #endregion SMAParameters
    )

    begin {
        if (! (verifyVars -VarList $Script:requiredVarList))
        {
            Throw($missingVarsMessage);
        }
        $smaParams=@{
            Host=$SMAHost;
            Port=$SMAPort;
            Version=$SMAVersion;
        }
    }
    process {
        Write-Verbose "Building full request uri including all bound parameters"
        $boundParam = @{
                   'list' = $true
                  'limit' = $limit
        }
                # Now check if any of the parameters was set by the commandline and set their values for the querystring

        # Dynamisch BoundParameters hinzufügen
        $apiParams = @('name', 
                       'email',
                       'partialMatch',
                       'uid',
                       'customer',
                       'active', 
                       'activeWithinDays',
                       'customerAssignment'
                       )        
        foreach ($param in $apiParams) {
            if ($PSBoundParameters.ContainsKey($param)) {
                $boundParam[$param] = $PSBoundParameters[$param]
            }
        }
        $uri = New-SMAQueryString -uriPath 'user' -qParam $boundParam @smaParams;
        Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod"
        $invokeParam = @{
            Uri         = $uri 
            Method      = 'GET'
            Cred        =  $SMACred
            SkipCertCheck = $SMASkipCertCheck
        }
        Write-Verbose "Call Invoke-SMARestMethod $uri" 
        $UserRaw = Invoke-SMARestMethod @invokeParam
        Write-Verbose 'Filter data and return as PSObject'
        Write-Verbose 'Converting Umlauts from ISO-8859-1 and DateTime correctly'
        $user = foreach ($u in $userRaw) {ConvertFrom-SMAPIFormat -inputobject $u}
        if ($User) {
                Write-Verbose "Returning $($User.Count) user(s)"
                return $User
        }
        else {
                Write-Verbose 'No users found matching the criteria'
                # Optional: Return empty array statt $null
                return @()
        }
    }
    end {}
}

<#
.SYNOPSIS
    Creates a new SEPPmail user.
 
.DESCRIPTION
    This cmdlet creates a new SEPPmail user with the specified properties.
     
    Three mandatory parameters are required: uid, email, and name.
     
    The uid (User ID) can be identical to the email address or a unique GUID.
    Additional optional properties can be set during user creation, including
    passwords, customer assignment, encryption/signing permissions, and more.
 
.PARAMETER uid
    Unique identifier for the user. Can be:
    - The email address (e.g., 'm.musterfrau@contoso.com')
    - A GUID (e.g., '245b8741-4724-4434-8343-bc26c9a10586')
     
    This parameter is mandatory.
 
.PARAMETER eMail
    The user's email address. This parameter is mandatory and case-insensitive.
 
.PARAMETER name
    The user's full display name (e.g., "Maria Musterfrau").
    This parameter is mandatory.
 
.PARAMETER password
    Initial password for the user as SecureString.
    If omitted, the user will need to set a password on first login.
     
    Example: 'MyPassword123!' | ConvertTo-SecureString -AsPlainText -Force
 
.PARAMETER customer
    **CASE-SENSITIVE** Customer assignment for MSP/multi-customer environments.
    Use '[default]' or '[none]' for special assignments.
     
    Default: Empty (unassigned)
 
.PARAMETER mayNotEncrypt
    If $true, disables encryption functionality for this user.
     
    Default: $false (encryption enabled)
 
.PARAMETER mayNotSign
    If $true, disables signing functionality for this user.
     
    Default: $false (signing enabled)
 
.PARAMETER locked
    If $true, creates the user account in locked state.
    Locked users cannot send or receive encrypted emails.
     
    Default: $false (unlocked)
 
.PARAMETER notifications
    Email notification settings for the user.
    Valid values: 'never', 'always', 'domain default'
     
    Default: 'domain default'
 
.PARAMETER mpkiSubjectPart
    User-specific static subject part for MPKI certificates.
    Example: 'OU=Sales,O=Contoso'
 
.PARAMETER memberOf
    SEPPmail group membership. Array of group names.
    Example: @('Marketing', 'Sales')
 
.PARAMETER mailAccountUID
    POP/IMAP account user ID (typically an email address).
    Used for external mail account integration.
 
.PARAMETER mailAccountPassword
    POP/IMAP account password as SecureString.
    Example: 'password123' | ConvertTo-SecureString -AsPlainText -Force
 
.PARAMETER mailAccountHost
    POP/IMAP mail server hostname (e.g., 'mail.contoso.com').
 
.PARAMETER mailAccountSSL
    Enable ($true) or disable ($false) SSL/TLS for POP/IMAP connection.
     
    Default: $false
 
.PARAMETER mustChangePassword
    If $true, forces the user to change their password on next login.
     
    Default: $false
 
.PARAMETER mfaExemption
    If $true, exempts this user from Multi-Factor Authentication requirements.
     
    Default: $false
 
.PARAMETER mfaSecret
    MFA secret string for TOTP configuration.
    Used for pre-configuring MFA for the user.
 
.PARAMETER SMAHost
    SEPPmail API hostname. Defaults to configured value.
 
.PARAMETER SMAPort
    SEPPmail API port. Defaults to configured value.
 
.PARAMETER SMAVersion
    SEPPmail API version. Defaults to configured value.
 
.PARAMETER SMACred
    API credentials (PSCredential). Defaults to configured value.
 
.PARAMETER SMASkipCertCheck
    Skip SSL certificate validation. Use only in test environments.
 
.INPUTS
    System.String, System.Security.SecureString
        You can pipe user properties to this cmdlet via property names.
 
.OUTPUTS
    System.String
        Returns the email address of the newly created user.
 
.NOTES
    - Requires an active SEPPmail API session (New-SMAConfiguration)
    - Supports -WhatIf and -Confirm parameters
    - uid and email can be identical or different (uid can be a GUID)
    - Use SecureString for sensitive parameters (password, mailAccountPassword)
    - Groups must exist before assigning users to them
    - Customer assignment is case-sensitive
 
.LINK
    https://github.com/seppmail/SEPPmailAPI/blob/main/docs/New-SMAUser.md
 
.LINK
    Get-SMAUser
 
.LINK
    Set-SMAUser
 
.LINK
    Remove-SMAUser
 
.LINK
    Find-SMAUser
 
.EXAMPLE
    PS C:\> New-SMAUser -uid 'm.musterfrau@contoso.com' -email 'm.musterfrau@contoso.com' -name 'Maria Musterfrau'
     
    Creates a basic user with uid identical to email address.
    User will need to set password on first login.
 
.EXAMPLE
    PS C:\> $uid = (New-Guid).Guid
    PS C:\> New-SMAUser -uid $uid -email 'm.musterfrau@contoso.com' -name 'Maria Musterfrau'
     
    Creates a user with a GUID as uid instead of using the email address.
    Useful for scenarios where email addresses might change.
 
.EXAMPLE
    PS C:\> $password = 'P@ssw0rd123!' | ConvertTo-SecureString -AsPlainText -Force
    PS C:\> New-SMAUser -uid 'm.musterfrau@contoso.com' -email 'm.musterfrau@contoso.com' `
            -name 'Maria Musterfrau' -password $password
     
    Creates a user with an initial password set.
 
.EXAMPLE
    PS C:\> $userInfo = @{
        uid = '245b8741-4724-4434-8343-bc26c9a10586'
        email = 'm.musterfrau@contoso.com'
        name = 'Maria Musterfrau'
        locked = $false
        mayNotEncrypt = $false
        mayNotSign = $false
        password = ('aBc1$6tgR' | ConvertTo-SecureString -AsPlainText -Force)
        customer = 'Contoso'
        notifications = 'never'
        mpkiSubjectPart = 'OU=Sales,O=Contoso'
        memberOf = @('Marketing', 'Sales')
    }
    PS C:\> New-SMAUser @userInfo
     
    Comprehensive example using parameter splatting to create a user with multiple properties.
 
.EXAMPLE
    PS C:\> New-SMAUser -uid 'john.doe@fabrikam.com' -email 'john.doe@fabrikam.com' `
            -name 'John Doe' -customer 'Fabrikam' -mustChangePassword $true
     
    Creates a user assigned to 'Fabrikam' customer who must change password on first login.
 
.EXAMPLE
    PS C:\> $mailPassword = 'ExternalMailPwd123!' | ConvertTo-SecureString -AsPlainText -Force
    PS C:\> New-SMAUser -uid 'alice@contoso.com' -email 'alice@contoso.com' -name 'Alice Smith' `
            -mailAccountUID 'alice@external.com' -mailAccountPassword $mailPassword `
            -mailAccountHost 'mail.external.com' -mailAccountSSL $true
     
    Creates a user with external POP/IMAP account integration.
 
.EXAMPLE
    PS C:\> New-SMAUser -uid 'bob@contoso.com' -email 'bob@contoso.com' -name 'Bob Brown' `
            -mayNotEncrypt $true -mayNotSign $true
     
    Creates a user without encryption and signing capabilities.
 
.EXAMPLE
    PS C:\> New-SMAUser -uid 'eve@contoso.com' -email 'eve@contoso.com' -name 'Eve Johnson' `
            -notifications 'always' -memberOf @('IT', 'Admins')
     
    Creates a user with email notifications enabled and membership in multiple groups.
 
.EXAMPLE
    PS C:\> New-SMAUser -uid 'test@contoso.com' -email 'test@contoso.com' -name 'Test User' `
            -locked $true
     
    Creates a locked user account (useful for pre-provisioning).
 
.EXAMPLE
    PS C:\> $users = Import-Csv 'users.csv'
    PS C:\> foreach ($user in $users) {
        New-SMAUser -uid $user.email -email $user.email -name $user.name -customer $user.customer
    }
     
    Bulk user creation from CSV file.
    CSV format: email,name,customer
 
.EXAMPLE
    PS C:\> New-SMAUser -uid 'admin@contoso.com' -email 'admin@contoso.com' `
            -name 'Admin User' -mfaExemption $false -WhatIf
     
    Preview user creation without actually creating the user using -WhatIf.
#>

function New-SMAUser
{
    [CmdletBinding(SupportsShouldProcess)]
    param (
        #region REST-API Parameters
        [Parameter(
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Unique ID, mostly the e-Mail address'
            )]
        [string]$uid,

        [Parameter(
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'User E-Mail address'
            )]
        [string]$eMail,

        [Parameter(
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'The users full name'
            )]
        [string]$name,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'You may set the password for the user or leave it blank. API default is blank'
            )]
        [SecureString]$password,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = '!!CASE_SENSITIVE!! For MSP´s, multi-customer and cloud environments, set the users customer, API default is blank'
            )]
        [string]$customer,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Disable the encrypt functionality for the user, API default is $false'
            )]
        [boolean]$mayNotEncrypt,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Disable the sign functionality for the user, API default is $false'
            )]
        [boolean]$mayNotSign,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Lock this user, API default is $false'
            )]
        [boolean]$locked,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Define if and how the user gets notified, API standard is domain default'
            )]
            [ValidateSet('never','always','domain default')]
        [string]$notifications,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Userspecific static subject part'
            )]
        [string]$mpkiSubjectPart,

        #MemberOF Setting will be removes #:TODO
        #[Parameter(
        # Mandatory = $false,
        # ValueFromPipelineByPropertyName = $true,
        # HelpMessage = 'SEPPmail group membership'
        # )]
        #[string[]]$memberOf,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account userID (e-mail address)'
            )]
        [string]$mailAccountUID,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account password as securestring'
            )]
        [secureString]$mailAccountPassword,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account host'
            )]
        [string]$mailAccountHost,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account host uses SSL'
            )]
        [boolean]$mailAccountSSL,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Require password change at net login'
            )]
        [boolean]$mustChangePassword,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Disable MFA requirement'
            )]
        [boolean]$mfaExemption,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'MFA secret string'
            )]
        [securestring]$mfaSecret,
        #endregion

        #region SMAparams
        [Parameter(Mandatory = $false)]
        [String]$SMAHost = $Script:activeCfg.SMAHost,

        [Parameter(Mandatory = $false)]
        [int]$SMAPort = $Script:activeCfg.SMAPort,

        [Parameter(Mandatory = $false)]
        [String]$SMAVersion = $Script:activeCfg.SMAPIVersion,

        [Parameter(Mandatory=$false)]
        [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred,

        [Parameter(Mandatory=$false)]
        [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck
        #endregion
    )

    begin {
        if (! (verifyVars -VarList $Script:requiredVarList))
        {
            Throw($missingVarsMessage);
        }; # end if

        try {
            Write-Verbose "Building full request uri"
            $smaParams=@{
                Host=$SMAHost;
                Port=$SMAPort;
                Version=$SMAVersion;
            }; # end smaParams

            $uri = New-SMAQueryString -uriPath 'user' @smaParams;
        }
        catch {
            Write-Error "Error $error.CategoryInfo occured"
        }
    }

    process {

        Write-Verbose 'Crafting empty $body JSON'
        $bodyHt = @{}
        Write-Verbose 'Adding parameter values to $body JSON'
        $apiParams = @( 'uid', 
                        'name',
                        'email',
                        'customer',
                        'locked',
                        'mayNotEncrypt',
                        'mayNotSign',
                        'notifications',
                        'password',
                        'mpkiSubjectPart',
                        #'memberOf',
                        'mailAccountUID',
                        'mailAccountPassword',
                        'mailAccountHost',
                        'mailAccountSSL',
                        'mustChangePassword',
                        'mfaExemption',         
                        'mfaSecret'
                       )
        foreach ($param in $apiParams) {
            if ($PSBoundParameters.ContainsKey($param)) {
                $bodyHt[$param] = $PSBoundParameters[$param]
            }
        }
        Write-Verbose "Transforming Securestrings to plaintext for API consumption"
        if ($bodyHt.password) {$bodyHt.password = ConvertFrom-SecureString -SecureString $bodyHt.password -AsPlainText}
        if ($bodyHt.mailAccountPassword) {$bodyHt.mailAccountPassword = ConvertFrom-SecureString -SecureString $bodyHt.mailAccountPassword -AsPlainText}
        if ($bodyHt.mfaSecret) {$bodyHt.mfaSecret = ConvertFrom-SecureString -SecureString $bodyHt.mfaSecret -AsPlainText}
        $body = $bodyHt|ConvertTo-JSON
        Write-verbose "Crafting InvokeParam for Invoke-SMARestMethod"
        $invokeParam = @{
                Uri         = $uri 
                Method      = 'POST'
                body        = $body
                Cred        =  $SMACred
                SkipCertCheck = $SMASkipCertCheck
        }
        if ($PSCmdLet.ShouldProcess($($bodyht.Email),"Create user")) {
            Write-Verbose "Call Invoke-SMARestMethod $uri"
            $UserRaw = Invoke-SMARestMethod @invokeParam
            #debug $userraw
            Write-Verbose 'Returning e-Mail address of new users'
            ($userraw.message -split ' ')[3]
        }

    }
    end {}
}

<#
.SYNOPSIS
    Modifies properties of an existing SEPPmail user.
 
.DESCRIPTION
    This cmdlet allows you to modify an existing SEPPmail user's properties.
    You must specify the user's email address to identify the user.
     
    Changes are applied immediately via the SEPPmail API.
    At least one property (besides email) must be specified for the update.
 
.PARAMETER eMail
    The email address of the user to modify. This parameter is mandatory and case-insensitive.
 
.PARAMETER name
    The full display name of the user (e.g., "Martha Musterfrau").
 
.PARAMETER customer
    **CASE-SENSITIVE** Customer assignment for MSP/multi-customer environments.
    Use '[default]' or '[none]' for special assignments.
     
    Note: Changing the customer may require re-authentication.
 
.PARAMETER locked
    Lock ($true) or unlock ($false) the user account.
    Locked users cannot send or receive encrypted emails.
 
.PARAMETER mayNotEncrypt
    Disable ($true) or enable ($false) encryption functionality for this user.
 
.PARAMETER mayNotSign
    Disable ($true) or enable ($false) signing functionality for this user.
 
.PARAMETER mustChangePassword
    Force the user to change their password on next login.
 
.PARAMETER notifications
    Email notification settings for the user.
    Valid values: 'never', 'always', 'domain default'
 
.PARAMETER mpkiSubjectPart
    User-specific static subject part for MPKI certificates.
 
.PARAMETER memberOf
    SEPPmail group membership. Array of group names.
 
.PARAMETER mailAccountUID
    POP/IMAP account user ID (typically an email address).
 
.PARAMETER mailAccountPassword
    POP/IMAP account password as SecureString.
    Example: 'password123' | ConvertTo-SecureString -AsPlainText -Force
 
.PARAMETER mailAccountHost
    POP/IMAP mail server hostname (e.g., 'mail.contoso.com').
 
.PARAMETER mailAccountSSL
    Enable ($true) or disable ($false) SSL/TLS for POP/IMAP connection.
 
.PARAMETER mfaExemption
    Exempt ($true) this user from Multi-Factor Authentication requirements.
 
.PARAMETER mfaSecret
    MFA secret string as SecureString for TOTP configuration.
 
.PARAMETER SMAHost
    SEPPmail API hostname. Defaults to configured value.
 
.PARAMETER SMAPort
    SEPPmail API port. Defaults to configured value.
 
.PARAMETER SMAVersion
    SEPPmail API version. Defaults to configured value.
 
.PARAMETER SMACred
    API credentials (PSCredential). Defaults to configured value.
 
.PARAMETER SMASkipCertCheck
    Skip SSL certificate validation. Use only in test environments.
 
.INPUTS
    System.String
        You can pipe email addresses to this cmdlet.
 
.OUTPUTS
    System.String
        Returns the email address of the modified user.
 
.NOTES
    - Requires an active SEPPmail API session (New-SMAConfiguration)
    - Supports -WhatIf and -Confirm parameters
    - Changing the customer may cause "user not found" errors (known API issue)
    - Use SecureString for sensitive parameters (passwords, MFA secrets)
 
.LINK
    https://github.com/seppmail/SEPPmailAPI/blob/main/docs/Set-SMAUser.md
 
.LINK
    Get-SMAUser
 
.LINK
    New-SMAUser
 
.LINK
    Remove-SMAUser
 
.EXAMPLE
    PS C:\> Set-SMAUser -eMail 'm.musterfrau@contoso.com' -name 'Martha Musterfrau'
     
    Changes the display name of the specified user.
 
.EXAMPLE
    PS C:\> Set-SMAUser -eMail 'm.musterfrau@contoso.com' -locked $true
     
    Locks the user account, preventing login and email processing.
 
.EXAMPLE
    PS C:\> Set-SMAUser -eMail 'm.musterfrau@contoso.com' -customer 'Contoso' -notifications 'always'
     
    Assigns the user to the 'Contoso' customer and enables email notifications.
 
.EXAMPLE
    PS C:\> $securePass = 'aBc1$6tgR' | ConvertTo-SecureString -AsPlainText -Force
    PS C:\> Set-SMAUser -eMail 'm.musterfrau@contoso.com' -mailAccountPassword $securePass
     
    Updates the POP/IMAP password using a SecureString.
 
.EXAMPLE
    PS C:\> $userInfo = @{
        eMail = 'm.musterfrau@contoso.com'
        name = 'Marie Musterfrau'
        locked = $false
        mayNotEncrypt = $false
        mayNotSign = $false
        customer = 'Contoso'
        notifications = 'never'
        mpkiSubjectPart = 'OU=Sales'
        memberOf = @('Marketing', 'Sales')
        mailAccountUID = 'm.musterfrau'
        mailAccountPassword = ('aBc1$6tgR' | ConvertTo-SecureString -AsPlainText -Force)
        mailAccountHost = 'mail.contoso.com'
        mailAccountSSL = $true
        mustChangePassword = $true
    }
    PS C:\> Set-SMAUser @userInfo
     
    Comprehensive example using parameter splatting to update multiple properties.
 
.EXAMPLE
    PS C:\> Get-SMAUser -email 'm.musterfrau@contoso.com' | Set-SMAUser -locked $false
     
    Pipeline example: Unlock a user account.
 
.EXAMPLE
    PS C:\> 'alice@contoso.com', 'bob@contoso.com' | Set-SMAUser -notifications 'always'
     
    Bulk update: Enable notifications for multiple users via pipeline.
 
.EXAMPLE
    PS C:\> Set-SMAUser -eMail 'm.musterfrau@contoso.com' -memberOf @('Group1', 'Group2') -WhatIf
     
    Preview changes without applying them using -WhatIf.
 
.EXAMPLE
    PS C:\> Set-SMAUser -eMail 'm.musterfrau@contoso.com' -mfaExemption $true
     
    Exempt a user from Multi-Factor Authentication requirements.
#>

function Set-SMAUser #TODO: Wait for resolved issue user not found when changing the customer
{
    [CmdletBinding(
        SupportsShouldProcess = $true,
        Confirmimpact = 'Medium'
        )]
    [OutputType([string])]

    param (
        #region API parameters
        [Parameter(
            Mandatory                       = $true,
            Position                        = 0,
            ValueFromPipeline               = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'User E-Mail address'
            )]
        [ValidateNotNullOrEmpty()]
        [ValidatePattern('^\S+@\S+$')]
        [string]$eMail,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'The users full name'
            )]
        [string]$name,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = '!!CASE_SENSITIVE!! For MSP´s, multi-customer and cloud environments, set the users customer, API default is blank'
            )]
        [SMAParamFilter('StringBool')]
        [ValidatePattern('^[a-zA-Z0-9\-_]+$|^\[(default|none)\]$')]
        [string]$customer,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Disable the encrypt functionality for the user, API default is $false'
            )]
        [boolean]$mayNotEncrypt,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Disable the sign functionality for the user, API default is $false'
            )]
        [boolean]$mayNotSign,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Trigger a password change on next logon'
            )]
        [boolean]$mustChangePassword,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Lock this user, API default is $false'
            )]
        [boolean]$locked,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Define if and how the user gets notified, API standard is domain default'
            )]
        [ValidateSet('never','always','domain default')]
        [string]$notifications,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Userspecific static subject part'
            )]
        [string]$mpkiSubjectPart,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'SEPPmail group membership'
            )]
        [string[]]$memberOf,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account userID (e-mail address)'
            )]
        [string]$mailAccountUID,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account password as securestring'
            )]
        [secureString]$mailAccountPassword,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account host'
            )]
        [string]$mailAccountHost,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'POP (IMAP) account host uses SSL'
            )]
        [boolean]$mailAccountSSL,    

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'Disable MFA requirement'
            )]
        [boolean]$mfaExemption,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'MFA secret string'
            )]
        [SecureString]$mfaSecret,

        #endregion

        #region SMAParams
        [Parameter(Mandatory = $false)]
        [String]$SMAHost = $Script:activeCfg.SMAHost,

        [Parameter(Mandatory = $false)]
        [int]$SMAPort = $Script:activeCfg.SMAPort,

        [Parameter(Mandatory = $false)]
        [String]$SMAVersion = $Script:activeCfg.SMAPIVersion,

        [Parameter(Mandatory=$false)]
        [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred,

        [Parameter(Mandatory=$false)]
        [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck 
        #endregion
    )
    begin {
        if (! (verifyVars -VarList $Script:requiredVarList))
        {
            Throw($missingVarsMessage);
        }
        
        $smaParams=@{
            Host=$SMAHost;
            Port=$SMAPort;
            Version=$SMAVersion;
        }
    }
    process {
        Write-Verbose "Creating URL path"
        $uriPath = "{0}/{1}" -f 'user', $eMail.ToLower()
        Write-Verbose "Building full request uri"
        $boundParam = @{
        }
        $uri = New-SMAQueryString -uriPath $uriPath -qParam $boundParam @smaParams;

        Write-Verbose 'Crafting mandatory $body JSON'
        $bodyHt = @{}

        Write-Verbose 'Adding parameter values to $body JSON'
        $apiParams = @( 'name',
                        'customer',
                        'locked',
                        'mayNotEncrypt',
                        'mayNotSign',
                        'mpkiSubjectPart',
                        'notifications',
                        'mustChangePassword',
                        'memberOf',
                        'mailAccountUID',
                        'mailAccountPassword',
                        'mailAccountHost',
                        'mailAccountSSL',
                        'mfaExemption',         
                        'mfaSecret'
                       )
        foreach ($param in $apiParams) {
            if ($PSBoundParameters.ContainsKey($param)) {
                $bodyHt[$param] = $PSBoundParameters[$param]
            }
        }
        Write-Verbose "Transforming Securestrings to plaintext for API consumption"
        if ($bodyHt.mailAccountPassword) {$bodyHt.mailAccountPassword = ConvertFrom-SecureString -SecureString $bodyHt.mailAccountPassword -AsPlainText}
        if ($bodyHt.mfaSecret) {$bodyHt.mfaSecret = ConvertFrom-SecureString -SecureString $bodyHt.mfaSecret -AsPlainText}
       
        $body = $bodyHt | ConvertTo-JSON
        if ($bodyHt.Count -eq 0) {
           Write-Warning "No parameters specified for update. User '$eMail' remains unchanged."
           return
        }
        Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod"
        $invokeParam = @{
            Uri           = $uri 
            Method        = 'PUT'
            body          = $body
            Cred          = $SMACred
            SkipCertCheck = $SMASkipCertCheck
        }
        if ($PSCmdLet.ShouldProcess($($bodyHt.Email),"Change user")) {
            Write-Verbose "Call Invoke-SMARestMethod $uri" 
            $UserRaw = Invoke-SMARestMethod @invokeParam
            Write-Verbose 'Returning e-Mail addresses of updated user'
            return ($userRaw.message -split ' ')[3]
        }
    }
    end {}
}

<#
.SYNOPSIS
    Removes a SEPPmail user from the system.
 
.DESCRIPTION
    This cmdlet deletes a SEPPmail user identified by their email address.
     
    By default, the user account is removed but can be recovered. Use the -purge
    parameter for permanent deletion.
     
    Certificates and private keys are deleted by default. Use -keepKeys to preserve
    them for potential future use if the user is recreated.
 
.PARAMETER eMail
    The email address of the user to remove. This parameter is mandatory and
    case-insensitive.
 
.PARAMETER keepKeys
    If specified, certificates and private keys will NOT be deleted.
     
    This is useful when you plan to recreate the user later with the same email
    address, as the keys will be automatically re-attached.
 
.PARAMETER purge
    If specified, the user is PERMANENTLY deleted from the database.
     
    WARNING: This action is irreversible. The user and all associated data
    will be lost forever and cannot be recovered.
 
.PARAMETER SMAHost
    SEPPmail API hostname. Defaults to configured value from New-SMAConfiguration.
 
.PARAMETER SMAPort
    SEPPmail API port. Defaults to configured value from New-SMAConfiguration.
 
.PARAMETER SMAVersion
    SEPPmail API version. Defaults to configured value from New-SMAConfiguration.
 
.PARAMETER SMACred
    API credentials (PSCredential). Defaults to configured credentials.
 
.PARAMETER SMASkipCertCheck
    Skip SSL certificate validation. Use only in test environments.
 
.INPUTS
    System.String
        You can pipe email addresses to this cmdlet.
 
.OUTPUTS
    System.String
        Returns the email address of the removed user.
 
.NOTES
    - Requires an active SEPPmail API session (New-SMAConfiguration)
    - Supports -WhatIf and -Confirm parameters for safety
    - Default behavior: User removed but recoverable, keys deleted
    - Use -keepKeys to preserve certificates for user recreation
    - Use -purge for permanent, irreversible deletion
     
    Warning: The -purge parameter permanently deletes all user data!
 
.LINK
    https://github.com/seppmail/SEPPmailAPI/blob/main/docs/Remove-SMAUser.md
 
.LINK
    Get-SMAUser
 
.LINK
    New-SMAUser
 
.LINK
    Set-SMAUser
 
.EXAMPLE
    PS C:\> Remove-SMAUser -email 'm.musterfrau@contoso.com'
     
    Removes the user and deletes all associated certificates and keys.
    The user can potentially be recovered through database restore.
 
.EXAMPLE
    PS C:\> Remove-SMAUser -email 'm.musterfrau@contoso.com' -keepKeys
     
    Removes the user but preserves their certificates and private keys.
    If you recreate the user with the same email, the keys will be automatically
    re-attached.
 
.EXAMPLE
    PS C:\> Remove-SMAUser -email 'm.musterfrau@contoso.com' -purge
     
    PERMANENTLY deletes the user from the database.
    This action is irreversible - all user data is lost forever.
 
.EXAMPLE
    PS C:\> Remove-SMAUser -email 'm.musterfrau@contoso.com' -WhatIf
     
    Preview what would happen without actually removing the user.
    Safe way to verify the operation before execution.
 
.EXAMPLE
    PS C:\> Remove-SMAUser -email 'm.musterfrau@contoso.com' -Confirm:$false
     
    Remove the user without prompting for confirmation.
    Use with caution in automated scripts.
 
.EXAMPLE
    PS C:\> 'alice@contoso.com', 'bob@contoso.com' | Remove-SMAUser -keepKeys
     
    Bulk removal: Remove multiple users via pipeline while preserving their keys.
 
.EXAMPLE
    PS C:\> Get-SMAUser -email 'inactive@contoso.com' | Remove-SMAUser
     
    Pipeline example: First verify the user exists, then remove it.
 
.EXAMPLE
    PS C:\> $users = Find-SMAUser -active $false -activeWithinDays 365
    PS C:\> $users | Where-Object { $_.email -like '*@oldcontoso.com' } |
            Remove-SMAUser -keepKeys -WhatIf
     
    Complex example: Find inactive users from a specific domain,
    preview their removal while keeping keys.
 
.EXAMPLE
    PS C:\> Remove-SMAUser -email 'testuser@contoso.com' -purge -Confirm
     
    Permanent deletion with explicit confirmation prompt.
    Best practice when using -purge parameter.
#>

function Remove-SMAUser
{
    [CmdletBinding(SupportsShouldProcess)]
    param (

        #region API Parameters
        [Parameter(
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromPipeline               = $true,
            Position                        = 0,
            HelpMessage                     = 'User E-Mail address'
            )]
        [string]$eMail,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'If true, certificates and private keys will not be deleted'
            )]
        [switch]$keepKeys,

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'If true, the user is REALLY deleted from the database and is LOST forever'
            )]
        [switch]$purge,
        #endregion

        #region SMA Parameters
        [Parameter(Mandatory = $false)]
        [String]$SMAHost = $Script:activeCfg.SMAHost,

        [Parameter(Mandatory = $false)]
        [int]$SMAPort = $Script:activeCfg.SMAPort,

        [Parameter(Mandatory = $false)]
        [String]$SMAVersion = $Script:activeCfg.SMAPIVersion,

        [Parameter(Mandatory=$false)]
        [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred,

        [Parameter(Mandatory=$false)]
        [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck
        #endregion

    )
    begin {
        if (! (verifyVars -VarList $Script:requiredVarList))
        {
            Throw($missingVarsMessage);
        }
        
        $smaParams=@{
            Host=$SMAHost;
            Port=$SMAPort;
            Version=$SMAVersion;
        }
    }
    process {
        Write-Verbose "Creating URL path"
        $uriPath = "{0}/{1}" -f 'user', $eMail

        Write-Verbose "Preparing full request uri"
        $boundParam = @{ }
        if ($keepKeys) {$boundParam.keepKeys = $keepKeys}
           if ($purge) {$boundParam.purge = $purge}

        $uri = New-SMAQueryString -uriPath $uriPath -qParam $boundParam @smaParams;

        Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod"
        $invokeParam = @{
            Uri           = $uri 
            Method        = 'DELETE'
            Cred          = $SMACred
            SkipCertCheck = $SMASkipCertCheck
            }
        
        if ($PSCmdLet.ShouldProcess($email,"Remove User")) {
            Write-Verbose "Call Invoke-SMARestMethod $uri"
            $UserRaw = Invoke-SMARestMethod @invokeParam
            Write-Verbose 'Returning e-Mail addresses of removed user'
            ($userRaw.message -split ' ')[3]
        }
    }
    end {}
}

# SIG # Begin signature block
# MIIVyAYJKoZIhvcNAQcCoIIVuTCCFbUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCB8DMwJjxc0EOO
# h0PHyd2rU3i8FZP/3TiJqrlsfBIqEKCCEgQwggVvMIIEV6ADAgECAhBI/JO0YFWU
# jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
# dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG
# EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv
# IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s
# hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD
# J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7
# P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme
# me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz
# T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q
# RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz
# mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc
# QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T
# OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/
# AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID
# AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD
# VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV
# HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE
# VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v
# ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE
# KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI
# hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF
# OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC
# J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ
# pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl
# d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH
# +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M
# UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD
# VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv
# ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5
# NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp
# BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G
# CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI
# ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV
# DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3
# 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw
# mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm
# +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe
# dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4
# 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM
# dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY
# MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU
# pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV
# HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG
# A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1
# YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG
# AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl
# U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0
# aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh
# w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd
# OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj
# cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc
# WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO
# hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs
# zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7
# 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J
# KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH
# j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2
# Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/
# L9Uo2bC5a4CH2RwwggZvMIIE16ADAgECAhBIqMP3CCLHOHtOKuaWNyeFMA0GCSqG
# SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0
# ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw
# HhcNMjYwNDE1MDAwMDAwWhcNMjcwNzE0MjM1OTU5WjBmMQswCQYDVQQGEwJERTEP
# MA0GA1UECAwGQmF5ZXJuMSIwIAYDVQQKDBlTRVBQbWFpbCBEZXV0c2NobGFuZCBH
# bWJIMSIwIAYDVQQDDBlTRVBQbWFpbCBEZXV0c2NobGFuZCBHbWJIMIICIjANBgkq
# hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvAFzE8MbJpvQt+IdIh1M+bKYsJBFDk4b
# 9ySe25IrCi00B9o5XmQtIw42MqyIKbUq1tDARtp9KTQedEP9W+rflAF2l+0Z046J
# kiqumU9/enbqWLDyln1aS/p7HOgwZFMhnsR9zH0MfFckiklUmkzJO+vmzYAK7ZmD
# xajNLJs0gkGRU2/BecAx/TSvLXMaKONsKZCyMKQCnwo1mCY/tFl5EgUz7YQFrPOR
# BQGfQke/hkdBfQDqNRsi/J6+KhJWc6LvgQihdRg/INQbQsTxlow18NWvyFsjjueH
# 7kG6HR4YKfbv07xgrsIh8xvq9ZJ1SBhLXmkg4SdoQGASjqR6o3keAX+bDRFf+hml
# WWJp/FqVHR5QomF3vbK2/bbz4jAclYSPx/sPasNJ0YnKFkgmowZ7Ysa0KA0/egBg
# tI4gJ+8V7zrqIVEG3rMQh9KCdMnJqP2aM9o4gUzQvE1M4x606liX9EWwdLLS+fe7
# 9o+Fzo5oH4wBE/En6hQQkzseHHu+TXCDd6zUUZ/PlTK0gTaDIRXt6UzPNqJ4RiRC
# W2pNFcPt078qqVTuwKUXoE4ufxGgXKFrZlCYST/9eG1TnW2oq19nz8A333GCsL3g
# poNIKvfmDyGMMNzvx2aeqn2v6e75z8kH19iGSNZ51xT+WgS9F1aIvjz08/T7XAv7
# iDPF1/gPIp8CAwEAAaOCAakwggGlMB8GA1UdIwQYMBaAFA8qyyCHKLjsb0iuK1Sm
# KaoXpM0MMB0GA1UdDgQWBBS30/Tq+alF3j2BY5up8n5zpAU23DAOBgNVHQ8BAf8E
# BAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzBKBgNVHSAE
# QzBBMDUGDCsGAQQBsjEBAgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3Rp
# Z28uY29tL0NQUzAIBgZngQwBBAEwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2Ny
# bC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcmww
# eQYIKwYBBQUHAQEEbTBrMEQGCCsGAQUFBzAChjhodHRwOi8vY3J0LnNlY3RpZ28u
# Y29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNydDAjBggrBgEFBQcw
# AYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wHgYDVR0RBBcwFYETc3VwcG9ydEBz
# ZXBwbWFpbC5jaDANBgkqhkiG9w0BAQwFAAOCAYEAi7fmb5UYoemWG3CC4K2UZWVr
# R6GOfi8gbJKgjPbKO4zrCrU/x6cOdyp6scKZfUEGFDf8KH6pP4pAQv1Hsbi49gU2
# kxoUWLlCiipn05qJY663DHx9hlStej/ZdEatou0wyCDiG5xD7kmG+1t6iLyyCBgE
# B88tJpzTjI61qXmBTS/FGEOAsB4SDEW1ngA7bc5FOv4IUKA43hp8M+N3GeYFzDqw
# JELYEfVVYheBW3o7q4VrCdfFEuaQihOtvfDfYpP6ANgekNn8HdsMT8rx9D1I50Rl
# i/qQFo2BOuPyb2SIQPzJvCs5wgi5qgp1nHiN6igumu2Cz7BmGjOazGUgCSUY5Qwy
# E8+F+R2tVM+2O15rfX01+e56ZfojBEiEjMwfPHs3fa3V3gokWWNwUMkton/v0R/n
# l2zjmOr2okohOINZEDh9frg21zUCN5ZD8Y4zQWuiJLCvvvBZs0JR4c9xl2k2wtw/
# QLPhGU69zM3smGpRoLE8M6zvUvSU7jXjvefazUniMYIDGjCCAxYCAQEwaDBUMQsw
# CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJT
# ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2AhBIqMP3CCLHOHtOKuaW
# NyeFMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAw
# GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG
# AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIP28Ru7eweSO6dFizCmkx2i2iY+p8z9g
# Zq3sUV7S0PSLMA0GCSqGSIb3DQEBAQUABIICAJkY53EDiY/1zvJMvsAPJ/8KOhc0
# madoIGSFsbhoYXrkxXiLxsrcuoIYp6v1f3kk9OOiZ90r3UYgz5SNAoACj/BDbf83
# e5xiC/9osid3GVJsP3ZG/z6PpjKLlfxE3DRngyPo5R8I0WgKRfTyPGKRBh8a00b3
# 3l3fg7/WlVsUbX5jS01DCy4WjcrfsCeUkLN9BuWp3BhFx0mOQ4+v8Ykquet9MtQh
# fJ2MHKBHxO0fNJuAVoZNdDr4DKXl2LTdMiIV0WvRkpJKU0yZ+O3tpzkNELQwhVn1
# u7nikq/761M9ilrtEEsbnB5PhURPRl66qgKuRzWxu44gH8mYI+dThBIPoSC3Jy+U
# 4C/tC5Z6f1m9RBRio3P6I6ooj4jH0+PQ6SsuT9Czy+KBbPqItjHiCge85xq/LVed
# P9r01mXDa3k0/Ner0ABhphn9bFjJG67WXLyfIkSaFjs+56TBImQeknRm+5ohrvUw
# DXj5FTw/5wSvPf+SCwPh3wo0nesqP+NwsCh2t8l2694vzQKYHH8ZZ6KIvFU6VISN
# g5RdrTC7Hcgq/cpXoeJESKX6oHZGlindwhoL0I2fUtRMXTqRvex00gjcs2G53oii
# uEA61qvFr7R0+4DIe9YYtI1YPZ09LxKu1hsIXcwNzcDAXPSyRg2JzlHu+4PWlygk
# wGTzu0vy2xI1vcgv
# SIG # End signature block