View a markdown version of this page

Create an Amazon SNS topic and publish messages - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

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 "=============================================="