RepletoryLib.Communication.Sms
1.0.0
dotnet add package RepletoryLib.Communication.Sms --version 1.0.0
NuGet\Install-Package RepletoryLib.Communication.Sms -Version 1.0.0
<PackageReference Include="RepletoryLib.Communication.Sms" Version="1.0.0" />
<PackageVersion Include="RepletoryLib.Communication.Sms" Version="1.0.0" />
<PackageReference Include="RepletoryLib.Communication.Sms" />
paket add RepletoryLib.Communication.Sms --version 1.0.0
#r "nuget: RepletoryLib.Communication.Sms, 1.0.0"
#:package RepletoryLib.Communication.Sms@1.0.0
#addin nuget:?package=RepletoryLib.Communication.Sms&version=1.0.0
#tool nuget:?package=RepletoryLib.Communication.Sms&version=1.0.0
RepletoryLib.Communication.Sms
AWS SNS SMS service implementation with sender ID support and transactional/promotional message routing.
Part of the RepletoryLib ecosystem -- standalone, reusable .NET 10 libraries with zero business logic.
Overview
RepletoryLib.Communication.Sms provides an AWS Simple Notification Service (SNS) implementation of the ISmsService interface from RepletoryLib.Communication.Abstractions. It sends SMS messages via the SNS Publish API to E.164-formatted phone numbers, with configurable sender IDs and transactional/promotional message type routing.
The service sets SNS message attributes for AWS.SNS.SMS.SMSType and AWS.SNS.SMS.SenderID, allowing carrier-level routing differentiation. It also automatically registers the unified ICommunicationService facade so messages can be routed across channels.
Key Features
- Single SMS -- Send individual SMS messages to E.164 phone numbers
- Bulk SMS -- Send multiple messages with per-message success/failure tracking
- Sender ID -- Configurable default sender ID with per-message override
- SMS type routing -- Transactional (OTP, alerts) or Promotional (marketing) via SNS message attributes
- Flexible authentication -- Explicit access/secret keys or default AWS credential chain
- Unified routing -- Automatically registers
ICommunicationServicefor cross-channel messaging
Installation
dotnet add package RepletoryLib.Communication.Sms
Or add to your .csproj:
<PackageReference Include="RepletoryLib.Communication.Sms" Version="1.0.0" />
Note: RepletoryLib packages are published to a local BaGet feed. See the main repository README for feed configuration.
Dependencies
| Package | Type |
|---|---|
RepletoryLib.Communication.Abstractions |
RepletoryLib |
AWSSDK.SimpleNotificationService |
NuGet (3.7.400.98) |
Microsoft.Extensions.Configuration.Binder |
NuGet (10.0.0) |
Microsoft.Extensions.DependencyInjection.Abstractions |
NuGet (10.0.0) |
Microsoft.Extensions.Logging.Abstractions |
NuGet (10.0.0) |
Microsoft.Extensions.Options.ConfigurationExtensions |
NuGet (10.0.0) |
Prerequisites
- AWS account with SNS SMS sending enabled
- SMS sending quota approved in the target AWS region
- AWS credentials (access key/secret key or IAM role)
- Phone numbers must be in E.164 format (e.g.,
+27821234567)
Quick Start
using RepletoryLib.Communication.Sms;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRepletrySms(builder.Configuration);
{
"Communication": {
"Sms": {
"Region": "af-south-1",
"AccessKey": "AKIAIOSFODNN7EXAMPLE",
"SecretKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"SenderId": "MyApp",
"DefaultSmsType": "Transactional"
}
}
}
Configuration
SnsOptions
| Property | Type | Default | Description |
|---|---|---|---|
Region |
string |
"af-south-1" |
AWS region endpoint for SNS |
AccessKey |
string? |
null |
AWS access key. When null, the default AWS credential chain is used |
SecretKey |
string? |
null |
AWS secret key. When null, the default AWS credential chain is used |
SenderId |
string? |
null |
Default sender ID displayed on the recipient's device. Can be overridden per message |
DefaultSmsType |
SmsType |
Transactional |
Default SMS type for carrier routing (Transactional or Promotional) |
Section name: "Communication:Sms"
Usage Examples
Register Services
using RepletoryLib.Communication.Sms;
var builder = WebApplication.CreateBuilder(args);
// Register the SNS SMS service
builder.Services.AddRepletrySms(builder.Configuration);
var app = builder.Build();
Send a Single SMS
using RepletoryLib.Communication.Abstractions.Interfaces;
using RepletoryLib.Communication.Abstractions.Models.Sms;
public class OtpService
{
private readonly ISmsService _smsService;
public OtpService(ISmsService smsService) => _smsService = smsService;
public async Task SendOtpAsync(string phoneNumber, string otpCode)
{
var result = await _smsService.SendAsync(new SmsMessage
{
To = phoneNumber, // E.164 format: "+27821234567"
Body = $"Your verification code is: {otpCode}. Valid for 5 minutes."
});
if (!result.Success)
throw new InvalidOperationException($"Failed to send OTP: {result.Error}");
Console.WriteLine($"OTP sent. MessageId: {result.MessageId}");
}
}
Send SMS with Custom Sender ID
var result = await _smsService.SendAsync(new SmsMessage
{
To = "+27821234567",
Body = "Your order #12345 has been shipped!",
SenderId = "ShopName" // Overrides the default SenderId from SnsOptions
});
Bulk Send
var messages = phoneNumbers.Select(phone => new SmsMessage
{
To = phone,
Body = "Reminder: Your appointment is tomorrow at 10:00 AM."
});
var bulkResult = await _smsService.SendBulkAsync(messages);
Console.WriteLine($"Sent: {bulkResult.SuccessCount}, Failed: {bulkResult.FailureCount}");
foreach (var failure in bulkResult.Results.Where(r => !r.Success))
{
Console.WriteLine($"Failed: {failure.Error}");
}
Using the Unified Communication Facade
using RepletoryLib.Communication.Abstractions.Enums;
using RepletoryLib.Communication.Abstractions.Interfaces;
using RepletoryLib.Communication.Abstractions.Models.Common;
public class AlertService
{
private readonly ICommunicationService _communication;
public AlertService(ICommunicationService communication) => _communication = communication;
public async Task SendSmsAlertAsync(string phoneNumber, string message)
{
var result = await _communication.SendAsync(new CommunicationMessage
{
Channel = CommunicationChannel.Sms,
Recipient = phoneNumber,
Body = message
});
}
}
Multi-Channel Registration
using RepletoryLib.Communication.Email;
using RepletoryLib.Communication.Sms;
var builder = WebApplication.CreateBuilder(args);
// Register both email and SMS -- ICommunicationService routes to both
builder.Services.AddRepletoryEmail(builder.Configuration);
builder.Services.AddRepletrySms(builder.Configuration);
API Reference
ServiceCollectionExtensions
| Method | Returns | Description |
|---|---|---|
AddRepletrySms(configuration) |
IServiceCollection |
Registers IAmazonSimpleNotificationService (singleton), ISmsService (scoped), and ICommunicationService (scoped) |
SnsSmsService (implements ISmsService)
| Method | Returns | Description |
|---|---|---|
SendAsync(SmsMessage, ct) |
Task<SendResult> |
Sends a single SMS via SNS Publish API |
SendBulkAsync(IEnumerable<SmsMessage>, ct) |
Task<BulkSendResult> |
Sends multiple SMS messages with per-message results |
SnsOptions
| Property | Type | Default | Description |
|---|---|---|---|
Region |
string |
"af-south-1" |
AWS region endpoint |
AccessKey |
string? |
null |
AWS access key (optional) |
SecretKey |
string? |
null |
AWS secret key (optional) |
SenderId |
string? |
null |
Default sender ID |
DefaultSmsType |
SmsType |
Transactional |
SMS type for carrier routing |
SNS Message Attributes
The service automatically sets the following SNS message attributes on each publish request:
| Attribute | Value | Description |
|---|---|---|
AWS.SNS.SMS.SMSType |
"Transactional" or "Promotional" |
Controls carrier routing priority |
AWS.SNS.SMS.SenderID |
Sender ID string | Displayed on recipient's device (when set) |
Integration with Other RepletoryLib Packages
| Package | Relationship |
|---|---|
RepletoryLib.Communication.Abstractions |
Direct dependency -- provides ISmsService, SmsMessage, SendResult |
RepletoryLib.Communication.Email |
Combine with email for multi-channel notifications |
RepletoryLib.Communication.WhatsApp |
Combine with WhatsApp for multi-channel notifications |
RepletoryLib.Communication.Push |
Combine with push for multi-channel notifications |
RepletoryLib.Common |
Transitive dependency via Abstractions |
Testing
using Moq;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using RepletoryLib.Communication.Abstractions.Enums;
using RepletoryLib.Communication.Abstractions.Models.Sms;
using RepletoryLib.Communication.Sms.Options;
using RepletoryLib.Communication.Sms.Services;
[Fact]
public async Task SendAsync_returns_success_with_message_id()
{
var mockSns = new Mock<IAmazonSimpleNotificationService>();
mockSns
.Setup(s => s.PublishAsync(It.IsAny<PublishRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new PublishResponse { MessageId = "sns-msg-001" });
var options = Options.Create(new SnsOptions
{
Region = "af-south-1",
SenderId = "TestApp",
DefaultSmsType = SmsType.Transactional
});
var service = new SnsSmsService(mockSns.Object, options, NullLogger<SnsSmsService>.Instance);
var result = await service.SendAsync(new SmsMessage
{
To = "+27821234567",
Body = "Your OTP is 123456"
});
result.Success.Should().BeTrue();
result.MessageId.Should().Be("sns-msg-001");
result.Channel.Should().Be(CommunicationChannel.Sms);
mockSns.Verify(s => s.PublishAsync(
It.Is<PublishRequest>(r =>
r.PhoneNumber == "+27821234567" &&
r.Message == "Your OTP is 123456" &&
r.MessageAttributes["AWS.SNS.SMS.SMSType"].StringValue == "Transactional" &&
r.MessageAttributes["AWS.SNS.SMS.SenderID"].StringValue == "TestApp"),
It.IsAny<CancellationToken>()), Times.Once);
}
Troubleshooting
| Issue | Solution |
|---|---|
AmazonSimpleNotificationServiceException: Access Denied |
Verify your AWS credentials and ensure the IAM role/user has sns:Publish permissions |
| SMS not delivered | Check the AWS SNS delivery status logs. Ensure the phone number is in E.164 format (e.g., +27821234567) |
| Sender ID not appearing | Sender IDs are not supported in all countries (e.g., the US). Check AWS SNS regional support |
DefaultSmsType not working |
Ensure the value is either Transactional or Promotional (case-sensitive in config) |
| Rate limiting errors | AWS SNS has regional SMS sending quotas. Request a quota increase via the AWS console |
SendResult.Error says "SMS service is not registered" |
Ensure AddRepletrySms(configuration) is called in Program.cs |
License
This project is licensed under the MIT License.
Copyright (c) 2024-2026 Repletory.
For complete documentation, infrastructure setup, and configuration reference, see the RepletoryLib main repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- AWSSDK.SimpleNotificationService (>= 3.7.400.98)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.0)
- RepletoryLib.Communication.Abstractions (>= 1.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 71 | 3/2/2026 |