# Managing Email Masks

**Email Masks** can be provisioned for different configured domains to provide more options to your users.

To provision an Email Mask, first check if it is valid and available. Once the address is chosen and confirmed, it can be used to provision the Email Mask.

### Get Email Mask Domains

Before checking for the availability of an address for an Email Mask for your user, a valid mask domain is needed. The Sudo Platform Email Service can be configured to support multiple domains for this purpose.

{% hint style="info" %}
Each project in your Sudo Platform account can be configured to support a set of email domains. Your solutions engineer can assist you in configuring DNS entries for domains you own or you can have the Sudo Platform do that on your behalf.
{% endhint %}

A call to the `getEmailMaskDomains` method provides a list of domains that are available for provisioning Email Masks.

{% tabs %}
{% tab title="TypeScript" %}

```typescript
try {
    const maskDomains = await emailClient.getEmailMaskDomains()
    // `maskDomains` contains an array of supported domains to be used for provisioning Email Masks
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
do {
    let maskDomains = try await client.getEmailMaskDomains()
    // `maskDomains` contains alist of domains available for provisioning Email Masks
catch {
    /// Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
launch {
    try {
        val maskDomains = withContext(Dispatchers.IO) {
            emailClient.getEmailMaskDomains()
        }
        // [maskDomains] contains a list of configured domains for provisioning Email Masks.
    } catch (e: EmailAddressException) {
        // Handle/notify user of exception
    }
 }
```

{% endtab %}
{% endtabs %}

### Check Email Mask Availability

In order to ensure your users can choose a unique, available, address for their Email Mask, you can use the same `checkEmailAddressAvailability` method as you would for a regular Sudo Platform email address. More information on that method can be found [here](https://docs.sudoplatform.com/guides/email/manage-email-addresses#check-email-address-availability).

### Provision Email Mask

Once your user has the address they would like to use for their Email Mask, it can be provisioned. The `provisionEmailMask` method will return the newly provisioned Email Mask object.

An `ownershipProofToken` is required as part of the input. This ties together the Sudo and Email Mask such that the Sudo becomes the owner of the Mask. Use the `getOwnershipProof` method on the `SudoProfilesClient` in the **Sudo** **Profiles SDK** in order to obtain an `ownershipProofToken`. See the [Sudo](https://docs.sudoplatform.com/guides/sudos) section for more information.

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const maskAddress: string = // The email address to use for the Mask, checked via the checkEmailAddressAvailability method
const ownershipProofToken: string = // Found via the get ownership proof API (See "Sudos" section)
const realAddress: string = // The real email address that the Mask will forward to
try {
    const emailMask = await emailClient.provisionEmailMask({
        maskAddress,
        realAddress,
        ownershipProofToken,
    })
} catch (e) {
    // Handle/notify user of errors 
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
let maskAddress: String = /// The email address to use for the Mask, checked via the checkEmailAddressAvailability method
let ownershipProofToken: String = /// Found via the get ownership proof API (See "Sudos" section)
let realAddress: String = /// The real email address that the Mask will forward to
do {
    let provisionEmailMaskInput = ProvisionEmailMaskInput(
        maskAddress: maskAddress,
        ownershipProofToken: ownershipProofToken,
        realAddress: realAddress
    )
    let emailMask = try await emailClient.provisionEmailMask(
        withInput: provisionEmailMaskInput
    )
    /// `emailMask` contains the newly provisioned Email Mask
} catch {
    /// Handle/notify user of error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val maskAddress: String = /// The email address to use for the Mask, checked via the checkEmailAddressAvailability method
val ownershipProofToken: String = /// Found via the get ownership proof API (See "Sudos" section)
val realAddress: String = /// The real email address that the Mask will forward to
launch {
    try {
        val input = ProvisionEmailMaskInput(
            maskAddress = maskAddress,
            ownershipProofToken = ownershipProofToken,
            realAddress = realAddress,
        )
        val emailMask = withContext(Dispatchers.IO) {
            emailClient.provisionEmailMask(input)
        }
        // The returned [emailMask] has been provisioned
    } catch (e: EmailAddressException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

#### Real Address Ownership

The `realAddress` property of the input must be the exact `local-part@domain` email address that the mask should forward to. For Sudo Platform Email Addresses, the address must be owned by the same user trying to provision the Mask.

If, however, you decide to enable the option to allow your users to set up Masks for external email addresses, then the Mask that gets provisioned will initially have its `state` set to `PENDING`. While in this state, it cannot receive messages. In order to change the `state` to `ENABLED`, the user must verify ownership of their external email address. See [verifying-external-email-addresses](https://docs.sudoplatform.com/guides/email/email-masks/verifying-external-email-addresses "mention").

#### Entitlements <a href="#entitlements" id="entitlements"></a>

In order to be able to provision an Email Mask, the user must be entitled. The following entitlement checks are performed:

1. The user is entitled to provision Email Masks by the `sudoplatform.email.emailMaskUserEntitled` entitlement.
2. The user against which the new email address is to be provisioned has at least 1 remaining `sudoplatform.email.emailMaskMaxPerUser` entitlement to consume.

If these entitlements' checks do not succeed, the `provisionEmailMask` API fails with an insufficient entitlements error.

{% hint style="info" %}
See [Email Entitlements](https://docs.sudoplatform.com/guides/email/email-entitlements) for an overview of how the Email service integrates with the Sudo Platform Entitlements system.
{% endhint %}

#### Optional Parameters

The `provisionEmailMask` method's input object can take up to two additional optional parameters:

1. `expiresAt` - If set, the mask will automatically be deprovisioned at the given date.
2. `metadata` - This is a string to string map that can be used to store information about the Email Mask such as the purpose of it. The data in this property gets encrypted with the user's default key pair before being sent to the server, and decrypted upon retrieval.

Both of these optional properties can be updated, or deleted via the `updateEmailMask` method.

### Deprovision Email Mask

An Email Mask can be deprovisioned using the `deprovisionEmailMask` method by passing in the `id` of an existing Email Mask object.

{% hint style="warning" %}
By deprovisioning an Email Mask, the user will no longer receive messages sent to that Mask, and a bounce will be returned to anyone sending messages to it.
{% endhint %}

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const emailMaskId: string = emailMask.id // Collect the Email Mask however makes sense for your application
try {
    const deprovisionedEmailMask = await emailClient.deprovisionEmailMask({
        emailMaskId: emailMaskId
    })
} catch (e) {
    // Handle/notify user of errors 
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
/// Collect the input email mask id however makes sense for your implementation.
let emailMaskId = emailMask.id
do {
    let deprovisionEmailMaskInput = DeprovisionEmailMaskInput(
        emailMaskId: emailMaskId
    )
    let deprovisionedEmailMask = try await emailClient.deprovisionEmailMask(
        withInput: deprovisionEmailMaskInput
    )
    /// `deprovisionedEmailMask` is the record that was just deprovisioned.
} catch {
    /// Handle/notify user of error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
/// Collect the input email mask id however makes sense for your implementation.
val emailMaskId = emailMask.id
launch {
    try {
        val input = DeprovisionEmailMaskInput(
            emailMaskId = emailMaskId
        )
        val emailMask = withContext(Dispatchers.IO) {
            emailClient.deprovisionEmailMask(input)
        }
        // The returned [emailMask] has been deprovisioned
    } catch (e: EmailAddressException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

### Updating an Email Mask

An existing email mask can have a subset of its data updated by the user by calling the `updateEmailMask` method. The properties that can be updated are outlined in the table below.

<table><thead><tr><th width="105.00390625">Property</th><th width="339.94921875">To ignore</th><th>To delete</th></tr></thead><tbody><tr><td>expiresAt</td><td>TypeScript: <code>undefined</code> (or exclude from object)<br>Swift: <code>nil</code><br>Kotlin: <code>null</code></td><td>Typescript: <code>null</code><br>Swift: <code>Date(timeIntervalSince1970: 0)</code><br>Kotlin: <code>Date(0)</code></td></tr><tr><td>metadata</td><td>TypeScript: <code>undefined</code> (or exclude from object)<br>Swift: <code>nil</code><br>Kotlin: <code>null</code></td><td>Typescript: <code>null</code><br>Swift: <code>[:]</code><br>Kotlin: <code>emptyMap()</code></td></tr></tbody></table>

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const emailMaskId: string = emailMask.id // Collect the Email Mask however makes sense for your application
try {
    const metadata = { prop1: 'abc', prop2: 123 }
    const expiresAt = new Date() // Construct the expiry date however makes sense
    let updatedMask = await emailClient.updateEmailMask({
        emailMaskId: emailMaskId,
        metadata: metadata,
        expiresAt: expiresAt,
    })
    // The Email Mask now has the updated properties
    
    updatedMask = await emailClient.updateEmailMask({
        emailMaskId: emailMaskId,
        metadata: null,
        expiresAt: null,
    })
    // The Email Mask no longer has the `metadata` or `expiresAt` set
} catch (e) {
    // Handle/notify user of errors 
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Collect the input email mask id however makes sense for your implementation.
let emailMaskId = emailMask.id
do {
    let metadata = [ "prop1": "abc", "prop2": String(123) ]
    let expiresAt = Date() /// Construct the expiry date however makes sense
    var input = UpdateEmailMaskInput(
        emailMaskId: emailMaskId,
        metadata: metadata,
        expiresAt: expiresAt
    )
    var updatedMask = try await emailClient.updateEmailMask(withInput: input)
    // The Email Mask now contains the updated properties
    
    input = UpdateEmailMaskInput(
        emailMaskId: emailMaskId,
        metadata: [:],
        expiresAt: Date(timeIntervalSince1970: 0)
    )
    updatedMask = try await emailClient.updateEmailMask(withInput: input)
    // The Email Mask no longer has metadata or expiresAt
} catch {
    /// Handle/notify user of error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
/// Collect the input email mask id however makes sense for your implementation.
val emailMaskId = emailMask.id
launch {
    try {
        val metadata = mapOf(
            "prop1" to "abc",
            "prop2" to "${123}"
        )
        val expiresAt = Date() // Construct the expiry date however makes sense
        var input = UpdateEmailMaskInput(
            emailMaskId = emailMaskId,
            metadata = metadata,
            expiresAt = expiresAt
        )
        var updatedMask = withContext(Dispatchers.IO) {
            emailClient.updateEmailMask(input)
        }
        // The Email Mask now contains the updated properties
        
        input = UpdateEmailMaskInput(
            emailMaskId = emailMaskId,
            metadata = emptyMap(),
            expiresAt = Date(0)
        )
        updatedMask = withContext(Dispatchers.IO) {
            emailClient.updateEmailMask(input)
        }
        // The Email Mask no longer has metadata or expiresAt
    } catch (e: EmailAddressException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

### Retrieving Existing Email Masks

Previously provisioned Email Masks can be retrieved as a paginated list via the `listEmailMasksForOwner` method.

A call to the API will return a `ListOutput<EmailMask>` object. The `items` property will contain a list of the masks and the `nextToken` property will contain a token that can be used for retrieving the next page of results if there are more.

The list can also be filtered by passing in an optional `filter` property to the method call. The call can be filtered by `status` and/or `realAddressType`. Each of those must further be specified as either `equal`, `oneOf`, `notEqual` or `notOneOf`.

The list can also be given a `limit` on how many results to return. By default, this limit is 10.

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const emailMaskId: string = emailMask.id // Collect the Email Mask however makes sense for your application
try {
    const result = await emailClient.listEmailMasksForOwner({
        filter: {
            status: { notOneOf: [EmailMaskStatus.PENDING, EmailMaskStatus.LOCKED] },
            realAddressType: { equal: EmailMaskRealAddressType.INTERNAL },
        }
    }
    // `result.items` contains a list of Masks that are not PENDING or LOCKED and have a real
    // address type of INTERNAL
    // Page through the results if result.nextToken != undefined.
} catch (e) {
    // Handle/notify user of errors 
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Collect the input email mask id however makes sense for your implementation.
let emailMaskId = emailMask.id
do {
    let filter = EmailMaskFilter(
        status: .notOneOf([.pending, .locked]),
        realAddressType: .equal(.internal),
    )
    let input = ListEmailMasksForOwnerInput(
        filter: filter
    )
    let result = try await emailClient.listEmailMasksForOwner(withInput: input)
    // `result.items` contains a list of Masks that are not PENDING or LOCKED and have a real
    // address type of INTERNAL
    // Page through the results if result.nextToken != nil.
} catch {
    /// Handle/notify user of error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
/// Collect the input email mask id however makes sense for your implementation.
val emailMaskId = emailMask.id
launch {
    try {
        val filter = EmailMaskFilterInput(
            status = NotOneOfStatusFilter(
                listOf(EmailMaskStatus.PENDING, EmailMaskStatus.LOCKED)
            ),
            realAddressType = EqualRealAddressTypeFilter(EmailMaskRealAddressType.INTERNAL)
        )
        val input = ListEmailMasksForOwnerInput(filter = filter)
        val result = withContext(Dispatchers.IO) { 
            emailClient.listEmailMasksForOwner(input)
        }
        // `result.items` contains a list of Masks that are not PENDING or LOCKED and have a real
        // address type of INTERNAL
        // Page through the results if result.nextToken != null.
    } catch (e: EmailAddressException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

### Disabling and Enabling Email Masks

An Email Mask can be disabled by the user to temporarily stop it from receiving emails without fully deprovisioning it. When in the `DISABLED` status, messages sent to the mask will not be delivered to the real address, and the sender will **not** receive a bounce in response until it is enabled again.

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const emailMaskId: string = emailMask.id // Collect the Email Mask however makes sense for your application
try {
    const disabledMask = await emailClient.disableEmailMask({
        emailMaskId: emailMaskId,
    })
    // Mask is now disabled; disabledMask.status == EmailMaskStatus.DISABLED
    
    const enabledMask = await emailClient.enableEmailMask({
        emailMaskId: emailMaskId,
    })
    // Mask is now enabled; enabledMask.status == EmailMaskStatus.ENABLED
} catch (e) {
    // Handle/notify user of errors 
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Collect the input email mask id however makes sense for your implementation.
let emailMaskId = emailMask.id
do {
    let disableInput = DisableEmailMaskInput(emailMaskId: emailMaskId)
    let disabledMask = try await client.disableEmailMask(withInput: disableInput)
    /// Email Mask is now disabled; disabledMask.status == .disabled
    
    let enableInput = EnableEmailMaskInput(emailMaskId: emailMaskId)
    let enabledMask = try await client.enableEmailMask(withInput: enableInput)
    /// Email Mask is now enabled; disabledMask.status == .enabled
} catch {
    /// Handle/notify user of error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
/// Collect the input email mask id however makes sense for your implementation.
val emailMaskId = emailMask.id
launch {
    try {
        val disableInput = DisableEmailMaskInput(emailMaskId)
        val disabledMask = withContext(Dispatchers.IO) {
            emailClient.disableEmailMask(disableInput)
        }
        // Email Mask is now disabled; disabledMask.status == EmailMaskStatus.DISABLED
        
        val enableInput = EnableEmailMaskInput(emailMaskId)
        val enabledMask = withContext(Dispatchers.IO) {
            emailClient.enableEmailMask(disableInput)
        }
        // Email Mask is now enabled; disabledMask.status == EmailMaskStatus.ENABLED
    } catch (e: EmailAddressException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}
