AWS Messaging & Targeting Blog

How to list over 1000 email addresses from account-level suppression list

Overview of solution

Amazon Simple Email Service (SES) offers an account-level suppression list, which assists customers in avoiding sending emails to addresses that have previously resulted in bounce or complaint events. This feature is designed to protect the sender’s reputation and enhance message delivery rates. There are various types of suppression lists available, including the global suppression List, account-level suppression list, and configuration set-level suppression. The account-level suppression list is owned and managed by the customer, providing them with control over their list and account reputation. Additionally, customers can utilize the configuration set-level suppression feature for more precise control over suppression list management, which overrides the account-level suppression list.

Maintaining a healthy sender reputation with email providers (such as Gmail, Yahoo, or Hotmail) increases the probability of emails reaching recipients’ inboxes instead of being marked as spam. One effective approach to uphold sender reputation involves refraining from sending emails to invalid email addresses and disinterested recipients.

The account-level suppression list can be managed using Amazon SES console or AWS CLI which provides an easy way to manage addresses including bulk actions to add or remove addresses.

Currently, If the account-level suppression list contains more than 1000 records, we need to use NextToken to obtain a complete list of email addresses in a paginated manner. If the email address you are looking for is not within the first 1000 records of the response, you won’t be able to obtain the information from the account-level suppression list with one single command. To list all the email addresses within the account-level suppression, we use Amazon SES ListSuppressedDestinations API. This API allows you to fetch the NextToken and pass it to a follow-up request in order to retrieve another page of results.

The code below creates a loop that makes multiple requests, in each iteration, the next token is replaced, aiding in retrieving all email addresses that have been added to the account-level suppression list.

Prerequisite

The code below can be used to run in your local machine or using AWS CloudShell As part of this blog spot, we will be using AWS CloudShell to fetch the list.

Note: Python 3 and Python 2 are both ready to use in the shell environment. Python 3 is now considered the default version of the programming language (support for Python 2 ended in January 2020).

1) An active AWS account.
2) User logged in to AWS management console must have “ses:ListSuppressedDestinations” permissions.

Walkthrough

  1. Sign in to AWS management console and select the region where you are using Amazon SES
  2. Launch AWS CloudShell
  3. Save the code specified below as a file in your local environment. Example: List_Account_Level.py
  4. Click Actions and Upload File (List_Account_Level.py)

Upload File to AWS CloudShell

5. Run Python code.

Python3 List_Account_Level.py >> Email_Addresses_List.json

6. The file Email_Addresses_List.json will be saved in current directory
7. To download the file – Click Actions and Download File providing File name Email_Addresses_List.json

Download File from AWS CloudShell

List the Email addresses in your Amazon SES account suppression list added to recent bounce or complaint event using Python.

We used the ListSuppressedDestinations operation in the SES API v2 to create a list with all the email addresses that are on your account-level suppression list for your account including bounces and complaints.

Note: SES account-level suppression list applies to your AWS account in the current AWS Region.

import boto3
from datetime import datetime
import json

def showTimestamp(results):
    updated_results = []
    for eachAddress in results:
        updated_address = eachAddress.copy()
        updated_address['LastUpdateTime'] = eachAddress['LastUpdateTime'].strftime("%m/%d/%Y, %H:%M:%S")
        updated_results.append(updated_address)
    return updated_results

def get_resources_from(supression_details):
    results = supression_details['SuppressedDestinationSummaries']
    next_token = supression_details.get('NextToken', None)
    return results, next_token

def main():
    client = boto3.client('sesv2')
    next_token = ''  # Variable to hold the pagination token
    results = []   # List for the entire resource collection
    # Call the `list_suppressed_destinations` method in a loop

    while next_token is not None:
        if next_token:
            suppression_response = client.list_suppressed_destinations(
                PageSize=1000,
                NextToken=next_token
            )
        else:
            suppression_response = client.list_suppressed_destinations(
                PageSize=1000
            )
        current_batch, next_token = get_resources_from(suppression_response)
        results += current_batch

    results = showTimestamp(results)

    print(json.dumps(results, indent=2, sort_keys=False))

if __name__ == "__main__":
    main()

Sample Response

Returns all of the email addresses and the output resembles the following example:

[{
    "EmailAddress": "example1@hello.com",
    "Reason": "BOUNCE",
    "LastUpdateTime": "04/30/2021, 15:43:01"
}, {
    "EmailAddress": "example2@invaliddomian.com",
    "Reason": "BOUNCE",
    "LastUpdateTime": "04/30/2021, 15:43:01"
}, {
    "EmailAddress": "example3@12345.99k",
    "Reason": "BOUNCE",
    "LastUpdateTime": "04/30/2021, 15:43:01"
}, {
    "EmailAddress": "1233@testing12344.com",
    "Reason": "BOUNCE",
    "LastUpdateTime": "04/30/2021, 15:43:00"
}, {
    "EmailAddress": "dasadaf@coma.com",
    "Reason": "COMPLAINT",
    "LastUpdateTime": "06/22/2023, 12:59:31"
}]

Cleaning up

The response file Email_Addresses_List.json will contain the list of all the email addresses on your account-level suppression list even if there are more than 1000 records. Please free to delete files that were created as part of the process if you no longer need them.

Conclusion

In this blog post, we explained listing of all email addresses if the account-level suppression list contains more than 1000 records using AWS CouldShell. Having complete list of email addresses will help you identify email addresses you are looking for and that are not included in the first 1000 records of the response. You can validate email address and determine who can receive email that can be removed from the account-level suppression list. This protect the sender reputations and improving delivery rates.

Follow-up

  1. https://docs.aws.amazon.com/ses/latest/dg/sending-email-suppression-list.html
  2. https://repost.aws/knowledge-center/ses-remove-email-from-suppresion-list

About the Author

vmgaddam

Venkata Manoj Gaddam is Cloud Support Engineer II at AWS and Service Matter Expert in Amazon Simple Email Service (SES) and Amazon Simple Storage Service (S3). Along with Amazon SES and S3, he is AWS Snow Family enthusiast. In his free time, he enjoys hanging out with friends and traveling.