# Draft Email Messages

The **Email SDK** supports the notion of draft email messages. A separate set of APIs are available to handle the lifecycle of drafts.

### Creating a Draft Email Message

To create and save a draft email message, call the `createDraftEmailMessage` method. This method takes in a `rfc822Data` input property which contains the email message content formatted under RFC 822 as well as the `senderEmailAddressId` input property which must match the identifier of the email addess from the `from` field in the RFC 822 data. A call to this method returns metadata of the saved draft. Draft email message data provides the ID of the draft and an `updatedAt` timestamp representing the last time the draft was saved.

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

```typescript
// Obtain the input RFC 822 data and sender email address id however makes sense for your implementation.
const rfc822Data: ArrayBuffer = // ...
const senderEmailAddressId = senderEmailAddress.id
try {
    const draftMetadata = await emailClient.createDraftEmailMessage({
        rfc822Data,
        senderEmailAddressId,
    })
    // `draftMetadata` is the metadata associated with the saved
    // draft email message including the id you can use this to access or
    // update the draft.
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Obtain the input RFC 822 data and sender email address id however makes sense for your implementation.
let rfc822Data: Data = // ...
let senderEmailAddressId = senderEmailAddress.id
let input = CreateDraftEmailMessageInput(
    rfc822Data: rfc822Data,
    senderEmailAddressId: senderEmailAddressId
)
do {
    let draftMetadata = try await emailClient.createDraftEmailMessage(
        withInput: input
    )
    // `draftMetadata` is the `DraftEmailMessageMetadata` associated with the saved
    // draft email message including the id which you can use to access or
    // update the draft.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// Obtain the input RFC 822 data and sender email address id however makes sense for your implementation.
val rfc822Data: ByteArray = // ...
val senderEmailAddressId = senderEmailAddress.id
launch {
    try {
        val input = CreateDraftEmailMessageInput(
            rfc822Data = rfc822Data,
            senderEmailAddressId = senderEmailAddressId
        )
        val draftId = withContext(Dispatchers.IO) {
            emailClient.createDraftEmailMessage(input)
        }
        // [draftId] is the unique id of the draft that you can use to access 
        // or update the draft
    } catch (e: EmailMessageException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

### Updating a Draft Email Message

Use the `updateDraftEmailMessage` method to update a previously created and saved draft email message. The input requires the `id` of the previously saved draft to perform the update. It is a requirement that the entire message content be replaced with an updated version as part of the `rfc822Data` input property. A call to this method returns the `id` of the draft that was updated which should match the `id` provided in the input.

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

```typescript
// Obtain the input RFC 822 data, sender email address id and existing draft id however makes sense for your implementation.
const id: string = // ...
const rfc822Data: ArrayBuffer = // ...
const senderEmailAddressId = senderEmailAddress.id 
try {
    const draftMetadata = await emailClient.updateDraftEmailMessage({
        id,
        rfc822Data,
        senderEmailAddressId,
    })
    // `draftMetadata` is the metadata associated with the saved
    // draft email message including the id you can use this to access or
    // update the draft.
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Obtain the input RFC 822 data, sender email address id and existing draft id however makes sense for your implementation.
let id: String = // ...
let rfc822Data: Data = // ...
let senderEmailAddressId = senderEmailAddress.id
let input = UpdateDraftEmailMessageInput(
    id: id,
    rfc822Data: rfc822Data,
    senderEmailAddressId: senderEmailAddressId
)
do {
    let draftMetadata = try await emailClient.updateDraftEmailMessage(
        withInput: input
    )
    // `draftMetadata` is the `DraftEmailMessageMetadata` associated with the
    // updated draft email message including the id which you can use to access
    // or update the draft.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// Obtain the input RFC 822 data, sender email address id and existing draft id however makes sense for your implementation.
val id: String = // ...
val rfc822Data: ByteArray = // ...
val senderEmailAddressId = senderEmailAddress.id
launch {
    try {
        val input = UpdateDraftEmailMessageInput(
            id = id,
            rfc822Data = rfc822Data,
            senderEmailAddressId = senderEmailAddressId
        )
        val draftId = withContext(Dispatchers.IO) {
            emailClient.updateDraftEmailMessage(input)
        }
        // [draftId] is the unique id of the draft that you can use to access 
        // or update the draft
    } catch (e: EmailMessageException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

### Deleting Draft Email Messages

Draft email messages can be deleted in batches using the `deleteDraftEmailMessages` method by passing in one or more draft message identifiers and the `id` of the email address associated with the drafts.

{% hint style="warning" %}
Draft email messages that have been deleted will no longer be available and all traces of the message data and metadata will be deleted permanently.
{% endhint %}

{% hint style="danger" %}
Draft email messages can only be deleted in batches of 10. Supplying identifiers to the input which exceed this limit will return a `LimitExceededError`.
{% endhint %}

A `BatchOperationResult` type is returned from this method call which contains the status of the batch delete operation. Three possible statuses can be returned:

| Status  | Definition                                                                                                                                                                                                                    |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Success | All of the draft email messages succeeded to delete. The return object will include a list of identifiers of messages which succeeded to delete.                                                                              |
| Partial | Only a subset of draft email messages succeeded to delete. The return object will include a list of identifiers and error descriptions of draft email messages which failed the delete and a list which succeeded the delete. |
| Failure | All of the draft email messages failed to delete.                                                                                                                                                                             |

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

```typescript
// Obtain the input draft message ids and email address id however makes sense for your implementation.
const ids = arrayOf('draft-msg-id-1', 'draft-msg-id-2')
const emailAddressId = emailAddress.id
try {
    const result = await emailClient.deleteDraftEmailMessages({
        ids,
        emailAddressId,
    })
    // `result` contains the status of the batch delete operation and associated success and failure metadata.
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Obtain the input draft message ids and email address id however makes sense for your implementation.
let ids = ['draft-msg-id-1', 'draft-msg-id-2']
let emailAddressId = emailAddress.id
let input = DeleteDraftEmailMessagesInput(
    ids: ids,
    emailAddressId: emailAddressId
)
do {
    let result = try await self.emailClient.deleteDraftEmailMessages(
        withInput: input
    )
    // `result` contains the status of the batch delete operation and associated success and failure metadata.
} catch {
    /// Handle/notify user of error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// Obtain the input draft message ids and email address id however makes sense for your implementation.
val ids = listOf("draft-msg-id-1", "draft-msg-id-2")
val emailAddressId = emailAddress.id
launch {
    try {
        val input = DeleteDraftEmailMessagesInput(
            ids = ids,
            emailAddressId = emailAddressId
        )
        val result = withContext(Dispatchers.IO) {
            emailClient.deleteDraftEmailMessages(input)
        }
        // [result] contains the status of the batch delete operation and associated success and failure metadata.
    } catch (e: EmailMessageException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

### Retrieving Draft Email Messages

Draft email messages can be accessed using its identifier or by querying for a list of its identifiers.

{% hint style="warning" %}
If a draft email message has been deleted, it will no longer be available for access.
{% endhint %}

#### Single Draft Email Message by Id

To retrieve a single draft email message, use the `getDraftEmailMessage` method. This method takes in the `id` of the draft to retrieve as well as the `id` of the email address that is associated with the draft. This method returns the draft email message data if it exists.

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

```typescript
// Obtain the input email address id and draft id however makes sense for
// your implementation.
const emailAddressId = emailAddress.id
try {
    const draftMessage = await emailClient.getDraftEmailMessage({
        id,
        emailAddressId,
    })
    // `draftMessage` containing draft message data and `updatedAt` timestamp
    // will be returned if a draft message corresponding to `id` is found,
    // else `undefined`.
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Obtain the input draft message id and email address id however makes sense for your implementation.
let id = 'draft-msg-id-1'
let emailAddressId = emailAddress.id
let input = GetDraftEmailMessageInput(
    id: id,
    emailAddressId: emailAddressId
)
do {
    let draftEmailMessage = try await emailClient.getDraftEmailMessage(
        withInput: input
    )
    // `draftMessage` containing draft message data and `updatedAt` timestamp
    // will be returned if a draft message corresponding to `id` is found,
    // else `nil`.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// Obtain the input draft message id and email address id however makes sense for your implementation.
val id = "draft-msg-id-1"
val emailAddressId = emailAddress.id
launch {
    try {
        val input = GetDraftEmailMessageInput(
            id = id,
            emailAddressId = emailAddressId
        )
        val draftMessage = withContext(Dispatchers.IO) {
            emailClient.getDraftEmailMessage(input)
        }
        // [draftMessage] containing draft message data and [updatedAt] timestamp
        // will be returned if a draft message corresponding to [id] is found,
        // else will throw an exception.
    } catch (e: EmailMessageException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

#### List of All Draft Email Messages \[Deprecated]

To retrieve a list of all draft email messages associated with a user, call the `listDraftEmailMessages` method. \
\
**Deprecated:** use `listDraftEmailMessagesForEmailAddressId` instead

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

```typescript
try {
    const result = await emailClient.listDraftEmailMessages()
    // `result` contains a list of draft messages consisting of the 
    // draft message data and the `updatedAt` timestamp.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
do {
    let result = try await emailClient.listDraftEmailMessages()
    // `result` contains a list of draft messages consisting of the 
    // draft message data and the `updatedAt` timestamp.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
launch {
    try {
        val result = withContext(Dispatchers.IO) {
            emailClient.listDraftEmailMessages()
        }
        // [result] contains a list of draft messages consisting of the 
        // draft message data and the [updatedAt] timestamp.
    } catch (e: EmailMessageException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

#### List of Draft Email Messages for an Email Address

To retrieve a list of multiple draft email messages associated with a certain email address, call the `listDraftEmailMessagesForEmailAddressId` method by passing in the `id` of the email address, the number of results you want (min: 1, max: 1000, default: 10) and the next token.\
\
The "next token" is returned from the previous call and is used to get the next set of results. When next token is undefined or nil or null, there are no further results. For the first set, pass a next token of undefined, nil, or null.

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

```typescript
// Obtain the input email address id however makes sense for your implementation.
const emailAddressId = emailAddress.id
let allItems: DraftEmailMessage[] = []

try {
    do {
      const metadataList =        
        await sudoEmailClient.listDraftEmailMessagesForEmailAddressId({
          emailAddressId: emailAddressId,
          limit: 5,
          nextToken: nextToken,
        })

      allItems = [...allItems, ...metadataList.items]

      nextToken = metadataList.nextToken
    } while (nextToken !== undefined && allItems.length < 50)
    // `allItems` contains a list of all of the draft email messages'
    // metadata.
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```kotlin
// Obtain the input email address id however makes sense for your implementation.
let emailAddressId = emailAddress.id
do {
    let result = try await emailClient.listDraftEmailMessagesForEmailAddressId(
        emailAddressId
    )
    // `result` contains a list of draft messages consisting of the 
    // draft message data and the `updatedAt` timestamp.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val allItems = mutableListOf<DraftEmailMessageWithContent>()
var nextToken: String? = null
do {
    val draftEmailMessages =
        emailClient.listDraftEmailMessagesForEmailAddressId(
            ListDraftEmailMessagesForEmailAddressIdInput(emailAddressId, 5, nextToken),
        ) 
    allItems.addAll(draftEmailMessages.items)
    nextToken = draftEmailMessages.nextToken
} while (nextToken != null)
// `allItems` contains a list of all of the draft email messages
```

{% endtab %}
{% endtabs %}

#### List of All Draft Email Message Metadata \[Deprecated]

Use `listDraftEmailMessageMetadata` to retrieve a list of all the metadata of the draft email messages associated with a user. The metadata returned in the list can be used to retrieve individual draft email message content, perform an update to an already saved draft, or identify which drafts to perform full retrieval of based on `updatedAt` timestamp.\
\
**Deprecated:** use `listDraftEmailMessageMetadataForEmailAddressId` instead

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

```typescript
try {
    const result = await emailClient.listDraftEmailMessageMetadata()
    // `result` contains a list of all of the draft email messages'
    // metadata.
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
do {
    let result = try await emailClient.listDraftEmailMessageMetadata()
    // `result` contains an array of `DraftEmailMessageMetadata` of all of the
    // draft email messages' metadata.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
launch {
    try {
        val result = withContext(Dispatchers.IO) {
            emailClient.listDraftEmailMessageMetadata()
        }
        // [result] contains a list of [DraftEmailMessageMetadata] of all of the
        // draft email messages' metadata.
    } catch (e: EmailMessageException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

#### List of Draft Email Message Metadata for an Email Address

To retrieve a list of all the metadata of the draft messages associated with an email address, call the `listDraftEmailMessageMetadataForEmailAddressId` method by passing in the `id` of the email address, the number of results you want (min: 1, max: 1000, default: 10) and the next token.\
\
The "next token" is returned from the previous call and is used to get the next set of results. When next token is undefined or nil or null, there are no further results. For the first set, pass a next token of undefined, nil, or null.

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

```typescript
// Obtain the input email address id however makes sense for your implementation.
const emailAddressId = emailAddress.id
let allItems: DraftEmailMessageMetadata[] = []

try {
    do {
      const metadataList =        
        await sudoEmailClient.listDraftEmailMessageMetadataForEmailAddressId({
          emailAddressId: emailAddressId,
          limit: 5,
          nextToken: nextToken,
        })

      allItems = [...allItems, ...metadataList.items]

      nextToken = metadataList.nextToken
    } while (nextToken !== undefined && allItems.length < 50)
    // `allItems` contains a list of all of the draft email messages'
    // metadata.
} catch (e) {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```kotlin
var allDraftMetadata: [DraftEmailMessageMetadata] = []
var nextToken: String?

// Loop through all pages of draft metadata
repeat {
    let input = ListDraftEmailMessageMetadataForEmailAddressIdInput(
        emailAddressId: emailAddressId,
        limit: 5,
        nextToken: nextToken
    )
    let draftsMetadata = try await emailClient.listDraftEmailMessageMetadataForEmailAddressId(
        withInput: input
    )
    allDraftMetadata.append(contentsOf: draftsMetadata.items)
    nextToken = draftsMetadata.nextToken
} while nextToken != nil
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val allItems = mutableListOf<DraftEmailMessageMetadata>()
var nextToken: String? = null
do {
    val draftEmailMessagesMetadata =
        emailClient.listDraftEmailMessageMetadataForEmailAddressId(
            ListDraftEmailMessageMetadataForEmailAddressIdInput(emailAddressId, 5, nextToken),
        ) 
    allItems.addAll(draftEmailMessagesMetadata.items)
    nextToken = draftEmailMessagesMetadata.nextToken
} while (nextToken != null)
// `allItems` contains a list of all of the draft email messages'
// metadata.
```

{% endtab %}
{% endtabs %}
