package main import ( "errors" "flag" "fmt" "log" "github.com/kardianos/service" ) type Program struct { smtpServer *SMTPServer webServer *WebServer } func (p *Program) Start( s service.Service, ) error { if err := p.smtpServer.Start(); err != nil { return fmt.Errorf( "failed to start SMTP server: %w", err, ) } if err := p.webServer.Start(); err != nil { if stopErr := p.smtpServer.Stop(); stopErr != nil { return errors.Join( fmt.Errorf( "failed to start web server: %w", err, ), fmt.Errorf( "failed to stop SMTP server after web startup failure: %w", stopErr, ), ) } return fmt.Errorf( "failed to start web server: %w", err, ) } return nil } func (p *Program) Stop( s service.Service, ) error { var errs []error if p.webServer != nil { if err := p.webServer.Stop(); err != nil { errs = append( errs, fmt.Errorf( "failed to stop web server: %w", err, ), ) } } if p.smtpServer != nil { if err := p.smtpServer.Stop(); err != nil { errs = append( errs, fmt.Errorf( "failed to stop SMTP server: %w", err, ), ) } } return errors.Join(errs...) } func main() { configPath := flag.String( "config", "config.yaml", "Path to YAML config file", ) flag.Parse() cfg, err := LoadConfig(*configPath) if err != nil { log.Fatalf( "Failed to load config: %v", err, ) } smtpServer := NewSMTPServer(cfg) webServer := NewWebServer( cfg, smtpServer, ) svcConfig := &service.Config{ Name: "ric930-fake-smtp", DisplayName: "Ric930 Fake SMTP Server", Description: "Fake SMTP server for testing with web interface", Arguments: []string{ "-config", *configPath, }, } prg := &Program{ smtpServer: smtpServer, webServer: webServer, } s, err := service.New( prg, svcConfig, ) if err != nil { log.Fatal(err) } logger, err := s.Logger(nil) if err != nil { log.Fatal(err) } smtpServer.logger = logger webServer.logger = logger // ric930-fake-smtp install // // ric930-fake-smtp \ // -config config.yaml \ // install // args := flag.Args() if len(args) > 1 { log.Fatalf( "Unexpected arguments: %v", args, ) } if len(args) == 1 { if err := service.Control( s, args[0], ); err != nil { log.Fatal(err) } return } if err := s.Run(); err != nil { logger.Error(err) } }