compress

package
v0.10.1 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package compress provides message body compression as a mailbox plugin.

The CompressionPlugin implements mailbox.SendHook and compresses the message body during send. Decompression is handled client-side via the Decompress function or automatically by crypto.Open when used with encryption.

Register this plugin before the encryption plugin for compress-then-encrypt:

svc, _ := mailbox.New(mailbox.Config{},
    mailbox.WithStore(store),
    mailbox.WithPlugins(
        compress.NewPlugin(compress.Gzip),
        crypto.NewEncryptionPlugin(keys),
    ),
)

Reading compressed messages:

msg, _ := mb.Get(ctx, msgID)
body, _ := compress.Open(msg)

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrUnsupportedEncoding = errors.New("compress: unsupported content encoding")

ErrUnsupportedEncoding is returned for unknown compression encodings.

Functions

func Decompress

func Decompress(data []byte, encoding string) ([]byte, error)

Decompress decompresses data using the specified encoding. Returns the data unchanged if encoding is empty.

func IsCompressed

func IsCompressed(msg MessageReader) bool

IsCompressed returns true if the message has a Content-Encoding header.

Example

ExampleIsCompressed demonstrates checking if a message is compressed.

package main

import (
	"context"
	"fmt"

	"github.com/rbaliyan/mailbox"
	"github.com/rbaliyan/mailbox/compress"
	"github.com/rbaliyan/mailbox/store"
	"github.com/rbaliyan/mailbox/store/memory"
)

func main() {
	ctx := context.Background()

	svc, _ := mailbox.New(mailbox.Config{},
		mailbox.WithStore(memory.New()),
		mailbox.WithPlugins(compress.NewPlugin(compress.Gzip)),
	)
	svc.Connect(ctx)
	defer svc.Close(ctx)

	svc.Client("alice").SendMessage(ctx, mailbox.SendRequest{
		RecipientIDs: []string{"bob"},
		Subject:      "test",
		Body:         "body",
	})

	inbox, _ := svc.Client("bob").Folder(ctx, store.FolderInbox, store.ListOptions{})
	fmt.Println("compressed:", compress.IsCompressed(inbox.All()[0]))
}
Output:
compressed: true

func Open

func Open(msg MessageReader) ([]byte, error)

Open decompresses a message body based on the Content-Encoding header. Returns the raw body if the message is not compressed.

Example

ExampleOpen demonstrates decompressing a message retrieved from a mailbox.

package main

import (
	"context"
	"fmt"

	"github.com/rbaliyan/mailbox"
	"github.com/rbaliyan/mailbox/compress"
	"github.com/rbaliyan/mailbox/store"
	"github.com/rbaliyan/mailbox/store/memory"
)

func main() {
	ctx := context.Background()

	svc, _ := mailbox.New(mailbox.Config{},
		mailbox.WithStore(memory.New()),
		mailbox.WithPlugins(compress.NewPlugin(compress.Gzip)),
	)
	svc.Connect(ctx)
	defer svc.Close(ctx)

	// Send a compressed message.
	svc.Client("system").SendMessage(ctx, mailbox.SendRequest{
		RecipientIDs: []string{"bob"},
		Subject:      "System notification",
		Body:         "<h1>Alert</h1><p>Disk usage at 90%.</p>",
		Headers:      map[string]string{"Content-Type": "text/html"},
	})

	// Read and decompress.
	bob := svc.Client("bob")
	inbox, _ := bob.Folder(ctx, store.FolderInbox, store.ListOptions{})
	msg := inbox.All()[0]

	fmt.Println("compressed:", compress.IsCompressed(msg))
	fmt.Println("subject:", msg.GetSubject())

	body, _ := compress.Open(msg)
	fmt.Println("body:", string(body))
}
Output:
compressed: true
subject: System notification
body: <h1>Alert</h1><p>Disk usage at 90%.</p>
Example (Uncompressed)

ExampleOpen_uncompressed demonstrates that Open works transparently on plain messages.

package main

import (
	"context"
	"fmt"

	"github.com/rbaliyan/mailbox"
	"github.com/rbaliyan/mailbox/compress"
	"github.com/rbaliyan/mailbox/store"
	"github.com/rbaliyan/mailbox/store/memory"
)

func main() {
	ctx := context.Background()

	// No compression plugin.
	svc, _ := mailbox.New(mailbox.Config{}, mailbox.WithStore(memory.New()))
	svc.Connect(ctx)
	defer svc.Close(ctx)

	svc.Client("alice").SendMessage(ctx, mailbox.SendRequest{
		RecipientIDs: []string{"bob"},
		Subject:      "Plain text",
		Body:         "No compression here.",
	})

	bob := svc.Client("bob")
	inbox, _ := bob.Folder(ctx, store.FolderInbox, store.ListOptions{})
	msg := inbox.All()[0]

	fmt.Println("compressed:", compress.IsCompressed(msg))
	body, _ := compress.Open(msg)
	fmt.Println("body:", string(body))
}
Output:
compressed: false
body: No compression here.

Types

type Compressor

type Compressor interface {
	// Algorithm returns the Content-Encoding value (e.g., "gzip", "zstd").
	Algorithm() string
	// Compress compresses data.
	Compress(data []byte) ([]byte, error)
	// Decompress decompresses data.
	Decompress(data []byte) ([]byte, error)
}

Compressor compresses and decompresses data.

var (
	// Gzip is a gzip compressor using default compression level.
	Gzip Compressor = &gzipCompressor{level: gzip.DefaultCompression}
	// GzipBest is a gzip compressor using best compression.
	GzipBest Compressor = &gzipCompressor{level: gzip.BestCompression}
)

Pre-built compressors.

type MessageReader

type MessageReader interface {
	GetBody() string
	GetHeaders() map[string]string
}

MessageReader is the minimal interface for reading compressed messages.

type Plugin

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

Plugin compresses message bodies before send. Implements mailbox.SendHook.

func NewPlugin

func NewPlugin(c Compressor) *Plugin

NewPlugin creates a compression plugin with the given compressor.

Example (Basic)

ExampleNewPlugin_basic demonstrates basic compression and decompression.

package main

import (
	"context"
	"fmt"

	"github.com/rbaliyan/mailbox"
	"github.com/rbaliyan/mailbox/compress"
	"github.com/rbaliyan/mailbox/store"
	"github.com/rbaliyan/mailbox/store/memory"
)

func main() {
	ctx := context.Background()

	svc, _ := mailbox.New(mailbox.Config{},
		mailbox.WithStore(memory.New()),
		mailbox.WithPlugins(compress.NewPlugin(compress.Gzip)),
	)
	svc.Connect(ctx)
	defer svc.Close(ctx)

	svc.Client("alice").SendMessage(ctx, mailbox.SendRequest{
		RecipientIDs: []string{"bob"},
		Subject:      "Compressed",
		Body:         "This body is gzip compressed before storage.",
	})

	bob := svc.Client("bob")
	inbox, _ := bob.Folder(ctx, store.FolderInbox, store.ListOptions{})
	msg := inbox.All()[0]

	fmt.Println("encoding:", msg.GetHeaders()["Content-Encoding"])
	plaintext, _ := compress.Open(msg)
	fmt.Println("body:", string(plaintext))
}
Output:
encoding: gzip
body: This body is gzip compressed before storage.
Example (BestCompression)

ExampleNewPlugin_bestCompression demonstrates using best compression level.

package main

import (
	"context"
	"fmt"

	"github.com/rbaliyan/mailbox"
	"github.com/rbaliyan/mailbox/compress"
	"github.com/rbaliyan/mailbox/store"
	"github.com/rbaliyan/mailbox/store/memory"
)

func main() {
	ctx := context.Background()

	svc, _ := mailbox.New(mailbox.Config{},
		mailbox.WithStore(memory.New()),
		mailbox.WithPlugins(compress.NewPlugin(compress.GzipBest)),
	)
	svc.Connect(ctx)
	defer svc.Close(ctx)

	svc.Client("alice").SendMessage(ctx, mailbox.SendRequest{
		RecipientIDs: []string{"bob"},
		Subject:      "Best compression",
		Body:         "Repetitive data benefits from best compression: aaaaaaaaaaaaaaaaaaaaaaaaaaa",
	})

	bob := svc.Client("bob")
	inbox, _ := bob.Folder(ctx, store.FolderInbox, store.ListOptions{})
	plaintext, _ := compress.Open(inbox.All()[0])
	fmt.Println("body:", string(plaintext))
}
Output:
body: Repetitive data benefits from best compression: aaaaaaaaaaaaaaaaaaaaaaaaaaa

func (*Plugin) AfterSend

func (p *Plugin) AfterSend(_ context.Context, _ string, _ store.Message) error

func (*Plugin) BeforeSend

func (p *Plugin) BeforeSend(ctx context.Context, _ string, draft store.DraftMessage) error

BeforeSend compresses the message body and sets the Content-Encoding header.

func (*Plugin) Close

func (p *Plugin) Close(_ context.Context) error

func (*Plugin) Init

func (p *Plugin) Init(_ context.Context) error

func (*Plugin) Name

func (p *Plugin) Name() string

Jump to

Keyboard shortcuts

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