aboutsummaryrefslogtreecommitdiff
blob: 2fe73e8ccb010d616b79b51ff108d22275401352 (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
package importer

import (
	"archives/pkg/config"
	"archives/pkg/database"
	"archives/pkg/models"
	"fmt"
	"io"
	"io/ioutil"
	"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),
		List:        getListName(path),
		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 {
			fmt.Println("Error while reading the body:")
			fmt.Println(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 getListName(path string) string {
	listName := strings.ReplaceAll(path, config.MailDirPath() + ".", "")
	listName = strings.Split(listName, "/")[0]
	return listName
}

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 publicList == getListName(path) {
			return true
		}
	}
	return false
}