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
|
package importer
import (
"archives/pkg/config"
"archives/pkg/database"
"archives/pkg/models"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/mail"
"os"
"regexp"
"strings"
"time"
)
func importMail(name, path, maildirPath string) {
file, _ := os.Open(path)
m, _ := mail.ReadMessage(file)
msg := models.Message{
Id: m.Header.Get("X-Archives-Hash"),
Filename: name,
Headers: m.Header,
Attachments: nil,
Body: getBody(m.Header, m.Body),
Date: getDate(m.Header),
Lists: getLists(m.Header),
Comment: "",
Hidden: false,
}
err := insertMessage(msg)
if err != nil {
fmt.Println("Error during importing Mail")
fmt.Println(err)
}
}
func getDepth(path, maildirPath string) int {
return strings.Count(strings.ReplaceAll(path, maildirPath, ""), "/")
}
func getBody(header mail.Header, body io.Reader) map[string]string {
if isMultipartMail(header) {
boundary := regexp.MustCompile(`boundary="(.*?)"`).
FindStringSubmatch(
header.Get("Content-Type"))
if len(boundary) != 2 {
//err
return map[string]string{
"text/plain": "",
}
}
return getBodyParts(body, boundary[1])
} else {
content, _ := ioutil.ReadAll(body)
return map[string]string{
getContentType(header): string(content),
}
}
}
func getBodyParts(body io.Reader, boundary string) map[string]string {
bodyParts := make(map[string]string)
mr := multipart.NewReader(body, boundary)
for {
p, err := mr.NextPart()
if err != nil {
return bodyParts
}
slurp, err := ioutil.ReadAll(p)
if err != nil {
log.Fatal(err)
}
bodyParts[p.Header.Get("Content-Type")] = string(slurp)
}
return bodyParts
}
func getContentType(header mail.Header) string {
contentTypes := regexp.MustCompile(`(.*?);`).
FindStringSubmatch(
header.Get("Content-Type"))
if len(contentTypes) < 2 {
// assume text/plain if we don't find a Content-Type header e.g. for git patches
return "text/plain"
}
return contentTypes[1]
}
func getDate(header mail.Header) time.Time {
date, _ := header.Date()
return date
}
func isMultipartMail(header mail.Header) bool {
return strings.Contains(getContentType(header), "multipart")
}
func getLists(header mail.Header) []string {
var lists []string
// To
adr, _ := mail.ParseAddressList(header.Get("To"))
for _, v := range adr {
lists = append(lists, v.Address)
}
// Cc
adr, _ = mail.ParseAddressList(header.Get("Cc"))
for _, v := range adr {
lists = append(lists, v.Address)
}
return lists
}
func insertMessage(message models.Message) error {
_, err := database.DBCon.Model(&message).
Value("tsv_subject", "to_tsvector(?)", message.GetSubject()).
Value("tsv_body", "to_tsvector(?)", message.GetBody()).
OnConflict("(id) DO NOTHING").
Insert()
return err
}
func isPublicList(path string) bool {
for _, publicList := range config.AllPublicMailingLists(){
if strings.HasPrefix(path, config.MailDirPath() + "." + publicList + "/") {
return true
}
}
return false
}
|