Add Technical Kiwi website with Go, templ, and HTMX.
Single-page site with gallery by album and event, contact form over SMTP, Docker dev/prod setup, and on-server image derivatives. Gallery photos stay local (app/images/ is gitignored). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
65
app/internal/contact/validate.go
Normal file
65
app/internal/contact/validate.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package contact
|
||||
|
||||
import (
|
||||
"net/mail"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
maxNameLen = 120
|
||||
maxEmailLen = 254
|
||||
maxMessageLen = 8000
|
||||
minMessageLen = 10
|
||||
)
|
||||
|
||||
// Submission is validated contact form input.
|
||||
type Submission struct {
|
||||
Name string
|
||||
Email string
|
||||
Message string
|
||||
}
|
||||
|
||||
// Errors maps field names to user-facing messages.
|
||||
type Errors map[string]string
|
||||
|
||||
func (e Errors) Any() bool {
|
||||
return len(e) > 0
|
||||
}
|
||||
|
||||
// Parse reads and validates a contact form POST.
|
||||
func Parse(name, email, message string) (Submission, Errors) {
|
||||
errs := make(Errors)
|
||||
|
||||
name = strings.TrimSpace(name)
|
||||
email = strings.TrimSpace(email)
|
||||
message = strings.TrimSpace(message)
|
||||
|
||||
if name == "" {
|
||||
errs["name"] = "Name is required."
|
||||
} else if utf8.RuneCountInString(name) > maxNameLen {
|
||||
errs["name"] = "Name is too long."
|
||||
}
|
||||
|
||||
if email == "" {
|
||||
errs["email"] = "Email is required."
|
||||
} else if utf8.RuneCountInString(email) > maxEmailLen {
|
||||
errs["email"] = "Email is too long."
|
||||
} else if _, err := mail.ParseAddress(email); err != nil {
|
||||
errs["email"] = "Enter a valid email address."
|
||||
}
|
||||
|
||||
if message == "" {
|
||||
errs["message"] = "Message is required."
|
||||
} else if utf8.RuneCountInString(message) < minMessageLen {
|
||||
errs["message"] = "Message must be at least 10 characters."
|
||||
} else if utf8.RuneCountInString(message) > maxMessageLen {
|
||||
errs["message"] = "Message is too long."
|
||||
}
|
||||
|
||||
if errs.Any() {
|
||||
return Submission{}, errs
|
||||
}
|
||||
|
||||
return Submission{Name: name, Email: email, Message: message}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user