//go:build standalone package checker import ( "errors" "net/http" "strconv" "strings" sdk "git.happydns.org/checker-sdk-go/checker" ) func (p *happyDeliverProvider) RenderForm() []sdk.CheckerOptionField { return []sdk.CheckerOptionField{ { Id: "domain_name", Type: "string", Label: "Domain name", Placeholder: "example.com", Required: true, Description: "Domain whose outbound deliverability will be tested.", }, { Id: "happydeliver_url", Type: "string", Label: "happyDeliver instance URL", Placeholder: "https://deliver.example.org", Required: true, Description: "Base URL of the happyDeliver API used to allocate the test address and fetch the report.", }, { Id: "happydeliver_token", Type: "string", Label: "happyDeliver API token", Description: "Bearer token for the happyDeliver API (optional if the instance is open).", }, { Id: "smtp_host", Type: "string", Label: "Sending SMTP host", Required: true, Description: "Hostname or IP of the submission server used to send the test email.", }, { Id: "smtp_port", Type: "string", Label: "Sending SMTP port", Placeholder: "587", Description: "Submission port (587 for STARTTLS, 465 for implicit TLS, 25 for plain). Defaults to 587.", }, { Id: "smtp_tls", Type: "string", Label: "TLS mode", Placeholder: "starttls", Description: "How to negotiate TLS with the submission server: starttls, tls, or none. Defaults to starttls.", }, { Id: "smtp_username", Type: "string", Label: "SMTP username", Description: "Username used to authenticate against the submission server (optional).", }, { Id: "smtp_password", Type: "string", Label: "SMTP password", Description: "Password used to authenticate against the submission server (optional).", }, { Id: "from_address", Type: "string", Label: "From address", Placeholder: "postmaster@example.com", Required: true, Description: "Address used in the From header of the test email. Must belong to the tested domain.", }, { Id: "subject_override", Type: "string", Label: "Subject (optional)", Description: "Override the default test subject.", }, { Id: "body_text_override", Type: "string", Label: "Plain-text body (optional)", Description: "Override the default plain-text body.", }, { Id: "body_html_override", Type: "string", Label: "HTML body (optional)", Description: "Override the default HTML body.", }, { Id: "wait_timeout", Type: "string", Label: "Wait timeout (s)", Placeholder: "900", Description: "Seconds to wait for happyDeliver to receive and analyse the message. Defaults to 900.", }, { Id: "poll_interval", Type: "string", Label: "Poll interval (s)", Placeholder: "5", Description: "Seconds between status polls. Clamped to [2, 60]. Defaults to 5.", }, } } func (p *happyDeliverProvider) ParseForm(r *http.Request) (sdk.CheckerOptions, error) { domain := strings.TrimSuffix(strings.TrimSpace(r.FormValue("domain_name")), ".") if domain == "" { return nil, errors.New("domain_name is required") } url := strings.TrimSpace(r.FormValue("happydeliver_url")) if url == "" { return nil, errors.New("happydeliver_url is required") } smtpHost := strings.TrimSpace(r.FormValue("smtp_host")) if smtpHost == "" { return nil, errors.New("smtp_host is required") } from := strings.TrimSpace(r.FormValue("from_address")) if from == "" { return nil, errors.New("from_address is required") } opts := sdk.CheckerOptions{ "domain_name": domain, "happydeliver_url": url, "happydeliver_token": strings.TrimSpace(r.FormValue("happydeliver_token")), "smtp_host": smtpHost, "smtp_username": strings.TrimSpace(r.FormValue("smtp_username")), "smtp_password": r.FormValue("smtp_password"), "from_address": from, "subject_override": r.FormValue("subject_override"), "body_text_override": r.FormValue("body_text_override"), "body_html_override": r.FormValue("body_html_override"), } if v := strings.TrimSpace(r.FormValue("smtp_tls")); v != "" { opts["smtp_tls"] = strings.ToLower(v) } if v := strings.TrimSpace(r.FormValue("smtp_port")); v != "" { port, err := strconv.Atoi(v) if err != nil { return nil, errors.New("smtp_port must be a number") } opts["smtp_port"] = float64(port) } if v := strings.TrimSpace(r.FormValue("wait_timeout")); v != "" { n, err := strconv.Atoi(v) if err != nil { return nil, errors.New("wait_timeout must be a number") } opts["wait_timeout"] = float64(n) } if v := strings.TrimSpace(r.FormValue("poll_interval")); v != "" { n, err := strconv.Atoi(v) if err != nil { return nil, errors.New("poll_interval must be a number") } opts["poll_interval"] = float64(n) } return opts, nil }