135 lines
2.9 KiB
Go
135 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"mime"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"io"
|
|
|
|
"github.com/jhillyerd/enmime"
|
|
"github.com/mhale/smtpd"
|
|
)
|
|
|
|
type Config struct {
|
|
Address string `json:"addr"`
|
|
ApiUrl string `json:"api_url"`
|
|
ApiKey string `json:"api_key"`
|
|
}
|
|
|
|
type MailContent struct {
|
|
Key string `json:"key"`
|
|
From string `json:"from"`
|
|
To string `json:"to"`
|
|
Title string `json:"title"`
|
|
Body string `json:"body"`
|
|
FromAddr string `json:"from_addr"`
|
|
FromProtocol string `json:"from_protocol"`
|
|
ReceivedAt string `json:"received_at"`
|
|
}
|
|
|
|
var appConfig Config
|
|
|
|
func decodeHeader(header string) (string, error) {
|
|
decoded, err := (&mime.WordDecoder{}).DecodeHeader(header)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return decoded, nil
|
|
}
|
|
|
|
func postMailContent(url string, key string, mailContent *MailContent) error {
|
|
jsonData, err := json.Marshal(mailContent)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(io.Reader(resp.Body))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Println("Response Status:", resp.Status)
|
|
log.Println("Response Body:", string(body))
|
|
|
|
return nil
|
|
}
|
|
|
|
func mailHandler(origin net.Addr, from string, to []string, data []byte) error {
|
|
reader := bytes.NewReader(data)
|
|
env, _ := enmime.ReadEnvelope(reader)
|
|
|
|
subject := env.GetHeader("Subject")
|
|
fmt.Printf("Text Body: %v chars\n", len(env.Text))
|
|
fmt.Printf("HTML Body: %v chars\n", len(env.HTML))
|
|
|
|
body := env.HTML
|
|
if len(body) == 0 {
|
|
body = env.Text
|
|
}
|
|
|
|
log.Printf("Received mail from %s for %s with subject %s", from, to[0], subject)
|
|
|
|
receivedAt := time.Now()
|
|
|
|
mailContent := &MailContent{
|
|
Key: appConfig.ApiKey,
|
|
From: from,
|
|
To: to[0],
|
|
Title: subject,
|
|
Body: body,
|
|
FromAddr: origin.String(),
|
|
FromProtocol: origin.Network(),
|
|
ReceivedAt: receivedAt.Format(time.RFC3339),
|
|
}
|
|
|
|
err := postMailContent(appConfig.ApiUrl, appConfig.ApiKey, mailContent)
|
|
if err != nil {
|
|
log.Println("Failed to post mail content:", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
configPath := flag.String("c", "config.json", "Path to the configuration file")
|
|
flag.Parse()
|
|
|
|
file, err := os.Open(*configPath)
|
|
if err != nil {
|
|
log.Fatalf("Error opening config file: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
configBytes, err := io.ReadAll(io.Reader(file))
|
|
if err != nil {
|
|
log.Fatalf("Error reading config file: %v", err)
|
|
}
|
|
|
|
if err := json.Unmarshal(configBytes, &appConfig); err != nil {
|
|
log.Fatalf("Error parsing config file: %v", err)
|
|
}
|
|
|
|
log.Printf("Starting server at %s", appConfig.Address)
|
|
smtpd.ListenAndServe(appConfig.Address, mailHandler, "MyServerApp", "")
|
|
}
|