GoAuth
Modules

Notification Module

The Notification Module is GoAuth's delivery layer for all transactional email and SMS communication. It subscribes to events emitted by other modules…

The Notification Module is GoAuth's delivery layer for all transactional email and SMS communication. It subscribes to events emitted by other modules (Core, Magic Link, Invitation, Organization) and automatically delivers the appropriate message — verification emails, password reset links, welcome messages, login alerts, invitations, and magic links. It does not expose any HTTP routes and does not own any business logic; it is a pure, event-driven delivery layer.

The module is designed to be fully pluggable. You can use the built-in senders for common providers, or implement the EmailSender / SMSSender interfaces to integrate any email or SMS service. Templates are customizable per message type with branding injection.

Capabilities

  • Automatic Event-Driven Delivery — Subscribes to lifecycle events and sends the right message automatically. No manual "send email" calls needed in your application code.
  • Multiple Email Providers — Built-in support for SendGrid, SMTP, and Resend. Switch providers by changing one line of configuration.
  • SMS Delivery — Built-in Twilio integration for phone verification OTPs, password reset codes, and login alerts.
  • Pluggable Senders — Implement EmailSender or SMSSender to integrate any provider (Amazon SES, Mailgun, Postmark, MessageBird, Vonage, etc.).
  • Custom Templates — Override any built-in email or SMS template with your own. Templates support Go template syntax with automatic branding variable injection.
  • Branding — Configure app name, logo, colors, footer text, and contact email once. Every template receives these values automatically.
  • Per-Feature Toggle — Enable welcome emails, login alerts, and password-change alerts with the three informational flags. Delivery hooks for verification, password reset, magic links, and invitations are always registered.
  • Template Defaults — Call DefaultEmailTemplates() or DefaultSMSTemplates() to get the full default template map as a starting point for customization.

Pluggable Infrastructure

The Notification module accepts any implementation of these interfaces. This is the primary extensibility point — implement one or both to use your preferred email/SMS provider:

type EmailSender interface {
    // SendEmail delivers an email message. Return an error to indicate delivery failure.
    SendEmail(ctx context.Context, message *EmailMessage) error

    // VerifyConfig validates the sender configuration at module init time.
    VerifyConfig(ctx context.Context) error
}

type SMSSender interface {
    // SendSMS delivers an SMS message. Return an error to indicate delivery failure.
    SendSMS(ctx context.Context, message *SMSMessage) error

    // VerifyConfig validates the sender configuration at module init time.
    VerifyConfig(ctx context.Context) error
}

Pass your custom sender in the module config:

if err := a.Use(notification.New(&notification.Config{
    EmailSender: myCustomEmailSender, // implements notification.EmailSender
    SMSSender:   myCustomSMSSender,   // implements notification.SMSSender
})); err != nil {
    return err
}

Built-in Senders

ProviderTypeConstructor
SendGridEmailsenders.NewSendGridEmailSender(&senders.SendGridConfig{...})
SMTPEmailsenders.NewSMTPEmailSender(&senders.SMTPConfig{...})
ResendEmailsenders.NewResendEmailSender(&senders.ResendConfig{...})
TwilioSMSsenders.NewTwilioSMSSender(&senders.TwilioConfig{...})

Providers

  • Email: SendGrid, SMTP, Resend (or any custom EmailSender implementation)
  • SMS: Twilio (or any custom SMSSender implementation)

Registration

import (
    "github.com/bete7512/goauth/pkg/modules/notification"
    "github.com/bete7512/goauth/pkg/modules/notification/senders"
)

if err := a.Use(notification.New(&notification.Config{
    EmailSender: senders.NewSendGridEmailSender(&senders.SendGridConfig{
        APIKey:          "SG.xxxxx",
        DefaultFrom:     "noreply@yourapp.com",
        DefaultFromName: "Your App",
    }),

    SMSSender: senders.NewTwilioSMSSender(&senders.TwilioConfig{
        AccountSID: "ACxxxxx",
        AuthToken:  "your-auth-token",
        FromNumber: "+1234567890",
    }),

    Branding: &notification.Branding{
        AppName:      "Your App",
        LogoURL:      "https://yourapp.com/logo.png",
        PrimaryColor: "#4F46E5",
        TextColor:    "#333333",
        ContactEmail: "support@yourapp.com",
        DomainName:   "yourapp.com",
        FooterText:   "(c) 2026 Your App. All rights reserved.",
    },

    EnableWelcomeEmail:        true,
    EnableLoginAlerts:         true,
    EnablePasswordChangeAlert: true,
})); err != nil {
    return err
}

Pass nil for default config (welcome email + password change alert enabled).

Must-have vs optional emails

Must-have delivery emails (password reset, magic link, invitations, email and phone verification) are always active when the notification module is registered. They only fire when the corresponding module emits the event -- no toggle needed.

Optional informational emails (welcome, login alerts, password change alerts) are controlled by config flags.

Configuration

type Config struct {
    EmailSender             notification.EmailSender            // Email provider (optional)
    SMSSender               notification.SMSSender              // SMS provider (optional)
    Branding                *notification.Branding              // Template branding (optional)
    EmailTemplates          map[string]notification.EmailTemplate // Override email templates by name
    SMSTemplates            map[string]notification.SMSTemplate   // Override SMS templates by name

    // Optional informational emails (off by default unless explicitly enabled)
    EnableWelcomeEmail        bool
    EnableLoginAlerts         bool
    EnablePasswordChangeAlert bool
}

Branding

The Branding struct is injected into every email template automatically:

type Branding struct {
    AppName      string // e.g. "Acme Corp" -- used in subject lines and headings
    LogoURL      string // Absolute URL to product logo (displayed in email header)
    PrimaryColor string // Hex color for buttons and header background, e.g. "#007bff"
    TextColor    string // Hex color for body text, defaults to "#333333"
    ContactEmail string // Support email shown in footer
    DomainName   string // Product domain shown in footer
    FooterText   string // Custom footer line
}

If nil, defaults to AppName: "GoAuth", PrimaryColor: "#007bff", TextColor: "#333333".

Email Providers

SendGrid

emailSender := senders.NewSendGridEmailSender(&senders.SendGridConfig{
    APIKey:          "SG.xxxxx",
    DefaultFrom:     "noreply@yourapp.com",
    DefaultFromName: "Your App",
})

SMTP

emailSender := senders.NewSMTPEmailSender(&senders.SMTPConfig{
    Host:            "smtp.gmail.com",
    Port:            587,
    Username:        "your-email@gmail.com",
    Password:        "your-16-char-app-password",
    DefaultFrom:     "noreply@yourapp.com",
    DefaultFromName: "Your App",
    UseTLS:          true,
})

Resend

emailSender := senders.NewResendEmailSender(&senders.ResendConfig{
    APIKey:          "re_xxxxx",
    DefaultFrom:     "noreply@yourapp.com",
    DefaultFromName: "Your App",
})

SMS Provider

Twilio

smsSender := senders.NewTwilioSMSSender(&senders.TwilioConfig{
    AccountSID: "ACxxxxx",
    AuthToken:  "your-auth-token",
    FromNumber: "+1234567890",
})

Custom Templates

Override built-in templates by providing EmailTemplates or SMSTemplates maps:

if err := a.Use(notification.New(&notification.Config{
    EmailSender: emailSender,
    EmailTemplates: map[string]notification.EmailTemplate{
        "welcome": {
            Name:     "welcome",
            Subject:  "Welcome to {{.Brand.AppName}}!",
            TextBody: "Hi {{.UserName}}, welcome!",
            HTMLBody: "<h1>Welcome {{.UserName}}</h1>",
        },
    },
    SMSTemplates: map[string]notification.SMSTemplate{
        "password_reset": {
            Name: "password_reset",
            Body: "{{.Brand.AppName}}: Reset code {{.Code}}, valid {{.ExpiryTime}}.",
        },
    },
})); err != nil {
    return err
}

Built-in email template names

welcome, email_verification, password_reset, password_changed, two_factor_code, login_alert, magic_link, invitation, org_invitation

Templates named two_factor_code are available for customization, but the module does not subscribe to a 2FA-code event or send TOTP codes automatically. TOTP codes come from the user’s authenticator.

Built-in SMS template names

password_reset, phone_verification, two_factor_code, login_alert

Use notification.DefaultEmailTemplates() or notification.DefaultSMSTemplates() to get the full default maps as a starting point.

Event Hooks

The module subscribes to events via RegisterHooks. Must-have delivery hooks are always registered; optional hooks are controlled by config flags.

Always active (fire only when the corresponding module emits the event):

EventAction
EventSendEmailVerificationEmail verification delivery
EventSendPhoneVerificationPhone verification SMS
EventSendPasswordResetEmailPassword reset email/SMS
EventSendMagicLinkMagic link email
EventInvitationSentStandalone invitation email
EventOrgInvitationSentOrganization invitation email

Optional (controlled by config flags):

EventActionConfig Flag
EventAfterSignupWelcome emailEnableWelcomeEmail
EventAfterChangePasswordPassword changed alertEnablePasswordChangeAlert
EventAfterResetPasswordPassword changed alertEnablePasswordChangeAlert
EventAfterLoginLogin alertEnableLoginAlerts

Sender Interfaces

Implement these to plug in a custom email or SMS provider:

type EmailSender interface {
    SendEmail(ctx context.Context, message *notification.EmailMessage) error
    VerifyConfig(ctx context.Context) error
}

type SMSSender interface {
    SendSMS(ctx context.Context, message *notification.SMSMessage) error
    VerifyConfig(ctx context.Context) error
}

Testing

Use Mailtrap or Ethereal for development:

emailSender := senders.NewSMTPEmailSender(&senders.SMTPConfig{
    Host:     "smtp.ethereal.email",
    Port:     587,
    Username: "your-ethereal-username",
    Password: "your-ethereal-password",
})

Extensibility

Writing a Custom Email Sender

Implement the EmailSender interface to integrate any email provider:

type MyEmailSender struct {
    apiKey string
}

func (s *MyEmailSender) SendEmail(ctx context.Context, msg *notification.EmailMessage) error {
    // msg.To, msg.Subject, msg.HTMLBody, msg.TextBody, msg.From, msg.FromName
    // Send via your provider's API
    return nil
}

func (s *MyEmailSender) VerifyConfig(ctx context.Context) error {
    // Validate API key, check connectivity, etc.
    // Called during module initialization
    return nil
}

Writing a Custom SMS Sender

Implement the SMSSender interface to integrate any SMS provider:

type MySMSSender struct {
    apiKey string
}

func (s *MySMSSender) SendSMS(ctx context.Context, msg *notification.SMSMessage) error {
    // msg.To, msg.Body, msg.From
    // Send via your provider's API
    return nil
}

func (s *MySMSSender) VerifyConfig(ctx context.Context) error {
    // Validate credentials at init time
    return nil
}

Async Event Processing

Notification delivery is processed asynchronously via the event system. By default, GoAuth uses an in-memory worker pool (10 workers, 1000 queue size). Use DurableEvents with an outbox-capable transactional store for supported durable operations. External backends implement types.AsyncBackend; acknowledged delivery has a separate capability. Delivery is at least once, so handlers should deduplicate by event ID. See the Enterprise page for details.

Next Steps

Edit this page on GitHub

On this page