Skip to content
GitHubDiscord

Notification (lexigram-notification)

SMS, push, and email notification delivery with Named DI multi-backend support for the Lexigram Framework.


lexigram-notification provides a unified notification delivery system with SMS (Twilio), push (FCM, APNS), email (SMTP, SendGrid), and per-user inbox storage. The package is organized into three subpackages: root (SMS/push), mail (email), and inbox (in-app notification storage) — each wired separately via its own module.


Terminal window
uv add lexigram-notification
# With SendGrid email
uv add "lexigram-notification[sendgrid]"
# With Twilio SMS
uv add "lexigram-notification[twilio]"
# With APNS push
uv add "lexigram-notification[apns]"
from lexigram.di.module import Module, module
from lexigram.notification import NotificationModule
from lexigram.notification.config import (
FCMDriverConfig,
NamedPushConfig,
NamedSMSConfig,
NotificationConfig,
TwilioDriverConfig,
)
from lexigram.notification.mail import MailerModule
from lexigram.notification.mail.config import (
MailerConfig,
NamedMailerConfig,
SMTPDriverConfig,
)
from lexigram.notification.inbox import InboxConfig, InboxModule
@module(
imports=[
NotificationModule.configure(
NotificationConfig(
sms_backends=[
NamedSMSConfig(
name="alerts",
primary=True,
driver="twilio",
twilio=TwilioDriverConfig(
account_sid="AC...",
auth_token="secret",
from_number="+15550000000",
),
)
],
push_backends=[
NamedPushConfig(
name="mobile",
primary=True,
driver="fcm",
fcm=FCMDriverConfig(server_key="fcm-key"),
)
],
)
),
MailerModule.configure(
MailerConfig(
backends=[
NamedMailerConfig(
name="transactional",
primary=True,
driver="smtp",
from_email="noreply@example.com",
smtp=SMTPDriverConfig(host="smtp.example.com", port=587),
)
]
)
),
InboxModule.configure(InboxConfig(store_backend="memory")),
]
)
class AppModule(Module):
pass

Zero-config usage: Call any .configure() with no arguments to use all defaults.

application.yaml
notification:
sms_backends: []
push_backends: []
mailer:
backends:
- name: transactional
primary: true
driver: smtp
from_email: "noreply@example.com"
smtp:
host: "smtp.example.com"
port: 587
inbox:
store_backend: "database"
retention_days: 30
Section titled “Option 2 — Profiles + Environment Variables (recommended)”
Terminal window
export LEX_NOTIFICATION__ENABLED=true
export LEX_NOTIFICATION__INBOX__STORE_BACKEND=database
from lexigram.notification import NotificationModule
from lexigram.notification.config import NotificationConfig
from lexigram.notification.mail import MailerModule
from lexigram.notification.mail.config import MailerConfig, NamedMailerConfig, SMTPDriverConfig
from lexigram.notification.inbox import InboxModule
from lexigram.notification.inbox.config import InboxConfig
NotificationModule.configure(NotificationConfig())
MailerModule.configure(
MailerConfig(
backends=[
NamedMailerConfig(
name="transactional",
primary=True,
driver="smtp",
from_email="noreply@example.com",
smtp=SMTPDriverConfig(host="smtp.example.com", port=587),
)
]
)
)
InboxModule.configure(InboxConfig(store_backend="database"))
FieldDefaultEnv varDescription
notification.sms_backends[]LEX_NOTIFICATION__SMS_BACKENDSNamed SMS backend configs
notification.push_backends[]LEX_NOTIFICATION__PUSH_BACKENDSNamed push backend configs
mailer.backends[n].driverLEX_NOTIFICATION__MAILER__BACKENDS__N__DRIVERMailer driver: smtp, sendgrid
mailer.backends[n].from_emailLEX_NOTIFICATION__MAILER__BACKENDS__N__FROM_EMAILSender email address
inbox.store_backend"database"LEX_NOTIFICATION__INBOX__STORE_BACKENDInbox store: database or memory
inbox.retention_days30LEX_NOTIFICATION__INBOX__RETENTION_DAYSDays to retain inbox messages
inbox.max_page_size50LEX_NOTIFICATION__INBOX__MAX_PAGE_SIZEMax messages returned per page
MethodDescription
NotificationModule.configure(config)Register SMS and push backends; exports SMSChannelProtocol, PushChannelProtocol
NotificationModule.stub()Empty config — no backends configured
MailerModule.configure(config)Register named mailer backends; exports MailerProtocol
MailerModule.stub(config=None)Empty or caller-supplied config for tests
InboxModule.configure(config)Register InboxStoreProtocol and InboxService
InboxModule.stub()In-memory inbox for tests
  • SMS delivery — Twilio backend via TwilioSMS
  • Push delivery — FCM and APNS backends with send_batch() support
  • Email delivery — SMTP (blocking, runs in executor) and SendGrid REST API
  • Retrying mailer — wraps any MailerProtocol with exponential backoff and delivery-store tracking
  • Per-user inbox — SQL or in-memory backend with InboxService (send, get_inbox, mark_read, delete, count_unread)
  • Named DI multi-backend — multiple backends registered via Annotated[QueueProtocol, Named("events")]
FileWhat it contains
src/lexigram/notification/module.pyNotificationModule.configure(), .stub()
src/lexigram/notification/config.pyNotificationConfig, NamedSMSConfig, NamedPushConfig
src/lexigram/notification/di/provider.pyNotificationProvider
src/lexigram/notification/mail/module.pyMailerModule.configure(), .stub()
src/lexigram/notification/mail/config.pyMailerConfig, NamedMailerConfig, SMTPDriverConfig
src/lexigram/notification/mail/di/provider.pyMailerProvider
src/lexigram/notification/inbox/module.pyInboxModule.configure(), .stub()
src/lexigram/notification/inbox/config.pyInboxConfig
src/lexigram/notification/inbox/di/provider.pyInboxProvider
src/lexigram/notification/inbox/service.pyInboxService