mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 12:46:46 +00:00
fix(GODT-2965): fix multipart/mixed testdata + structure parsing steps related to this.
This commit is contained in:
@ -322,11 +322,21 @@ Feature: IMAP import messages
|
|||||||
Content-Type: multipart/mixed; boundary="boundary"
|
Content-Type: multipart/mixed; boundary="boundary"
|
||||||
Received: by 2002:0:0:0:0:0:0:0 with SMTP id 0123456789abcdef; Wed, 30 Dec 2020 01:23:45 0000
|
Received: by 2002:0:0:0:0:0:0:0 with SMTP id 0123456789abcdef; Wed, 30 Dec 2020 01:23:45 0000
|
||||||
|
|
||||||
|
--boundary
|
||||||
|
|
||||||
This is a multi-part message in MIME format.
|
This is a multi-part message in MIME format.
|
||||||
|
|
||||||
--boundary
|
--boundary
|
||||||
Content-Type: text/plain; charset=utf-8
|
Content-Type: text/plain; charset=utf-8
|
||||||
Content-Transfer-Encoding: 7bit
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
Hello
|
||||||
|
|
||||||
|
--boundary
|
||||||
|
Content-Type: text/html; charset=utf-8
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
<h1> HELLO </h1>
|
||||||
|
|
||||||
--boundary
|
--boundary
|
||||||
Content-Type: message/rfc822; name="embedded.eml"
|
Content-Type: message/rfc822; name="embedded.eml"
|
||||||
@ -345,33 +355,41 @@ Feature: IMAP import messages
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
Then it succeeds
|
Then it succeeds
|
||||||
# And IMAP client "1" eventually sees the following message in "INBOX" with this structure:
|
And IMAP client "1" eventually sees the following message in "INBOX" with this structure:
|
||||||
# """
|
"""
|
||||||
# {
|
{
|
||||||
# "from": "Foo <foo@example.com>",
|
"from": "Foo <foo@example.com>",
|
||||||
# "date": "01 Jan 80 00:00 +0000",
|
"date": "01 Jan 80 00:00 +0000",
|
||||||
# "to": "Bridge Test <bridgetest@pm.test>",
|
"to": "Bridge Test <bridgetest@pm.test>",
|
||||||
# "subject": "Embedded message",
|
"subject": "Embedded message",
|
||||||
# "body-contains": "Hello",
|
"body-contains": "Hello",
|
||||||
# "content": {
|
"content": {
|
||||||
# "content-type": "multipart/mixed",
|
"content-type": "multipart/mixed",
|
||||||
# "body-contains": "This is a multi-part message in MIME format.",
|
"sections":[
|
||||||
# "sections":[
|
{
|
||||||
# {
|
"body-is": "This is a multi-part message in MIME format."
|
||||||
# "content-type": "text/plain",
|
},
|
||||||
# "content-type-charset": "utf-8",
|
{
|
||||||
# "transfer-encoding": "7bit",
|
"content-type": "text/plain",
|
||||||
# "body-is": ""
|
"content-type-charset": "utf-8",
|
||||||
# },
|
"transfer-encoding": "7bit",
|
||||||
# {
|
"body-is": "Hello"
|
||||||
# "content-type": "message/rfc822",
|
},
|
||||||
# "content-type-name": "embedded.eml",
|
{
|
||||||
# "transfer-encoding": "7bit",
|
"content-type": "text/html",
|
||||||
# "content-disposition": "attachment",
|
"content-type-charset": "utf-8",
|
||||||
# "content-disposition-filename": "embedded.eml",
|
"transfer-encoding": "7bit",
|
||||||
# "body-is": "From: Bar <bar@example.com>\n\rTo: Bridge Test <bridgetest@pm.test>\n\rSubject: (No Subject)\n\rContent-Type: text/plain; charset=utf-8\n\rContent-Transfer-Encoding: quoted-printable\n\r\n\rhello"
|
"body-contains": "HELLO"
|
||||||
# }
|
},
|
||||||
# ]
|
{
|
||||||
# }
|
"content-type": "message/rfc822",
|
||||||
# }
|
"content-type-name": "embedded.eml",
|
||||||
# """
|
"transfer-encoding": "7bit",
|
||||||
|
"content-disposition": "attachment",
|
||||||
|
"content-disposition-filename": "embedded.eml",
|
||||||
|
"body-is": "From: Bar <bar@example.com>\nTo: Bridge Test <bridgetest@pm.test>\nSubject: (No Subject)\nContent-Type: text/plain; charset=utf-8\nContent-Transfer-Encoding: quoted-printable\n\nhello"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|||||||
@ -207,9 +207,12 @@ func newMessageStructFromIMAP(msg *imap.Message) MessageStruct {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
var body string
|
var body string
|
||||||
if m.MIMEType == rfc822.TextPlain {
|
switch {
|
||||||
|
case m.MIMEType == rfc822.TextPlain:
|
||||||
body = strings.TrimSpace(string(m.PlainBody))
|
body = strings.TrimSpace(string(m.PlainBody))
|
||||||
} else {
|
case m.MIMEType == rfc822.MultipartMixed:
|
||||||
|
_, body, _ = strings.Cut(string(m.MIMEBody), "\r\n\r\n")
|
||||||
|
default:
|
||||||
body = strings.TrimSpace(string(m.RichBody))
|
body = strings.TrimSpace(string(m.RichBody))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +224,7 @@ func newMessageStructFromIMAP(msg *imap.Message) MessageStruct {
|
|||||||
CC: formatAddressList(msg.Envelope.Cc),
|
CC: formatAddressList(msg.Envelope.Cc),
|
||||||
BCC: formatAddressList(msg.Envelope.Bcc),
|
BCC: formatAddressList(msg.Envelope.Bcc),
|
||||||
|
|
||||||
Content: parseMessageSection(literal, body),
|
Content: parseMessageSection([]byte(strings.TrimSpace(string(literal))), strings.TrimSpace(body)),
|
||||||
}
|
}
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
@ -262,20 +265,30 @@ func parseMessageSection(literal []byte, body string) MessageSection {
|
|||||||
for id, value := range contentDisposition {
|
for id, value := range contentDisposition {
|
||||||
if id == 0 {
|
if id == 0 {
|
||||||
msgSect.ContentDisposition = strings.TrimSpace(string(value))
|
msgSect.ContentDisposition = strings.TrimSpace(string(value))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
param := bytes.Split(value, []byte("="))
|
param := bytes.Split(value, []byte("="))
|
||||||
if strings.TrimSpace(string(param[0])) == "filename" && len(param) >= 2 {
|
if strings.TrimSpace(string(param[0])) == "filename" && len(param) >= 2 {
|
||||||
filename := strings.TrimPrefix(string(value), "filename=")
|
_, filename, _ := strings.Cut(string(value), "filename=")
|
||||||
|
filename = strings.Trim(filename, "\"")
|
||||||
msgSect.ContentDispositionFilename = strings.TrimSpace(filename)
|
msgSect.ContentDispositionFilename = strings.TrimSpace(filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if msgSect.ContentTypeBoundary != "" {
|
if msgSect.ContentTypeBoundary != "" {
|
||||||
sections := bytes.Split([]byte(msgSect.BodyIs), []byte("--"+msgSect.ContentTypeBoundary))
|
sections := bytes.Split(literal, []byte("--"+msgSect.ContentTypeBoundary))
|
||||||
// Remove last element that will be the -- from finale boundary
|
// Remove last element that will be the -- from finale boundary
|
||||||
sections = sections[:len(sections)-1]
|
sections = sections[:len(sections)-1]
|
||||||
|
sections = sections[1:]
|
||||||
for _, v := range sections {
|
for _, v := range sections {
|
||||||
msgSect.Sections = append(msgSect.Sections, parseMessageSection(v, string(v)))
|
str := strings.TrimSpace(string(v))
|
||||||
|
_, sectionBody, found := strings.Cut(str, "\r\n\r\n")
|
||||||
|
if !found {
|
||||||
|
if _, sectionBody, found = strings.Cut(str, "\n\n"); !found {
|
||||||
|
sectionBody = str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msgSect.Sections = append(msgSect.Sections, parseMessageSection([]byte(str), strings.TrimSpace(sectionBody)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return msgSect
|
return msgSect
|
||||||
@ -367,18 +380,20 @@ func matchContent(have MessageSection, want MessageSection) bool {
|
|||||||
if want.TransferEncoding != "" && want.TransferEncoding != have.TransferEncoding {
|
if want.TransferEncoding != "" && want.TransferEncoding != have.TransferEncoding {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if want.BodyContains != "" && strings.Contains(have.BodyIs, want.BodyContains) {
|
if want.BodyContains != "" && !strings.Contains(strings.TrimSpace(have.BodyIs), strings.TrimSpace(want.BodyContains)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if want.BodyIs != "" && want.BodyIs != have.BodyIs {
|
if want.BodyIs != "" && strings.TrimSpace(have.BodyIs) != strings.TrimSpace(want.BodyIs) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, section := range want.Sections {
|
if len(have.Sections) != len(want.Sections) {
|
||||||
if !matchContent(have, section) {
|
return false
|
||||||
|
}
|
||||||
|
for i, section := range want.Sections {
|
||||||
|
if !matchContent(have.Sections[i], section) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,7 +551,3 @@ type Contact struct {
|
|||||||
Sign string `bdd:"signature"`
|
Sign string `bdd:"signature"`
|
||||||
Encrypt string `bdd:"encryption"`
|
Encrypt string `bdd:"encryption"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func FullAddress(addr *imap.Address) string {
|
|
||||||
return addr.PersonalName + " <" + addr.MailboxName + "@" + addr.HostName + ">"
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user