aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/meta/request.go40
-rw-r--r--utils/meta/types.go3
-rw-r--r--utils/meta/value.go23
-rw-r--r--utils/smtp/constants.go5
-rw-r--r--utils/smtp/server.go56
-rw-r--r--utils/smtp/session.go61
-rw-r--r--utils/smtp/storage.go22
-rw-r--r--utils/smtp/types.go13
8 files changed, 202 insertions, 21 deletions
diff --git a/utils/meta/request.go b/utils/meta/request.go
index 3098970..34a659a 100644
--- a/utils/meta/request.go
+++ b/utils/meta/request.go
@@ -8,36 +8,56 @@ import (
"github.com/gofiber/fiber/v2"
)
-func Request(context *fiber.Ctx) request {
+func Request(context *fiber.Ctx) *request {
data, ok := context.Locals(REQUEST_KEY).(types.Request)
if !ok {
logger.Errorf(LOG_PREFIX, messages.MetaRequestContextMissing)
- return request{}
+ return nil
}
- return request{
+ return &request{
Request: data,
context: context,
}
}
-func (self request) Param(key string) value {
+func (self *request) Param(key string) *value {
+ if self == nil {
+ return nil
+ }
+
if self.context != nil {
result := self.context.Params(key)
if result != "" {
- return value{data: result, found: true}
+ return &value{data: result}
}
}
- return value{}
+ return nil
}
-func (self request) Query(key string) value {
+func (self *request) Query(key string) *value {
+ if self == nil {
+ return nil
+ }
+
result, found := findParam(self.Request.Query, key)
- return value{data: result, found: found}
+ if found {
+ return &value{data: result}
+ }
+
+ return nil
}
-func (self request) Header(key string) value {
+func (self *request) Header(key string) *value {
+ if self == nil {
+ return nil
+ }
+
result, found := findParam(self.Request.Headers, key)
- return value{data: result, found: found}
+ if found {
+ return &value{data: result}
+ }
+
+ return nil
}
diff --git a/utils/meta/types.go b/utils/meta/types.go
index 8aa710f..3bc8a0e 100644
--- a/utils/meta/types.go
+++ b/utils/meta/types.go
@@ -12,6 +12,5 @@ type request struct {
}
type value struct {
- data string
- found bool
+ data string
}
diff --git a/utils/meta/value.go b/utils/meta/value.go
index fb90500..889ba0e 100644
--- a/utils/meta/value.go
+++ b/utils/meta/value.go
@@ -5,25 +5,30 @@ import (
"dove/utils/logger"
)
-func (self value) String() string {
+func (self *value) String() string {
+ if self == nil {
+ return ""
+ }
+
return self.data
}
-func (self value) Exists() bool {
- return self.found
+func (self *value) Exists() bool {
+ return self != nil
}
-func (self value) Or(fallback string) string {
- if self.found {
- return self.data
+func (self *value) Or(fallback string) string {
+ if self == nil {
+ return fallback
}
- return fallback
+ return self.data
}
-func (self value) Required() string {
- if !self.found {
+func (self *value) Required() string {
+ if self == nil {
logger.Errorf(LOG_PREFIX, messages.MetaRequiredValueMissing)
+ return ""
}
return self.data
diff --git a/utils/smtp/constants.go b/utils/smtp/constants.go
new file mode 100644
index 0000000..cc6d173
--- /dev/null
+++ b/utils/smtp/constants.go
@@ -0,0 +1,5 @@
+package smtp
+
+const (
+ LOG_PREFIX = "SMTP"
+)
diff --git a/utils/smtp/server.go b/utils/smtp/server.go
new file mode 100644
index 0000000..0092c16
--- /dev/null
+++ b/utils/smtp/server.go
@@ -0,0 +1,56 @@
+package smtp
+
+import (
+ "dove/config"
+ "dove/messages"
+ "dove/utils/logger"
+ "fmt"
+ "time"
+
+ gosmtp "github.com/emersion/go-smtp"
+)
+
+var activeServers []serverInstance
+
+func Start() {
+ plainAddress := fmt.Sprintf("%s:%d", config.SMTP.Host, config.SMTP.Port)
+ plainServer := createServer(plainAddress)
+
+ activeServers = append(activeServers, serverInstance{server: plainServer, label: LOG_PREFIX})
+
+ go startListener(plainServer, LOG_PREFIX, plainAddress)
+}
+
+func Shutdown() {
+ for _, instance := range activeServers {
+ if shutdownError := instance.server.Close(); shutdownError != nil {
+ logger.Errorf(LOG_PREFIX, messages.SMTPShutdownFailed, instance.label, shutdownError)
+ }
+ }
+
+ logger.Infof(LOG_PREFIX, messages.SMTPShutdownComplete)
+}
+
+func createServer(address string) *gosmtp.Server {
+ smtpServer := gosmtp.NewServer(gosmtp.BackendFunc(func(connection *gosmtp.Conn) (gosmtp.Session, error) {
+ logger.Debugf(LOG_PREFIX, messages.SMTPSessionStarted, connection.Hostname())
+ return &session{}, nil
+ }))
+
+ smtpServer.Addr = address
+ smtpServer.Domain = config.SMTP.Domain
+ smtpServer.ReadTimeout = time.Duration(config.SMTP.ReadTimeout) * time.Second
+ smtpServer.WriteTimeout = time.Duration(config.SMTP.WriteTimeout) * time.Second
+ smtpServer.MaxMessageBytes = int64(config.SMTP.MaxMessageSize)
+ smtpServer.AllowInsecureAuth = true
+
+ return smtpServer
+}
+
+func startListener(smtpServer *gosmtp.Server, label string, address string) {
+ logger.Successf(LOG_PREFIX, messages.SMTPServerStarting, label, address)
+
+ if listenError := smtpServer.ListenAndServe(); listenError != nil {
+ logger.Fatalf(LOG_PREFIX, messages.SMTPListenFailed, label, listenError)
+ }
+}
diff --git a/utils/smtp/session.go b/utils/smtp/session.go
new file mode 100644
index 0000000..029c257
--- /dev/null
+++ b/utils/smtp/session.go
@@ -0,0 +1,61 @@
+package smtp
+
+import (
+ "dove/config"
+ "dove/messages"
+ "dove/utils/logger"
+ "dove/utils/errors"
+ "io"
+
+ gosmtp "github.com/emersion/go-smtp"
+)
+
+func (self *session) AuthPlain(username string, password string) error {
+ if !config.SMTP.AuthRequired {
+ return nil
+ }
+
+ if username != config.SMTP.Username || password != config.SMTP.Password {
+ logger.Warnf(LOG_PREFIX, messages.SMTPAuthFailed, username)
+ return errors.Error(messages.SMTPInvalidCredentials)
+ }
+
+ return nil
+}
+
+func (self *session) Mail(senderAddress string, mailOptions *gosmtp.MailOptions) error {
+ logger.Debugf(LOG_PREFIX, messages.SMTPMailFrom, senderAddress)
+ self.fromAddress = senderAddress
+ return nil
+}
+
+func (self *session) Rcpt(recipientAddress string, recipientOptions *gosmtp.RcptOptions) error {
+ logger.Debugf(LOG_PREFIX, messages.SMTPRecipient, recipientAddress)
+ self.toAddresses = append(self.toAddresses, recipientAddress)
+ return nil
+}
+
+func (self *session) Data(messageReader io.Reader) error {
+ rawMessage, readError := io.ReadAll(messageReader)
+ if readError != nil {
+ return readError
+ }
+
+ logger.Infof(LOG_PREFIX, messages.SMTPMessageReceived, len(rawMessage))
+
+ if storeError := storeMessage(self.fromAddress, self.toAddresses, rawMessage); storeError != nil {
+ logger.Errorf(LOG_PREFIX, messages.SMTPMessageStoreFailed, storeError)
+ return storeError
+ }
+
+ return nil
+}
+
+func (self *session) Reset() {
+ self.fromAddress = ""
+ self.toAddresses = nil
+}
+
+func (self *session) Logout() error {
+ return nil
+}
diff --git a/utils/smtp/storage.go b/utils/smtp/storage.go
new file mode 100644
index 0000000..b580d67
--- /dev/null
+++ b/utils/smtp/storage.go
@@ -0,0 +1,22 @@
+package smtp
+
+import (
+ "dove/config"
+ "fmt"
+ "os"
+ "path/filepath"
+ "time"
+)
+
+func storeMessage(fromAddress string, toAddresses []string, rawMessage []byte) error {
+ emailDirectory := filepath.Join(config.DataDir, "emails")
+
+ if directoryError := os.MkdirAll(emailDirectory, 0750); directoryError != nil {
+ return directoryError
+ }
+
+ filename := fmt.Sprintf("%d.eml", time.Now().UnixNano())
+ filePath := filepath.Join(emailDirectory, filename)
+
+ return os.WriteFile(filePath, rawMessage, 0640)
+} \ No newline at end of file
diff --git a/utils/smtp/types.go b/utils/smtp/types.go
new file mode 100644
index 0000000..38c6504
--- /dev/null
+++ b/utils/smtp/types.go
@@ -0,0 +1,13 @@
+package smtp
+
+import gosmtp "github.com/emersion/go-smtp"
+
+type session struct {
+ fromAddress string
+ toAddresses []string
+}
+
+type serverInstance struct {
+ server *gosmtp.Server
+ label string
+}