There are more AWS SDK examples available in the AWS Doc SDK Examples
Create an Amazon SNS topic and publish messages
The following code example shows how to:
Create an Amazon SNS topic
Subscribe an email endpoint to the topic
Verify your subscription
Publish a message to the topic
Clean up resources
- Bash
-
- AWS CLI with Bash script
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials
repository. #!/bin/bash # Amazon SNS Getting Started Script # This script demonstrates how to create an SNS topic, subscribe to it, publish a message, # and clean up resources. set -euo pipefail # Set up logging with secure file permissions LOG_FILE="sns-tutorial.log" touch "$LOG_FILE" chmod 600 "$LOG_FILE" exec > >(tee -a "$LOG_FILE") 2>&1 echo "Starting Amazon SNS Getting Started Tutorial..." echo "$(date)" echo "==============================================" # Function to handle errors handle_error() { echo "ERROR: $1" >&2 echo "Attempting to clean up resources..." cleanup_resources exit 1 } # Function to clean up resources cleanup_resources() { local exit_code=$? if [ -n "${SUBSCRIPTION_ARN:-}" ] && [ "$SUBSCRIPTION_ARN" != "pending confirmation" ] && [ "$SUBSCRIPTION_ARN" != "PendingConfirmation" ]; then echo "Deleting subscription: $SUBSCRIPTION_ARN" if ! aws sns unsubscribe --subscription-arn "$SUBSCRIPTION_ARN" --region "$AWS_REGION" 2>/dev/null; then echo "Warning: Failed to delete subscription" >&2 fi fi if [ -n "${TOPIC_ARN:-}" ]; then echo "Deleting topic: $TOPIC_ARN" if ! aws sns delete-topic --topic-arn "$TOPIC_ARN" --region "$AWS_REGION" 2>/dev/null; then echo "Warning: Failed to delete topic" >&2 fi fi return $exit_code } # Validate AWS region AWS_REGION="${AWS_REGION:-us-east-1}" if [[ ! "$AWS_REGION" =~ ^[a-z]{2}-[a-z]+-[0-9]{1}$ ]]; then handle_error "Invalid AWS region format: $AWS_REGION" fi # Set trap to cleanup on exit trap cleanup_resources EXIT # Verify AWS CLI is installed and configured if ! command -v aws &> /dev/null; then handle_error "AWS CLI is not installed or not in PATH" fi if ! command -v jq &> /dev/null; then handle_error "jq is not installed or not in PATH" fi if ! aws sts get-caller-identity --region "$AWS_REGION" &> /dev/null; then handle_error "AWS credentials are not configured or invalid" fi # Generate a random topic name suffix using secure method RANDOM_SUFFIX=$(openssl rand -hex 4) TOPIC_NAME="my-topic-${RANDOM_SUFFIX}" # Validate topic name length (max 256 characters) if [ ${#TOPIC_NAME} -gt 256 ]; then handle_error "Topic name exceeds maximum length of 256 characters" fi # Step 1: Create an SNS topic echo "Creating SNS topic: $TOPIC_NAME" TOPIC_RESULT=$(aws sns create-topic \ --name "$TOPIC_NAME" \ --region "$AWS_REGION" \ --tags Key=project,Value=doc-smith Key=tutorial,Value=amazon-simple-notification-service-gs \ --output json) || handle_error "Failed to create SNS topic" # Extract the topic ARN using jq for reliable parsing TOPIC_ARN=$(echo "$TOPIC_RESULT" | jq -r '.TopicArn // empty') || handle_error "Failed to parse topic result" if [ -z "$TOPIC_ARN" ]; then handle_error "Failed to extract topic ARN from result: $TOPIC_RESULT" fi # Validate ARN format if [[ ! "$TOPIC_ARN" =~ ^arn:aws:sns:[a-z0-9-]+:[0-9]{12}:[a-zA-Z0-9_-]+$ ]]; then handle_error "Invalid SNS topic ARN format: $TOPIC_ARN" fi echo "Successfully created topic with ARN: $TOPIC_ARN" # Step 2: Subscribe to the topic using Email-JSON protocol to reduce costs echo "" echo "==============================================" echo "EMAIL SUBSCRIPTION" echo "==============================================" EMAIL_ADDRESS="test-${RANDOM_SUFFIX}@example.com" # Validate email format (basic validation) if [[ ! "$EMAIL_ADDRESS" =~ ^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then handle_error "Invalid email format: $EMAIL_ADDRESS" fi echo "Subscribing email: $EMAIL_ADDRESS to topic using Email-JSON protocol" SUBSCRIPTION_RESULT=$(aws sns subscribe \ --topic-arn "$TOPIC_ARN" \ --protocol email-json \ --notification-endpoint "$EMAIL_ADDRESS" \ --region "$AWS_REGION" \ --output json) || handle_error "Failed to create subscription" # Extract the subscription ARN using jq SUBSCRIPTION_ARN=$(echo "$SUBSCRIPTION_RESULT" | jq -r '.SubscriptionArn // empty') || handle_error "Failed to parse subscription result" echo "Subscription created: $SUBSCRIPTION_ARN" echo "A confirmation email has been sent to $EMAIL_ADDRESS" echo "" # Tag the subscription if [ "$SUBSCRIPTION_ARN" != "PendingConfirmation" ] && [ "$SUBSCRIPTION_ARN" != "pending confirmation" ]; then aws sns tag-resource \ --resource-arn "$SUBSCRIPTION_ARN" \ --tags Key=project,Value=doc-smith Key=tutorial,Value=amazon-simple-notification-service-gs \ --region "$AWS_REGION" 2>/dev/null || echo "Warning: Failed to tag subscription" fi # Step 3: List subscriptions to verify echo "Listing subscriptions for topic: $TOPIC_ARN" SUBSCRIPTIONS=$(aws sns list-subscriptions-by-topic --topic-arn "$TOPIC_ARN" --region "$AWS_REGION" --output json) || handle_error "Failed to list subscriptions" echo "Current subscriptions:" echo "$SUBSCRIPTIONS" | jq '.' # Get the confirmed subscription ARN with optimized jq query and improved error handling CONFIRMED_SUBSCRIPTION=$(echo "$SUBSCRIPTIONS" | jq -r '.Subscriptions[]? | select(.SubscriptionArn != "PendingConfirmation") | .SubscriptionArn' 2>/dev/null | head -n 1) if [ -n "$CONFIRMED_SUBSCRIPTION" ]; then SUBSCRIPTION_ARN="$CONFIRMED_SUBSCRIPTION" else echo "Warning: No confirmed subscription found. You may not have confirmed the subscription yet." echo "The script will continue, but you may not receive the test message." fi # Step 4: Publish a message to the topic echo "" echo "Publishing a test message to the topic" MESSAGE="Hello from Amazon SNS! This is a test message sent at $(date)." # Validate message length (max 256 KB for SNS) if [ ${#MESSAGE} -gt 262144 ]; then handle_error "Message exceeds maximum size of 256 KB" fi PUBLISH_RESULT=$(aws sns publish \ --topic-arn "$TOPIC_ARN" \ --message "$MESSAGE" \ --region "$AWS_REGION" \ --output json) || handle_error "Failed to publish message" MESSAGE_ID=$(echo "$PUBLISH_RESULT" | jq -r '.MessageId // empty') || handle_error "Failed to parse publish result" if [ -z "$MESSAGE_ID" ]; then handle_error "No message ID returned from publish operation" fi # Validate message ID format (UUID v4) if [[ ! "$MESSAGE_ID" =~ ^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$ ]]; then handle_error "Unexpected message ID format: $MESSAGE_ID" fi echo "Message published successfully with ID: $MESSAGE_ID" echo "Check your email for the message." # Pause to allow the user to check their email echo "" echo "Pausing for 3 seconds to allow message delivery..." sleep 3 # Step 5: Clean up resources echo "" echo "==============================================" echo "CLEANUP CONFIRMATION" echo "==============================================" echo "Resources created:" echo "- SNS Topic: $TOPIC_ARN" echo "- Subscription: ${SUBSCRIPTION_ARN:-N/A}" echo "" echo "Cleaning up resources to avoid unnecessary charges..." echo "" echo "Tutorial completed successfully!" echo "$(date)" echo "=============================================="-
For API details, see the following topics in AWS CLI Command Reference.
-
Create an Amazon Textract explorer application
Create and publish to a FIFO topic