-
Notifications
You must be signed in to change notification settings - Fork 350
DRAFT: replace inbucket with minimal implementation #4730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
DRAFT: replace inbucket with minimal implementation #4730
Conversation
Implements an embedded SMTP server that replaces the Docker-based
inbucket container for local email testing. Emails are stored as
.eml files on disk for easy access.
Features:
- SMTP server using github.com/emersion/go-smtp
- File-based storage with configurable path via SUPABASE_MAIL_PATH
- Email parsing using github.com/jhillyerd/enmime/v2
- API to list mailboxes, list emails, read and delete emails
Storage format:
$SUPABASE_MAIL_PATH/
└── {recipient-email}/
└── {timestamp}-{id}.eml
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Documents the embedded mail server package including: - Configuration options and environment variables - Usage examples for starting server and reading emails - Storage format explanation - API reference - Comparison with Docker-based solution
Add comprehensive tests covering: - HTML/multipart email handling - StoreFromReader method - Server stop idempotency - DeleteMailbox via server API - Raw email content preservation - Multiple emails sorting in mailbox
…opment - Add InbucketProvider config option to choose between "embedded" (default) and "mailpit" (Docker-based) email servers - Modify start.go to launch embedded SMTP server when using embedded provider - Update GoTrue SMTP config to connect via host.docker.internal:2500 - CLI stays running in foreground when embedded mail is active (Ctrl+C to stop) - Emails stored in .supabase/mail/ or SUPABASE_MAIL_PATH directory - Docker mailpit container only starts when provider = "mailpit" in config.toml
- Write PID file to .supabase/mail.pid when embedded server starts - supabase stop reads PID file and sends SIGTERM to gracefully stop the server - Clean up PID file on shutdown - Allows stopping embedded mail server from separate terminal via supabase stop
- Add validatePath() to ensure paths stay within storage directory - Add sanitizeID() to remove dangerous characters from email IDs - Use filepath.Abs() in NewStorage for consistent path validation - Apply path validation to ListEmails, GetEmail, DeleteEmail, DeleteMailbox - Use filepath.Clean() and filepath.Base() to sanitize filenames Fixes Snyk CWE-23 path traversal warnings.
| // If embedded mail server is running, keep the CLI process alive | ||
| // This is needed because the embedded server runs in this process | ||
| if embeddedMailServer != nil { | ||
| fmt.Fprintln(os.Stderr, "\nEmbedded mail server is running. Press Ctrl+C to stop all services.") | ||
| // Wait for context cancellation (Ctrl+C) | ||
| <-ctx.Done() | ||
| fmt.Fprintln(os.Stderr, "\nStopping embedded mail server...") | ||
| StopEmbeddedMailServer() | ||
| // Also stop Docker containers | ||
| if err := utils.DockerRemoveAll(context.Background(), os.Stderr, utils.Config.ProjectId); err != nil { | ||
| fmt.Fprintln(os.Stderr, err) | ||
| } | ||
| fmt.Fprintln(os.Stderr, "Stopped all services.") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern here is that it relies on cli to be running on foreground. For anyone running local stack in background, we still need to fallback to mailpit container.
For ease of maintenance, I would avoid duplicating the implementation.
You can also measure the overhead of mailpit container by setting [inbucket] enabled = false. I suspect the impact is negligible.
The best outcome IMO is to use docker compose for starting all services. We already import that as a library. Remaining work is move individual DockerStart API calls to a single compose spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a good point - i think my main idea was to minimize the surface area. I didn't realize we are using mailpit (because the container name was still inbucket but the docker image is only 13MB so already quite small
I'll close for now
Implements an embedded SMTP server that replaces the Docker-based inbucket container for local email testing. This will make the CLI lighter and faster to start.
Emails are stored as .eml files on disk for easy access.
Features:
Storage format:
$SUPABASE_MAIL_PATH/
└── {recipient-email}/
└── {timestamp}-{id}.eml