Universal notification and messaging integrations for Go.
A Go library for sending notifications and messages across multiple platforms and services with a unified interface using the functional options pattern.
- 15+ integrations for popular messaging and notification services
- Fluent builder pattern for clean, readable configuration
- Built-in validation with compile-time type safety
- Comprehensive test coverage
- MongoDB support
- OpenTelemetry observability and tracing support
go get github.com/uug-ai/integrationspackage main
import (
"log"
"github.com/uug-ai/integrations/pkg/integrations"
)
func main() {
// Build SMTP options
opts := integrations.NewSMTPOptions().
Server("smtp.gmail.com").
Port(587).
Username("your-email@gmail.com").
Password("your-app-password").
From("sender@example.com").
To("recipient@example.com").
Build()
// Create SMTP client with options
smtp, err := integrations.NewSMTP(opts)
if err != nil {
log.Fatal(err)
}
// Send an email
err = smtp.Send(
"Email Subject",
"Plain text body",
"<h1>HTML body</h1>",
)
if err != nil {
log.Fatal(err)
}
}| Integration | Description | Status |
|---|---|---|
| Slack | Send messages to Slack channels | Ready |
| Telegram | Send messages via Telegram Bot API | Ready |
| Webhook | Generic HTTP webhooks | Ready |
| SMTP | Email via SMTP | Ready |
| SendGrid | Email via SendGrid API | Ready |
| Pushover | Push notifications to mobile devices | Ready |
| Pushbullet | Push notifications and file sharing | Ready |
| Pusher | Real-time messaging via Pusher | Ready |
| MQTT | IoT messaging protocol | Ready |
| Alexa | Amazon Alexa notifications | Ready |
| IFTTT | If This Then That automation | Ready |
| Tweet updates (via Twitter API) | Ready | |
| SMS | SMS via Twilio | Ready |
| Email via Mailgun | Ready | |
| MongoDB | Database storage integration | Ready |
All integrations use the options builder pattern (similar to MongoDB's driver). This provides:
- Clean Syntax: Build options separately, then pass to constructor
- Readability: Self-documenting method chains
- Separation of Concerns: Options building is separate from client creation
- Validation: Built-in validation when creating the client
- Type Safety: Compile-time type checking
- Flexibility: Configure only what you need
Each integration follows this pattern:
- Build Options using
integrations.New<Integration>Options()with method chaining - Call
.Build()to get the options object - Create Client by passing options to
integrations.New<Integration>(opts) - Send messages using the
Send()method
The SMTP integration demonstrates the options builder pattern:
package main
import (
"log"
"github.com/uug-ai/integrations/pkg/integrations"
)
func main() {
// Build SMTP options
opts := integrations.NewSMTPOptions().
Server("smtp.gmail.com").
Port(587).
Username("your-email@gmail.com").
Password("your-app-password").
From("sender@example.com").
To("recipient@example.com").
Build()
// Create SMTP client with options
smtp, err := integrations.NewSMTP(opts)
if err != nil {
log.Fatal(err)
}
// Send an email
err = smtp.Send(
"Email Subject", // title
"Plain text body", // body
"<h1>HTML body</h1>", // textBody (HTML alternative)
)
if err != nil {
log.Fatal(err)
}
}Available Methods:
.Server(server string)- SMTP server hostname.Port(port int)- SMTP server port.Username(username string)- Authentication username.Password(password string)- Authentication password.From(email string)- Sender email address.To(email string)- Recipient email address.Build()- Returns the SMTPOptions object
// Build Slack options
opts := integrations.NewSlackOptions().
Hook("https://hooks.slack.com/services/YOUR/WEBHOOK/URL").
Username("MyBot").
Build()
// Create Slack client
slack, err := integrations.NewSlack(opts)
if err != nil {
log.Fatal(err)
}
// Send a text message
err = slack.Send("Hello from Slack!", "")
// Send a message with an image attachment
err = slack.Send("Check out this image!", "https://example.com/image.png")Available Methods:
.Hook(hook string)- Slack webhook URL.Username(username string)- Bot username to display.Build()- Returns the SlackOptions object
.
├── pkg/
│ └── integrations/ # Core integration implementations
│ ├── alexa.go
│ ├── ifttt.go
│ ├── mail.go
│ ├── mongodb.go
│ ├── mqtt.go
│ ├── option.go # Generic functional option type
│ ├── pushbullet.go
│ ├── pusher.go
│ ├── pushover.go
│ ├── sendgrid.go
│ ├── slack.go
│ ├── sms.go
│ ├── smtp.go
│ ├── telegram.go
│ ├── twitter.go
│ └── webhook.go
├── main.go
├── go.mod
└── README.md
To create a new integration following the options builder pattern:
package integrations
// MyServiceOptions holds the configuration for MyService
type MyServiceOptions struct {
apiKey string `validate:"required"`
endpoint string `validate:"required,url"`
}// MyService represents a MyService client instance
type MyService struct {
options *MyServiceOptions
}// MyServiceOptionsBuilder provides a fluent interface for building MyService options
type MyServiceOptionsBuilder struct {
options *MyServiceOptions
}// NewMyServiceOptions creates a new MyService options builder
func NewMyServiceOptions() *MyServiceOptionsBuilder {
return &MyServiceOptionsBuilder{
options: &MyServiceOptions{},
}
}// APIKey sets the API key
func (b *MyServiceOptionsBuilder) APIKey(apiKey string) *MyServiceOptionsBuilder {
b.options.apiKey = apiKey
return b
}
// Endpoint sets the endpoint URL
func (b *MyServiceOptionsBuilder) Endpoint(endpoint string) *MyServiceOptionsBuilder {
b.options.endpoint = endpoint
return b
}
// Build returns the configured MyServiceOptions
func (b *MyServiceOptionsBuilder) Build() *MyServiceOptions {
return b.options
}// NewMyService creates a new MyService client with the provided options
func NewMyService(opts *MyServiceOptions) (*MyService, error) {
// Validate configuration
validate := validator.New()
err := validate.Struct(opts)
if err != nil {
return nil, err
}
return &MyService{
options: opts,
}, nil
}func (s *MyService) Send(message string) error {
// Use s.options.apiKey, s.options.endpoint, etc.
// Implementation here
return nil
}// Build options
opts := integrations.NewMyServiceOptions().
APIKey("your-api-key").
Endpoint("https://api.example.com").
Build()
// Create client with options
service, err := integrations.NewMyService(opts)
if err != nil {
log.Fatal(err)
}
// Use the client
err = service.Send("Hello, World!")All integrations use go-playground/validator for configuration validation. Common validation tags:
required- Field must not be emptyemail- Must be a valid email addressurl- Must be a valid URLgt=0- Must be greater than 0min=<value>- Minimum value/lengthmax=<value>- Maximum value/length
Validation is automatically performed when calling New<Integration>(opts), ensuring invalid configurations are caught before the client is created.
opts := integrations.NewSMTPOptions().
Server("smtp.gmail.com").
Port(587).
Username("user@example.com").
Password("password").
From("from@example.com").
To("to@example.com").
Build()
smtp, err := integrations.NewSMTP(opts)You can load configuration from environment variables:
import "os"
opts := integrations.NewSMTPOptions().
Server(os.Getenv("SMTP_SERVER")).
Port(587).
Username(os.Getenv("SMTP_USERNAME")).
Password(os.Getenv("SMTP_PASSWORD")).
From(os.Getenv("SMTP_FROM")).
To(os.Getenv("SMTP_TO")).
Build()
smtp, err := integrations.NewSMTP(opts)Example .env file:
# SMTP Configuration
SMTP_SERVER=smtp.gmail.com
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM=sender@example.com
SMTP_TO=recipient@example.com
# Slack Configuration
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
SLACK_USERNAME=MyBot
# Telegram Configuration
TELEGRAM_BOT_TOKEN=your_token
TELEGRAM_CHANNEL_ID=your_channelThe options builder pattern provides clear error handling:
// Build options (no error here)
opts := integrations.NewSMTPOptions().
Server("smtp.gmail.com").
Port(587).
// Missing required fields...
Build()
// Validation happens when creating the client
smtp, err := integrations.NewSMTP(opts)
if err != nil {
// Validation error caught at client creation time
log.Printf("Configuration error: %v", err)
return
}
// If we get here, the configuration is valid
err = smtp.Send("Subject", "Body", "<h1>HTML</h1>")
if err != nil {
// Runtime error during send
log.Printf("Send error: %v", err)
return
}Run the test suite:
go test ./...Run tests with coverage:
go test -cover ./...Run tests for a specific integration:
# SMTP tests
go test ./pkg/integrations -run TestSMTP
# Slack tests
go test ./pkg/integrations -run TestSlackRun all integration tests:
go test ./pkg/integrations/... -vContributions are welcome! When adding new integrations, please follow the options builder pattern demonstrated in this repository.
- Fork the repository
- Create a feature branch (
git checkout -b feat/amazing-feature) - Follow the options builder pattern (see "Creating a New Integration" above)
- Add comprehensive tests for your integration
- Ensure all tests pass:
go test ./... - Add usage examples to the README
- Commit your changes following Conventional Commits
- Push to your branch (
git push origin feat/amazing-feature) - Open a Pull Request
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, types
Scopes:
models- Changes to data structuresapi- API-related changestypes- Type definitionsdocs- Documentation updates- Integration names (e.g.,
smtp,slack,telegram)
Examples:
feat(smtp): add options builder pattern implementation
feat(telegram): add options builder with method chaining
fix(slack): correct webhook payload formatting
docs(readme): update usage examples with options builder pattern
refactor(pushover): migrate to options builder pattern
test(smtp): add validation tests
This project is licensed under the MIT License - see the LICENSE file for details.
This project uses the following key libraries:
- go-playground/validator - Struct validation
- slack-go/slack - Slack API in Go
- telegram-bot-api - Telegram Bot API
- sendgrid-go - SendGrid email API
- mongo-driver - MongoDB driver
- paho.mqtt.golang - MQTT client
- gomail - SMTP email library
See go.mod for the complete list of dependencies.
Build options separately from client creation:
opts := integrations.NewSMTPOptions().
Server("smtp.gmail.com").
Port(587).
Build()
smtp, err := integrations.NewSMTP(opts)Options building is completely separate from client creation, following the same pattern as MongoDB's official driver.
Compile-time type checking prevents configuration errors.
Configure only the options you need. Method chaining is optional.
Built-in validation when creating the client ensures configurations are correct before use, catching errors early.
Adding new builder methods doesn't break existing code. Simply add new chainable methods to the options builder.
Self-documenting fluent API makes code easy to read and understand:
// Clear and readable - MongoDB style
opts := integrations.NewSMTPOptions().
Server("smtp.gmail.com").
Port(587).
Username("user@example.com").
Password("password").
From("from@example.com").
To("to@example.com").
Build()
smtp, err := integrations.NewSMTP(opts)- Issues: GitHub Issues
- Discussions: GitHub Discussions