package mail import ( "context" "log" "strings" "time" "plumber/internal/events" "plumber/internal/store" ) // Subscribe sends reply emails from PostCreated events. Nop or nil is a no-op. func Subscribe(bus *events.Bus, st store.Store, n Notifier) { if bus == nil || st == nil || n == nil { return } if _, disabled := n.(Nop); disabled { return } s := subscriber{store: st, mail: n} bus.Subscribe(s.handle) } type subscriber struct { store store.Store mail Notifier } func (s subscriber) handle(_ context.Context, ev any) { created, ok := ev.(events.PostCreated) if !ok { return } if strings.TrimSpace(created.ParentID) == "" { return } go s.notifyReply(created.PostEvent) } func (s subscriber) notifyReply(ev events.PostEvent) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() parent, err := s.store.GetPost(ctx, ev.ParentID) if err != nil { log.Printf("notify reply %s: load parent: %v", ev.PostID, err) return } root, err := s.store.GetPost(ctx, ev.RootID) if err != nil { log.Printf("notify reply %s: load root: %v", ev.PostID, err) return } author, err := s.store.UserByID(ctx, ev.AuthorID) if err != nil { log.Printf("notify reply %s: load author: %v", ev.PostID, err) return } recipientID := parent.AuthorID if author.Admin() { recipientID = root.AuthorID } if recipientID == author.ID { return } msg := PostReply{ RootID: root.ID, RootTitle: root.Title, ReplyID: ev.PostID, ReplyBody: ev.Body, ReplyAuthorName: author.Name, } recipient, err := s.store.UserByID(ctx, recipientID) if err != nil { log.Printf("notify reply %s: load recipient: %v", msg.ReplyID, err) return } if recipient == nil || strings.TrimSpace(recipient.Email) == "" { return } msg.ToEmail = recipient.Email msg.ToName = recipient.Name if err := s.mail.NotifyPostReply(ctx, msg); err != nil { log.Printf("notify reply %s: %v", msg.ReplyID, err) return } log.Printf("notify reply %s: accepted", msg.ReplyID) }