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:
@@ -64,6 +64,17 @@ type Settings struct {
|
||||
|
||||
// App-to-app integration state (e.g., "onlyoffice:filebrowser" → state)
|
||||
Integrations map[string]IntegrationState `json:"integrations,omitempty"`
|
||||
|
||||
// AppEmail is the global app-email (SMTP relay) toggle. When on, deployed apps with an
|
||||
// smtp_mapping can send mail via the in-controller shim → hub → Resend. Relay-only:
|
||||
// no BYO host/port/user/pass (that escape hatch is deferred).
|
||||
AppEmail *AppEmail `json:"app_email,omitempty"`
|
||||
}
|
||||
|
||||
// AppEmail holds the global app-email toggle and an optional household display name.
|
||||
type AppEmail struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
FromName string `json:"from_name,omitempty"` // optional household display name for the From line
|
||||
}
|
||||
|
||||
// IntegrationState holds the state of a provider:target integration pair.
|
||||
@@ -1178,6 +1189,36 @@ func (s *Settings) SetGeoSyncState(zoneID, rulesetID, syncError string) error {
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// --- App email (SMTP relay) ---
|
||||
|
||||
// GetAppEmail returns the global app-email toggle (a copy; never the live pointer).
|
||||
func (s *Settings) GetAppEmail() AppEmail {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if s.AppEmail == nil {
|
||||
return AppEmail{}
|
||||
}
|
||||
return *s.AppEmail
|
||||
}
|
||||
|
||||
// AppEmailEnabled reports whether app-email is globally on.
|
||||
func (s *Settings) AppEmailEnabled() bool {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.AppEmail != nil && s.AppEmail.Enabled
|
||||
}
|
||||
|
||||
// SetAppEmail updates the global app-email toggle and persists it.
|
||||
func (s *Settings) SetAppEmail(enabled bool, fromName string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] SetAppEmail enabled=%v from_name=%q", enabled, fromName)
|
||||
}
|
||||
s.AppEmail = &AppEmail{Enabled: enabled, FromName: strings.TrimSpace(fromName)}
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// --- App-to-app integrations ---
|
||||
|
||||
// GetIntegrationState returns the state for a specific integration key (e.g., "onlyoffice:filebrowser").
|
||||
|
||||
Reference in New Issue
Block a user