summaryrefslogtreecommitdiff
path: root/services/emails.go
diff options
context:
space:
mode:
authorBobby <[email protected]>2025-12-24 17:17:15 +0530
committerBobby <[email protected]>2025-12-24 17:17:15 +0530
commitd5ea2aa824eee4b7e2d169d21da0107d057e7bc6 (patch)
treee608fea8cf91d6915b7b6ce5eb46896dbdc2ad79 /services/emails.go
parentb77d75f05fb2059389c05f6c01484e0cd12e796e (diff)
downloadlain-d5ea2aa824eee4b7e2d169d21da0107d057e7bc6.tar.xz
lain-d5ea2aa824eee4b7e2d169d21da0107d057e7bc6.zip
feat: Implement API endpoints for email details and actions, and refactor email preview for client-side rendering with Shadow DOM.
Diffstat (limited to 'services/emails.go')
-rw-r--r--services/emails.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/services/emails.go b/services/emails.go
index e007f87..4b440f4 100644
--- a/services/emails.go
+++ b/services/emails.go
@@ -4,6 +4,8 @@ import (
"lain/jobs"
"lain/models"
"lain/repository"
+ "lain/utils/crypto"
+ "lain/utils/email"
"lain/utils/format"
"net/url"
"strings"
@@ -56,3 +58,111 @@ func GetEmails(userEmail, folderPath string, prefs *models.Preferences, page int
return emails, nil
}
+
+func GetEmailDetails(userEmail string, emailID uint) (fiber.Map, error) {
+ message, err := repository.GetEmailByID(userEmail, emailID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Get attachments
+ attachments, _ := repository.GetAttachmentsByEmailID(emailID)
+
+ var attachmentMaps []fiber.Map
+ for _, att := range attachments {
+ attachmentMaps = append(attachmentMaps, fiber.Map{
+ "ID": att.ID,
+ "Filename": att.Filename,
+ "ContentType": att.ContentType,
+ "Size": format.FormatFileSize(att.Size),
+ })
+ }
+
+ // Sanitize HTML body
+ body := message.BodyHTML
+ if body == "" {
+ body = "<pre>" + format.DecodeHTML(message.BodyText) + "</pre>"
+ } else {
+ body = format.SanitizeHTML(body)
+ }
+
+ return fiber.Map{
+ "ID": message.ID,
+ "Subject": format.DecodeHTML(message.Subject),
+ "From": format.DecodeHTML(message.From),
+ "FromName": format.DecodeHTML(message.FromName),
+ "To": format.DecodeHTML(message.To),
+ "CC": format.DecodeHTML(message.CC),
+ "Date": message.Date,
+ "Body": body,
+ "IsRead": message.IsRead,
+ "IsFlagged": message.IsFlagged,
+ "Attachments": attachmentMaps,
+ }, nil
+}
+
+func ToggleEmailFlag(userEmail string, emailID uint) (bool, error) {
+ message, err := repository.GetEmailByID(userEmail, emailID)
+ if err != nil {
+ return false, err
+ }
+
+ prefs, err := repository.GetPreferencesByEmail(userEmail)
+ if err != nil {
+ return false, err
+ }
+
+ password, err := crypto.Decrypt(prefs.Authorization)
+ if err != nil {
+ return false, err
+ }
+
+ client, err := email.ConnectIMAP(userEmail, password)
+ if err != nil {
+ return false, err
+ }
+ defer email.DisconnectIMAP(client)
+
+ if err := email.ToggleFlag(client, message.Folder.IMAPName, message.UID, message.IsFlagged); err != nil {
+ return false, err
+ }
+
+ message.IsFlagged = !message.IsFlagged
+ repository.UpdateEmail(message)
+
+ return message.IsFlagged, nil
+}
+
+func MarkEmailAsRead(userEmail string, emailID uint) error {
+ message, err := repository.GetEmailByID(userEmail, emailID)
+ if err != nil {
+ return err
+ }
+
+ if message.IsRead {
+ return nil
+ }
+
+ prefs, err := repository.GetPreferencesByEmail(userEmail)
+ if err != nil {
+ return err
+ }
+
+ password, err := crypto.Decrypt(prefs.Authorization)
+ if err != nil {
+ return err
+ }
+
+ client, err := email.ConnectIMAP(userEmail, password)
+ if err != nil {
+ return err
+ }
+ defer email.DisconnectIMAP(client)
+
+ if err := email.MarkAsRead(client, message.Folder.IMAPName, message.UID); err != nil {
+ return err
+ }
+
+ message.IsRead = true
+ return repository.UpdateEmail(message)
+}