mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 12:46:46 +00:00
fix(GODT-2464): Filter attachment name from content-type parameter to not send it twice to the API.
This commit is contained in:
@ -438,6 +438,10 @@ func (user *User) createAttachments(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exclude name from params since this is already provided using Filename.
|
||||||
|
delete(att.MIMEParams, "name")
|
||||||
|
delete(att.MIMEParams, "filename")
|
||||||
|
|
||||||
attachment, err := client.UploadAttachment(ctx, addrKR, proton.CreateAttachmentReq{
|
attachment, err := client.UploadAttachment(ctx, addrKR, proton.CreateAttachmentReq{
|
||||||
Filename: att.Name,
|
Filename: att.Name,
|
||||||
MessageID: draftID,
|
MessageID: draftID,
|
||||||
|
|||||||
@ -673,6 +673,40 @@ func TestParsePanic(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseTextPlainWithPdfttachmentCyrillic(t *testing.T) {
|
||||||
|
f := getFileReader("text_plain_pdf_attachment_cyrillic.eml")
|
||||||
|
|
||||||
|
m, err := Parse(f)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
|
||||||
|
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
|
||||||
|
|
||||||
|
assert.Equal(t, "Shake that body", string(m.RichBody))
|
||||||
|
assert.Equal(t, "Shake that body", string(m.PlainBody))
|
||||||
|
|
||||||
|
require.Len(t, m.Attachments, 1)
|
||||||
|
require.Equal(t, "application/pdf", m.Attachments[0].MIMEType)
|
||||||
|
assert.Equal(t, "АБВГДЃЕЖЗЅИЈКЛЉМНЊОПРСТЌУФХЧЏЗШ.pdf", m.Attachments[0].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseTextPlainWithDocxAttachmentCyrillic(t *testing.T) {
|
||||||
|
f := getFileReader("text_plain_docx_attachment_cyrillic.eml")
|
||||||
|
|
||||||
|
m, err := Parse(f)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
|
||||||
|
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
|
||||||
|
|
||||||
|
assert.Equal(t, "Shake that body", string(m.RichBody))
|
||||||
|
assert.Equal(t, "Shake that body", string(m.PlainBody))
|
||||||
|
|
||||||
|
require.Len(t, m.Attachments, 1)
|
||||||
|
require.Equal(t, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", m.Attachments[0].MIMEType)
|
||||||
|
assert.Equal(t, "АБВГДЃЕЖЗЅИЈКЛЉМНЊОПРСТЌУФХЧЏЗШ.docx", m.Attachments[0].Name)
|
||||||
|
}
|
||||||
|
|
||||||
func getFileReader(filename string) io.Reader {
|
func getFileReader(filename string) io.Reader {
|
||||||
f, err := os.Open(filepath.Join("testdata", filename))
|
f, err := os.Open(filepath.Join("testdata", filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
24
pkg/message/testdata/text_plain_docx_attachment_cyrillic.eml
vendored
Normal file
24
pkg/message/testdata/text_plain_docx_attachment_cyrillic.eml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Content-Type: multipart/mixed; boundary="------------nq8WTMHkJcymWO6pWfby0uY3"
|
||||||
|
To: "Receiver" <receiver@pm.me>
|
||||||
|
From: "Sender" <sender@pm.me>
|
||||||
|
Subject: Test with cyrillic attachment
|
||||||
|
|
||||||
|
--------------nq8WTMHkJcymWO6pWfby0uY3
|
||||||
|
Content-Type: text/plain; charset=UTF-8; format=flowed
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
Shake that body
|
||||||
|
--------------nq8WTMHkJcymWO6pWfby0uY3
|
||||||
|
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document;
|
||||||
|
name="=?UTF-8?B?0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg?=
|
||||||
|
=?UTF-8?B?0KHQotCM0KPQpNCl0KfQj9CX0KguZG9jeA==?="
|
||||||
|
Content-Disposition: attachment;
|
||||||
|
filename*0*=UTF-8''%D0%90%D0%91%D0%92%D0%93%D0%94%D0%83%D0%95%D0%96%D0%97;
|
||||||
|
filename*1*=%D0%85%D0%98%D0%88%D0%9A%D0%9B%D0%89%D0%9C%D0%9D%D0%8A%D0%9E;
|
||||||
|
filename*2*=%D0%9F%D0%A0%D0%A1%D0%A2%D0%8C%D0%A3%D0%A4%D0%A5%D0%A7%D0%8F;
|
||||||
|
filename*3*=%D0%97%D0%A8%2E%64%6F%63%78
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
|
||||||
|
0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg0KHQotCM0KPQpNCl0KfQj9CX0Kg=
|
||||||
|
|
||||||
|
--------------nq8WTMHkJcymWO6pWfby0uY3--
|
||||||
25
pkg/message/testdata/text_plain_pdf_attachment_cyrillic.eml
vendored
Normal file
25
pkg/message/testdata/text_plain_pdf_attachment_cyrillic.eml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
Content-Type: multipart/mixed; boundary="------------bYzsV6z0EdKTbltmCDZgIM15"
|
||||||
|
To: "Receiver" <receiver@pm.me>
|
||||||
|
From: "Sender" <sender@pm.me>
|
||||||
|
Subject: Test with cyrillic attachment
|
||||||
|
|
||||||
|
--------------bYzsV6z0EdKTbltmCDZgIM15
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
|
||||||
|
Shake that body
|
||||||
|
--------------bYzsV6z0EdKTbltmCDZgIM15
|
||||||
|
Content-Type: application/pdf;
|
||||||
|
name="=?UTF-8?B?0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg?=
|
||||||
|
=?UTF-8?B?0KHQotCM0KPQpNCl0KfQj9CX0KgucGRm?="
|
||||||
|
Content-Disposition: attachment;
|
||||||
|
filename*0*=UTF-8''%D0%90%D0%91%D0%92%D0%93%D0%94%D0%83%D0%95%D0%96%D0%97;
|
||||||
|
filename*1*=%D0%85%D0%98%D0%88%D0%9A%D0%9B%D0%89%D0%9C%D0%9D%D0%8A%D0%9E;
|
||||||
|
filename*2*=%D0%9F%D0%A0%D0%A1%D0%A2%D0%8C%D0%A3%D0%A4%D0%A5%D0%A7%D0%8F;
|
||||||
|
filename*3*=%D0%97%D0%A8%2E%70%64%66
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
|
||||||
|
0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg0KHQotCM0KPQpNCl0KfQj9CX0Kg=
|
||||||
|
|
||||||
|
|
||||||
|
--------------bYzsV6z0EdKTbltmCDZgIM15--
|
||||||
@ -106,6 +106,7 @@ func TestFeatures(testingT *testing.T) {
|
|||||||
ctx.Step(`^the user agent is "([^"]*)"$`, s.theUserAgentIs)
|
ctx.Step(`^the user agent is "([^"]*)"$`, s.theUserAgentIs)
|
||||||
ctx.Step(`^the header in the "([^"]*)" request to "([^"]*)" has "([^"]*)" set to "([^"]*)"$`, s.theHeaderInTheRequestToHasSetTo)
|
ctx.Step(`^the header in the "([^"]*)" request to "([^"]*)" has "([^"]*)" set to "([^"]*)"$`, s.theHeaderInTheRequestToHasSetTo)
|
||||||
ctx.Step(`^the body in the "([^"]*)" request to "([^"]*)" is:$`, s.theBodyInTheRequestToIs)
|
ctx.Step(`^the body in the "([^"]*)" request to "([^"]*)" is:$`, s.theBodyInTheRequestToIs)
|
||||||
|
ctx.Step(`^the body in the "([^"]*)" response to "([^"]*)" is:$`, s.theBodyInTheResponseToIs)
|
||||||
ctx.Step(`^the API requires bridge version at least "([^"]*)"$`, s.theAPIRequiresBridgeVersion)
|
ctx.Step(`^the API requires bridge version at least "([^"]*)"$`, s.theAPIRequiresBridgeVersion)
|
||||||
ctx.Step(`^the network port (\d+) is busy$`, s.networkPortIsBusy)
|
ctx.Step(`^the network port (\d+) is busy$`, s.networkPortIsBusy)
|
||||||
ctx.Step(`^the network port range (\d+)-(\d+) is busy$`, s.networkPortRangeIsBusy)
|
ctx.Step(`^the network port range (\d+)-(\d+) is busy$`, s.networkPortRangeIsBusy)
|
||||||
|
|||||||
@ -110,3 +110,27 @@ func (s *scenario) theBodyInTheRequestToIs(method, path string, value *godog.Doc
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *scenario) theBodyInTheResponseToIs(method, path string, value *godog.DocString) error {
|
||||||
|
// We have to exclude HTTP-Overrides to avoid race condition with the creating and sending of the draft message.
|
||||||
|
call, err := s.t.getLastCallExcludingHTTPOverride(method, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var body, want map[string]any
|
||||||
|
|
||||||
|
if err := json.Unmarshal(call.ResponseBody, &body); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(value.Content), &want); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !IsSub(body, want) {
|
||||||
|
return fmt.Errorf("have body %v, want %v", body, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
143
tests/features/smtp/send/attachment.feature
Normal file
143
tests/features/smtp/send/attachment.feature
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
Feature: SMTP sending with attachment
|
||||||
|
Background:
|
||||||
|
Given there exists an account with username "[user:user1]" and password "password"
|
||||||
|
And there exists an account with username "[user:user2]" and password "password"
|
||||||
|
Then it succeeds
|
||||||
|
When bridge starts
|
||||||
|
And the user logs in with username "[user:user1]" and password "password"
|
||||||
|
And user "[user:user1]" finishes syncing
|
||||||
|
Then it succeeds
|
||||||
|
When user "[user:user1]" connects and authenticates SMTP client "1"
|
||||||
|
And user "[user:user1]" connects and authenticates IMAP client "1"
|
||||||
|
Then it succeeds
|
||||||
|
|
||||||
|
@long-black
|
||||||
|
Scenario: Sending with cyrillic PDF attachment
|
||||||
|
When SMTP client "1" sends the following message from "[user:user1]@[domain]" to "[user:user2]@[domain]":
|
||||||
|
"""
|
||||||
|
Content-Type: multipart/mixed; boundary="------------bYzsV6z0EdKTbltmCDZgIM15"
|
||||||
|
From: Bridge Test <[user:user1]@[domain]>
|
||||||
|
To: Internal Bridge <[user:user2]@[domain]>
|
||||||
|
Subject: Test with cyrillic attachment
|
||||||
|
|
||||||
|
--------------bYzsV6z0EdKTbltmCDZgIM15
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
|
||||||
|
Shake that body
|
||||||
|
--------------bYzsV6z0EdKTbltmCDZgIM15
|
||||||
|
Content-Type: application/pdf;
|
||||||
|
name="=?UTF-8?B?0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg?=
|
||||||
|
=?UTF-8?B?0KHQotCM0KPQpNCl0KfQj9CX0KgucGRm?="
|
||||||
|
Content-Disposition: attachment;
|
||||||
|
filename*0*=UTF-8''%D0%90%D0%91%D0%92%D0%93%D0%94%D0%83%D0%95%D0%96%D0%97;
|
||||||
|
filename*1*=%D0%85%D0%98%D0%88%D0%9A%D0%9B%D0%89%D0%9C%D0%9D%D0%8A%D0%9E;
|
||||||
|
filename*2*=%D0%9F%D0%A0%D0%A1%D0%A2%D0%8C%D0%A3%D0%A4%D0%A5%D0%A7%D0%8F;
|
||||||
|
filename*3*=%D0%97%D0%A8%2E%70%64%66
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
|
||||||
|
0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg0KHQotCM0KPQpNCl0KfQj9CX0Kg=
|
||||||
|
|
||||||
|
--------------bYzsV6z0EdKTbltmCDZgIM15--
|
||||||
|
|
||||||
|
"""
|
||||||
|
Then it succeeds
|
||||||
|
Then IMAP client "1" eventually sees the following messages in "Sent":
|
||||||
|
| from | to | subject |
|
||||||
|
| [user:user1]@[domain] | [user:user2]@[domain] | Test with cyrillic attachment |
|
||||||
|
And the body in the "POST" request to "/mail/v4/messages" is:
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Message": {
|
||||||
|
"Subject": "Test with cyrillic attachment",
|
||||||
|
"Sender": {
|
||||||
|
"Name": "Bridge Test"
|
||||||
|
},
|
||||||
|
"ToList": [
|
||||||
|
{
|
||||||
|
"Address": "[user:user2]@[domain]",
|
||||||
|
"Name": "Internal Bridge"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CCList": [],
|
||||||
|
"BCCList": [],
|
||||||
|
"MIMEType": "text/plain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
And the body in the "POST" response to "/mail/v4/attachments" is:
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Attachment":{
|
||||||
|
"Name": "АБВГДЃЕЖЗЅИЈКЛЉМНЊОПРСТЌУФХЧЏЗШ.pdf",
|
||||||
|
"MIMEType": "application/pdf",
|
||||||
|
"Disposition": "attachment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@long-black
|
||||||
|
Scenario: Sending with cyrillic docx attachment
|
||||||
|
When SMTP client "1" sends the following message from "[user:user1]@[domain]" to "[user:user2]@[domain]":
|
||||||
|
"""
|
||||||
|
Content-Type: multipart/mixed; boundary="------------9xfXriG1c1v5iJlMiIMCaIWP"
|
||||||
|
From: Bridge Test <[user:user1]@[domain]>
|
||||||
|
To: Internal Bridge <[user:user2]@[domain]>
|
||||||
|
Subject: Test with cyrillic attachment
|
||||||
|
|
||||||
|
--------------9xfXriG1c1v5iJlMiIMCaIWP
|
||||||
|
Content-Type: text/plain; charset=UTF-8; format=flowed
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
Shake that body
|
||||||
|
--------------9xfXriG1c1v5iJlMiIMCaIWP
|
||||||
|
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document;
|
||||||
|
name="=?UTF-8?B?0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg?=
|
||||||
|
=?UTF-8?B?0KHQotCM0KPQpNCl0KfQj9CX0KguZG9jeA==?="
|
||||||
|
Content-Disposition: attachment;
|
||||||
|
filename*0*=UTF-8''%D0%90%D0%91%D0%92%D0%93%D0%94%D0%83%D0%95%D0%96%D0%97;
|
||||||
|
filename*1*=%D0%85%D0%98%D0%88%D0%9A%D0%9B%D0%89%D0%9C%D0%9D%D0%8A%D0%9E;
|
||||||
|
filename*2*=%D0%9F%D0%A0%D0%A1%D0%A2%D0%8C%D0%A3%D0%A4%D0%A5%D0%A7%D0%8F;
|
||||||
|
filename*3*=%D0%97%D0%A8%2E%64%6F%63%78
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
|
||||||
|
0JDQkdCS0JPQlNCD0JXQltCX0IXQmNCI0JrQm9CJ0JzQndCK0J7Qn9Cg0KHQotCM0KPQpNCl0KfQj9CX0Kg=
|
||||||
|
|
||||||
|
--------------9xfXriG1c1v5iJlMiIMCaIWP--
|
||||||
|
|
||||||
|
"""
|
||||||
|
Then it succeeds
|
||||||
|
Then IMAP client "1" eventually sees the following messages in "Sent":
|
||||||
|
| from | to | subject |
|
||||||
|
| [user:user1]@[domain] | [user:user2]@[domain] | Test with cyrillic attachment |
|
||||||
|
And the body in the "POST" request to "/mail/v4/messages" is:
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Message": {
|
||||||
|
"Subject": "Test with cyrillic attachment",
|
||||||
|
"Sender": {
|
||||||
|
"Name": "Bridge Test"
|
||||||
|
},
|
||||||
|
"ToList": [
|
||||||
|
{
|
||||||
|
"Address": "[user:user2]@[domain]",
|
||||||
|
"Name": "Internal Bridge"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CCList": [],
|
||||||
|
"BCCList": [],
|
||||||
|
"MIMEType": "text/plain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
And the body in the "POST" response to "/mail/v4/attachments" is:
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Attachment":{
|
||||||
|
"Name": "АБВГДЃЕЖЗЅИЈКЛЉМНЊОПРСТЌУФХЧЏЗШ.docx",
|
||||||
|
"MIMEType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
"Disposition": "attachment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
Reference in New Issue
Block a user