sms

package module
v0.0.0-...-713ea49 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 5, 2025 License: MIT Imports: 6 Imported by: 0

README

go-sms

A flexible and extensible Go module for sending SMS messages and voice calls through multiple providers with a unified API.

Overview

go-sms is a service component library that enables Go applications to send SMS messages and voice calls through various providers using a standardized interface. Instead of integrating with multiple SMS provider APIs directly, you can use go-sms as an abstraction layer to simplify your code and make it more maintainable.

Key Features
  • Unified API: Send SMS and voice calls through any supported provider with the same API
  • Multiple Providers: Support for various SMS providers including Twilio, eSMS, and SpeedSMS
  • Provider Management: Easily switch between providers at runtime
  • Message Templates: Dynamic message content with template variable substitution
  • Configuration Management: Simple YAML-based configuration with validation
  • Retry Mechanism: Built-in retry logic with exponential backoff
  • Extensible Architecture: Easily add new provider adapters

Installation

Core Module
go get github.com/go-fork/sms
Provider Adapters

Install only the provider adapters you need:

# For Twilio
go get github.com/go-fork/sms/adapters/twilio

# For eSMS (Vietnam)
go get github.com/go-fork/sms/adapters/esms

# For SpeedSMS (Vietnam)
go get github.com/go-fork/sms/adapters/speedsms

Quick Start

1. Create a Configuration File

Create a config.yaml file with your provider credentials:

# Default provider to use
default_provider: twilio

# HTTP client configuration
http_timeout: 10s

# Retry configuration
retry_attempts: 3
retry_delay: 500ms

# Default message templates
sms_template: "Your message from {app_name}: {message}"
voice_template: "Your message from {app_name} is {message}"

# Provider configurations
providers:
  twilio:
    account_sid: your_account_sid
    auth_token: your_auth_token
    from_number: +1234567890
  esms:
    api_key: your_api_key
    secret: your_secret_key
    brandname: your_brandname
  speedsms:
    token: your_access_token
    sender: your_sender_id
2. Initialize the Module and Send an SMS
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/go-fork/sms"
	"github.com/go-fork/sms/adapters/twilio"
	"github.com/go-fork/sms/model"
)

func main() {
	// Initialize the SMS module with configuration
	module, err := sms.NewModule("./config.yaml")
	if err != nil {
		log.Fatalf("Failed to initialize SMS module: %v", err)
	}

	// Initialize and add the Twilio provider
	twilioProvider, err := twilio.NewProvider("./config.yaml")
	if err != nil {
		log.Fatalf("Failed to initialize Twilio provider: %v", err)
	}
	err = module.AddProvider(twilioProvider)
	if err != nil {
		log.Fatalf("Failed to add Twilio provider: %v", err)
	}

	// Create a context with timeout
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// Create an SMS request
	request := model.SendSMSRequest{
		Message: model.Message{
			From: "", // Use default from number in config
			To:   "+1234567890", // Recipient's phone number
			By:   "MyApp", // Your application's name
		},
		Data: map[string]interface{}{
			"app_name": "MyApp",
			"message":  "Hello from go-sms!",
		},
	}

	// Send the SMS
	response, err := module.SendSMS(ctx, request)
	if err != nil {
		log.Fatalf("Failed to send SMS: %v", err)
	}

	fmt.Printf("SMS sent successfully! Message ID: %s\n", response.MessageID)
}

Configuration Options

Top-Level Configuration
Option Description Default Example
default_provider Name of the default provider to use "twilio"
http_timeout Timeout for HTTP requests 10s "30s"
retry_attempts Number of retry attempts 3 5
retry_delay Initial delay between retries 500ms "1s"
sms_template Default template for SMS messages "Your message is {message}" "Message from {app_name}: {message}"
voice_template Default template for voice calls "Your message is {message}" "Message from {app_name}: {message}"
Provider-Specific Configuration
Twilio
providers:
  twilio:
    account_sid: your_account_sid  # Required
    auth_token: your_auth_token    # Required
    from_number: +1234567890       # Required - must be in E.164 format
    region: us1                    # Optional - defaults to "us1"
    api_version: 2010-04-01        # Optional - defaults to "2010-04-01"
eSMS (Vietnam)
providers:
  esms:
    api_key: your_api_key          # Required
    secret: your_secret_key        # Required
    brandname: your_brandname      # Required for branded messages
    sms_type: 2                    # Optional - defaults to 2 (2=branded, 4=OTP)
    base_url: http://rest.esms.vn/api  # Optional
SpeedSMS (Vietnam)
providers:
  speedsms:
    token: your_access_token       # Required
    sender: your_sender_id         # Optional
    sms_type: 2                    # Optional - defaults to 2
    base_url: https://api.speedsms.vn/index.php  # Optional

Message Model and Templates

The message model represents the core information needed to send a message:

type Message struct {
	From string // Sender identifier (phone number, brandname)
	To   string // Recipient's phone number
	By   string // Application identifier (e.g., "MyApp")
}
Template Variables

You can use the following variables in your message templates:

  • {from}: The sender's identifier
  • {to}: The recipient's phone number
  • {by}: The application identifier
  • Any custom variables provided in the Data map
Example Templates
# Basic template
sms_template: "Your message is {message}"

# More detailed template
sms_template: "Hello from {app_name}! Your verification code is {code}."

# Template with transaction information
sms_template: "Your order #{order_id} has been confirmed. Total: ${amount}."

API Reference

Module Initialization
func NewModule(configFile string) (*Module, error)
Provider Management
func (m *Module) AddProvider(provider model.Provider) error
func (m *Module) SwitchProvider(name string) error
func (m *Module) GetProvider(name string) (model.Provider, error)
func (m *Module) GetActiveProvider() (model.Provider, error)
Sending Messages
func (m *Module) SendSMS(ctx context.Context, req model.SendSMSRequest) (model.SendSMSResponse, error)
func (m *Module) SendVoiceCall(ctx context.Context, req model.SendVoiceRequest) (model.SendVoiceResponse, error)
Request Structures
type SendSMSRequest struct {
	Message  model.Message
	Template string // Optional - overrides config template
	Data     map[string]interface{}
	Options  map[string]interface{} // Provider-specific options
}

type SendVoiceRequest struct {
	Message  model.Message
	Template string // Optional - overrides config template
	Data     map[string]interface{}
	Options  map[string]interface{} // Provider-specific options
}
Response Structures
type SendSMSResponse struct {
	MessageID        string
	Status           MessageStatus
	Provider         string
	SentAt           time.Time
	Cost             float64 // Optional
	Currency         string  // Optional
	ProviderResponse map[string]interface{}
}

type SendVoiceResponse struct {
	CallID           string
	Status           CallStatus
	Provider         string
	StartedAt        time.Time
	EndedAt          *time.Time // Optional
	Duration         int        // In seconds
	Cost             float64    // Optional
	Currency         string     // Optional
	ProviderResponse map[string]interface{}
}

Examples

See the /examples directory for more comprehensive examples:

  • examples/simple/main.go: Basic usage example
  • examples/template/main.go: Examples of using templates
  • examples/multi-provider/main.go: Working with multiple providers

Performance Benchmarks

The go-sms module is designed for high performance and reliability:

Operation Average Latency Throughput (msgs/sec)
SMS Sending ~200-500ms Up to 100 with rate limiting
Voice Call Initiation ~300-700ms Up to 20 with rate limiting
Template Rendering <1ms >10,000
Provider Switching <1ms >5,000

Benchmarks performed on standard cloud infrastructure. Your results may vary depending on network conditions and provider responsiveness.

Integration Examples

With Web Frameworks
Using with Gin
import (
    "github.com/gin-gonic/gin"
    "github.com/go-fork/sms"
    "github.com/go-fork/sms/adapters/twilio"
)

func setupRouter(smsModule *sms.Module) *gin.Engine {
    r := gin.Default()
    
    r.POST("/send-sms", func(c *gin.Context) {
        var req struct {
            PhoneNumber string `json:"phone_number" binding:"required"`
            Message     string `json:"message" binding:"required"`
        }
        
        if err := c.ShouldBindJSON(&req); err != nil {
            c.JSON(400, gin.H{"error": err.Error()})
            return
        }
        
        smsRequest := model.SendSMSRequest{
            Message: model.Message{
                To: req.PhoneNumber,
                By: "WebApp",
            },
            Data: map[string]interface{}{
                "message": req.Message,
            },
        }
        
        resp, err := smsModule.SendSMS(c.Request.Context(), smsRequest)
        if err != nil {
            c.JSON(500, gin.H{"error": err.Error()})
            return
        }
        
        c.JSON(200, gin.H{
            "message_id": resp.MessageID,
            "status": resp.Status,
        })
    })
    
    return r
}
Using with Echo
import (
    "github.com/labstack/echo/v4"
    "github.com/go-fork/sms"
)

func setupRoutes(e *echo.Echo, smsModule *sms.Module) {
    e.POST("/send-sms", func(c echo.Context) error {
        // Implementation similar to Gin example
    })
}
With GORM for Notifications
import (
    "gorm.io/gorm"
    "github.com/go-fork/sms"
)

type Notification struct {
    gorm.Model
    UserID      uint
    PhoneNumber string
    Message     string
    Status      string
    MessageID   string
}

func SendPendingNotifications(db *gorm.DB, smsModule *sms.Module) error {
    var notifications []Notification
    
    // Find pending notifications
    result := db.Where("status = ?", "pending").Find(&notifications)
    if result.Error != nil {
        return result.Error
    }
    
    for _, notification := range notifications {
        // Send SMS
        req := model.SendSMSRequest{
            Message: model.Message{
                To: notification.PhoneNumber,
                By: "DatabaseNotifier",
            },
            Data: map[string]interface{}{
                "message": notification.Message,
            },
        }
        
        resp, err := smsModule.SendSMS(context.Background(), req)
        
        // Update notification status
        if err != nil {
            db.Model(&notification).Updates(map[string]interface{}{
                "status": "failed",
            })
        } else {
            db.Model(&notification).Updates(map[string]interface{}{
                "status": string(resp.Status),
                "message_id": resp.MessageID,
            })
        }
    }
    
    return nil
}

Comparison with Other Solutions

Feature go-sms aws-sdk-go (SNS) messagebird/go-rest-api twilio-go
Multiple Providers
Template System
Voice Calls
Provider Switching
Retry Logic
Configuration Management
Vietnamese Providers

Community and Support

  • GitHub Issues: For bug reports and feature requests
  • Discussions: For questions and community support
  • Contributing: See CONTRIBUTING.md for guidelines

Roadmap

Future plans for go-sms include:

  • Additional Providers: Implementing more international and regional SMS providers
  • Advanced Analytics: Message delivery tracking and reporting
  • Batch Sending: Optimized bulk messaging capabilities
  • Scheduling: Time-delayed message delivery
  • Webhooks: Support for delivery status callbacks
  • Admin Dashboard: Web interface for managing and monitoring messages

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module represents the main SMS module that manages providers and handles message sending

func NewModule

func NewModule(configFile string) (*Module, error)

NewModule creates a new SMS module instance with the given configuration file

func (*Module) AddProvider

func (m *Module) AddProvider(provider model.Provider) error

AddProvider registers a provider with the module

func (*Module) GetActiveProvider

func (m *Module) GetActiveProvider() (model.Provider, error)

GetActiveProvider returns the currently active provider

func (*Module) GetProvider

func (m *Module) GetProvider(name string) (model.Provider, error)

GetProvider returns a provider by name

func (*Module) SendSMS

SendSMS sends an SMS message using the active provider with retry logic

func (*Module) SendVoiceCall

func (m *Module) SendVoiceCall(ctx context.Context, req model.SendVoiceRequest) (model.SendVoiceResponse, error)

SendVoiceCall initiates a voice call using the active provider with retry logic

func (*Module) SwitchProvider

func (m *Module) SwitchProvider(name string) error

SwitchProvider changes the active provider to the one with the specified name

Directories

Path Synopsis
adapters
esms module
speedsms module
twilio module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL