Send RSVP confirmation emails via Resend

This commit is contained in:
Ian Gulliver
2026-01-03 21:39:24 -08:00
parent acb98238d7
commit ef0198ed01
3 changed files with 72 additions and 0 deletions

1
go.mod
View File

@@ -4,6 +4,7 @@ go 1.24.0
require (
github.com/lib/pq v1.10.9
github.com/resend/resend-go/v2 v2.28.0
github.com/stripe/stripe-go/v76 v76.25.0
google.golang.org/api v0.258.0
)

2
go.sum
View File

@@ -30,6 +30,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/resend/resend-go/v2 v2.28.0 h1:ttM1/VZR4fApBv3xI1TneSKi1pbfFsVrq7fXFlHKtj4=
github.com/resend/resend-go/v2 v2.28.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=

69
main.go
View File

@@ -18,12 +18,29 @@ import (
"strings"
_ "github.com/lib/pq"
"github.com/resend/resend-go/v2"
"github.com/stripe/stripe-go/v76"
"github.com/stripe/stripe-go/v76/checkout/session"
"github.com/stripe/stripe-go/v76/webhook"
"google.golang.org/api/idtoken"
)
type eventInfo struct {
Name string
Date string
Location string
Address string
}
var events = map[string]eventInfo{
"afac26": {
Name: "Applause for a Cause",
Date: "Saturday, February 7, 2026 at 6:30 PM",
Location: "Helios Gym",
Address: "597 Central Avenue, Sunnyvale, CA 94086",
},
}
var (
templates *template.Template
db *sql.DB
@@ -241,6 +258,9 @@ func handleRSVPPost(w http.ResponseWriter, r *http.Request) {
http.Error(w, "database error", http.StatusInternalServerError)
return
}
if *req.NumPeople > 0 {
go sendRSVPConfirmation(eventID, email, *req.NumPeople)
}
}
numPeople, donation, err := getRSVP(eventID, email)
@@ -352,6 +372,55 @@ func processPayment(sess *stripe.CheckoutSession) error {
return nil
}
func sendRSVPConfirmation(eventID, email string, numPeople int) {
event, ok := events[eventID]
if !ok {
log.Printf("[ERROR] unknown event %s for email confirmation", eventID)
return
}
resendKey := os.Getenv("RESEND_KEY")
if resendKey == "" {
log.Println("[ERROR] RESEND_KEY not set, skipping confirmation email")
return
}
client := resend.NewClient(resendKey)
word := "person"
if numPeople != 1 {
word = "people"
}
html := fmt.Sprintf(`
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
<h2>Your RSVP is Confirmed!</h2>
<p>You're all set for <strong>%s</strong>.</p>
<table style="margin: 20px 0; border-collapse: collapse;">
<tr><td style="padding: 8px 0; color: #666;">Party Size</td><td style="padding: 8px 0 8px 20px;"><strong>%d %s</strong></td></tr>
<tr><td style="padding: 8px 0; color: #666;">Date</td><td style="padding: 8px 0 8px 20px;"><strong>%s</strong></td></tr>
<tr><td style="padding: 8px 0; color: #666;">Location</td><td style="padding: 8px 0 8px 20px;"><strong>%s</strong><br>%s</td></tr>
</table>
<p>See you there!</p>
<p style="color: #666; font-size: 14px; margin-top: 30px;">— HCA Events</p>
</div>
`, event.Name, numPeople, word, event.Date, event.Location, event.Address)
params := &resend.SendEmailRequest{
From: "HCA Events <events@hca.run>",
To: []string{email},
Subject: fmt.Sprintf("RSVP Confirmed: %s", event.Name),
Html: html,
}
_, err := client.Emails.Send(params)
if err != nil {
log.Printf("[ERROR] failed to send confirmation email to %s: %v", email, err)
return
}
log.Printf("sent confirmation email to %s for %s", email, eventID)
}
func handleDonateSuccess(w http.ResponseWriter, r *http.Request) {
eventID := r.PathValue("eventID")