Commits
Diff
diff --git a/email/main.go b/email/main.go
deleted file mode 100644
index 8919f0d..0000000
--- a/email/main.go
+++ /dev/null
@@ -1,179 +0,0 @@
-package email
-
-import (
- "github.com/emersion/go-imap"
- "github.com/emersion/go-imap/client"
- "io"
- "log"
- "mime/quotedprintable"
- "net/mail"
- "strings"
-)
-
-type Inbox struct {
- Client *client.Client
- Threads []Thread
-}
-
-type Thread struct {
- Tag string `json:"tag" xml:"tag" text:"Tag"`
- Root Message `json:"root" xml:"root" text:"Root"`
- Subject string `json:"subject" xml:"subject" text:"Subject"`
- ThreadId string `json:"threadid" xml:"threadid" text:"Thread Id"`
-}
-
-type Message struct {
- Children []*Message `json:"children" xml:"children>message" text:"Children"`
- InReplyTo string `json:"inreplyto" xml:"inreplyto" text:"In Reply To,omitempty"`
- To string `json:"to" xml:"to" text:"To"`
- From string `json:"from" xml:"from" text:"from"`
- Cc string `json:"cc" xml:"cc" text:"CC"`
- Bcc string `json:"bcc" xml:"bcc" text:"BCC"`
- Tag string `json:"tag" xml:"tag" text:"Tag"`
- Subject string `json:"subject" xml:"subject" text:"Subject"`
- Body string `json:"body" xml:"body" text:"Body"`
- MessageId string `json:"messageId" xml:"messageid" text:"Message ID"`
-}
-
-func Connect(server, username, password string) Inbox {
- // Connect to server
- c, err := client.DialTLS(server, nil)
- if err != nil {
- log.Fatal(err)
- }
-
- // Login
- if err := c.Login(username, password); err != nil {
- log.Fatal(err)
- }
-
- return Inbox{
- Threads: []Thread{},
- Client: c,
- }
-}
-
-func (i *Inbox) GetMessages(inbox string) {
- mbox, _ := i.Client.Select(inbox, false)
- from := uint32(1)
- to := mbox.Messages
-
- seqset := new(imap.SeqSet)
- seqset.AddRange(from, to)
-
- messages := make(chan *imap.Message, 10)
- done := make(chan error, 1)
- go func() {
- done <- i.Client.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchItem("BODY.PEEK[]")}, messages)
- }()
-
- // Initialize a map to store messages by their In-Reply-To for efficient parent-child linking
- messageMap := make(map[string]*Message)
-
- for msg := range messages {
- tags := parseTags(msg.Envelope.Subject)
- if len(tags) > 0 {
- m := Message{
- Children: []*Message{},
- }
-
- holder := ""
- for _, bodyPart := range msg.Body {
- if bodyPart != nil {
- b, _ := io.ReadAll(bodyPart)
- holder += string(b)
- }
- }
- msgReader, _ := mail.ReadMessage(strings.NewReader(holder))
- body, _ := io.ReadAll(msgReader.Body)
-
- decoder := quotedprintable.NewReader(strings.NewReader(string(body)))
-
- decoded, _ := io.ReadAll(decoder)
- m.Body = string(decoded)
- m.Tag = tags[0]
- m.Subject = parseSubject(msg.Envelope.Subject)
- m.InReplyTo = msg.Envelope.InReplyTo
- var to, from, cc, bcc string
- for _, v := range msg.Envelope.To {
- to += ", "+v.AtDomainList
- }
- for _, v := range msg.Envelope.From {
- from += ", "+v.AtDomainList
- }
- for _, v := range msg.Envelope.Cc {
- cc += ", "+v.AtDomainList
- }
- for _, v := range msg.Envelope.Bcc {
- bcc += ", "+v.AtDomainList
- }
- m.To = to
- m.From = from
- m.Cc = cc
- m.Bcc = bcc
- m.InReplyTo = msg.Envelope.InReplyTo
-
- // Store the message in the map using its Message-ID as the key
- messageID := msg.Envelope.MessageId
- m.MessageId = messageID[1:strings.Index(messageID,"@")]
- messageMap[messageID] = &m
- }
- }
-
- // Link parent and child messages
- for _, msg := range messageMap {
- if msg.InReplyTo != "" { // Only process root-level messages initially
- if parentMsg, ok := messageMap[msg.InReplyTo]; ok {
- parentMsg.Children = append(parentMsg.Children, msg)
- }
- }
- }
-
- // Create threads from root-level messages
- for _, v := range messageMap {
- if v.InReplyTo == "" {
- thread := Thread{
- Tag: v.Tag,
- Root: *v, // Dereference here to avoid storing a pointer in the Thread root
- Subject: v.Subject,
- ThreadId: v.MessageId,
- }
- i.Threads = append(i.Threads, thread)
- }
- }
-}
-
-func parseTags(subject string) []string {
- tags := []string{}
- currentTag := ""
- record := false
-
- for _, v := range subject {
- if v == ']' && record {
- record = false
- tags = append(tags, currentTag)
- currentTag = ""
- }
- if record {
- currentTag += string(v)
- }
- if v == '[' && !record {
- record = true
- }
-
- }
- return tags
-}
-
-func parseSubject(subject string) string {
- var title string
-
- for i := len(subject) - 1; i >= 0; i-- {
- if subject[i] == ']' {
- break
- } else {
- title = string(subject[i]) + title
- }
- }
- return strings.TrimSpace(title)
-}
package email
import (
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"io"
"log"
"mime/quotedprintable"
"net/mail"
"strings"
)
type Inbox struct {
Client *client.Client
Threads []Thread
}
type Thread struct {
Tag string `json:"tag" xml:"tag" text:"Tag"`
Root Message `json:"root" xml:"root" text:"Root"`
Subject string `json:"subject" xml:"subject" text:"Subject"`
ThreadId string `json:"threadid" xml:"threadid" text:"Thread Id"`
}
type Message struct {
Children []*Message `json:"children" xml:"children>message" text:"Children"`
InReplyTo string `json:"inreplyto" xml:"inreplyto" text:"In Reply To,omitempty"`
To string `json:"to" xml:"to" text:"To"`
From string `json:"from" xml:"from" text:"from"`
Cc string `json:"cc" xml:"cc" text:"CC"`
Bcc string `json:"bcc" xml:"bcc" text:"BCC"`
Tag string `json:"tag" xml:"tag" text:"Tag"`
Subject string `json:"subject" xml:"subject" text:"Subject"`
Body string `json:"body" xml:"body" text:"Body"`
MessageId string `json:"messageId" xml:"messageid" text:"Message ID"`
}
func Connect(server, username, password string) Inbox {
// Connect to server
c, err := client.DialTLS(server, nil)
if err != nil {
log.Fatal(err)
}
// Login
if err := c.Login(username, password); err != nil {
log.Fatal(err)
}
return Inbox{
Threads: []Thread{},
Client: c,
}
}
func (i *Inbox) GetMessages(inbox string) {
mbox, _ := i.Client.Select(inbox, false)
from := uint32(1)
to := mbox.Messages
seqset := new(imap.SeqSet)
seqset.AddRange(from, to)
messages := make(chan *imap.Message, 10)
done := make(chan error, 1)
go func() {
done <- i.Client.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchItem("BODY.PEEK[]")}, messages)
}()
// Initialize a map to store messages by their In-Reply-To for efficient parent-child linking
messageMap := make(map[string]*Message)
for msg := range messages {
tags := parseTags(msg.Envelope.Subject)
if len(tags) > 0 {
m := Message{
Children: []*Message{},
}
holder := ""
for _, bodyPart := range msg.Body {
if bodyPart != nil {
b, _ := io.ReadAll(bodyPart)
holder += string(b)
}
}
msgReader, _ := mail.ReadMessage(strings.NewReader(holder))
body, _ := io.ReadAll(msgReader.Body)
decoder := quotedprintable.NewReader(strings.NewReader(string(body)))
decoded, _ := io.ReadAll(decoder)
m.Body = string(decoded)
m.Tag = tags[0]
m.Subject = parseSubject(msg.Envelope.Subject)
m.InReplyTo = msg.Envelope.InReplyTo
var to, from, cc, bcc string
for _, v := range msg.Envelope.To {
to += ", "+v.AtDomainList
}
for _, v := range msg.Envelope.From {
from += ", "+v.AtDomainList
}
for _, v := range msg.Envelope.Cc {
cc += ", "+v.AtDomainList
}
for _, v := range msg.Envelope.Bcc {
bcc += ", "+v.AtDomainList
}
m.To = to
m.From = from
m.Cc = cc
m.Bcc = bcc
m.InReplyTo = msg.Envelope.InReplyTo
// Store the message in the map using its Message-ID as the key
messageID := msg.Envelope.MessageId
m.MessageId = messageID[1:strings.Index(messageID,"@")]
messageMap[messageID] = &m
}
}
// Link parent and child messages
for _, msg := range messageMap {
if msg.InReplyTo != "" { // Only process root-level messages initially
if parentMsg, ok := messageMap[msg.InReplyTo]; ok {
parentMsg.Children = append(parentMsg.Children, msg)
}
}
}
// Create threads from root-level messages
for _, v := range messageMap {
if v.InReplyTo == "" {
thread := Thread{
Tag: v.Tag,
Root: *v, // Dereference here to avoid storing a pointer in the Thread root
Subject: v.Subject,
ThreadId: v.MessageId,
}
i.Threads = append(i.Threads, thread)
}
}
}
func parseTags(subject string) []string {
tags := []string{}
currentTag := ""
record := false
for _, v := range subject {
if v == ']' && record {
record = false
tags = append(tags, currentTag)
currentTag = ""
}
if record {
currentTag += string(v)
}
if v == '[' && !record {
record = true
}
}
return tags
}
func parseSubject(subject string) string {
var title string
for i := len(subject) - 1; i >= 0; i-- {
if subject[i] == ']' {
break
} else {
title = string(subject[i]) + title
}
}
return strings.TrimSpace(title)
}