Provides the essentials to give your users their own email address with the privacy and security benefits of a Sudo
Email addresses are a core component of the Email SDK. Addresses for different configured domains can be provisioned and used to communicate with other recipients.
Provisioning an email address is a two-step process. First, a check should be performed to determine if the email address is valid and available. Once results are returned and the desired address is selected, the address can be provisioned to a Sudo.
Get Supported Email Domains
When provisioning a new email address for your user, a domain is needed to ensure the email address will be valid. The Sudo Platform email service can be configured to support issuing email addresses for multiple domains.
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.
A call to the getSupportedEmailDomains method allows your user to perform a domain search in order to retrieve a list of supported domains for provisioning an email address.
It is required that CachePolicy set to RemoteOnly be used before CacheOnly for at least one successful call to the service.
try {constdomains=awaitemailClient.getSupportedEmailDomains(CachePolicy.RemoteOnly )// `domains` contains a list of supported domains to be used for email address provisioning.} catch {// Handle/notify user of errors}
do {let domains =tryawait self.getSupportedEmailDomains( cachePolicy: .remoteOnly)/// `domains` contains a list of supported domains to be used for email address provisioning.} catch {/// Handle/notify user of errors}
launch {try {val domains =withContext(Dispatchers.IO) { emailClient.getSupportedEmailDomains() }// [domains] contains a list of supported domains to be used for email address provisioning. } catch (e: EmailAddressException) {// Handle/notify user of exception } }
Get Configured Email Domains
The Email SDK also provides a method to retrieve the configured email domains in your Sudo Platform account. This is used as part of email send operations to allows appropriate encryption decisions to be made when attempting to send end-to-end encrypted email messages.
A call to the getConfiguredEmailDomains method returns a list of these configured email domains.
try {constconfiguredDomains=awaitemailClient.getConfiguredEmailDomains(CachePolicy.RemoteOnly )// `configuredDomains` contains a list of configured domains.} catch {// Handle/notify user of errors}
do {let configuredDomains =tryawait self.getConfiguredEmailDomains( cachePolicy: .remoteOnly)/// `configuredDomains` contains a list of configured domains.} catch {/// Handle/notify user of errors}
launch {try {val domains =withContext(Dispatchers.IO) { emailClient.getConfiguredEmailDomains() }// [configuredDomains] contains a list of configured domains. } catch (e: EmailAddressException) {// Handle/notify user of exception } }
Check Email Address Availability
When choosing a unique email address, it is important to give your user feedback as to whether the email address they are attempting to provision is valid or not. This is achieved by using the checkEmailAddressAvailability method.
The first input property, localParts, takes in a set of local parts to validate and check if they are available. If any of the local parts are invalid or the input contains more than five local parts to check, an invalid argument error will be returned.
The second input property, domains, should be a set of email domains exclusively supported by the email service. It is recommended to use the getSupportedEmailDomains method to retrieve this set. If an unsupported domain is supplied, an invalid email domain error will be returned.
try {constlocalParts=Set(['johndoe','jane.citizen'])constdomains=awaitemailClient.getSupportedEmailDomains(CachePolicy.RemoteOnly )constemailAddresses=awaitemailClient.checkEmailAddressAvailability({ localParts, domains, })// For example, if the domains list is:// [// "example.com",// "sudoplatform.com"// ]// And all emails are available for both domains, this would return a result // that looks like this:// [// "johndoe@example.com",// "johndoe@sudoplatform.com",// "jane.citizen@example.com",// "jane.citizen@sudoplatform.com"// ]} catch {// Handle/notify user of errors}
let localParts = ["johndoe", "jane.citizen"]/// In reality, this would be a subset of the result of `getSupportedDomains`.let supportedDomains = ["example.com", "sudoplatform.com"]do {let checkAddressInput =CheckEmailAddressAvailabilityInput( localParts: [localPart], domains: [domain])let validAddresses =tryawait emailClient.checkEmailAddressAvailability( withInput: checkAddressInput)/// If all emails were available for both domains, this would return a result that looks like this:/// [/// "johndoe@example.com",/// "johndoe@sudoplatform.com",/// "jane.citizen@example.com",/// "jane.citizen@sudoplatform.com"/// ]} catch {/// Handle/notify user of error}
launch {try {val localParts =listOf("johndoe", "jane.citizen")val supportedDomains = emailClient.getSupportedEmailDomains()val input =CheckEmailAddressAvailabilityInput( localParts = localParts, domains = supportedDomains )val emailAddresses = emailClient.checkEmailAddressAvailability(input)// If all emails are available for both domains, // this would return a result that looks like this:// [// "johndoe@example.com",// "johndoe@sudoplatform.com",// "jane.citizen@example.com",// "jane.citizen@sudoplatform.com"// ] } catch (e: EmailAddressException) {// Handle/notify user of error }}
All email addresses will be lower-cased in the return result. For example a local part input of JoHnDoE would be returned as johndoe....
Provision Email Address
Once an available email address has been found, it can be used to provision a valid email address for a Sudo. An email address can be provisioned by calling the provisionEmailAddress method and will return the newly provisioned email address object.
The input email address must be valid and available, so it is highly recommended that you use the Check Email Address Availability API to validate the email address first.
An ownershipProofToken is required as part of the input. This ties together the Sudo and email address such that the Sudo becomes the owner of the email address. Use the getOwnershipProof method on the SudoProfilesClient in the SudoProfiles SDK in order to obtain an ownershipProofToken. See the Sudo section for more information.
An optional alias can also be provided as part of the input to provision an email address. The alias can be updated after initially provisioning the email address as discussed in the Updating Metadata of an Email Address section.
When an email address is provisioned, a set of standard email folders is also created and associated with the newly provisioned email address. Find out more about managing email folders here.
constemailAddressInput:string=// Found via the check email address availability APIconstownershipProofToken:string=// Found via the get ownership proof API (See "Sudos" section)try {constemailAddress=awaitemailClient.provisionEmailAddress({ emailAddressInput, ownershipProofToken, alias:'John Smith'// Optionally supply an alias })} catch {// Handle/notify user of errors }
let emailAddress = self.input.emailAddress /// String of the form "\(localPart)@\(domain)"let ownershipProofToken = self.input.ownershipProofToken /// Found via the get ownership proof API (See "Sudos" section)do {let provisionAddressInput =ProvisionEmailAddressInput( emailAddress: emailAddress, ownershipProofToken: ownershipProofToken, alias:"Fred Smith"/// optional alias for the provisioned email address)let provisionedEmailAddress =tryawait emailClient.provisionEmailAddress( withInput: provisionAddressInput)/// `provisionedEmailAddress` contains the newly provisioned email address.} catch {/// Handle/notify user of error}
val emailAddress: String=// Found via the check email address availability APIval ownershipProofToken: String=// Found via the getOwnershipProof API (See "Sudos" section)launch {try {val input =ProvisionEmailAddressInput( emailAddress = emailAddress, ownershipProofToken = ownershipProofToken, alias ='John Smith'// Optionally supply an alias )val emailAddress =withContext(Dispatchers.IO) { emailClient.provisionEmailAddress(input) }// The returned [emailAddress] has been provisioned } catch (e: EmailAddressException) {// Handle/notify user of exception } }
Entitlements
In order to be able to provision an email address, the user must be entitled. To provision an email address the following entitlement checks are performed:
The user must not have more Sudo Profiles than permitted by their sudoplatform.sudo.max entitlement.
The user is entitled to provision email addresses by the sudoplatform.email.emailAddressUserEntitled entitlement.
The Sudo Profile against which the new email address is to be provisioned has at least 1 remaining sudoplatform.email.emailAddressMaxPerSudo entitlement to consume.
If these entitlements' checks do not succeed, the provisionEmailAddress API fails with an insufficient entitlements error.
See Email Entitlements for an overview of how the Email service integrates with the Sudo Platform Entitlements system.
Deprovision Email Address
An email address can be deprovisioned using the deprovisionEmailAddress method by passing in the id of an existing email address object. The email address object that was deprovisioned will be returned and will no longer be usable for provisioning another email address.
By deprovisioning the email address, the user's address and all associated user data including messages and folders will be deleted; the email address will no longer be usable. The deprovisioned address will also be held indefinitely and be blocked for re-use from a subsequent provision call.
// Collect the input email address id however makes sense for your implementation.constemailAddressId=emailAddress.idtry {constemailAddress=awaitemailClient.deprovisionEmailAddress( emailAddressId )// The returned `emailAddress` has now been deprovisioned.} catch {// Handle/notify user of errors }
/// Collect the input email address id however makes sense for your implementation.let provisionedEmailAddressId = self.input.emailAddressIddo {let deprovisionedEmailAddress =tryawait emailClient.deprovisionEmailAddress( provisionedEmailAddressId)/// `deprovisionedEmailAddress` is the record that was just deprovisioned.} catch {/// Handle/notify user of error}
// Collect the input email address id however makes sense for your implementation.val emailAddressId = emailAddress.idlaunch {try {val emailAddress =withContext(Dispatchers.IO) { emailClient.deprovisionEmailAddress(emailAddressId) }// The returned [emailAddress] has now been deprovisioned. } catch (e: EmailAddressException) {// Handle/notify user of exception }}
Updating Metadata of an Email Address
The metadata of an email address object can be updated by calling the updateEmailAddressMetadata method. Currently, the only attribute that can be updated on an email address object is the alias. The alias is an encrypted optional attribute on the email address object which can be modified by the user.
// Collect the input email address id however makes sense for your implementation.try {constid=awaitemailClient.updateEmailAddressMetadata({ id, values: { alias:'John Smith' }, })// `id` contains the identifier of the newly updated email address object.} catch {// Handle/notify user of errors }
/// Collect the input email address id however makes sense for your implementation.let emailAddressId = input.emailAddress.idlet updateEmailAddressMetadataInput =UpdateEmailAddressMetadataInput( id: emailAddress.id, values: UpdateEmailAddressMetadataValues(alias:"newAlias"))do {let updatedEmailAddressId =tryawait client.updateEmailAddressMetadata( withInput: updateEmailAddressMetadataInput)/// `updatedEmailAddressId` contains the identifier of the newly updated email address object.} catch {/// Handle/notify user of error}
/// Collect the input email address id however makes sense for your implementation.val emailAddressId = emailAddress.idlaunch {try {val input =UpdateEmailAddressMetadataInput( id = emailAddress.id, alias ="newAlias" )val updatedEmailAddressId =withContext(Dispatchers.IO) { emailClient.updateEmailAddressMetadata(input) }// The returned [updatedEmailAddressId] contains the identifier of the newly updated email address object. } catch (e: EmailAddressException) {// Handle/notify user of exception }}
If an email address has been provisioned and then deprovisioned, it will no longer be available via the methods discussed in this section.
A fetch of single or multiple email addresses can be performed remotely or locally by specifying the appropriate CachePolicy as part of the input.
Single Email Address by Id
To retrieve a single email address given its unique id, use the getEmailAddress method. This method will return the record if it exists.
try {constemailAddress=awaitemailClient.getEmailAddress({ id, cachePolicy:CachePolicy.RemoteOnly, })// `emailAddress` contains the email address object, else `undefined` if not found.} catch {// Handle/notify user of errors}
/// Collect the input address of the email address object.let emailAddressId = input.address.idlet getEmailAddressInput =GetEmailAddressInput( id: emailAddressId, cachePolicy: .remoteOnly)do {let emailAddress =tryawait emailClient.getEmailAddress( withInput: getEmailAddressInput)/// `emailAddress` contains the email address object, else `nil` if not found.} catch {/// Handle/notify user of error}
val emailAddressId = emailAddress.idlaunch {try {val input =GetEmailAddressInput( id = emailAddressId )val emailAddress =withContext(Dispatchers.IO) { emailClient.getEmailAddress(input) }// [emailAddress] contains the email address object, else [null] if not found. } catch (e: EmailAddressException) {// Handle/notify user of exception }}
Multiple Provisioned Email Addresses
The ability to retrieve multiple or all email addresses available to the user is supported. These results can be paginated.
A call to a list API will return a ListEmailAddressesResult with a status and depending on the status, a list of matching items and a nextToken to support pagination. If no results matching the input are found, the result will contain empty items. There can be three possible statuses returned:
Status
Definition
Success
A list of all requested email addresses are returned.
Partial
A list of all email addresses that were successfully fetched and unencrypted are returned as well as a list of all email addresses that failed to unencrypt successfully, including an error indicating the reason for the failure.
Failure
All email addresses failed to be fetched or unencrypted. Contains an error indicating the reason for the failure.
An email address may fail to be unencrypted if the version of the client is not up-to-date or if the required cryptographic key is missing from the client device.
All Provisioned Email Addresses
To retrieve multiple email addresses that are owned by the signed in user, call the listEmailAddresses method.
try {constresult=awaitemailClient.listEmailAddresses({ cachePolicy:CachePolicy.RemoteOnly, limit:20, nextToken, })if (result.status ===ListOperationResultStatus.Success) {// `result` contains the list of items matching the input.// Page through the results if result.nextToken != undefined. }} catch {// Handle/notify user of errors}
let listEmailAddressesInput =ListEmailAddressesInput( cachePolicy: .remoteOnly, limit:20, nextToken:nil)do {let output =tryawait emailClient.listEmailAddresses( withInput: input)/// `output` contains a `ListOutput` item of results matching the call./// `output.items` contains an array of `EmailAddress`} catch {/// Handle/notify user}
launch {try {val input =ListEmailAddressesInput( limit =20, nextToken = nextToken )val result =withContext(Dispatchers.IO) { emailClient.listEmailAddresses(input) }when (result) {is ListAPIResult.Success -> {// [result.items] contains the list of items matching the input.// Page through the results if [output.nextToken] != null. }is ListAPIResult.Partial -> {// [result.items] contains the list of items matching the input that decrypted successfully.// [result.failed] contains the list of items that failed decryption with associated error.// Page through the results if [partial.nextToken] != null. } } } catch (e: EmailAddressException) {// Handle/notify user of exception }}
All Provisioned Email Addresses for a Sudo
To retrieve multiple email addresses that are owned by a particular Sudo, call the listEmailAddressesForSudoId method by passing in the id of the Sudo to query.
// Collect the input sudo id however makes sense for your implementation.constsudoId=sudo.idtry {constresult=awaitemailClient.listEmailAddressesForSudoId({ sudoId, cachePolicy:CachePolicy.RemoteOnly, limit:20, nextToken, })if (result.status ===ListOperationResultStatus.Success) {// `result` contains the list of items matching the input.// Page through the results if result.nextToken != undefined. }} catch {// Handle/notify user of errors}
/// Collect the input sudo id however makes sense for your implementation.let sudoId = sudo.idlet listEmailAddressesForSudoIdInput =ListEmailAddressesForSudoIdInput( sudoId: sudoId, cachePolicy: .remoteOnly, limit:20, nextToken:nil)do {let output =tryawait emailClient.listEmailAddressesForSudoId( withInput: listEmailAddressesForSudoId)/// `output` contains a `ListOutput` item of results matching the call./// `output.items` contains an array of `EmailAddress`} catch {/// Handle/notify user}
// Collect the input sudo id however makes sense for your implementation.val sudoId = sudo.idlaunch {try {val input =ListEmailAddressesForSudoIdInput( sudoId = sudoId, limit =20, nextToken = nextToken )val result =withContext(Dispatchers.IO) { emailClient.listEmailAddressesForSudoId(input) }when (result) {is ListAPIResult.Success -> {// [result.items] contains the list of items matching the input.// Page through the results if [output.nextToken] != null. }is ListAPIResult.Partial -> {// [result.items] contains the list of items matching the input that decrypted successfully.// [result.failed] contains the list of items that failed decryption with associated error.// Page through the results if [partial.nextToken] != null. } } } catch (e: EmailAddressException) {// Handle/notify user of exception }}
For the best performance depending on your use case, look up email addresses by Sudo.
By default, list email addresses API have a limit of 1MB of data when no limit is supplied.