A comprehensive, production-grade XMPP library for Go supporting both client and server roles with a plugin architecture covering 50+ XEPs.
- Unified client/server
Sessiontype - Plugin architecture with dependency resolution
- Streaming XML parser optimized for XMPP
- Multiple transports: TCP, WebSocket, BOSH
- Full SASL support: PLAIN, SCRAM-SHA-1/256/512 (+PLUS), EXTERNAL, ANONYMOUS
- STARTTLS with certificate verification
- Stanza multiplexer with middleware support
- DNS SRV and host-meta resolution
- Pluggable storage backends: Memory, File, SQLite, PostgreSQL, MySQL, MongoDB, Redis
go get github.com/meszmate/xmpp-gopackage main
import (
"context"
"log"
xmpp "github.com/meszmate/xmpp-go"
"github.com/meszmate/xmpp-go/jid"
"github.com/meszmate/xmpp-go/stanza"
"github.com/meszmate/xmpp-go/plugins/disco"
"github.com/meszmate/xmpp-go/plugins/roster"
)
func main() {
client, err := xmpp.NewClient(
jid.MustParse("user@example.com"),
"password",
xmpp.WithPlugins(disco.New(), roster.New()),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
ctx := context.Background()
if err := client.Connect(ctx); err != nil {
log.Fatal(err)
}
msg := stanza.NewMessage(stanza.MessageChat)
msg.To = jid.MustParse("friend@example.com")
msg.Body = "Hello from xmpp-go!"
_ = client.Send(ctx, msg)
}xmpp-go provides a standalone registration flow in plugins/register for account creation before authentication.
The helper functions automatically handle stream setup, STARTTLS upgrade, classic register fields, and data-form registration.
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/meszmate/xmpp-go/plugins/register"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
form, err := register.FetchRegistrationForm(ctx, "example.com", 5222)
if err != nil {
log.Fatal(err)
}
fields := map[string]string{
"username": "newuser",
"password": "strong-password",
"email": "newuser@example.com",
}
result, err := register.SubmitRegistration(
ctx,
"example.com",
5222,
fields,
form.IsDataForm,
form.FormType,
)
if err != nil {
log.Fatal(err)
}
if !result.Success {
log.Fatal(result.Error)
}
fmt.Println("Registered JID:", result.JID)
}For data-form registration, include all required fields from the fetched form in fields (including hidden fields and CAPTCHA answers when requested).
- JID parsing and validation (RFC 7622)
- JID escaping (XEP-0106)
- XML stream reader/writer
- Stream error conditions
- STARTTLS negotiation
- SASL authentication
- Resource binding
- Stanza types: Message, Presence, IQ
- Stanza error conditions
- Roster management (RFC 6121)
- Presence management (RFC 6121)
- TCP transport
- WebSocket transport (RFC 7395)
- BOSH transport (XEP-0124/0206)
- PLAIN
- SCRAM-SHA-1 / SCRAM-SHA-1-PLUS
- SCRAM-SHA-256 / SCRAM-SHA-256-PLUS
- SCRAM-SHA-512 / SCRAM-SHA-512-PLUS
- EXTERNAL
- ANONYMOUS
- XEP-0030: Service Discovery
- XEP-0115: Entity Capabilities
- XEP-0085: Chat State Notifications
- XEP-0184: Message Delivery Receipts
- XEP-0280: Message Carbons
- XEP-0308: Last Message Correction
- XEP-0313: Message Archive Management
- XEP-0333: Chat Markers
- XEP-0334: Message Processing Hints
- XEP-0359: Unique/Stable Stanza IDs
- XEP-0393: Message Styling
- XEP-0424: Message Retraction
- XEP-0444: Message Reactions
- XEP-0045: Multi-User Chat
- XEP-0249: Direct MUC Invitations
- XEP-0369: MIX Core
- XEP-0403/0405/0406/0407: MIX extensions
- XEP-0425: Message Moderation
- XEP-0198: Stream Management
- XEP-0004: Data Forms
- XEP-0060: Publish-Subscribe
- XEP-0163: Personal Eventing Protocol
- XEP-0402: PEP Native Bookmarks
- XEP-0054: vcard-temp
- XEP-0084: User Avatar
- XEP-0092: Software Version
- XEP-0153: vCard-Based Avatars
- XEP-0292: vCard4 over XMPP
- XEP-0047: In-Band Bytestreams
- XEP-0065: SOCKS5 Bytestreams
- XEP-0066: Out of Band Data
- XEP-0234: Jingle File Transfer
- XEP-0363: HTTP File Upload
- XEP-0446/0447/0448: Stateless File Sharing
- XEP-0380: Explicit Message Encryption
- XEP-0384: OMEMO Encryption (with Signal protocol crypto module)
- XEP-0454: OMEMO Media Sharing
- XEP-0166: Jingle
- XEP-0167: Jingle RTP Sessions
- XEP-0176: Jingle ICE-UDP Transport
- XEP-0177: Jingle Raw UDP Transport
- XEP-0320: DTLS-SRTP in Jingle
- XEP-0353: Jingle Message Initiation
- XEP-0352: Client State Indication
- XEP-0357: Push Notifications
- XEP-0012: Last Activity
- XEP-0050: Ad-Hoc Commands
- XEP-0059: Result Set Management
- XEP-0077: In-Band Registration
- XEP-0114: Jabber Component Protocol
- XEP-0191: Blocking Command
- XEP-0215: External Service Discovery
- XEP-0220: Server Dialback
- XEP-0288: Bidirectional Server-to-Server
- XEP-0082: Date/Time Profiles
- XEP-0156: DNS/host-meta resolution
- XEP-0199: XMPP Ping
- XEP-0202: Entity Time
- XEP-0203: Delayed Delivery
- XEP-0231: Bits of Binary
- XEP-0297: Stanza Forwarding
- XEP-0300: Cryptographic Hash Functions
- XEP-0368: SRV records for XMPP over TLS
- XEP-0386: Bind 2
- XEP-0388: SASL2
- XEP-0440: SASL Channel-Binding Type Capability
- XEP-0484: FAST
xmpp-go includes a pluggable storage layer. All stateful plugins (roster, blocking, vcard, MUC, MAM, PubSub, bookmarks) automatically use the configured backend, falling back to in-memory storage when none is set.
| Backend | Package | External Dependency |
|---|---|---|
| Memory | storage/memory |
None |
| File (JSON) | storage/file |
None |
| SQLite | storage/sqlite |
github.com/mattn/go-sqlite3 |
| PostgreSQL | storage/postgres |
github.com/jackc/pgx/v5 |
| MySQL | storage/mysql |
github.com/go-sql-driver/mysql |
| MongoDB | storage/mongodb |
go.mongodb.org/mongo-driver/v2 |
| Redis | storage/redis |
github.com/redis/go-redis/v9 |
import (
xmpp "github.com/meszmate/xmpp-go"
"github.com/meszmate/xmpp-go/storage/memory"
)
server, _ := xmpp.NewServer("example.com",
xmpp.WithServerStorage(memory.New()),
// ...
)Backends with external dependencies live in separate Go modules so the main module stays dependency-free. Install only what you need:
go get github.com/meszmate/xmpp-go/storage/postgresSee the Storage Guide for full details.
xmpp-go includes a standalone Signal protocol implementation at crypto/omemo/ for OMEMO v2 (XEP-0384) end-to-end encryption. It is a separate Go module with no dependency on the main library.
go get github.com/meszmate/xmpp-go/crypto/omemoOMEMO works across both the server and client:
- Server side: The PubSub plugin + storage backend persists device lists and bundles (public key material only). No OMEMO-specific configuration needed -- it uses standard PEP nodes.
- Client side: The
crypto/omemopackage handles X3DH key agreement, Double Ratchet encryption, and AES-256-GCM. Private keys and session state are stored locally via theomemo.Storeinterface.
import "github.com/meszmate/xmpp-go/crypto/omemo"
// Client-side crypto store (private keys, sessions, trust)
store := omemo.NewMemoryStore(myDeviceID)
manager := omemo.NewManager(store)
// Generate bundle (private keys stay local, public parts go to server via PEP)
bundle, _ := manager.GenerateBundle(25)
// After fetching a contact's bundle from the server:
manager.ProcessBundle(addr, remoteBundleParsedFromXML)
// Encrypt for recipient devices
encMsg, _ := manager.Encrypt([]byte("Hello!"), recipientAddresses...)
// Decrypt incoming messages
plaintext, _ := manager.Decrypt(senderAddr, incomingMsg)See the OMEMO Guide for the full server/client architecture, step-by-step setup, and conversion between XML and crypto types.
- Architecture Overview
- Plugin Development Guide
- Client Usage Guide
- Server Usage Guide
- Storage Guide
- OMEMO Encryption Guide
MIT License - see LICENSE for details.