GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

azure-communication-sms-java

Send SMS messages with Azure Communication Services SMS Java SDK. Use when implementing SMS notifications, alerts, OTP delivery, bulk messaging, or delivery reports.

Ciza · 0 points · 17 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_plugins_azure-sdk-java_skills_azure-communication-sms-java-e58528d.zip · 6 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-java/skills/azure-communication-sms-java
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Azure Communication SMS (Java)

Send SMS messages to single or multiple recipients with delivery reporting.

Installation

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-communication-sms</artifactId>
    <version>1.2.0</version>
</dependency>

Client Creation

import com.azure.communication.sms.SmsClient;
import com.azure.communication.sms.SmsClientBuilder;
import com.azure.core.credential.TokenCredential;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
    .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
    .build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();

// With DefaultAzureCredential (recommended)
SmsClient smsClient = new SmsClientBuilder()
    .endpoint("https://<resource>.communication.azure.com")
    .credential(credential)
    .buildClient();

// With connection string
SmsClient smsClient = new SmsClientBuilder()
    .connectionString("<connection-string>")
    .buildClient();

// With AzureKeyCredential
import com.azure.core.credential.AzureKeyCredential;

SmsClient smsClient = new SmsClientBuilder()
    .endpoint("https://<resource>.communication.azure.com")
    .credential(new AzureKeyCredential("<access-key>"))
    .buildClient();

// Async client
SmsAsyncClient smsAsyncClient = new SmsClientBuilder()
    .connectionString("<connection-string>")
    .buildAsyncClient();

Send SMS to Single Recipient

import com.azure.communication.sms.models.SmsSendResult;

// Simple send
SmsSendResult result = smsClient.send(
    "+14255550100",      // From (your ACS phone number)
    "+14255551234",      // To
    "Your verification code is 123456");

System.out.println("Message ID: " + result.getMessageId());
System.out.println("To: " + result.getTo());
System.out.println("Success: " + result.isSuccessful());

if (!result.isSuccessful()) {
    System.out.println("Error: " + result.getErrorMessage());
    System.out.println("Status: " + result.getHttpStatusCode());
}

Send SMS to Multiple Recipients

import com.azure.communication.sms.models.SmsSendOptions;
import java.util.Arrays;
import java.util.List;

List<String> recipients = Arrays.asList(
    "+14255551111",
    "+14255552222",
    "+14255553333"
);

// With options
SmsSendOptions options = new SmsSendOptions()
    .setDeliveryReportEnabled(true)
    .setTag("marketing-campaign-001");

Iterable<SmsSendResult> results = smsClient.sendWithResponse(
    "+14255550100",      // From
    recipients,          // To list
    "Flash sale! 50% off today only.",
    options,
    Context.NONE
).getValue();

for (SmsSendResult result : results) {
    if (result.isSuccessful()) {
        System.out.println("Sent to " + result.getTo() + ": " + result.getMessageId());
    } else {
        System.out.println("Failed to " + result.getTo() + ": " + result.getErrorMessage());
    }
}

Send Options

SmsSendOptions options = new SmsSendOptions();

// Enable delivery reports (sent via Event Grid)
options.setDeliveryReportEnabled(true);

// Add custom tag for tracking
options.setTag("order-confirmation-12345");

Response Handling

import com.azure.core.http.rest.Response;

Response<Iterable<SmsSendResult>> response = smsClient.sendWithResponse(
    "+14255550100",
    Arrays.asList("+14255551234"),
    "Hello!",
    new SmsSendOptions().setDeliveryReportEnabled(true),
    Context.NONE
);

// Check HTTP response
System.out.println("Status code: " + response.getStatusCode());
System.out.println("Headers: " + response.getHeaders());

// Process results
for (SmsSendResult result : response.getValue()) {
    System.out.println("Message ID: " + result.getMessageId());
    System.out.println("Successful: " + result.isSuccessful());
    
    if (!result.isSuccessful()) {
        System.out.println("HTTP Status: " + result.getHttpStatusCode());
        System.out.println("Error: " + result.getErrorMessage());
    }
}

Async Operations

import reactor.core.publisher.Mono;

SmsAsyncClient asyncClient = new SmsClientBuilder()
    .connectionString("<connection-string>")
    .buildAsyncClient();

// Send single message
asyncClient.send("+14255550100", "+14255551234", "Async message!")
    .subscribe(
        result -> System.out.println("Sent: " + result.getMessageId()),
        error -> System.out.println("Error: " + error.getMessage())
    );

// Send to multiple with options
SmsSendOptions options = new SmsSendOptions()
    .setDeliveryReportEnabled(true);

asyncClient.sendWithResponse(
    "+14255550100",
    Arrays.asList("+14255551111", "+14255552222"),
    "Bulk async message",
    options)
    .subscribe(response -> {
        for (SmsSendResult result : response.getValue()) {
            System.out.println("Result: " + result.getTo() + " - " + result.isSuccessful());
        }
    });

Error Handling

import com.azure.core.exception.HttpResponseException;

try {
    SmsSendResult result = smsClient.send(
        "+14255550100",
        "+14255551234",
        "Test message"
    );
    
    // Individual message errors don't throw exceptions
    if (!result.isSuccessful()) {
        handleMessageError(result);
    }
    
} catch (HttpResponseException e) {
    // Request-level failures (auth, network, etc.)
    System.out.println("Request failed: " + e.getMessage());
    System.out.println("Status: " + e.getResponse().getStatusCode());
} catch (RuntimeException e) {
    System.out.println("Unexpected error: " + e.getMessage());
}

private void handleMessageError(SmsSendResult result) {
    int status = result.getHttpStatusCode();
    String error = result.getErrorMessage();
    
    if (status == 400) {
        System.out.println("Invalid phone number: " + result.getTo());
    } else if (status == 429) {
        System.out.println("Rate limited - retry later");
    } else {
        System.out.println("Error " + status + ": " + error);
    }
}

Delivery Reports

Delivery reports are sent via Azure Event Grid. Configure an Event Grid subscription for your ACS resource.

// Event Grid webhook handler (in your endpoint)
public void handleDeliveryReport(String eventJson) {
    // Parse Event Grid event
    // Event type: Microsoft.Communication.SMSDeliveryReportReceived
    
    // Event data contains:
    // - messageId: correlates to SmsSendResult.getMessageId()
    // - from: sender number
    // - to: recipient number
    // - deliveryStatus: "Delivered", "Failed", etc.
    // - deliveryStatusDetails: detailed status
    // - receivedTimestamp: when status was received
    // - tag: your custom tag from SmsSendOptions
}

SmsSendResult Properties

Property Type Description
getMessageId() String Unique message identifier
getTo() String Recipient phone number
isSuccessful() boolean Whether send succeeded
getHttpStatusCode() int HTTP status for this recipient
getErrorMessage() String Error details if failed
getRepeatabilityResult() RepeatabilityResult Idempotency result

Environment Variables

AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com  # Required for all auth methods
AZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=...  # Alternative to Entra ID auth
SMS_FROM_NUMBER=+14255550100  # Required for the sender phone number
AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production

Best Practices

  1. Phone Number Format - Use E.164 format: +[country code][number]
  2. Delivery Reports - Enable for critical messages (OTP, alerts)
  3. Tagging - Use tags to correlate messages with business context
  4. Error Handling - Check isSuccessful() for each recipient individually
  5. Rate Limiting - Implement retry with backoff for 429 responses
  6. Bulk Sending - Use batch send for multiple recipients (more efficient)

Trigger Phrases

  • "send SMS Java", "text message Java"
  • "SMS notification", "OTP SMS", "bulk SMS"
  • "delivery report SMS", "Azure Communication Services SMS"
Files (skills)
  • references
    • examples.md 14.9 KB
      # Azure Communication SMS Java SDK - Examples
      
      Comprehensive code examples for the Azure Communication Services SMS SDK for Java.
      
      ## Table of Contents
      - [Maven Dependency](#maven-dependency)
      - [Client Creation](#client-creation)
      - [Send Single SMS](#send-single-sms)
      - [Send Bulk SMS](#send-bulk-sms)
      - [Delivery Reports](#delivery-reports)
      - [Async Operations](#async-operations)
      - [Error Handling](#error-handling)
      - [Complete Application Example](#complete-application-example)
      
      ## Maven Dependency
      
      ```xml
      <dependency>
          <groupId>com.azure</groupId>
          <artifactId>azure-communication-sms</artifactId>
          <version>1.2.0</version>
      </dependency>
      ```
      
      ## Client Creation
      
      ### With DefaultAzureCredential (Recommended)
      
      ```java
      import com.azure.communication.sms.SmsClient;
      import com.azure.communication.sms.SmsClientBuilder;
      import com.azure.identity.DefaultAzureCredentialBuilder;
      
      SmsClient smsClient = new SmsClientBuilder()
          .endpoint("https://<resource>.communication.azure.com")
          .credential(new DefaultAzureCredentialBuilder().build())
          .buildClient();
      ```
      
      ### With Connection String
      
      ```java
      SmsClient smsClient = new SmsClientBuilder()
          .connectionString(System.getenv("AZURE_COMMUNICATION_CONNECTION_STRING"))
          .buildClient();
      ```
      
      ### With AzureKeyCredential
      
      ```java
      import com.azure.core.credential.AzureKeyCredential;
      
      SmsClient smsClient = new SmsClientBuilder()
          .endpoint("https://<resource>.communication.azure.com")
          .credential(new AzureKeyCredential("<access-key>"))
          .buildClient();
      ```
      
      ### Async Client
      
      ```java
      import com.azure.communication.sms.SmsAsyncClient;
      
      SmsAsyncClient asyncClient = new SmsClientBuilder()
          .connectionString(connectionString)
          .buildAsyncClient();
      ```
      
      ## Send Single SMS
      
      ### Simple Send
      
      ```java
      import com.azure.communication.sms.models.SmsSendResult;
      
      SmsSendResult result = smsClient.send(
          "+14255550100",      // From (your ACS phone number)
          "+14255551234",      // To
          "Your verification code is 123456"
      );
      
      System.out.println("Message ID: " + result.getMessageId());
      System.out.println("Success: " + result.isSuccessful());
      ```
      
      ### Send with Options
      
      ```java
      import com.azure.communication.sms.models.SmsSendOptions;
      import com.azure.core.util.Context;
      import java.util.Collections;
      
      SmsSendOptions options = new SmsSendOptions()
          .setDeliveryReportEnabled(true)
          .setTag("verification-code");
      
      SmsSendResult result = smsClient.sendWithResponse(
          "+14255550100",
          Collections.singletonList("+14255551234"),
          "Your verification code is 123456",
          options,
          Context.NONE
      ).getValue().iterator().next();
      ```
      
      ## Send Bulk SMS
      
      ### Send to Multiple Recipients
      
      ```java
      import java.util.Arrays;
      import java.util.List;
      
      List<String> recipients = Arrays.asList(
          "+14255551111",
          "+14255552222",
          "+14255553333"
      );
      
      SmsSendOptions options = new SmsSendOptions()
          .setDeliveryReportEnabled(true)
          .setTag("marketing-campaign-001");
      
      Iterable<SmsSendResult> results = smsClient.sendWithResponse(
          "+14255550100",
          recipients,
          "Flash sale! 50% off today only.",
          options,
          Context.NONE
      ).getValue();
      
      // Process results for each recipient
      for (SmsSendResult result : results) {
          if (result.isSuccessful()) {
              System.out.printf("✓ Sent to %s: %s%n", result.getTo(), result.getMessageId());
          } else {
              System.out.printf("✗ Failed to %s: %s (HTTP %d)%n", 
                  result.getTo(), 
                  result.getErrorMessage(),
                  result.getHttpStatusCode());
          }
      }
      ```
      
      ### Batch SMS with Retry Logic
      
      ```java
      import java.util.ArrayList;
      import java.util.List;
      
      public class SmsBatchSender {
          private final SmsClient smsClient;
          private final String fromNumber;
          
          public SmsBatchSender(SmsClient smsClient, String fromNumber) {
              this.smsClient = smsClient;
              this.fromNumber = fromNumber;
          }
          
          public List<SmsSendResult> sendBatch(List<String> recipients, String message) {
              List<SmsSendResult> allResults = new ArrayList<>();
              List<String> failedRecipients = new ArrayList<>();
              
              SmsSendOptions options = new SmsSendOptions()
                  .setDeliveryReportEnabled(true);
              
              // First attempt
              Iterable<SmsSendResult> results = smsClient.sendWithResponse(
                  fromNumber, recipients, message, options, Context.NONE
              ).getValue();
              
              for (SmsSendResult result : results) {
                  allResults.add(result);
                  if (!result.isSuccessful() && result.getHttpStatusCode() == 429) {
                      failedRecipients.add(result.getTo());
                  }
              }
              
              // Retry rate-limited messages after delay
              if (!failedRecipients.isEmpty()) {
                  try {
                      Thread.sleep(2000); // Wait 2 seconds
                      Iterable<SmsSendResult> retryResults = smsClient.sendWithResponse(
                          fromNumber, failedRecipients, message, options, Context.NONE
                      ).getValue();
                      
                      for (SmsSendResult result : retryResults) {
                          allResults.add(result);
                      }
                  } catch (InterruptedException e) {
                      Thread.currentThread().interrupt();
                  }
              }
              
              return allResults;
          }
      }
      ```
      
      ## Delivery Reports
      
      Delivery reports are sent via Azure Event Grid. Configure an Event Grid subscription for your ACS resource.
      
      ### Event Grid Webhook Handler
      
      ```java
      import com.azure.messaging.eventgrid.EventGridEvent;
      import com.fasterxml.jackson.databind.JsonNode;
      import com.fasterxml.jackson.databind.ObjectMapper;
      
      public class SmsDeliveryReportHandler {
          private final ObjectMapper objectMapper = new ObjectMapper();
          
          public void handleDeliveryReport(String eventJson) throws Exception {
              List<EventGridEvent> events = EventGridEvent.fromString(eventJson);
              
              for (EventGridEvent event : events) {
                  if ("Microsoft.Communication.SMSDeliveryReportReceived".equals(event.getEventType())) {
                      JsonNode data = objectMapper.readTree(event.getData().toString());
                      
                      String messageId = data.get("messageId").asText();
                      String from = data.get("from").asText();
                      String to = data.get("to").asText();
                      String deliveryStatus = data.get("deliveryStatus").asText();
                      String deliveryStatusDetails = data.get("deliveryStatusDetails").asText();
                      String tag = data.has("tag") ? data.get("tag").asText() : null;
                      
                      System.out.printf("Delivery Report - MessageId: %s, To: %s, Status: %s%n",
                          messageId, to, deliveryStatus);
                      
                      // Update your database or trigger actions based on status
                      switch (deliveryStatus) {
                          case "Delivered":
                              onMessageDelivered(messageId, to, tag);
                              break;
                          case "Failed":
                              onMessageFailed(messageId, to, deliveryStatusDetails, tag);
                              break;
                      }
                  }
              }
          }
          
          private void onMessageDelivered(String messageId, String to, String tag) {
              System.out.printf("Message %s delivered to %s (tag: %s)%n", messageId, to, tag);
          }
          
          private void onMessageFailed(String messageId, String to, String reason, String tag) {
              System.out.printf("Message %s failed to %s: %s (tag: %s)%n", 
                  messageId, to, reason, tag);
          }
      }
      ```
      
      ## Async Operations
      
      ### Async Send Single Message
      
      ```java
      import reactor.core.publisher.Mono;
      
      SmsAsyncClient asyncClient = new SmsClientBuilder()
          .connectionString(connectionString)
          .buildAsyncClient();
      
      asyncClient.send("+14255550100", "+14255551234", "Async message!")
          .subscribe(
              result -> {
                  System.out.println("Sent: " + result.getMessageId());
                  System.out.println("Success: " + result.isSuccessful());
              },
              error -> System.err.println("Error: " + error.getMessage())
          );
      ```
      
      ### Async Bulk Send with Reactive Streams
      
      ```java
      import reactor.core.publisher.Flux;
      
      SmsSendOptions options = new SmsSendOptions()
          .setDeliveryReportEnabled(true);
      
      asyncClient.sendWithResponse(
          "+14255550100",
          Arrays.asList("+14255551111", "+14255552222"),
          "Bulk async message",
          options)
          .flatMapMany(response -> Flux.fromIterable(response.getValue()))
          .subscribe(
              result -> {
                  if (result.isSuccessful()) {
                      System.out.printf("✓ %s: %s%n", result.getTo(), result.getMessageId());
                  } else {
                      System.out.printf("✗ %s: %s%n", result.getTo(), result.getErrorMessage());
                  }
              },
              error -> System.err.println("Error: " + error.getMessage()),
              () -> System.out.println("All messages processed")
          );
      ```
      
      ## Error Handling
      
      ### Comprehensive Error Handling
      
      ```java
      import com.azure.core.exception.HttpResponseException;
      
      public class SmsService {
          private final SmsClient smsClient;
          private final String fromNumber;
          
          public SmsService(SmsClient smsClient, String fromNumber) {
              this.smsClient = smsClient;
              this.fromNumber = fromNumber;
          }
          
          public SmsSendResult sendSms(String to, String message) {
              try {
                  SmsSendResult result = smsClient.send(fromNumber, to, message);
                  
                  if (!result.isSuccessful()) {
                      handleMessageError(result);
                  }
                  
                  return result;
                  
              } catch (HttpResponseException e) {
                  // Request-level failures (auth, network, etc.)
                  System.err.printf("HTTP Error %d: %s%n", 
                      e.getResponse().getStatusCode(), e.getMessage());
                  throw new RuntimeException("Failed to send SMS", e);
              } catch (RuntimeException e) {
                  System.err.println("Unexpected error: " + e.getMessage());
                  throw e;
              }
          }
          
          private void handleMessageError(SmsSendResult result) {
              int status = result.getHttpStatusCode();
              String to = result.getTo();
              String error = result.getErrorMessage();
              
              switch (status) {
                  case 400:
                      System.err.printf("Invalid phone number: %s%n", to);
                      break;
                  case 401:
                      System.err.println("Authentication failed - check credentials");
                      break;
                  case 403:
                      System.err.printf("Not authorized to send to: %s%n", to);
                      break;
                  case 429:
                      System.err.println("Rate limited - implement backoff retry");
                      break;
                  default:
                      System.err.printf("Error %d sending to %s: %s%n", status, to, error);
              }
          }
      }
      ```
      
      ## Complete Application Example
      
      ### OTP SMS Service
      
      ```java
      import com.azure.communication.sms.SmsClient;
      import com.azure.communication.sms.SmsClientBuilder;
      import com.azure.communication.sms.models.SmsSendOptions;
      import com.azure.communication.sms.models.SmsSendResult;
      import com.azure.core.util.Context;
      import java.security.SecureRandom;
      import java.util.Collections;
      import java.util.Map;
      import java.util.concurrent.ConcurrentHashMap;
      
      public class OtpSmsService {
          private final SmsClient smsClient;
          private final String fromNumber;
          private final Map<String, OtpEntry> otpStore = new ConcurrentHashMap<>();
          private final SecureRandom random = new SecureRandom();
          
          public OtpSmsService(String connectionString, String fromNumber) {
              this.smsClient = new SmsClientBuilder()
                  .connectionString(connectionString)
                  .buildClient();
              this.fromNumber = fromNumber;
          }
          
          public String sendOtp(String phoneNumber) {
              // Generate 6-digit OTP
              String otp = String.format("%06d", random.nextInt(1000000));
              
              // Store OTP with expiry
              otpStore.put(phoneNumber, new OtpEntry(otp, System.currentTimeMillis() + 300000));
              
              // Send SMS
              String message = String.format("Your verification code is %s. Valid for 5 minutes.", otp);
              
              SmsSendOptions options = new SmsSendOptions()
                  .setDeliveryReportEnabled(true)
                  .setTag("otp-" + phoneNumber);
              
              SmsSendResult result = smsClient.sendWithResponse(
                  fromNumber,
                  Collections.singletonList(phoneNumber),
                  message,
                  options,
                  Context.NONE
              ).getValue().iterator().next();
              
              if (result.isSuccessful()) {
                  System.out.printf("OTP sent to %s: %s%n", phoneNumber, result.getMessageId());
                  return result.getMessageId();
              } else {
                  throw new RuntimeException("Failed to send OTP: " + result.getErrorMessage());
              }
          }
          
          public boolean verifyOtp(String phoneNumber, String otp) {
              OtpEntry entry = otpStore.get(phoneNumber);
              
              if (entry == null) {
                  return false;
              }
              
              if (System.currentTimeMillis() > entry.expiryTime) {
                  otpStore.remove(phoneNumber);
                  return false;
              }
              
              if (entry.otp.equals(otp)) {
                  otpStore.remove(phoneNumber);
                  return true;
              }
              
              return false;
          }
          
          private static class OtpEntry {
              final String otp;
              final long expiryTime;
              
              OtpEntry(String otp, long expiryTime) {
                  this.otp = otp;
                  this.expiryTime = expiryTime;
              }
          }
      }
      ```
      
      ### Usage
      
      ```java
      public class Main {
          public static void main(String[] args) {
              String connectionString = System.getenv("AZURE_COMMUNICATION_CONNECTION_STRING");
              String fromNumber = System.getenv("SMS_FROM_NUMBER");
              
              OtpSmsService otpService = new OtpSmsService(connectionString, fromNumber);
              
              // Send OTP
              String messageId = otpService.sendOtp("+14255551234");
              System.out.println("OTP sent with message ID: " + messageId);
              
              // Verify OTP (user enters code)
              boolean verified = otpService.verifyOtp("+14255551234", "123456");
              System.out.println("OTP verified: " + verified);
          }
      }
      ```
      
      ## Environment Variables
      
      ```bash
      AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com
      AZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=...
      SMS_FROM_NUMBER=+14255550100
      ```
      
      ## Best Practices
      
      1. **Phone Number Format** - Use E.164 format: `+[country code][number]`
      2. **Delivery Reports** - Enable for critical messages (OTP, alerts)
      3. **Tagging** - Use tags to correlate messages with business context
      4. **Error Handling** - Check `isSuccessful()` for each recipient individually
      5. **Rate Limiting** - Implement retry with exponential backoff for 429 responses
      6. **Bulk Sending** - Use batch send for multiple recipients (more efficient)
      7. **Connection Reuse** - Reuse `SmsClient` instances across requests
      
  • SKILL.md 8.8 KB
    ---
    name: azure-communication-sms-java
    description: Send SMS messages with Azure Communication Services SMS Java SDK. Use when implementing SMS notifications, alerts, OTP delivery, bulk messaging, or delivery reports.
    license: MIT
    metadata:
      author: Microsoft
      version: "1.0.0"
      package: com.azure:azure-communication-sms
    ---
    
    # Azure Communication SMS (Java)
    
    Send SMS messages to single or multiple recipients with delivery reporting.
    
    ## Installation
    
    ```xml
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-communication-sms</artifactId>
        <version>1.2.0</version>
    </dependency>
    ```
    
    ## Client Creation
    
    ```java
    import com.azure.communication.sms.SmsClient;
    import com.azure.communication.sms.SmsClientBuilder;
    import com.azure.core.credential.TokenCredential;
    import com.azure.identity.AzureIdentityEnvVars;
    import com.azure.identity.DefaultAzureCredentialBuilder;
    import com.azure.identity.ManagedIdentityCredentialBuilder;
    
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    TokenCredential credential = new DefaultAzureCredentialBuilder()
        .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
        .build();
    // Or use a specific credential directly in production:
    // See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
    // TokenCredential credential = new ManagedIdentityCredentialBuilder().build();
    
    // With DefaultAzureCredential (recommended)
    SmsClient smsClient = new SmsClientBuilder()
        .endpoint("https://<resource>.communication.azure.com")
        .credential(credential)
        .buildClient();
    
    // With connection string
    SmsClient smsClient = new SmsClientBuilder()
        .connectionString("<connection-string>")
        .buildClient();
    
    // With AzureKeyCredential
    import com.azure.core.credential.AzureKeyCredential;
    
    SmsClient smsClient = new SmsClientBuilder()
        .endpoint("https://<resource>.communication.azure.com")
        .credential(new AzureKeyCredential("<access-key>"))
        .buildClient();
    
    // Async client
    SmsAsyncClient smsAsyncClient = new SmsClientBuilder()
        .connectionString("<connection-string>")
        .buildAsyncClient();
    ```
    
    ## Send SMS to Single Recipient
    
    ```java
    import com.azure.communication.sms.models.SmsSendResult;
    
    // Simple send
    SmsSendResult result = smsClient.send(
        "+14255550100",      // From (your ACS phone number)
        "+14255551234",      // To
        "Your verification code is 123456");
    
    System.out.println("Message ID: " + result.getMessageId());
    System.out.println("To: " + result.getTo());
    System.out.println("Success: " + result.isSuccessful());
    
    if (!result.isSuccessful()) {
        System.out.println("Error: " + result.getErrorMessage());
        System.out.println("Status: " + result.getHttpStatusCode());
    }
    ```
    
    ## Send SMS to Multiple Recipients
    
    ```java
    import com.azure.communication.sms.models.SmsSendOptions;
    import java.util.Arrays;
    import java.util.List;
    
    List<String> recipients = Arrays.asList(
        "+14255551111",
        "+14255552222",
        "+14255553333"
    );
    
    // With options
    SmsSendOptions options = new SmsSendOptions()
        .setDeliveryReportEnabled(true)
        .setTag("marketing-campaign-001");
    
    Iterable<SmsSendResult> results = smsClient.sendWithResponse(
        "+14255550100",      // From
        recipients,          // To list
        "Flash sale! 50% off today only.",
        options,
        Context.NONE
    ).getValue();
    
    for (SmsSendResult result : results) {
        if (result.isSuccessful()) {
            System.out.println("Sent to " + result.getTo() + ": " + result.getMessageId());
        } else {
            System.out.println("Failed to " + result.getTo() + ": " + result.getErrorMessage());
        }
    }
    ```
    
    ## Send Options
    
    ```java
    SmsSendOptions options = new SmsSendOptions();
    
    // Enable delivery reports (sent via Event Grid)
    options.setDeliveryReportEnabled(true);
    
    // Add custom tag for tracking
    options.setTag("order-confirmation-12345");
    ```
    
    ## Response Handling
    
    ```java
    import com.azure.core.http.rest.Response;
    
    Response<Iterable<SmsSendResult>> response = smsClient.sendWithResponse(
        "+14255550100",
        Arrays.asList("+14255551234"),
        "Hello!",
        new SmsSendOptions().setDeliveryReportEnabled(true),
        Context.NONE
    );
    
    // Check HTTP response
    System.out.println("Status code: " + response.getStatusCode());
    System.out.println("Headers: " + response.getHeaders());
    
    // Process results
    for (SmsSendResult result : response.getValue()) {
        System.out.println("Message ID: " + result.getMessageId());
        System.out.println("Successful: " + result.isSuccessful());
        
        if (!result.isSuccessful()) {
            System.out.println("HTTP Status: " + result.getHttpStatusCode());
            System.out.println("Error: " + result.getErrorMessage());
        }
    }
    ```
    
    ## Async Operations
    
    ```java
    import reactor.core.publisher.Mono;
    
    SmsAsyncClient asyncClient = new SmsClientBuilder()
        .connectionString("<connection-string>")
        .buildAsyncClient();
    
    // Send single message
    asyncClient.send("+14255550100", "+14255551234", "Async message!")
        .subscribe(
            result -> System.out.println("Sent: " + result.getMessageId()),
            error -> System.out.println("Error: " + error.getMessage())
        );
    
    // Send to multiple with options
    SmsSendOptions options = new SmsSendOptions()
        .setDeliveryReportEnabled(true);
    
    asyncClient.sendWithResponse(
        "+14255550100",
        Arrays.asList("+14255551111", "+14255552222"),
        "Bulk async message",
        options)
        .subscribe(response -> {
            for (SmsSendResult result : response.getValue()) {
                System.out.println("Result: " + result.getTo() + " - " + result.isSuccessful());
            }
        });
    ```
    
    ## Error Handling
    
    ```java
    import com.azure.core.exception.HttpResponseException;
    
    try {
        SmsSendResult result = smsClient.send(
            "+14255550100",
            "+14255551234",
            "Test message"
        );
        
        // Individual message errors don't throw exceptions
        if (!result.isSuccessful()) {
            handleMessageError(result);
        }
        
    } catch (HttpResponseException e) {
        // Request-level failures (auth, network, etc.)
        System.out.println("Request failed: " + e.getMessage());
        System.out.println("Status: " + e.getResponse().getStatusCode());
    } catch (RuntimeException e) {
        System.out.println("Unexpected error: " + e.getMessage());
    }
    
    private void handleMessageError(SmsSendResult result) {
        int status = result.getHttpStatusCode();
        String error = result.getErrorMessage();
        
        if (status == 400) {
            System.out.println("Invalid phone number: " + result.getTo());
        } else if (status == 429) {
            System.out.println("Rate limited - retry later");
        } else {
            System.out.println("Error " + status + ": " + error);
        }
    }
    ```
    
    ## Delivery Reports
    
    Delivery reports are sent via Azure Event Grid. Configure an Event Grid subscription for your ACS resource.
    
    ```java
    // Event Grid webhook handler (in your endpoint)
    public void handleDeliveryReport(String eventJson) {
        // Parse Event Grid event
        // Event type: Microsoft.Communication.SMSDeliveryReportReceived
        
        // Event data contains:
        // - messageId: correlates to SmsSendResult.getMessageId()
        // - from: sender number
        // - to: recipient number
        // - deliveryStatus: "Delivered", "Failed", etc.
        // - deliveryStatusDetails: detailed status
        // - receivedTimestamp: when status was received
        // - tag: your custom tag from SmsSendOptions
    }
    ```
    
    ## SmsSendResult Properties
    
    | Property | Type | Description |
    |----------|------|-------------|
    | `getMessageId()` | String | Unique message identifier |
    | `getTo()` | String | Recipient phone number |
    | `isSuccessful()` | boolean | Whether send succeeded |
    | `getHttpStatusCode()` | int | HTTP status for this recipient |
    | `getErrorMessage()` | String | Error details if failed |
    | `getRepeatabilityResult()` | RepeatabilityResult | Idempotency result |
    
    ## Environment Variables
    
    ```bash
    AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com  # Required for all auth methods
    AZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=...  # Alternative to Entra ID auth
    SMS_FROM_NUMBER=+14255550100  # Required for the sender phone number
    AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production
    ```
    
    ## Best Practices
    
    1. **Phone Number Format** - Use E.164 format: `+[country code][number]`
    2. **Delivery Reports** - Enable for critical messages (OTP, alerts)
    3. **Tagging** - Use tags to correlate messages with business context
    4. **Error Handling** - Check `isSuccessful()` for each recipient individually
    5. **Rate Limiting** - Implement retry with backoff for 429 responses
    6. **Bulk Sending** - Use batch send for multiple recipients (more efficient)
    
    ## Trigger Phrases
    
    - "send SMS Java", "text message Java"
    - "SMS notification", "OTP SMS", "bulk SMS"
    - "delivery report SMS", "Azure Communication Services SMS"
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related