Files
warmbly/internal/api/handler/test_email.go
T

118 lines
2.9 KiB
Go

package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/warmbly/warmbly/internal/api/middleware"
"github.com/warmbly/warmbly/internal/errx"
"github.com/warmbly/warmbly/internal/models"
)
type sendTestEmailRequest struct {
SequenceID *uuid.UUID `json:"step_id"`
AccountID uuid.UUID `json:"account_id" binding:"required"`
Recipient string `json:"recipient" binding:"required,email"`
// ContactID renders the copy for a real contact of the organization
// instead of the placeholder one.
ContactID *uuid.UUID `json:"contact_id"`
}
// SendTestEmail sends a preview/test email for a campaign sequence
// POST /campaigns/:id/test-email
func (h *Handler) SendTestEmail(c *gin.Context) {
orgID := middleware.GetOrganizationID(c)
if orgID == nil {
errx.JSON(c, errx.New(errx.BadRequest, "no organization selected"))
return
}
campaignID, err := uuid.Parse(c.Param("id"))
if err != nil {
errx.JSON(c, errx.ErrUuid)
return
}
var req sendTestEmailRequest
if err := c.ShouldBindJSON(&req); err != nil {
errx.JSON(c, errx.ErrInvalid)
return
}
// Load campaign
campaign, xerr := h.CampaignService.Get(c.Request.Context(), orgID.String(), campaignID.String())
if xerr != nil {
errx.JSON(c, xerr)
return
}
// Load sequences
sequences, err := h.TasksService.GetCampaignSequences(c.Request.Context(), campaignID)
if err != nil {
errx.JSON(c, errx.InternalError())
return
}
if len(sequences) == 0 {
errx.JSON(c, errx.New(errx.BadRequest, "campaign has no sequences"))
return
}
// Select the right sequence
var sequence *models.Sequence
if req.SequenceID != nil {
for i := range sequences {
if sequences[i].ID == *req.SequenceID {
sequence = &sequences[i]
break
}
}
if sequence == nil {
errx.JSON(c, errx.New(errx.NotFound, "sequence not found"))
return
}
} else {
sequence = &sequences[0]
}
if xerr := mailboxAllowed(c, req.AccountID); xerr != nil {
errx.JSON(c, xerr)
return
}
var contact *models.Contact
if req.ContactID != nil {
// Rendering a real contact reads its fields back, so it takes the
// contacts read permission on top of the route's campaigns one.
if xerr := h.hasAccess(c, models.PermViewContacts, models.APIPermReadContacts); xerr != nil {
errx.JSON(c, xerr)
return
}
found, cxerr := h.orgContact(c.Request.Context(), *orgID, *req.ContactID)
if cxerr != nil {
errx.JSON(c, cxerr)
return
}
contact = found
}
// Send the test email
xerr = h.TasksService.SendTestEmail(c.Request.Context(), *orgID, req.AccountID, req.Recipient, campaign, sequence, contact)
if xerr != nil {
errx.JSON(c, xerr)
return
}
resp := gin.H{
"message": "test email sent",
"recipient": req.Recipient,
"subject": sequence.Subject,
"account_id": req.AccountID.String(),
"step_id": sequence.ID.String(),
}
if contact != nil {
resp["contact_id"] = contact.ID.String()
}
c.JSON(http.StatusOK, resp)
}