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
|
package importer
import (
"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
}
|