aboutsummaryrefslogtreecommitdiff
blob: 56725772ec67e0460276da7aca23b64bd424538b (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
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
}