fix(GODT-1804): Only promote content headers if non-empty
When attaching public key, we take the root mime part, create a new root, and put the old root alongside an additional public key mime part. But when moving the root, we would copy all content headers, even empty ones. So we’d be left with Content-Disposition: "" which would fail to parse.
This commit is contained in:
parent
e89dcb2cca
commit
3bd39b3ea5
2
go.mod
2
go.mod
|
@ -7,7 +7,7 @@ require (
|
|||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
github.com/ProtonMail/gluon v0.14.2-0.20230127085305-bc2d818d9d13
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
|
||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230126112849-3c1ac277855e
|
||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b
|
||||
github.com/ProtonMail/go-rfc5322 v0.11.0
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.10
|
||||
github.com/PuerkitoBio/goquery v1.8.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB
|
|||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM=
|
||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230126112849-3c1ac277855e h1:UkfLQc44UvknNCLoBEZb1qg7zfVWVLMvCE/LtdVEcAw=
|
||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230126112849-3c1ac277855e/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos=
|
||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b h1:3UX0j2WA3NsqmrjTK769sCIOX2KnISfo8tZdFl7+mRE=
|
||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos=
|
||||
github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY=
|
||||
github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw=
|
||||
github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg=
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
package bridge_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -217,3 +219,114 @@ func TestBridge_SendDraftFlags(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBridge_SendInvite(t *testing.T) {
|
||||
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) {
|
||||
// Create a recipient user.
|
||||
_, _, err := s.CreateUser("recipient", password)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Set "attach public keys" to true for the user.
|
||||
withClient(ctx, t, s, username, password, func(ctx context.Context, client *proton.Client) {
|
||||
settings, err := client.SetAttachPublicKey(ctx, proton.SetAttachPublicKeyReq{AttachPublicKey: true})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, proton.Bool(true), settings.AttachPublicKey)
|
||||
})
|
||||
|
||||
// The sender should be fully synced.
|
||||
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, _ *bridge.Mocks) {
|
||||
syncCh, done := chToType[events.Event, events.SyncFinished](bridge.GetEvents(events.SyncFinished{}))
|
||||
defer done()
|
||||
|
||||
userID, err := bridge.LoginFull(ctx, username, password, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, userID, (<-syncCh).UserID)
|
||||
})
|
||||
|
||||
// Start the bridge.
|
||||
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, _ *bridge.Mocks) {
|
||||
// Get the sender user info.
|
||||
userInfo, err := bridge.QueryUserInfo(username)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Connect the sender IMAP client.
|
||||
imapClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass)))
|
||||
defer imapClient.Logout() //nolint:errcheck
|
||||
|
||||
// The message to send.
|
||||
b, err := os.ReadFile("testdata/invite.eml")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Save a draft.
|
||||
require.NoError(t, imapClient.Append("Drafts", []string{imap.DraftFlag}, time.Now(), bytes.NewReader(b)))
|
||||
|
||||
// Assert that the draft exists and is marked as a draft.
|
||||
{
|
||||
messages, err := clientFetch(imapClient, "Drafts")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, messages, 1)
|
||||
require.Contains(t, messages[0].Flags, imap.DraftFlag)
|
||||
}
|
||||
|
||||
// Connect the SMTP client.
|
||||
smtpClient, err := smtp.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetSMTPPort())))
|
||||
require.NoError(t, err)
|
||||
defer smtpClient.Close() //nolint:errcheck
|
||||
|
||||
// Upgrade to TLS.
|
||||
require.NoError(t, smtpClient.StartTLS(&tls.Config{InsecureSkipVerify: true}))
|
||||
|
||||
// Authorize with SASL PLAIN.
|
||||
require.NoError(t, smtpClient.Auth(sasl.NewPlainClient(
|
||||
userInfo.Addresses[0],
|
||||
userInfo.Addresses[0],
|
||||
string(userInfo.BridgePass)),
|
||||
))
|
||||
|
||||
// Send the message.
|
||||
require.NoError(t, smtpClient.SendMail(
|
||||
userInfo.Addresses[0],
|
||||
[]string{"recipient@" + s.GetDomain()},
|
||||
bytes.NewReader(b),
|
||||
))
|
||||
|
||||
// Delete the draft: add the \Deleted flag and expunge.
|
||||
{
|
||||
status, err := imapClient.Select("Drafts", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint32(1), status.Messages)
|
||||
|
||||
// Add the \Deleted flag.
|
||||
require.NoError(t, clientStore(imapClient, 1, 1, true, imap.FormatFlagsOp(imap.AddFlags, true), imap.DeletedFlag))
|
||||
|
||||
// Expunge.
|
||||
require.NoError(t, imapClient.Expunge(nil))
|
||||
}
|
||||
|
||||
// Assert that the draft is eventually gone.
|
||||
require.Eventually(t, func() bool {
|
||||
status, err := imapClient.Select("Drafts", false)
|
||||
require.NoError(t, err)
|
||||
return status.Messages == 0
|
||||
}, 10*time.Second, 100*time.Millisecond)
|
||||
|
||||
// Assert that the message is eventually in the sent folder.
|
||||
require.Eventually(t, func() bool {
|
||||
messages, err := clientFetch(imapClient, "Sent")
|
||||
require.NoError(t, err)
|
||||
return len(messages) == 1
|
||||
}, 10*time.Second, 100*time.Millisecond)
|
||||
|
||||
// Assert that the message is not marked as a draft.
|
||||
{
|
||||
messages, err := clientFetch(imapClient, "Sent")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, messages, 1)
|
||||
require.NotContains(t, messages[0].Flags, imap.DraftFlag)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
From: <username@proton.local>
|
||||
To: <recipient@proton.local>
|
||||
Subject: Testing calendar invite
|
||||
Date: Fri, 3 Feb 2023 01:04:32 +0100
|
||||
Message-ID: <000001d93763$183b74e0$48b25ea0$@proton.local>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/calendar; method=REQUEST;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Mailer: Microsoft Outlook 16.0
|
||||
Thread-Index: Adk3Yw5pLdgwsT46RviXb/nfvQlesQAAAmGA
|
||||
Content-Language: en-gb
|
||||
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN
|
||||
VERSION:2.0
|
||||
METHOD:REQUEST
|
||||
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Central European Standard Time
|
||||
BEGIN:STANDARD
|
||||
DTSTART:16011028T030000
|
||||
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETTO:+0100
|
||||
END:STANDARD
|
||||
BEGIN:DAYLIGHT
|
||||
DTSTART:16010325T020000
|
||||
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0200
|
||||
END:DAYLIGHT
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
ATTENDEE;CN=recipient@proton.local;RSVP=TRUE:mailto:recipient@proton.local
|
||||
CLASS:PUBLIC
|
||||
CREATED:20230203T000432Z
|
||||
DESCRIPTION:qweqweqweqweqweqwe/gn\\n
|
||||
DTEND;TZID="Central European Standard Time":20230203T020000
|
||||
DTSTAMP:20230203T000432Z
|
||||
DTSTART;TZID="Central European Standard Time":20230203T013000
|
||||
LAST-MODIFIED:20230203T000432Z
|
||||
LOCATION:qweqwe
|
||||
ORGANIZER;CN=username@proton.local:mailto:username@proton.local
|
||||
PRIORITY:5
|
||||
SEQUENCE:0
|
||||
SUMMARY;LANGUAGE=en-gb:Testing calendar invite
|
||||
TRANSP:OPAQUE
|
||||
UID:040000008200E00074C5B7101A82E008000000003080B2796B37D901000000000000000
|
||||
0100000001236CD1CD93CA9449C6FF1AC4DEAC44E
|
||||
X-ALT-DESC;FMTTYPE=text/html:<html xmlns:v="urn:schemas-microsoft-com:vml"
|
||||
xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-mic
|
||||
rosoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/
|
||||
12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Co
|
||||
ntent-Type content="text/html/g; charset=us-ascii"><meta name=Generator con
|
||||
tent="Microsoft Word 15 (filtered medium)"><style><!--/gn/* Font Definition
|
||||
s *//gn@font-face\\n {font-family:"Cambria Math"\\;\\n panose-1:2 4 5 3 5 4 6
|
||||
3 2 4/g;}\\n@font-face\\n {font-family:Calibri\\;\\n panose-1:2 15 5 2 2 2 4 3
|
||||
2 4/g;}\\n/* Style Definitions */\\np.MsoNormal\\, li.MsoNormal\\, div.MsoNorma
|
||||
l/gn {margin:0cm\\;\\n font-size:11.0pt\\;\\n font-family:"Calibri"\\,sans-serif
|
||||
/g;\\n mso-fareast-language:EN-US\\;}\\nspan.EmailStyle18\\n {mso-style-type:pe
|
||||
rsonal-compose/g;\\n font-family:"Calibri"\\,sans-serif\\;\\n color:windowtext\\
|
||||
;}/gn.MsoChpDefault\\n {mso-style-type:export-only\\;\\n font-size:10.0pt\\;}\\n
|
||||
@page WordSection1/gn {size:612.0pt 792.0pt\\;\\n margin:72.0pt 72.0pt 72.0pt
|
||||
72.0pt/g;}\\ndiv.WordSection1\\n {page:WordSection1\\;}\\n--></style><!--[if g
|
||||
te mso 9]><xml>/gn<o:shapedefaults v:ext="edit" spidmax="1026" />\\n</xml><!
|
||||
[endif]--><!--[if gte mso 9]><xml>/gn<o:shapelayout v:ext="edit">\\n<o:idmap
|
||||
v:ext="edit" data="1" />/gn</o:shapelayout></xml><![endif]--></head><body
|
||||
lang=EN-GB link="#0563C1" vlink="#954F72" style='word-wrap:break-word'><di
|
||||
v class=WordSection1><p class=MsoNormal><span lang=EN-US>qweqweqweqweqweqw
|
||||
e<o:p></o:p></span></p></div></body></html>
|
||||
X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
|
||||
X-MICROSOFT-CDO-IMPORTANCE:1
|
||||
X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
|
||||
X-MICROSOFT-DISALLOW-COUNTER:FALSE
|
||||
X-MS-OLK-AUTOSTARTCHECK:FALSE
|
||||
X-MS-OLK-CONFTYPE:0
|
||||
BEGIN:VALARM
|
||||
TRIGGER:-PT15M
|
||||
ACTION:DISPLAY
|
||||
DESCRIPTION:Reminder
|
||||
END:VALARM
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
|
@ -120,7 +120,7 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader)
|
|||
}
|
||||
|
||||
// If we have to attach the public key, do it now.
|
||||
if settings.AttachPublicKey == proton.AttachPublicKeyEnabled {
|
||||
if settings.AttachPublicKey {
|
||||
key, err := addrKR.GetKey(0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get sending key: %w", err)
|
||||
|
|
|
@ -186,9 +186,17 @@ func (p *Part) isMultipartMixed() bool {
|
|||
func getContentHeaders(header message.Header) message.Header {
|
||||
var res message.Header
|
||||
|
||||
res.Set("Content-Type", header.Get("Content-Type"))
|
||||
res.Set("Content-Disposition", header.Get("Content-Disposition"))
|
||||
res.Set("Content-Transfer-Encoding", header.Get("Content-Transfer-Encoding"))
|
||||
if contentType := header.Get("Content-Type"); contentType != "" {
|
||||
res.Set("Content-Type", contentType)
|
||||
}
|
||||
|
||||
if contentDisposition := header.Get("Content-Disposition"); contentDisposition != "" {
|
||||
res.Set("Content-Disposition", contentDisposition)
|
||||
}
|
||||
|
||||
if contentTransferEncoding := header.Get("Content-Transfer-Encoding"); contentTransferEncoding != "" {
|
||||
res.Set("Content-Transfer-Encoding", contentTransferEncoding)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue