commit 0017e12f942c741362ee5305930055a0de8fd494
parent d5f0f7daf9c4c382bb314c024cae1c98f8f139fe
Author: dwrz <dwrz@dwrz.net>
Date: Fri, 2 Dec 2022 16:00:08 +0000
Add sgm command
Diffstat:
3 files changed, 130 insertions(+), 0 deletions(-)
diff --git a/cmd/sgm/config/config.go b/cmd/sgm/config/config.go
@@ -0,0 +1,47 @@
+package config
+
+import (
+ _ "embed"
+ "encoding/json"
+ "flag"
+ "fmt"
+)
+
+var (
+ //go:embed config.json
+ configuration []byte
+
+ attachment = flag.String("a", "", "attachment path")
+ from = flag.String("f", "", "sender address")
+ subject = flag.String("s", "", "subject")
+ text = flag.String("m", "", "message text")
+ to = flag.String("t", "", "recipient address, comma delimited")
+)
+
+type Config struct {
+ Attachment string
+ From string
+ Pass string
+ Subject string
+ Text string
+ To string
+ User string
+}
+
+func New() (*Config, error) {
+ flag.Parse()
+
+ var cfg = &Config{
+ Attachment: *attachment,
+ From: *from,
+ Subject: *subject,
+ Text: *text,
+ To: *to,
+ }
+ // Load the username and password from the embedded configuration.
+ if err := json.Unmarshal(configuration, cfg); err != nil {
+ return nil, fmt.Errorf("failed to parse config file: %v", err)
+ }
+
+ return cfg, nil
+}
diff --git a/cmd/sgm/config/config.json.template b/cmd/sgm/config/config.json.template
@@ -0,0 +1,4 @@
+{
+ "user": "",
+ "pass": ""
+}
diff --git a/cmd/sgm/main.go b/cmd/sgm/main.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "encoding/base64"
+ "fmt"
+ "net/http"
+ "net/smtp"
+ "os"
+ "strings"
+
+ "code.dwrz.net/src/cmd/sgm/config"
+ "code.dwrz.net/src/pkg/gmail"
+ "code.dwrz.net/src/pkg/log"
+)
+
+func main() {
+ var l = log.New(os.Stderr)
+
+ // Get the configuration.
+ cfg, err := config.New()
+ if err != nil {
+ l.Error.Fatalf("failed to get config: %v", err)
+ }
+
+ // Compose email.
+ var str strings.Builder
+
+ fmt.Fprintf(&str, "From: %s\r\n", cfg.From)
+ fmt.Fprintf(&str, "To: %s\r\n", cfg.To)
+ fmt.Fprintf(&str, "Subject: %s\r\n", cfg.Subject)
+
+ str.WriteString("MIME-Version: 1.0\n")
+ str.WriteString("Content-Type: multipart/mixed; boundary=\"=-=-=\"\n")
+ str.WriteString("\n")
+ str.WriteString("--=-=-=\n")
+ str.WriteString("Content-Type: text/plain; format=flowed\n")
+ str.WriteString("\n")
+ str.WriteString("\n")
+ str.WriteString(cfg.Text)
+ str.WriteString("\n")
+ str.WriteString("--=-=-=\n")
+
+ // Add the attachment, if provided.
+ if cfg.Attachment != "" {
+ data, err := os.ReadFile(cfg.Attachment)
+ if err != nil {
+ l.Error.Fatalf("failed to open file: %v", err)
+ }
+
+ fmt.Fprintf(
+ &str,
+ "Content-Type: %s\n", http.DetectContentType(data),
+ )
+ fmt.Fprintf(
+ &str,
+ "Content-Disposition: attachment; filename=%s\n",
+ *&cfg.Attachment,
+ )
+ str.WriteString("Content-Transfer-Encoding: base64\n")
+ fmt.Fprintf(&str, "Content-Description: %s\n", cfg.Attachment)
+ str.WriteString("\n")
+ str.WriteString(base64.StdEncoding.EncodeToString([]byte(data)))
+ str.WriteString("--=-=-=\n")
+ }
+
+ // Send the email.
+ if err := smtp.SendMail(
+ gmail.Address,
+ &gmail.Auth{
+ Username: cfg.User,
+ Password: cfg.Pass,
+ },
+ cfg.From,
+ strings.Split(cfg.To, ","),
+ []byte(str.String()),
+ ); err != nil {
+ l.Error.Fatalf("failed to send email: %v", err)
+ }
+}