/
AttachmentHeader.go
133 lines (109 loc) · 4.86 KB
/
AttachmentHeader.go
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
// Copyright 2013-2018 Adam Presley. All rights reserved
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package mailslurper
import (
"strings"
"github.com/sirupsen/logrus"
)
/*
AttachmentHeader provides information that describes an attachment. It has information
such as the type of content, file name, etc...
*/
type AttachmentHeader struct {
ContentType string `json:"contentType"`
MIMEVersion string `json:"mimeVersion"`
ContentTransferEncoding string `json:"contentTransferEncoding"`
ContentDisposition string `json:"contentDisposition"`
FileName string `json:"fileName"`
Body string `json:"body"`
Logger *logrus.Entry
}
/*
NewAttachmentHeader creates a new AttachmentHeader object
*/
func NewAttachmentHeader(contentType, mimeVersion, contentTransferEncoding, contentDisposition, fileName, body string) *AttachmentHeader {
return &AttachmentHeader{
ContentType: contentType,
MIMEVersion: mimeVersion,
ContentTransferEncoding: contentTransferEncoding,
ContentDisposition: contentDisposition,
FileName: fileName,
Body: body,
}
}
/*
Parse processes a set of attachment headers. Splits lines up and figures out what
header data goes into what structure key. Most headers follow this format:
Header-Name: Some value here\r\n
*/
func (attachmentHeader *AttachmentHeader) Parse(contents string) {
var key string
attachmentHeader.FileName = ""
attachmentHeader.ContentType = ""
attachmentHeader.ContentDisposition = ""
attachmentHeader.ContentTransferEncoding = ""
attachmentHeader.MIMEVersion = ""
attachmentHeader.Body = ""
headerBodySplit := strings.Split(contents, "\r\n\r\n")
if len(headerBodySplit) < 2 {
attachmentHeader.Logger.Debugf("Attachment has no body content")
} else {
attachmentHeader.Body = strings.Join(headerBodySplit[1:], "\r\n\r\n")
}
contents = headerBodySplit[0]
/*
* Unfold and split the header into lines. Loop over each line
* and figure out what headers are present. Store them.
* Sadly some headers require special processing.
*/
contents = UnfoldHeaders(contents)
splitHeader := strings.Split(contents, "\r\n")
numLines := len(splitHeader)
for index := 0; index < numLines; index++ {
splitItem := strings.Split(splitHeader[index], ":")
key = splitItem[0]
switch strings.ToLower(key) {
case "content-disposition":
contentDisposition := strings.TrimSpace(strings.Join(splitItem[1:], ""))
attachmentHeader.Logger.WithField("contentDisposition", contentDisposition).Debugf("Attachment Content-Disposition")
contentDispositionSplit := strings.Split(contentDisposition, ";")
contentDispositionRightSide := strings.TrimSpace(strings.Join(contentDispositionSplit[1:], ";"))
if len(contentDispositionSplit) < 2 || (len(contentDispositionSplit) > 1 && len(strings.TrimSpace(contentDispositionRightSide)) <= 0) {
attachmentHeader.ContentDisposition = contentDisposition
} else {
attachmentHeader.ContentDisposition = strings.TrimSpace(contentDispositionSplit[0])
/*
* See if we have an attachment and filename
*/
if strings.Contains(strings.ToLower(attachmentHeader.ContentDisposition), "attachment") && len(strings.TrimSpace(contentDispositionRightSide)) > 0 {
filenameSplit := strings.Split(contentDispositionRightSide, "=")
attachmentHeader.FileName = strings.Replace(strings.Join(filenameSplit[1:], "="), "\"", "", -1)
}
}
case "content-transfer-encoding":
attachmentHeader.ContentTransferEncoding = strings.TrimSpace(strings.Join(splitItem[1:], ""))
attachmentHeader.Logger.WithField("content-transfer-encoding", attachmentHeader.ContentTransferEncoding).Debugf("Attachment Content-Transfer-Encoding")
case "content-type":
contentType := strings.TrimSpace(strings.Join(splitItem[1:], ""))
attachmentHeader.Logger.WithField("content-type", contentType).Debugf("Attachment Content-Type")
contentTypeSplit := strings.Split(contentType, ";")
if len(contentTypeSplit) < 2 {
attachmentHeader.ContentType = contentType
} else {
attachmentHeader.ContentType = strings.TrimSpace(contentTypeSplit[0])
contentTypeRightSide := strings.TrimSpace(strings.Join(contentTypeSplit[1:], ";"))
/*
* See if there is a "name" portion to this
*/
if strings.Contains(strings.ToLower(contentTypeRightSide), "name") || strings.Contains(strings.ToLower(contentTypeRightSide), "filename") {
filenameSplit := strings.Split(contentTypeRightSide, "=")
attachmentHeader.FileName = strings.Replace(strings.Join(filenameSplit[1:], "="), "\"", "", -1)
}
}
case "mime-version":
attachmentHeader.MIMEVersion = strings.TrimSpace(strings.Join(splitItem[1:], ""))
attachmentHeader.Logger.WithField("mime-version", attachmentHeader.MIMEVersion).Debugf("Attachment MIME-Version")
}
}
}