diff --git a/internal/imap/mailbox_message.go b/internal/imap/mailbox_message.go index ce912de..16af76b 100644 --- a/internal/imap/mailbox_message.go +++ b/internal/imap/mailbox_message.go @@ -493,7 +493,7 @@ const customMessageTemplate = `
-{{.Error}}
@@ -514,15 +514,18 @@ type customMessageData struct {
Body string
}
-func (im *imapMailbox) customMessage(m *pmapi.Message, err error, attachBody bool) {
+func (im *imapMailbox) makeCustomMessage(m *pmapi.Message, decodeError error, attachBody bool) (err error) {
t := template.Must(template.New("customMessage").Parse(customMessageTemplate))
b := new(bytes.Buffer)
- t.Execute(b, customMessageData{
- Error: err.Error(),
+
+ if err = t.Execute(b, customMessageData{
+ Error: decodeError.Error(),
AttachBody: attachBody,
Body: m.Body,
- })
+ }); err != nil {
+ return
+ }
m.MIMEType = pmapi.ContentTypeHTML
m.Body = b.String()
@@ -531,6 +534,8 @@ func (im *imapMailbox) customMessage(m *pmapi.Message, err error, attachBody boo
if m.Header == nil {
m.Header = make(mail.Header)
}
+
+ return
}
func (im *imapMailbox) writeMessageBody(w io.Writer, m *pmapi.Message) (err error) {
@@ -546,7 +551,9 @@ func (im *imapMailbox) writeMessageBody(w io.Writer, m *pmapi.Message) (err erro
kr := im.user.client.KeyRingForAddressID(m.AddressID)
err = message.WriteBody(w, kr, m)
if err != nil {
- im.customMessage(m, err, true)
+ if customMessageErr := im.makeCustomMessage(m, err, true); customMessageErr != nil {
+ im.log.WithError(customMessageErr).Warn("Failed to make custom message")
+ }
_, _ = io.WriteString(w, m.Body)
err = nil
}
@@ -672,7 +679,9 @@ func (im *imapMailbox) buildMessage(m *pmapi.Message) (structure *message.BodySt
if errDecrypt != nil && errDecrypt != openpgperrors.ErrSignatureExpired {
errNoCache.add(errDecrypt)
- im.customMessage(m, errDecrypt, true)
+ if customMessageErr := im.makeCustomMessage(m, errDecrypt, true); customMessageErr != nil {
+ im.log.WithError(customMessageErr).Warn("Failed to make custom message")
+ }
}
// Inner function can fail even when message is decrypted.
@@ -686,7 +695,9 @@ func (im *imapMailbox) buildMessage(m *pmapi.Message) (structure *message.BodySt
return nil, nil, err
} else if err != nil {
errNoCache.add(err)
- im.customMessage(m, err, true)
+ if customMessageErr := im.makeCustomMessage(m, err, true); customMessageErr != nil {
+ im.log.WithError(customMessageErr).Warn("Failed to make custom message")
+ }
structure, msgBody, err = im.buildMessageInner(m, kr)
if err != nil {
return nil, nil, err
diff --git a/pkg/message/message.go b/pkg/message/message.go
index fedfaa5..2115112 100644
--- a/pkg/message/message.go
+++ b/pkg/message/message.go
@@ -22,15 +22,9 @@ import (
"fmt"
"strings"
- pmmime "github.com/ProtonMail/proton-bridge/pkg/mime"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
- "github.com/emersion/go-imap"
- "github.com/jhillyerd/enmime"
- log "github.com/sirupsen/logrus"
)
-const textPlain = "text/plain"
-
func GetBoundary(m *pmapi.Message) string {
// The boundary needs to be deterministic because messages are not supposed to
// change.
@@ -43,85 +37,6 @@ func GetRelatedBoundary(m *pmapi.Message) string {
return fmt.Sprintf("%x", sha512.Sum512_256([]byte(m.ID+m.ID)))
}
-func GetBodyStructure(m *pmapi.Message) (bs *imap.BodyStructure) { //nolint[funlen]
- bs = &imap.BodyStructure{
- MIMEType: "multipart",
- MIMESubType: "mixed",
- Params: map[string]string{"boundary": GetBoundary(m)},
- }
- var inlineParts []*imap.BodyStructure
- var attParts []*imap.BodyStructure
-
- for _, att := range m.Attachments {
- typeParts := strings.SplitN(att.MIMEType, "/", 2)
- if len(typeParts) != 2 {
- continue
- }
-
- if typeParts[0] == "application" && typeParts[1] == "pgp-encrypted" {
- typeParts[1] = "octet-stream"
- }
-
- part := &imap.BodyStructure{
- MIMEType: typeParts[0],
- MIMESubType: typeParts[1],
- Params: map[string]string{"name": att.Name},
- Encoding: "base64",
- }
-
- if strings.Contains(att.Header.Get("Content-Disposition"), "inline") {
- part.Disposition = "inline"
- inlineParts = append(inlineParts, part)
- } else {
- part.Disposition = "attachment"
- attParts = append(attParts, part)
- }
- }
-
- if len(inlineParts) > 0 {
- // Set to multipart-related for inline attachments.
- relatedPart := &imap.BodyStructure{
- MIMEType: "multipart",
- MIMESubType: "related",
- Params: map[string]string{"boundary": GetRelatedBoundary(m)},
- }
-
- subType := "html"
-
- if m.MIMEType == textPlain {
- subType = "plain"
- }
-
- relatedPart.Parts = append(relatedPart.Parts, &imap.BodyStructure{
- MIMEType: "text",
- MIMESubType: subType,
- Params: map[string]string{"charset": "utf-8"},
- Encoding: "quoted-printable",
- Disposition: "inline",
- })
-
- bs.Parts = append(bs.Parts, relatedPart)
- } else {
- subType := "html"
-
- if m.MIMEType == textPlain {
- subType = "plain"
- }
-
- bs.Parts = append(bs.Parts, &imap.BodyStructure{
- MIMEType: "text",
- MIMESubType: subType,
- Params: map[string]string{"charset": "utf-8"},
- Encoding: "quoted-printable",
- Disposition: "inline",
- })
- }
-
- bs.Parts = append(bs.Parts, attParts...)
-
- return bs
-}
-
func SeparateInlineAttachments(m *pmapi.Message) (atts, inlines []*pmapi.Attachment) {
for _, att := range m.Attachments {
if strings.Contains(att.Header.Get("Content-Disposition"), "inline") {
@@ -132,57 +47,3 @@ func SeparateInlineAttachments(m *pmapi.Message) (atts, inlines []*pmapi.Attachm
}
return
}
-
-func GetMIMEBodyStructure(m *pmapi.Message, parsedMsg *enmime.Envelope) (bs *imap.BodyStructure, err error) {
- // We recursively look through the MIME structure.
- root := parsedMsg.Root
- if root == nil {
- return GetBodyStructure(m), nil
- }
-
- mediaType, params, err := pmmime.ParseMediaType(root.ContentType)
- if err != nil {
- log.Warnf("Cannot parse Content-Type '%v': %v", root.ContentType, err)
- err = nil
- mediaType = textPlain
- }
-
- typeParts := strings.SplitN(mediaType, "/", 2)
-
- bs = &imap.BodyStructure{
- MIMEType: typeParts[0],
- Params: params,
- }
-
- if len(typeParts) > 1 {
- bs.MIMESubType = typeParts[1]
- }
-
- bs.Parts = getChildrenParts(root)
-
- return
-}
-
-func getChildrenParts(root *enmime.Part) (parts []*imap.BodyStructure) {
- for child := root.FirstChild; child != nil; child = child.NextSibling {
- mediaType, params, err := pmmime.ParseMediaType(child.ContentType)
- if err != nil {
- log.Warnf("Cannot parse Content-Type '%v': %v", child.ContentType, err)
- mediaType = textPlain
- }
- typeParts := strings.SplitN(mediaType, "/", 2)
- childrenParts := getChildrenParts(child)
- part := &imap.BodyStructure{
- MIMEType: typeParts[0],
- Params: params,
- Encoding: child.Charset,
- Disposition: child.Disposition,
- Parts: childrenParts,
- }
- if len(typeParts) > 1 {
- part.MIMESubType = typeParts[1]
- }
- parts = append(parts, part)
- }
- return
-}
diff --git a/pkg/message/section.go b/pkg/message/section.go
index fac92ea..b593125 100644
--- a/pkg/message/section.go
+++ b/pkg/message/section.go
@@ -347,14 +347,6 @@ func (bs *BodyStructure) GetSectionHeader(sectionPath []int) (header textproto.M
return
}
-func (bs *BodyStructure) Size() uint32 {
- info, err := bs.getInfo([]int{})
- if err != nil {
- return uint32(0)
- }
- return uint32(info.size)
-}
-
func (bs *BodyStructure) IMAPBodyStructure(currentPart []int) (imapBS *imap.BodyStructure, err error) {
var info *sectionInfo
if info, err = bs.getInfo(currentPart); err != nil {
diff --git a/pkg/mime/encoding_test.go b/pkg/mime/encoding_test.go
index 85c492b..319f45f 100644
--- a/pkg/mime/encoding_test.go
+++ b/pkg/mime/encoding_test.go
@@ -59,8 +59,6 @@ func TestDecodeHeader(t *testing.T) {
for _, val := range testData {
if decoded, err := DecodeHeader(val.raw); strings.Compare(val.expected, decoded) != 0 {
t.Errorf("Incorrect decoding of header %q expected %q but have %q; Error %v", val.raw, val.expected, decoded, err)
- } else {
- // fmt.Println("Header", val.raw, "successfully decoded", decoded, ". Error", err)
}
}
}
diff --git a/pkg/mime/mediaType.go b/pkg/mime/mediaType.go
index 9cdc9f7..5613128 100644
--- a/pkg/mime/mediaType.go
+++ b/pkg/mime/mediaType.go
@@ -87,19 +87,17 @@ func changeEncodingAndKeepLastParamDefinition(v string) (out string, err error)
return
}
- if continuation != nil {
- for paramKey, contMap := range continuation {
- value, err := mergeContinuations(paramKey, contMap)
- if err == nil {
- params[paramKey+"*"] = value
- continue
- }
+ for paramKey, contMap := range continuation {
+ value, err := mergeContinuations(paramKey, contMap)
+ if err == nil {
+ params[paramKey+"*"] = value
+ continue
+ }
- // Fallback.
- log.Errorln("Merge param", paramKey, ":", err)
- for ck, cv := range contMap {
- params[ck] = cv
- }
+ // Fallback.
+ log.Errorln("Merge param", paramKey, ":", err)
+ for ck, cv := range contMap {
+ params[ck] = cv
}
}
diff --git a/pkg/mime/parser.go b/pkg/mime/parser.go
index af03337..2f30d7a 100644
--- a/pkg/mime/parser.go
+++ b/pkg/mime/parser.go
@@ -18,7 +18,6 @@
package pmmime
import (
- "bufio"
"bytes"
"io"
"io/ioutil"
@@ -106,50 +105,6 @@ func NewMimeVisitor(targetAccepter VisitAcceptor) *MimeVisitor {
return &MimeVisitor{targetAccepter}
}
-func GetRawMimePart(rawdata io.Reader, boundary string) (io.Reader, io.Reader) {
- b, _ := ioutil.ReadAll(rawdata)
- tee := bytes.NewReader(b)
-
- reader := bufio.NewReader(bytes.NewReader(b))
- byteBoundary := []byte(boundary)
- bodyBuffer := &bytes.Buffer{}
- for {
- line, _, err := reader.ReadLine()
- if err != nil {
- return tee, bytes.NewReader(bodyBuffer.Bytes())
- }
- if bytes.HasPrefix(line, byteBoundary) {
- break
- }
- }
- lineEndingLength := 0
- for {
- line, isPrefix, err := reader.ReadLine()
- if err != nil {
- return tee, bytes.NewReader(bodyBuffer.Bytes())
- }
- if bytes.HasPrefix(line, byteBoundary) {
- break
- }
- lineEndingLength = 0
- bodyBuffer.Write(line)
- if !isPrefix {
- reader.UnreadByte()
- reader.UnreadByte()
- token, _ := reader.ReadByte()
- if token == '\r' {
- lineEndingLength++
- bodyBuffer.WriteByte(token)
- }
- lineEndingLength++
- bodyBuffer.WriteByte(token)
- }
- }
- ioutil.ReadAll(reader)
- data := bodyBuffer.Bytes()
- return tee, bytes.NewReader(data[0 : len(data)-lineEndingLength])
-}
-
func GetAllChildParts(part io.Reader, h textproto.MIMEHeader) (parts []io.Reader, headers []textproto.MIMEHeader, err error) {
mediaType, params, err := getContentType(h)
if err != nil {
@@ -272,25 +227,6 @@ func parseAddressComment(raw string) string {
return strings.Join(parsed, ", ")
}
-func checkHeaders(headers []textproto.MIMEHeader) bool {
- foundAttachment := false
-
- for i := 0; i < len(headers); i++ {
- h := headers[i]
-
- mediaType, _, _ := getContentType(h)
-
- if !strings.HasPrefix(mediaType, "text/") {
- foundAttachment = true
- } else if foundAttachment {
- // This means that there is a text part after the first attachment,
- // so we will have to convert the body from plain->HTML.
- return true
- }
- }
- return false
-}
-
func decodePart(partReader io.Reader, header textproto.MIMEHeader) (decodedPart io.Reader) {
decodedPart = DecodeContentEncoding(partReader, header.Get("Content-Transfer-Encoding"))
if decodedPart == nil {
diff --git a/pkg/mime/parser_test.go b/pkg/mime/parser_test.go
index eaa2036..8bff3d4 100644
--- a/pkg/mime/parser_test.go
+++ b/pkg/mime/parser_test.go
@@ -60,6 +60,9 @@ func androidParse(mimeBody string) (body, headers string, atts, attHeaders []str
h := textproto.MIMEHeader(mm.Header)
mmBodyData, err := ioutil.ReadAll(mm.Body)
+ if err != nil {
+ return
+ }
printAccepter := NewMIMEPrinter()
bodyCollector := NewBodyCollector(printAccepter)