v0.88.0: app-email SMTP relay (in-process shim + per-app injection)
In-process go-smtp shim (Shape 1): apps → shim → hub → Resend, Resend key stays hub-side. From-header allowlist (reject 5xx pre-hub), single-shot raw-MIME forward, status→SMTP mapping. Global + per-app toggles gate compose-time env injection from .felhom.yml smtp_mapping. Hungarian UI on settings + app config pages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,12 +81,27 @@ type Server struct {
|
||||
// manual trigger goes through the loop (stop stacks → backup → resume), never a bare agent call.
|
||||
backupTrigger BackupTrigger
|
||||
|
||||
// App-email SMTP shim lifecycle (optional — nil when no hub is configured or the kill-switch is
|
||||
// off). The global app-email settings toggle calls Apply() so the shim starts/stops at runtime.
|
||||
mailShim MailShimController
|
||||
|
||||
// Debug mode support
|
||||
logBuffer *LogBuffer
|
||||
debugCallbacks *DebugCallbacks
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
// MailShimController is the lifecycle handle the settings toggle uses to start/stop the
|
||||
// app-email SMTP shim at runtime. Satisfied by *mailrelay.Lifecycle (kept as an interface
|
||||
// to avoid a web→mailrelay import cycle risk and to allow a fake in tests).
|
||||
type MailShimController interface {
|
||||
Apply(enabled bool) error
|
||||
Running() bool
|
||||
}
|
||||
|
||||
// SetMailShim wires the app-email shim lifecycle (optional).
|
||||
func (s *Server) SetMailShim(c MailShimController) { s.mailShim = c }
|
||||
|
||||
func NewServer(cfg *config.Config, stackMgr *stacks.Manager, cpuCollector *system.CPUCollector, backupMgr *backup.Manager, sched *scheduler.Scheduler, sett *settings.Settings, alertMgr *AlertManager, notif *notify.Notifier, updater *selfupdate.Updater, logger *log.Logger, version string) *Server {
|
||||
s := &Server{
|
||||
cfg: cfg,
|
||||
@@ -253,6 +268,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
s.settingsNotificationsHandler(w, r)
|
||||
case path == "/settings/notifications/test" && r.Method == http.MethodPost:
|
||||
s.settingsNotificationsTestHandler(w, r)
|
||||
case path == "/settings/app-email" && r.Method == http.MethodPost:
|
||||
s.settingsAppEmailHandler(w, r)
|
||||
case path == "/settings/storage/add" && r.Method == http.MethodPost:
|
||||
s.settingsStorageAddHandler(w, r)
|
||||
case path == "/settings/storage/remove" && r.Method == http.MethodPost:
|
||||
@@ -287,6 +304,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
case strings.HasPrefix(path, "/stacks/") && strings.HasSuffix(path, "/backup") && r.Method == http.MethodPost:
|
||||
name := strings.TrimSuffix(strings.TrimPrefix(path, "/stacks/"), "/backup")
|
||||
s.tier2ConfigSaveHandler(w, r, name)
|
||||
case strings.HasPrefix(path, "/stacks/") && strings.HasSuffix(path, "/app-email") && r.Method == http.MethodPost:
|
||||
name := strings.TrimSuffix(strings.TrimPrefix(path, "/stacks/"), "/app-email")
|
||||
s.appEmailToggleHandler(w, r, name)
|
||||
case path == "/import":
|
||||
s.importPageHandler(w, r)
|
||||
case path == "/static/style.css":
|
||||
|
||||
Reference in New Issue
Block a user