feat: contact form backend for linux and freebsd servers
Test / test (push) Successful in 2m1s
Release / gates (push) Successful in 1m57s
Release / build (amd64, freebsd) (push) Successful in 1m26s
Release / build (amd64, linux) (push) Successful in 1m30s
Release / build (arm64, freebsd) (push) Successful in 1m28s
Release / build (arm64, linux) (push) Successful in 1m49s
Release / build (loong64, linux) (push) Successful in 1m30s
Release / build (riscv64, linux) (push) Successful in 1m29s
Release / release (push) Successful in 41s

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-29 00:32:56 +02:00
commit 3a38f00dc0
49 changed files with 10769 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: MIT
//go:build linux || freebsd
package email
import (
"bytes"
"fmt"
"net/smtp"
"time"
"sourcedock.dev/petrbalvin/nuntius/internal/config"
)
// SendConfirmation mails the double opt-in link directly to the subscriber.
// It uses the form's SMTP identity so replies land at the owner address,
// which is set as Reply-To.
func (s *FormSender) SendConfirmation(to, link string) error {
auth := smtp.PlainAuth("", s.form.SMTP.User, s.form.SMTP.Password, s.form.SMTP.Host)
msg := composeConfirmation(s.form.From, to, s.form.To, s.form, link)
return sendMail(s.form.SMTP, auth, s.form.From, []string{to}, msg, s.form.SMTP.Timeout(), s.TLSConfig)
}
// composeConfirmation builds a single-part plain-text message. Transactional
// confirmations stay deliberately simple: one link, no tracking, no HTML.
// The subject prefix and the footer brand come from the form's
// configuration; the defaults reproduce the earlier wording.
func composeConfirmation(from, to, replyToOwner string, form *config.Form, link string) []byte {
subject := "Confirm your subscription"
if prefix := form.EmailSubjectPrefix(); prefix != "" {
subject = fmt.Sprintf("[%s/%s] %s", prefix, form.Name, subject)
}
var body bytes.Buffer
fmt.Fprintf(&body, "Hi,\r\n\r\n")
fmt.Fprintf(&body, "someone signed this address up for the \"%s\" form.\r\n", form.Name)
fmt.Fprintf(&body, "If that was you, please confirm the subscription by opening:\r\n\r\n")
fmt.Fprintf(&body, " %s\r\n\r\n", link)
fmt.Fprintf(&body, "If it was not you, ignore this message and nothing will happen:\r\n")
fmt.Fprintf(&body, "the request expires automatically without any action from you.\r\n\r\n")
if brand := form.Brand(); brand != "" {
fmt.Fprintf(&body, "Delivered by %s\r\n", brand)
}
var msg bytes.Buffer
msg.WriteString(fmt.Sprintf("From: %s\r\n", sanitizeHeaderValue(from)))
msg.WriteString(fmt.Sprintf("To: %s\r\n", sanitizeHeaderValue(to)))
msg.WriteString(fmt.Sprintf("Subject: %s\r\n", sanitizeHeaderValue(subject)))
msg.WriteString(fmt.Sprintf("Date: %s\r\n", time.Now().UTC().Format(time.RFC1123Z)))
msg.WriteString(fmt.Sprintf("Reply-To: %s\r\n", sanitizeHeaderValue(replyToOwner)))
msg.WriteString("MIME-Version: 1.0\r\n")
msg.WriteString("Content-Type: text/plain; charset=UTF-8\r\n")
msg.WriteString("Content-Transfer-Encoding: 8bit\r\n")
msg.WriteString("\r\n")
msg.Write(body.Bytes())
return msg.Bytes()
}