108 lines
2.8 KiB
Go
108 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"log/slog"
|
|
"net/smtp"
|
|
"os"
|
|
|
|
"git.nakama.town/fmartingr/gotoolkit/encoding"
|
|
"github.com/emersion/go-sasl"
|
|
|
|
"codeberg.org/fmartingr/smtp2shoutrrr"
|
|
)
|
|
|
|
// The ANONYMOUS mechanism name.
|
|
const Anonymous = "ANONYMOUS"
|
|
|
|
type anonymousClient struct {
|
|
Trace string
|
|
}
|
|
|
|
func (c *anonymousClient) Start(si *smtp.ServerInfo) (mech string, ir []byte, err error) {
|
|
mech = Anonymous
|
|
ir = []byte(c.Trace)
|
|
return
|
|
}
|
|
|
|
func (c *anonymousClient) Next(challenge []byte, b bool) (response []byte, err error) {
|
|
return nil, sasl.ErrUnexpectedServerChallenge
|
|
}
|
|
|
|
// A client implementation of the ANONYMOUS authentication mechanism, as
|
|
// described in RFC 4505.
|
|
func NewAnonymousClient(trace string) smtp.Auth {
|
|
return &anonymousClient{trace}
|
|
}
|
|
|
|
// The PLAIN mechanism name.
|
|
const Plain = "PLAIN"
|
|
|
|
type plainClient struct {
|
|
Identity string
|
|
Username string
|
|
Password string
|
|
}
|
|
|
|
func (a *plainClient) Start(si *smtp.ServerInfo) (mech string, ir []byte, err error) {
|
|
mech = "PLAIN"
|
|
ir = []byte(a.Identity + "\x00" + a.Username + "\x00" + a.Password)
|
|
return
|
|
}
|
|
|
|
func (a *plainClient) Next(challenge []byte, b bool) (response []byte, err error) {
|
|
slog.Info("Next: %v", slog.String("challenge", string(challenge)))
|
|
return nil, nil
|
|
}
|
|
|
|
// A client implementation of the PLAIN authentication mechanism, as described
|
|
// in RFC 4616. Authorization identity may be left blank to indicate that it is
|
|
// the same as the username.
|
|
func NewPlainClient(identity, username, password string) smtp.Auth {
|
|
return &plainClient{identity, username, password}
|
|
}
|
|
|
|
func main() {
|
|
var config smtp2shoutrrr.Config
|
|
configPath := "config.toml"
|
|
|
|
f, err := os.Open(configPath)
|
|
if err != nil {
|
|
slog.Error("Error opening config file", slog.String("err", err.Error()), slog.String("path", configPath))
|
|
return
|
|
}
|
|
|
|
enc := encoding.NewTOMLEncoding()
|
|
if err := enc.DecodeReader(f, &config); err != nil {
|
|
slog.Error("Error decoding config file", slog.String("err", err.Error()), slog.String("path", configPath))
|
|
return
|
|
}
|
|
|
|
config.SetDefaults()
|
|
|
|
// hostname is used by PlainAuth to validate the TLS certificate.
|
|
hostname := "localhost"
|
|
auth := NewPlainClient("", config.Username, config.Password)
|
|
// auth := NewAnonymousClient("test")
|
|
|
|
slog.Info("Using first recipient configuration to send a test email")
|
|
|
|
if len(config.Recipients) == 0 {
|
|
slog.Error("No recipients found in configuration")
|
|
return
|
|
}
|
|
|
|
if len(config.Recipients[0].Addresses) == 0 {
|
|
slog.Error("No email addresses found in first recipient configuration")
|
|
return
|
|
}
|
|
|
|
recipients := []string{config.Recipients[0].Addresses[0]}
|
|
msg := []byte("Subject: Test notification\r\n\r\nThis is a test notification")
|
|
from := "hello@localhost"
|
|
err = smtp.SendMail(fmt.Sprintf("%s:%d", hostname, config.Port), auth, from, recipients, msg)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|