Files
amsterdam/email/message.go
T

165 lines
4.0 KiB
Go

/*
* Amsterdam Web Communities System
* Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// Package email contains support for E-mail messages sent by Amsterdam.
package email
import (
"fmt"
"sync"
"git.erbosoft.com/amy/amsterdam/config"
"github.com/CloudyKit/jet/v6"
)
// Message is the interface for an E-mail message to be sent.
type Message interface {
SetFrom(string, string)
AddTo(string, string)
AddCC(string, string)
AddBCC(string, string)
GetSubject() string
SetSubject(string)
SetText(string)
AddHeader(string, string)
SetTemplate(string)
AddVariable(string, any)
Send()
}
// amMessage is the internal structure of the Message.
type amMessage struct {
from string
fromAddr string
to []string
toAddrs []string
cc []string
bcc []string
subject string
text string
headers map[string]string
template string
vars jet.VarMap
uid int32
ip string
}
// freeMessages is a free list for amMessage structures.
var freeMessages sync.Pool
// formatAddress outputs an E-mail address with optional name associated with it.
func formatAddress(addr string, name string) string {
if name == "" {
return addr
} else {
return fmt.Sprintf("%s <%s>", name, addr)
}
}
// SetFrom sets the From: address of the message.
func (m *amMessage) SetFrom(addr string, name string) {
m.from = formatAddress(addr, name)
m.fromAddr = addr
}
// AddTo ads a To: address to the message.
func (m *amMessage) AddTo(addr string, name string) {
m.to = append(m.to, formatAddress(addr, name))
m.toAddrs = append(m.toAddrs, addr)
}
// AddCC ads a Cc: address to the message.
func (m *amMessage) AddCC(addr string, name string) {
m.cc = append(m.cc, formatAddress(addr, name))
m.toAddrs = append(m.toAddrs, addr)
}
// AddBCC ads a Bcc: address to the message.
func (m *amMessage) AddBCC(addr string, name string) {
m.bcc = append(m.bcc, formatAddress(addr, name))
m.toAddrs = append(m.toAddrs, addr)
}
// GetSubject gets the message's subject.
func (m *amMessage) GetSubject() string {
return m.subject
}
// SetSubject sets the message's subject.
func (m *amMessage) SetSubject(s string) {
m.subject = s
}
// SetText sets the text of the message.
func (m *amMessage) SetText(txt string) {
m.text = txt
}
// AddHaader adds a new header to the message.
func (m *amMessage) AddHeader(name string, value string) {
m.headers[name] = value
}
func (m *amMessage) SetTemplate(templ string) {
m.template = templ
}
func (m *amMessage) AddVariable(name string, value any) {
m.vars.Set(name, value)
}
func (m *amMessage) Send() {
sendChan <- m
}
/* AmNewEmailMessage creates a new message and returns it.
* Parameters:
* sender = User ID of the person sending the message.
* ip = IP address of the person sending the message.
* Returns:
* The new Message.
*/
func AmNewEmailMessage(sender int32, ip string) Message {
rc := freeMessages.Get().(*amMessage)
if rc == nil {
rc = &amMessage{to: make([]string, 0), cc: make([]string, 0), bcc: make([]string, 0),
headers: make(map[string]string), vars: make(jet.VarMap)}
}
rc.uid = sender
rc.ip = ip
rc.SetFrom(config.GlobalConfig.Email.MailFromAddr, config.GlobalConfig.Email.MailFromName)
return rc
}
// The "recycle bin" for messages.
var messageRecycleBin chan *amMessage
// recycleMessages is a goroutine that recycles the messages on its queue.
func recycleMessages(messages chan *amMessage, done chan bool) {
for m := range messages {
m.from = ""
m.fromAddr = ""
m.to = make([]string, 0)
m.toAddrs = make([]string, 0)
m.cc = make([]string, 0)
m.bcc = make([]string, 0)
m.subject = ""
m.text = ""
for k := range m.headers {
delete(m.headers, k)
}
m.template = ""
for k := range m.vars {
delete(m.vars, k)
}
freeMessages.Put(m)
}
done <- true
}