(ctx context.Context, in *createMessageInput)
| 432 | } |
| 433 | |
| 434 | func (s *Server) handleCreateMessage(ctx context.Context, in *createMessageInput) (*sendOutput, error) { |
| 435 | ag, err := s.resolveOwnedAgent(ctx, in.Address) |
| 436 | if err != nil { |
| 437 | return nil, err |
| 438 | } |
| 439 | user, uerr := s.requireUser(ctx) |
| 440 | if uerr != nil { |
| 441 | return nil, uerr |
| 442 | } |
| 443 | b := in.Body |
| 444 | if env := s.validateOutboundBody(b.Subject, b.Body, b.To, b.CC, b.BCC, b.ConversationID); env != nil { |
| 445 | return nil, env |
| 446 | } |
| 447 | // The sender is the path agent (decision 3) — there is no body `from`; the |
| 448 | // agent is the path and auth scopes the sender, so no spoofing is possible. |
| 449 | req := outbound.SendRequest{ |
| 450 | From: ag.EmailAddress(), To: b.To, CC: b.CC, BCC: b.BCC, Subject: b.Subject, |
| 451 | Body: b.Body, HTMLBody: b.HTMLBody, ConversationID: b.ConversationID, Attachments: b.Attachments, |
| 452 | } |
| 453 | // The agent moved from the body (`from`) to the path, so fold the agent id |
| 454 | // into the idempotency route — otherwise two agents owned by the same user |
| 455 | // could collide on an identical key+body (the body hash alone no longer |
| 456 | // separates them). |
| 457 | route := "/v1/agents/" + ag.ID + "/messages" |
| 458 | // A cold send has no referenced inbound (nil) — it's not a reply/forward. |
| 459 | return s.deliver(ctx, user, ag, req, "send", "", route, in.IdempotencyKey, in.RawBody, nil) |
| 460 | } |
nothing calls this directly
no test coverage detected