> ## Documentation Index
> Fetch the complete documentation index at: https://docs.serval.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Exchange (on-prem)

> Connect on-premises Microsoft Exchange to Serval to automate mailboxes, distribution groups, and other Exchange administration through remote PowerShell.

<Note>
  This integration is available by request during preview. Contact your Serval team to enable it for testing.
</Note>

## About Exchange (on-prem)

The Exchange (on-prem) integration connects Serval to an on-premises Microsoft Exchange server - Exchange 2016, Exchange 2019, or Exchange Subscription Edition - using remote PowerShell (PSRP over WinRM) against the server's `/PowerShell` virtual directory (for example, `https://mail.corp.example.com/PowerShell`). It is a **separate integration** from [Exchange Online](/sections/integrations/exchange-online), which targets Microsoft 365 tenants: connecting one does not grant the other.

**Authentication:** an approved Active Directory account (username and password) with Exchange management roles. The connection supports Negotiate (the default), NTLM, and Basic authentication. Kerberos is not supported yet, so the `/PowerShell` virtual directory must accept NTLM (or Basic over HTTPS).

**Worker requirements:** an on-prem Exchange server lives on your private network, so this integration requires a **hybrid (self-hosted) Serval worker** with network reach to the server. Serval's cloud workers cannot reach a private-network target.

**Data sync:** On-demand only. There is no background sync, entity ingestion, or scheduled polling - each action opens a fresh remote PowerShell session against your server, runs, and disconnects.

<Note>
  Operations run as **structured cmdlet pipelines, not free-form scripts**. The Exchange remote PowerShell endpoint is a NoLanguage constrained runspace - it only accepts Exchange cmdlet invocations, so arbitrary PowerShell script text (variables, loops, expressions) is rejected by the server itself.
</Note>

## Set up the account

<Steps>
  <Step title="Choose an approved account">
    Choose an Active Directory identity your organization approves for automation. A dedicated service account is optional; a named account can also authenticate. Grant only the management roles your workflows need.
  </Step>

  <Step title="Assign Exchange management roles">
    Add the account to the Exchange role group(s) that cover the operations your workflows need - **Recipient Management** covers common mailbox and distribution-group administration. Use the Exchange admin center (**Permissions → Admin roles**) or the Exchange Management Shell:

    ```powershell theme={null}
    Add-RoleGroupMember -Identity "Recipient Management" -Member "svc-serval"
    ```

    The account must also have remote PowerShell access enabled. Verify `RemotePowerShellEnabled` with `Get-User -Identity "svc-serval" | Format-List RemotePowerShellEnabled`.
  </Step>

  <Step title="Verify remote PowerShell access">
    From a domain-joined machine, confirm the account can open a session against the endpoint before involving Serval:

    ```powershell theme={null}
    $cred = Get-Credential   # enter the approved account credentials
    New-PSSession -ConfigurationName Microsoft.Exchange `
      -ConnectionUri https://mail.corp.example.com/PowerShell `
      -Authentication Negotiate -Credential $cred
    ```

    If this fails, fix the account, roles, or endpoint configuration first. A successful Windows Negotiate connection can use Kerberos, so it does not prove that the NTLM-only Linux worker can authenticate. Run the Serval connection healthchecks from the intended worker as well.
  </Step>
</Steps>

## Connect in Serval

<Steps>
  <Step title="Open the Exchange (on-prem) connect form">
    In Serval, open the Exchange (on-prem) integration and start a new connection.
  </Step>

  <Step title="Enter the server and credentials">
    * **Server URI** (required) - the URL of your Exchange server's PowerShell virtual directory, e.g. `https://mail.corp.example.com/PowerShell`. Must be an `http://` or `https://` URL.
    * **Username** (required) - the approved account, as `CORP\svc-serval` or `svc-serval@corp.example.com`.
    * **Password** (required) - the account's password.
  </Step>

  <Step title="Choose an Authentication Method">
    * **Negotiate (NTLM)** - the default; negotiates the strongest mechanism the worker offers, which is NTLM today.
    * **NTLM** - force NTLM explicitly.
    * **Basic (requires HTTPS)** - sends credentials directly; Serval refuses Basic over plain `http://` because the credentials would travel unencrypted.
  </Step>

  <Step title="Name the connection (optional)">
    **Instance Name (Optional)** - a friendly name for this connection. If left blank, the connection is named after the server's host name.
  </Step>
</Steps>

<Note>
  **Skip TLS certificate verification** is available for servers with self-signed certificates. It weakens transport security - prefer mounting a PEM CA bundle and setting `REQUESTS_CA_BUNDLE` in the worker environment while leaving verification on.
</Note>

The connection healthchecks query `Get-Recipient`, `Get-Mailbox`, and `Get-DistributionGroup` with a one-item limit. The account needs these read cmdlets in its role assignments; the connection check does not require organization configuration permissions.

## SecureString parameters

Commands such as `New-RemoteMailbox` require a PowerShell `SecureString` for their password parameter. Use `microsoft.powershell.exchangeOnPrem.secureString(value)` as the parameter value in a structured pipeline. The runner negotiates a PSRP session key and encrypts this value in the protocol's SecureString format.

The wrapper selects a wire type; it does not make workflow inputs secret or prevent them from being persisted. Do not put passwords directly in workflow source or assume this wrapper redacts them from workflow history. Use your approved workflow secret-handling mechanism. The password for a new AD user is separate from the credentials used to connect to Exchange.

## Operation results

Typed actions fail when Exchange reports an error, including non-terminating PowerShell errors. The raw pipeline action returns `errors` and `hadErrors`; check both before using its output. Runner output is limited to 32 MiB; narrow large queries or select fewer properties. A timeout or an error does not roll back changes already applied on the Exchange server. Check the current state before retrying a write.

`getDistributionGroup` reads group metadata without enumerating members. Use `getDistributionGroupMembers` when you need the membership list.

Group writes normally require the account to be listed in the group's `ManagedBy` owners. For an approved non-owner administrator, set `bypassSecurityGroupManagerCheck: true` on the update, delete, add-member, or remove-member action. Exchange still requires the **Security Group Creation and Membership** role and the applicable recipient scope; this option does not bypass RBAC.

Group notes (including the `description` alias) are updated through `Set-Group`. When you also update mail settings, the helper issues separate commands; they are not atomic.

## Gotchas and troubleshooting

<AccordionGroup>
  <Accordion title="401 Unauthorized when connecting">
    The server rejected the credentials or the account lacks remote PowerShell access. Verify the username and password, confirm the account has the required Exchange roles and `RemotePowerShellEnabled` is enabled, and check that the chosen authentication method is enabled on the PowerShell virtual directory in IIS. Kerberos-only endpoints are not supported. Confirm an approved authentication method with your Exchange administrator before configuring this integration.
  </Accordion>

  <Accordion title="Connection refused or timeout">
    The worker can't reach the server. The hybrid worker needs network egress to the Exchange server's host and port - check firewalls and routing, and make sure the worker's Kubernetes NetworkPolicy allows egress to your private CIDR ranges (cluster policies often allow only public internet egress by default).
  </Accordion>

  <Accordion title="TLS certificate errors">
    The Exchange server presents a certificate the worker doesn't trust - typically a self-signed or internal-CA certificate. Mount a PEM CA bundle in the worker and set `REQUESTS_CA_BUNDLE` to its path, or enable **Skip TLS certificate verification** on the connection if you accept the weaker transport security.
  </Accordion>

  <Accordion title="Arbitrary PowerShell script is rejected">
    The Exchange remote endpoint is a NoLanguage constrained runspace: it accepts Exchange cmdlet invocations with parameters, but no script syntax (variables, loops, expressions). Serval sends operations as structured cmdlet pipelines for this reason - compose multiple cmdlets rather than writing a script.
  </Accordion>

  <Accordion title="Exchange (on-prem) and Exchange Online are separate integrations">
    This integration targets your on-premises servers over PSRP/WinRM; [Exchange Online](/sections/integrations/exchange-online) targets Microsoft 365 with an Entra app registration. In hybrid organizations, on-prem-synced recipients must be changed on-prem - cloud writes to synced objects fail.
  </Accordion>
</AccordionGroup>

***

Need help? Contact **[support@serval.com](mailto:support@serval.com)** for assistance with your Exchange (on-prem) integration.
