aboutsummaryrefslogtreecommitdiff
blob: 17bbb9d7e3b65c149dc501967101817dc3e3f265 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package models

import (
	"mime"
	"net/mail"
	"strings"
	"time"
)

type Message struct {
	Id       string `pg:",pk"`
	Filename string

	Headers     map[string][]string
	Body        map[string]string
	Attachments []Attachment

	Lists []string
	Date  time.Time

	//Search           types.ValueAppender // tsvector

	Comment string
	Hidden  bool

	//ParentId         string
	//Parent           Message -> pg fk?
}

type Header struct {
	Name    string
	Content string
}

type Body struct {
	ContentType string
	Content     string
}

type Attachment struct {
	Filename string
	Mime     string
	Content  string
}

func (m Message) GetSubject() string {
	return m.GetHeaderField("Subject")
}

func (m Message) GetListNameFromSubject() string {
	subject := m.GetSubject()
	listName := strings.Split(subject, "]")[0]
	listName = strings.ReplaceAll(listName, "[", "")
	listName = strings.ReplaceAll(listName, "Re:", "")
	listName = strings.TrimSpace(listName)
	return listName
}

func (m Message) GetAuthorName() string {
	addr, err := mail.ParseAddress(m.GetHeaderField("From"))
	if err != nil {
		return ""
	}
	return addr.Name
}

func (m Message) GetMessageId() string {
	messageId := m.GetHeaderField("Message-Id")
	messageId = strings.ReplaceAll(messageId, "<", "")
	messageId = strings.ReplaceAll(messageId, ">", "")
	messageId = strings.ReplaceAll(messageId, "\"", "")
	return messageId
}

func (m Message) GetInReplyTo() string {
	inReplyTo := m.GetHeaderField("In-Reply-To")
	inReplyTo = strings.ReplaceAll(inReplyTo, "<", "")
	inReplyTo = strings.ReplaceAll(inReplyTo, ">", "")
	inReplyTo = strings.ReplaceAll(inReplyTo, " ", "")
	return inReplyTo
}

func (m Message) GetHeaderField(key string) string {
	subject, found := m.Headers[key]
	if !found {
		return ""
	}
	header := strings.Join(subject, " ")
	if strings.Contains(header, "=?") {
		dec := new(mime.WordDecoder)
		decodedHeader, err := dec.DecodeHeader(header)
		if err != nil {
			return ""
		}
		return decodedHeader
	}
	return header
}

func (m Message) HasHeaderField(key string) bool {
	_, found := m.Headers[key]
	return found
}

func (m Message) GetBody() string {
	// Get text/plain body
	for contentType, content := range m.Body {
		if strings.Contains(contentType, "text/plain") {
			return content
		}
	}

	// If text/plain is not present, fall back to html
	for contentType, content := range m.Body {
		if strings.Contains(contentType, "text/html") {
			return content
		}
	}

	// If neither text/plain nor text/html is available return nothing
	return ""
}

func (m Message) HasAttachments() bool {
	for key, _ := range m.Body {
		if !(strings.Contains(key, "text/plain") || strings.Contains(key, "text/plain")) {
			return true
		}
	}
	return false
}

func (m Message) GetAttachments() []Attachment {
	var attachments []Attachment
	for key, content := range m.Body {
		if !(strings.Contains(key, "text/plain") || strings.Contains(key, "text/plain")) {
			attachments = append(attachments, Attachment{
				Filename: getAttachmentFileName(key),
				Mime:     strings.Split(key, ";")[0],
				Content:  content,
			})
		}
	}
	return attachments
}

// utility methods

func getAttachmentFileName(contentTypeHeader string) string {
	parts := strings.Split(contentTypeHeader, "name=")
	if len(parts) < 2 {
		return "unknown"
	}
	return strings.ReplaceAll(parts[1], "\"", "")
}