aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorBobby <[email protected]>2026-03-08 03:06:23 +0530
committerBobby <[email protected]>2026-03-08 03:06:23 +0530
commitcaf265e7050edefa64ecf7e13828ec9636bce867 (patch)
tree6bb8554dbb34695a74c2dca556bf512998cf62ab /services
parentcca905d35412f1549400fc3d1aca6dc704d8cae6 (diff)
downloaddove-caf265e7050edefa64ecf7e13828ec9636bce867.tar.xz
dove-caf265e7050edefa64ecf7e13828ec9636bce867.zip
Refactor configuration handling and add mail management features
- Removed dependency on messages package in TOML loading and parsing. - Introduced new config constants and messages for better clarity and maintainability. - Implemented mail user and mailbox management with corresponding controllers and views. - Added new templates for mailboxes, mailbox creation, and user management. - Enhanced logging and error handling throughout the application. - Established a structured approach for applying default values in TOML configuration. - Created new utility functions for SMTP and email handling.
Diffstat (limited to 'services')
-rw-r--r--services/auth.go37
-rw-r--r--services/auth/auth.go2
-rw-r--r--services/constants.go5
-rw-r--r--services/email.go31
-rw-r--r--services/functions.go137
-rw-r--r--services/mail/mailboxes.go18
-rw-r--r--services/mail/users.go16
-rw-r--r--services/mailbox.go68
-rw-r--r--services/overview.go16
-rw-r--r--services/user.go50
10 files changed, 18 insertions, 362 deletions
diff --git a/services/auth.go b/services/auth.go
deleted file mode 100644
index ce62d10..0000000
--- a/services/auth.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package services
-
-import (
- "dove/config"
- "dove/enums"
- "dove/messages"
- "dove/types"
- "dove/utils/auth"
- "dove/utils/shortcuts"
-
- "github.com/gofiber/fiber/v2"
-)
-
-func Authenticate(context *fiber.Ctx, request types.LoginRequest) (*types.MessageResponse, *types.ServiceError) {
- switch request.Username == config.Server.Username && request.Password == config.Server.Password {
- case true:
- if sessionError := auth.Authenticate(context); sessionError != nil {
- return nil, shortcuts.ServiceError(enums.Internal, sessionError.Error())
- }
-
- return &types.MessageResponse{
- Message: messages.AuthAuthenticated,
- }, nil
- default:
- return nil, shortcuts.ServiceError(enums.Unauthorized, messages.AuthInvalidCredentials)
- }
-}
-
-func Deauthenticate(context *fiber.Ctx) (*types.MessageResponse, *types.ServiceError) {
- if sessionError := auth.Deauthenticate(context); sessionError != nil {
- return nil, shortcuts.ServiceError(enums.Internal, sessionError.Error())
- }
-
- return &types.MessageResponse{
- Message: messages.AuthLoggedOut,
- }, nil
-} \ No newline at end of file
diff --git a/services/auth/auth.go b/services/auth/auth.go
index 89ef205..b8a0e13 100644
--- a/services/auth/auth.go
+++ b/services/auth/auth.go
@@ -18,7 +18,7 @@ type MessageResponse struct {
}
func Authenticate(context *fiber.Ctx, request LoginRequest) (*MessageResponse, *shortcuts.Error) {
- switch request.Username == config.Server.Username && request.Password == config.Server.Password {
+ switch request.Username == config.HTTP.Username && request.Password == config.HTTP.Password {
case true:
if sessionError := authUtils.Authenticate(context); sessionError != nil {
return nil, shortcuts.ServiceError(shortcuts.Internal, sessionError.Error())
diff --git a/services/constants.go b/services/constants.go
deleted file mode 100644
index bba619b..0000000
--- a/services/constants.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package services
-
-const (
- LOG_PREFIX = "Services"
-)
diff --git a/services/email.go b/services/email.go
deleted file mode 100644
index 36ae5f6..0000000
--- a/services/email.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package services
-
-import (
- "dove/messages"
- "dove/utils/email"
- "dove/utils/logger"
-)
-
-func ProcessEmail(rawMessage []byte, recipientAddresses []string) error {
- parsedEmail, parseError := email.Parse(rawMessage)
- if parseError != nil {
- logger.Errorf(LOG_PREFIX, messages.EmailParseFailed, parseError)
- return parseError
- }
-
- mailboxes := ResolveMailboxes(recipientAddresses)
- if len(mailboxes) == 0 {
- return nil
- }
-
- for _, mailbox := range mailboxes {
- if storeError := storeEmailForMailbox(rawMessage, parsedEmail, mailbox); storeError != nil {
- logger.Errorf(LOG_PREFIX, messages.EmailStoreFailed, storeError)
- return storeError
- }
- }
-
- logger.Infof(LOG_PREFIX, messages.EmailProcessed, len(mailboxes))
-
- return nil
-}
diff --git a/services/functions.go b/services/functions.go
deleted file mode 100644
index ffba7f4..0000000
--- a/services/functions.go
+++ /dev/null
@@ -1,137 +0,0 @@
-package services
-
-import (
- "dove/config"
- "dove/enums"
- "dove/messages"
- "dove/models"
- "dove/repositories"
- "dove/utils/email"
- "dove/utils/logger"
- "fmt"
- "os"
- "path/filepath"
- "strings"
- "time"
-)
-
-func resolveMailbox(address string) *models.Mailbox {
- mailbox := repositories.FindMailboxByAddress(address)
- if mailbox != nil {
- return mailbox
- }
-
- alias := repositories.FindAliasByAddress(address)
- if alias != nil {
- return &alias.Mailbox
- }
-
- switch config.Mailbox.Mode {
- case enums.Catchall:
- return createMailboxForAddress(address)
- default:
- logger.Warnf(LOG_PREFIX, messages.MailboxNotRegistered, address)
- return nil
- }
-}
-
-func createMailboxForAddress(address string) *models.Mailbox {
- user := repositories.FindUserByUsername(address)
- if user == nil {
- user = &models.User{
- Username: address,
- DisplayName: address,
- }
- repositories.CreateUser(user)
- }
-
- mailbox := &models.Mailbox{
- Address: address,
- UserID: user.ID,
- }
-
- repositories.CreateMailbox(mailbox)
- logger.Infof(LOG_PREFIX, messages.MailboxAutoCreated, address)
-
- return mailbox
-}
-
-func storeEmailForMailbox(rawMessage []byte, parsedEmail *email.ParsedEmail, mailbox models.Mailbox) error {
- filename, saveError := saveEmailFile(rawMessage, mailbox.ID)
- if saveError != nil {
- return saveError
- }
-
- attachmentCount, inlineCount := countAttachments(parsedEmail.Attachments)
-
- emailRecord := &models.Email{
- MailboxID: mailbox.ID,
- MessageID: parsedEmail.MessageID,
- Filename: filename,
- FromAddress: parsedEmail.FromAddress,
- FromName: parsedEmail.FromName,
- ToAddresses: strings.Join(parsedEmail.ToAddresses, ", "),
- CcAddresses: strings.Join(parsedEmail.CcAddresses, ", "),
- BccAddresses: strings.Join(parsedEmail.BccAddresses, ", "),
- ReplyToAddress: parsedEmail.ReplyToAddress,
- ReturnPath: parsedEmail.ReturnPath,
- Subject: parsedEmail.Subject,
- Snippet: parsedEmail.Snippet,
- Size: parsedEmail.Size,
- AttachmentCount: attachmentCount,
- InlineCount: inlineCount,
- }
-
- if indexError := repositories.CreateEmail(emailRecord); indexError != nil {
- logger.Errorf(LOG_PREFIX, messages.EmailIndexFailed, indexError)
- return indexError
- }
-
- for _, parsedAttachment := range parsedEmail.Attachments {
- attachmentRecord := &models.Attachment{
- EmailID: emailRecord.ID,
- Filename: parsedAttachment.Filename,
- ContentType: parsedAttachment.ContentType,
- ContentID: parsedAttachment.ContentID,
- Size: parsedAttachment.Size,
- IsInline: parsedAttachment.IsInline,
- }
-
- repositories.CreateAttachment(attachmentRecord)
- }
-
- return nil
-}
-
-func saveEmailFile(rawMessage []byte, mailboxID uint) (string, error) {
- mailboxDirectory := filepath.Join(config.DataDir, "emails", fmt.Sprintf("%d", mailboxID))
-
- if directoryError := os.MkdirAll(mailboxDirectory, 0750); directoryError != nil {
- return "", directoryError
- }
-
- filename := fmt.Sprintf("%d.eml", time.Now().UnixNano())
- filePath := filepath.Join(mailboxDirectory, filename)
-
- if writeError := os.WriteFile(filePath, rawMessage, 0640); writeError != nil {
- return "", writeError
- }
-
- return filename, nil
-}
-
-func countAttachments(attachments []email.ParsedAttachment) (int, int) {
- attachmentCount := 0
- inlineCount := 0
-
- for _, attachment := range attachments {
- switch attachment.IsInline {
- case true:
- inlineCount++
- default:
- attachmentCount++
- }
- }
-
- return attachmentCount, inlineCount
-}
diff --git a/services/mail/mailboxes.go b/services/mail/mailboxes.go
index b124dc9..89af4c4 100644
--- a/services/mail/mailboxes.go
+++ b/services/mail/mailboxes.go
@@ -3,8 +3,8 @@ package mail
import (
"strings"
- "dove/models"
- "dove/repositories"
+ mailModel "dove/models/mail"
+ mailRepo "dove/repositories/mail"
"dove/utils/meta"
"dove/utils/shortcuts"
)
@@ -15,7 +15,7 @@ type CreateMailboxRequest struct {
}
type MailboxFormResponse struct {
- Users []models.User `json:"users"`
+ Users []mailModel.User `json:"users"`
}
type MailboxView struct {
@@ -23,13 +23,13 @@ type MailboxView struct {
}
func ListMailboxes(pagination meta.Pagination, sorting meta.Sorting, search string) meta.PaginatedResponse {
- mailboxes, total := repositories.ListMailboxes(pagination, sorting, search)
+ mailboxes, total := mailRepo.ListMailboxes(pagination, sorting, search)
return pagination.Response(mailboxes, total)
}
func MailboxFormData() MailboxFormResponse {
return MailboxFormResponse{
- Users: repositories.AllUsers(),
+ Users: mailRepo.AllUsers(),
}
}
@@ -43,20 +43,20 @@ func CreateMailbox(request CreateMailboxRequest) *shortcuts.Error {
return shortcuts.ServiceError(shortcuts.BadRequest, UserRequired)
}
- if repositories.FindUserByID(request.UserID) == nil {
+ if mailRepo.FindUserByID(request.UserID) == nil {
return shortcuts.ServiceError(shortcuts.Unprocessable, UserNotFound)
}
- if repositories.FindMailboxByAddress(address) != nil {
+ if mailRepo.FindMailboxByAddress(address) != nil {
return shortcuts.ServiceError(shortcuts.Unprocessable, AlreadyExists)
}
- mailbox := &models.Mailbox{
+ mailbox := &mailModel.Mailbox{
Address: address,
UserID: request.UserID,
}
- if createError := repositories.CreateMailbox(mailbox); createError != nil {
+ if createError := mailRepo.CreateMailbox(mailbox); createError != nil {
return shortcuts.ServiceError(shortcuts.Internal, CreationFailed)
}
diff --git a/services/mail/users.go b/services/mail/users.go
index 9520219..9c776a1 100644
--- a/services/mail/users.go
+++ b/services/mail/users.go
@@ -3,8 +3,8 @@ package mail
import (
"strings"
- "dove/models"
- "dove/repositories"
+ mailModel "dove/models/mail"
+ mailRepo "dove/repositories/mail"
"dove/utils/meta"
"dove/utils/shortcuts"
)
@@ -15,7 +15,7 @@ type CreateUserRequest struct {
}
func ListUsers(pagination meta.Pagination, sorting meta.Sorting, search string) meta.PaginatedResponse {
- users, total := repositories.ListUsers(pagination, sorting, search)
+ users, total := mailRepo.ListUsers(pagination, sorting, search)
return pagination.Response(users, total)
}
@@ -31,22 +31,22 @@ func CreateUser(request CreateUserRequest) *shortcuts.Error {
return shortcuts.ServiceError(shortcuts.BadRequest, DisplayNameRequired)
}
- if repositories.FindUserByUsername(username) != nil {
+ if mailRepo.FindUserByUsername(username) != nil {
return shortcuts.ServiceError(shortcuts.Unprocessable, UserAlreadyExists)
}
- newUser := &models.User{
+ newUser := &mailModel.User{
Username: username,
DisplayName: displayName,
}
- if createError := repositories.CreateUser(newUser); createError != nil {
+ if createError := mailRepo.CreateUser(newUser); createError != nil {
return shortcuts.ServiceError(shortcuts.Internal, UserCreationFailed)
}
return nil
}
-func AllUsers() []models.User {
- return repositories.AllUsers()
+func AllUsers() []mailModel.User {
+ return mailRepo.AllUsers()
}
diff --git a/services/mailbox.go b/services/mailbox.go
deleted file mode 100644
index d1e954d..0000000
--- a/services/mailbox.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package services
-
-import (
- "strings"
-
- "dove/enums"
- "dove/messages"
- "dove/models"
- "dove/repositories"
- "dove/types"
- "dove/utils/meta"
- "dove/utils/shortcuts"
-)
-
-func ListMailboxes(pagination meta.Pagination, sorting meta.Sorting, search string) types.PaginatedResponse {
- mailboxes, total := repositories.ListMailboxes(pagination, sorting, search)
- return pagination.Response(mailboxes, total)
-}
-
-func MailboxFormData() types.MailboxFormResponse {
- return types.MailboxFormResponse{
- Users: repositories.AllUsers(),
- }
-}
-
-func CreateMailbox(request types.CreateMailboxRequest) *types.ServiceError {
- address := strings.TrimSpace(request.Address)
-
- if address == "" {
- return shortcuts.ServiceError(enums.BadRequest, messages.MailboxAddressRequired)
- }
-
- if request.UserID == 0 {
- return shortcuts.ServiceError(enums.BadRequest, messages.MailboxUserRequired)
- }
-
- if repositories.FindUserByID(request.UserID) == nil {
- return shortcuts.ServiceError(enums.Unprocessable, messages.MailboxUserNotFound)
- }
-
- if repositories.FindMailboxByAddress(address) != nil {
- return shortcuts.ServiceError(enums.Unprocessable, messages.MailboxAlreadyExists)
- }
-
- mailbox := &models.Mailbox{
- Address: address,
- UserID: request.UserID,
- }
-
- if createError := repositories.CreateMailbox(mailbox); createError != nil {
- return shortcuts.ServiceError(enums.Internal, messages.MailboxCreationFailed)
- }
-
- return nil
-}
-
-func ResolveMailboxes(recipientAddresses []string) []models.Mailbox {
- var resolvedMailboxes []models.Mailbox
-
- for _, address := range recipientAddresses {
- mailbox := resolveMailbox(address)
- if mailbox != nil {
- resolvedMailboxes = append(resolvedMailboxes, *mailbox)
- }
- }
-
- return resolvedMailboxes
-}
diff --git a/services/overview.go b/services/overview.go
deleted file mode 100644
index d0d3f60..0000000
--- a/services/overview.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package services
-
-import (
- "dove/config"
- "dove/repositories"
- "dove/types"
- "fmt"
-)
-
-func Overview() types.Overview {
- return types.Overview{
- MailboxCount: repositories.CountMailboxes(),
- EmailCount: repositories.CountEmails(),
- SMTPAddress: fmt.Sprintf(":%d", config.SMTP.Port),
- }
-}
diff --git a/services/user.go b/services/user.go
deleted file mode 100644
index b2d43cf..0000000
--- a/services/user.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package services
-
-import (
- "strings"
-
- "dove/enums"
- "dove/messages"
- "dove/models"
- "dove/repositories"
- "dove/types"
- "dove/utils/meta"
- "dove/utils/shortcuts"
-)
-
-func ListUsers(pagination meta.Pagination, sorting meta.Sorting, search string) types.PaginatedResponse {
- users, total := repositories.ListUsers(pagination, sorting, search)
- return pagination.Response(users, total)
-}
-
-func CreateUser(request types.CreateUserRequest) *types.ServiceError {
- username := strings.TrimSpace(request.Username)
- displayName := strings.TrimSpace(request.DisplayName)
-
- if username == "" {
- return shortcuts.ServiceError(enums.BadRequest, messages.UserUsernameRequired)
- }
-
- if displayName == "" {
- return shortcuts.ServiceError(enums.BadRequest, messages.UserDisplayNameRequired)
- }
-
- if repositories.FindUserByUsername(username) != nil {
- return shortcuts.ServiceError(enums.Unprocessable, messages.UserAlreadyExists)
- }
-
- user := &models.User{
- Username: username,
- DisplayName: displayName,
- }
-
- if createError := repositories.CreateUser(user); createError != nil {
- return shortcuts.ServiceError(enums.Internal, messages.UserCreationFailed)
- }
-
- return nil
-}
-
-func AllUsers() []models.User {
- return repositories.AllUsers()
-}