1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

Compare commits

...

12 Commits
v3.1.0 ... main

Author SHA1 Message Date
James Hillyerd
be7d29c5d5 chore: Central go-version for GitHub actions (#591)
* chore: Init AGENTS.md

Signed-off-by: James Hillyerd <james@hillyerd.com>

* chore: Central go-version for GitHub actions

Signed-off-by: James Hillyerd <james@hillyerd.com>

---------

Signed-off-by: James Hillyerd <james@hillyerd.com>
2025-12-06 12:45:11 -08:00
James Hillyerd
6eff554469 chore: release 3.1.1 (#590)
Signed-off-by: James Hillyerd <james@hillyerd.com>
2025-12-06 10:18:15 -08:00
James Hillyerd
7413d06616 chore: Remove broken windows arm7 build (#589)
Signed-off-by: James Hillyerd <james@hillyerd.com>
2025-12-06 10:12:11 -08:00
dependabot[bot]
22c276ea1a build(deps): bump actions/checkout from 5 to 6 (#588)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 20:41:59 -08:00
dependabot[bot]
dd22202aea build(deps): bump golangci/golangci-lint-action from 8 to 9 (#583)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 8 to 9.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v8...v9)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-22 12:18:57 -08:00
James Hillyerd
32b0ff1ac6 chore: Update Go version to 1.25 in release workflow (#587) 2025-11-22 12:01:01 -08:00
dependabot[bot]
e0824eb0aa build(deps): bump actions/setup-node from 4 to 6 (#582)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-22 11:44:05 -08:00
dependabot[bot]
f210b4c47c build(deps): bump actions/setup-go from 5 to 6 (#580)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-22 11:38:57 -08:00
James Hillyerd
2ea0639509 chore: Update Go version in lint workflow to 1.25 (#586) 2025-11-22 11:35:33 -08:00
dependabot[bot]
4399d02f0b build(deps): bump actions/checkout from 4 to 5 (#578)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-22 10:42:57 -08:00
dependabot[bot]
25007f4506 build(deps): bump js-yaml from 4.1.0 to 4.1.1 in /ui (#584)
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-22 10:42:34 -08:00
James Hillyerd
fe0e3a00e1 chore: bump go to 1.25 (#585)
Signed-off-by: James Hillyerd <james@hillyerd.com>
2025-11-22 10:41:48 -08:00
12 changed files with 335 additions and 33 deletions

View File

@@ -9,19 +9,15 @@ on:
jobs:
linux-go-build:
runs-on: ubuntu-latest
name: Linux Go ${{ matrix.go }} build
strategy:
matrix:
go:
- '1.24'
name: Linux Go build
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}
go-version-file: '.go-version'
check-latest: true
- name: Build and test
run: |
@@ -31,20 +27,20 @@ jobs:
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: profile.cov
flag-name: Linux-Go-${{ matrix.go }}
flag-name: Linux-Go
parallel: true
windows-go-build:
runs-on: windows-latest
name: Windows Go build
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: '1.24'
go-version-file: '.go-version'
- name: Build
run: go build ./...
- name: Test
@@ -60,11 +56,11 @@ jobs:
runs-on: ubuntu-latest
name: UI Build
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: '20.x'
cache: 'yarn'

View File

@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Docker meta
id: meta

View File

@@ -7,11 +7,11 @@ jobs:
golangci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: '1.24'
go-version-file: '.go-version'
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
version: latest

View File

@@ -13,18 +13,18 @@ jobs:
name: 'Go Releaser'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: '1.24'
go-version-file: '.go-version'
check-latest: true
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: '20.x'
cache: 'yarn'

1
.go-version Normal file
View File

@@ -0,0 +1 @@
1.25

View File

@@ -27,6 +27,9 @@ builds:
- arm64
goarm:
- "7"
ignore:
- goos: windows
goarch: arm
main: ./cmd/inbucket
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
- id: inbucket-client
@@ -44,6 +47,9 @@ builds:
- arm64
goarm:
- "7"
ignore:
- goos: windows
goarch: arm
main: ./cmd/client
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}

293
AGENTS.md Normal file
View File

@@ -0,0 +1,293 @@
# AGENTS.md - Inbucket
Guidance for AI agents working in this codebase.
## Project Overview
Inbucket is an email testing service that accepts messages for any email address and makes them available via web, REST, and POP3 interfaces. It's a self-contained Go application with an Elm-based web UI.
**Tech Stack:**
- Backend: Go 1.25+
- Frontend: Elm 0.19.1 with Parcel bundler
- Logging: zerolog
- Testing: testify (assert/require/suite), goldiff for golden file tests
- HTTP Router: gorilla/mux
- Configuration: envconfig (environment variables)
- Optional: Lua scripting for extensions (gopher-lua)
## Essential Commands
### Build
```bash
# Build Go binaries (inbucket server + client CLI)
make build
# Or build directly
go build ./cmd/inbucket
go build ./cmd/client
# Build UI (required before running server)
cd ui && yarn install && yarn build
```
### Test
```bash
# Run all Go tests with race detection
make test
# or
go test -race ./...
# Run tests for a specific package
go test -race ./pkg/storage/...
# Run tests with coverage
go test -race -coverprofile=profile.cov ./...
```
### Lint
```bash
# CI uses golangci-lint
golangci-lint run
# Make's lint target (older, uses golint)
make lint
```
### Run Development Server
```bash
# Build everything first
make build
cd ui && yarn build && cd ..
# Run with dev config
./etc/dev-start.sh
# Or run directly with defaults
./inbucket
```
Default ports:
- Web UI: http://localhost:9000
- SMTP: localhost:2500
- POP3: localhost:1100
### UI Development
```bash
cd ui
# Install dependencies
yarn install
# Development server with HMR (proxies to Go backend)
yarn start
# Production build
yarn build
# Clean build artifacts
yarn clean
```
## Code Organization
```
cmd/
inbucket/ # Main server binary
client/ # CLI client for REST API
pkg/
config/ # Environment-based configuration
extension/ # Lua extension system
luahost/ # Lua VM pool and bindings
event/ # Extension event types
message/ # Message manager (storage abstraction)
metric/ # Expvar metrics
msghub/ # Real-time message pub/sub
policy/ # Email address/domain policies
rest/ # REST API v1/v2 controllers
client/ # Go client library for REST API
model/ # JSON API models
server/
smtp/ # SMTP server
pop3/ # POP3 server
web/ # HTTP server, handlers, helpers
storage/ # Storage interface and implementations
file/ # File-based storage
mem/ # In-memory storage
stringutil/ # String utilities
test/ # Test utilities and integration tests
webui/ # Web UI controllers
ui/
src/
Main.elm # Elm app entry point
Api.elm # API client
Page/ # Page modules (Home, Mailbox, Monitor, Status)
Data/ # Data models
tests/ # Elm tests
```
## Configuration
Inbucket uses environment variables for all configuration. Key variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `INBUCKET_LOGLEVEL` | `info` | debug, info, warn, error |
| `INBUCKET_MAILBOXNAMING` | `local` | local, full, or domain |
| `INBUCKET_SMTP_ADDR` | `0.0.0.0:2500` | SMTP listen address |
| `INBUCKET_WEB_ADDR` | `0.0.0.0:9000` | HTTP listen address |
| `INBUCKET_POP3_ADDR` | `0.0.0.0:1100` | POP3 listen address |
| `INBUCKET_STORAGE_TYPE` | `memory` | `memory` or `file` |
| `INBUCKET_WEB_UIDIR` | `ui/dist` | Path to built UI files |
Run `./inbucket -help` for complete list.
See `doc/config.md` for detailed documentation.
## Code Patterns
### Error Handling
- Use zerolog for structured logging
- Return errors up the call stack; log at the top level
- Use `github.com/pkg/errors` patterns for wrapping
### HTTP Handlers
Handlers follow this pattern in `pkg/server/web/`:
```go
func Handler(f func(http.ResponseWriter, *http.Request, *Context) error) http.Handler
```
Controllers return errors; the wrapper handles HTTP responses.
### Storage Interface
New storage backends implement `storage.Store` interface (`pkg/storage/storage.go`):
```go
type Store interface {
AddMessage(message Message) (id string, err error)
GetMessage(mailbox, id string) (Message, error)
GetMessages(mailbox string) ([]Message, error)
MarkSeen(mailbox, id string) error
PurgeMessages(mailbox string) error
RemoveMessage(mailbox, id string) error
VisitMailboxes(f func([]Message) (cont bool)) error
}
```
Register in `cmd/inbucket/main.go` init():
```go
storage.Constructors["mytype"] = mystore.New
```
### JSON Tag Convention
JSON fields use kebab-case (configured in `.golangci.yml` tagliatelle):
```go
type Example struct {
FieldName string `json:"field-name"`
}
```
### Elm Architecture
The UI follows The Elm Architecture:
- `Main.elm` - App shell, routing
- `Page/*.elm` - Page modules with Model, Msg, init, update, view
- `Data/*.elm` - Data types and JSON decoders
- `Api.elm` - HTTP client for REST API
## Testing
### Test Structure
- Unit tests: alongside source files (`*_test.go`)
- Integration tests: `pkg/test/integration_test.go`
- Test utilities: `pkg/test/`
### Test Frameworks
- Standard `testing` package
- `github.com/stretchr/testify/assert` - assertions
- `github.com/stretchr/testify/require` - fatal assertions
- `github.com/stretchr/testify/suite` - test suites
- `github.com/jhillyerd/goldiff` - golden file testing
### Test Utilities
Located in `pkg/test/`:
- `StoreStub`, `ManagerStub` - mock implementations
- `DeliverToStore()` - create test messages
- `StoreSuite()` - table-driven storage tests
- `NewLuaState()` - Lua testing helper
### Golden File Tests
Input in `pkg/test/testdata/*.txt`, expected output in `*.golden`:
```go
goldiff.File(t, got, "testdata", "basic.golden")
```
### Running Specific Tests
```bash
# Run tests matching pattern
go test -race -run TestIntegration ./pkg/test/
# Run with verbose output
go test -race -v ./pkg/storage/mem/
# Run storage suite for specific implementation
go test -race -run TestMemStore ./pkg/storage/mem/
```
## CI/CD
GitHub Actions workflows in `.github/workflows/`:
- `build-and-test.yml` - Build and test on Linux/Windows, coverage to coveralls
- `lint.yml` - golangci-lint
- `docker-build.yml` - Docker image builds
- `release.yml` - goreleaser for releases
## Important Gotchas
1. **UI must be built before running server** - The Go server serves static files from `ui/dist/`
2. **Storage type affects persistence** - `memory` storage loses all data on restart; use `file` for persistence
3. **Port conflicts** - Default ports (9000, 2500, 1100) may conflict with other services
4. **Lua scripting is optional** - If `inbucket.lua` is not present, the server runs without extensions
5. **Test coverage requires race detector** - CI always runs with `-race`
6. **golangci-lint v2 config** - Uses v2 format in `.golangci.yml`
7. **Windows paths in storage** - Use `$` instead of `:` in file storage paths (e.g., `D$/inbucket`)
## REST API
Base URL: `http://localhost:9000/api/`
### API v1 Endpoints
- `GET /v1/mailbox/{name}` - List messages
- `GET /v1/mailbox/{name}/{id}` - Get message
- `PATCH /v1/mailbox/{name}/{id}` - Mark as seen
- `DELETE /v1/mailbox/{name}` - Purge mailbox
- `DELETE /v1/mailbox/{name}/{id}` - Delete message
- `GET /v1/mailbox/{name}/{id}/source` - Get raw source
### API v2 Endpoints
- `GET /v2/monitor/messages` - WebSocket for real-time messages
Go client available: `github.com/inbucket/inbucket/v3/pkg/rest/client`
## Development Tips
1. **Quick iteration** - Use `make reflex` for auto-rebuild on Go file changes
2. **UI development** - Run `yarn start` in `ui/` for HMR; it proxies API requests to the Go server
3. **Debug network** - Run with `-netdebug` flag to dump SMTP/POP3 traffic
4. **Test email sending** - Use swaks or the test scripts in `etc/swaks-tests/`
5. **Check configuration** - Run `./inbucket -help` to see all env vars and defaults

View File

@@ -7,6 +7,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [v3.1.1] - 2025-12-06
### Fixed
- Go version update for CVE-2025-47907
- Removed broken Windows arm7 build (#589)
## [v3.1.0] - 2025-07-27
### Added
@@ -379,7 +386,8 @@ No change from beta1.
specific message.
[Unreleased]: https://github.com/inbucket/inbucket/compare/v3.1.0...main
[Unreleased]: https://github.com/inbucket/inbucket/compare/v3.1.1...main
[v3.1.1]: https://github.com/inbucket/inbucket/compare/v3.1.0...v3.1.1
[v3.1.0]: https://github.com/inbucket/inbucket/compare/v3.1.0-beta3...v3.1.0
[v3.1.0-beta3]: https://github.com/inbucket/inbucket/compare/v3.1.0-beta2...v3.1.0-beta3
[v3.1.0-beta2]: https://github.com/inbucket/inbucket/compare/v3.1.0-beta1...v3.1.0-beta2

View File

@@ -12,7 +12,7 @@ RUN yarn install --frozen-lockfile --non-interactive
RUN yarn run build
### Build backend
FROM golang:1.24-alpine3.21 AS backend
FROM golang:1.25-alpine3.22 AS backend
RUN apk add --no-cache --virtual .build-deps g++ git make
WORKDIR /build
COPY . .
@@ -23,7 +23,7 @@ RUN go build -o inbucket \
-v ./cmd/inbucket
### Run in minimal image
FROM alpine:3.21
FROM alpine:3.22
RUN apk --no-cache add tzdata
WORKDIR /opt/inbucket
RUN mkdir bin defaults ui

4
go.mod
View File

@@ -1,8 +1,6 @@
module github.com/inbucket/inbucket/v3
go 1.23.0
toolchain go1.24.2
go 1.25.0
require (
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9

View File

@@ -24,7 +24,7 @@ pkgs.mkShell {
elmPackages.elm-json
elmPackages.elm-language-server
elmPackages.elm-test
go_1_24
go_1_25
golangci-lint
golint
gopls

View File

@@ -1578,9 +1578,9 @@ js-tokens@^4.0.0:
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
version "4.1.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b"
integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==
dependencies:
argparse "^2.0.1"