Prefer From header instead of MAIL FROM address

This commit is contained in:
Michal Horejsek
2020-12-16 11:17:00 +01:00
parent 2a0052dda6
commit 7b112fc448
17 changed files with 179 additions and 110 deletions

View File

@ -70,7 +70,7 @@ func (im *imapMailbox) CreateMessage(flags []string, date time.Time, body imap.L
// Called from go-imap in goroutines - we need to handle panics for each function. // Called from go-imap in goroutines - we need to handle panics for each function.
defer im.panicHandler.HandlePanic() defer im.panicHandler.HandlePanic()
m, _, _, readers, err := message.Parse(body, "", "") m, _, _, readers, err := message.Parse(body)
if err != nil { if err != nil {
return err return err
} }

View File

@ -31,7 +31,8 @@ import (
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/internal/events" "github.com/ProtonMail/proton-bridge/internal/events"
"github.com/ProtonMail/proton-bridge/pkg/listener" "github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/ProtonMail/proton-bridge/pkg/message" pkgMessage "github.com/ProtonMail/proton-bridge/pkg/message"
"github.com/ProtonMail/proton-bridge/pkg/message/parser"
"github.com/ProtonMail/proton-bridge/pkg/pmapi" "github.com/ProtonMail/proton-bridge/pkg/pmapi"
goSMTPBackend "github.com/emersion/go-smtp" goSMTPBackend "github.com/emersion/go-smtp"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -47,8 +48,8 @@ type smtpUser struct {
username string username string
addressID string addressID string
from string returnPath string
to []string to []string
} }
// newSMTPUser returns struct implementing go-smtp/session interface. // newSMTPUser returns struct implementing go-smtp/session interface.
@ -154,13 +155,13 @@ func (su *smtpUser) getAPIKeyData(recipient string) (apiKeys []pmapi.PublicKey,
// Discard currently processed message. // Discard currently processed message.
func (su *smtpUser) Reset() { func (su *smtpUser) Reset() {
log.Trace("Resetting the session") log.Trace("Resetting the session")
su.from = "" su.returnPath = ""
su.to = []string{} su.to = []string{}
} }
// Set return path for currently processed message. // Set return path for currently processed message.
func (su *smtpUser) Mail(from string, opts goSMTPBackend.MailOptions) error { func (su *smtpUser) Mail(returnPath string, opts goSMTPBackend.MailOptions) error {
log.WithField("from", from).WithField("opts", opts).Trace("Setting mail from") log.WithField("returnPath", returnPath).WithField("opts", opts).Trace("Setting mail from")
// REQUIRETLS and SMTPUTF8 have to be announced to be used by client. // REQUIRETLS and SMTPUTF8 have to be announced to be used by client.
// Bridge does not use those extensions so this should not happen. // Bridge does not use those extensions so this should not happen.
@ -175,7 +176,14 @@ func (su *smtpUser) Mail(from string, opts goSMTPBackend.MailOptions) error {
return errors.New("changing identity is not supported") return errors.New("changing identity is not supported")
} }
su.from = from if returnPath != "" {
addr := su.client().Addresses().ByEmail(returnPath)
if addr == nil {
return errors.New("backend: invalid return path: not owned by user")
}
}
su.returnPath = returnPath
return nil return nil
} }
@ -191,17 +199,17 @@ func (su *smtpUser) Rcpt(to string) error {
// Set currently processed message contents and send it. // Set currently processed message contents and send it.
func (su *smtpUser) Data(r io.Reader) error { func (su *smtpUser) Data(r io.Reader) error {
log.Trace("Sending the message") log.Trace("Sending the message")
if su.from == "" { if su.returnPath == "" {
return errors.New("missing sender") return errors.New("missing return path")
} }
if len(su.to) == 0 { if len(su.to) == 0 {
return errors.New("missing recipient") return errors.New("missing recipient")
} }
return su.Send(su.from, su.to, r) return su.Send(su.returnPath, su.to, r)
} }
// Send sends an email from the given address to the given addresses with the given body. // Send sends an email from the given address to the given addresses with the given body.
func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err error) { //nolint[funlen] func (su *smtpUser) Send(returnPath string, to []string, messageReader io.Reader) (err error) { //nolint[funlen]
// Called from go-smtp in goroutines - we need to handle panics for each function. // Called from go-smtp in goroutines - we need to handle panics for each function.
defer su.panicHandler.HandlePanic() defer su.panicHandler.HandlePanic()
@ -210,7 +218,34 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
return err return err
} }
var addr *pmapi.Address = su.client().Addresses().ByEmail(from) returnPathAddr := su.client().Addresses().ByEmail(returnPath)
if returnPathAddr == nil {
err = errors.New("backend: invalid return path: not owned by user")
return
}
parser, err := parser.New(messageReader)
if err != nil {
err = errors.Wrap(err, "failed to create new parser")
return
}
message, plainBody, attReaders, err := pkgMessage.ParserWithParser(parser)
if err != nil {
log.WithError(err).Error("Failed to parse message")
return
}
richBody := message.Body
externalID := message.Header.Get("Message-Id")
externalID = strings.Trim(externalID, "<>")
draftID, parentID := su.handleReferencesHeader(message)
if err = su.handleSenderAndRecipients(message, returnPathAddr, returnPath, to); err != nil {
return err
}
addr := su.client().Addresses().ByEmail(message.Sender.Address)
if addr == nil { if addr == nil {
err = errors.New("backend: invalid email address: not owned by user") err = errors.New("backend: invalid email address: not owned by user")
return return
@ -237,20 +272,14 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
attachedPublicKeyName = fmt.Sprintf("publickey - %v - %v", kr.GetIdentities()[0].Name, firstKey.GetFingerprint()[:8]) attachedPublicKeyName = fmt.Sprintf("publickey - %v - %v", kr.GetIdentities()[0].Name, firstKey.GetFingerprint()[:8])
} }
message, mimeBody, plainBody, attReaders, err := message.Parse(messageReader, attachedPublicKey, attachedPublicKeyName) if attachedPublicKey != "" {
if err != nil { pkgMessage.AttachPublicKey(parser, attachedPublicKey, attachedPublicKeyName)
log.WithError(err).Error("Failed to parse message")
return
} }
richBody := message.Body
externalID := message.Header.Get("Message-Id") mimeBody, err := pkgMessage.BuildMIMEBody(parser)
externalID = strings.Trim(externalID, "<>") if err != nil {
log.WithError(err).Error("Failed to build message")
draftID, parentID := su.handleReferencesHeader(message) return
if err = su.handleSenderAndRecipients(message, addr, from, to); err != nil {
return err
} }
message.AddressID = addr.ID message.AddressID = addr.ID
@ -415,14 +444,14 @@ func (su *smtpUser) handleReferencesHeader(m *pmapi.Message) (draftID, parentID
return draftID, parentID return draftID, parentID
} }
func (su *smtpUser) handleSenderAndRecipients(m *pmapi.Message, addr *pmapi.Address, from string, to []string) (err error) { func (su *smtpUser) handleSenderAndRecipients(m *pmapi.Message, returnPathAddr *pmapi.Address, returnPath string, to []string) (err error) {
from = pmapi.ConstructAddress(from, addr.Email) returnPath = pmapi.ConstructAddress(returnPath, returnPathAddr.Email)
// Check sender. // Check sender.
if m.Sender == nil { if m.Sender == nil {
m.Sender = &mail.Address{Address: from} m.Sender = &mail.Address{Address: returnPath}
} else { } else if m.Sender.Address == "" {
m.Sender.Address = from m.Sender.Address = returnPath
} }
// Check recipients. // Check recipients.

View File

@ -263,7 +263,7 @@ func (p *PMAPIProvider) parseMessage(msg Message) (m *pmapi.Message, r []io.Read
} }
} }
}() }()
message, _, _, attachmentReaders, err := pkgMessage.Parse(bytes.NewBuffer(msg.Body), "", "") message, _, _, attachmentReaders, err := pkgMessage.Parse(bytes.NewBuffer(msg.Body))
return message, attachmentReaders, err return message, attachmentReaders, err
} }

View File

@ -36,15 +36,30 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
func Parse(r io.Reader, key, keyName string) (m *pmapi.Message, mimeBody, plainBody string, attReaders []io.Reader, err error) { // Parse parses RAW message.
logrus.Trace("Parsing message") func Parse(r io.Reader) (m *pmapi.Message, mimeBody, plainBody string, attReaders []io.Reader, err error) {
p, err := parser.New(r) p, err := parser.New(r)
if err != nil { if err != nil {
err = errors.Wrap(err, "failed to create new parser") return nil, "", "", nil, errors.Wrap(err, "failed to create new parser")
return
} }
m, plainBody, attReaders, err = ParserWithParser(p)
if err != nil {
return nil, "", "", nil, errors.Wrap(err, "failed to parse the message")
}
mimeBody, err = BuildMIMEBody(p)
if err != nil {
return nil, "", "", nil, errors.Wrap(err, "failed to build mime body")
}
return m, mimeBody, plainBody, attReaders, nil
}
// ParserWithParser parses message from Parser without building MIME body.
func ParserWithParser(p *parser.Parser) (m *pmapi.Message, plainBody string, attReaders []io.Reader, err error) {
logrus.Trace("Parsing message")
if err = convertEncodedTransferEncoding(p); err != nil { if err = convertEncodedTransferEncoding(p); err != nil {
err = errors.Wrap(err, "failed to convert encoded transfer encodings") err = errors.Wrap(err, "failed to convert encoded transfer encodings")
return return
@ -77,13 +92,11 @@ func Parse(r io.Reader, key, keyName string) (m *pmapi.Message, mimeBody, plainB
return return
} }
// We only attach the public key manually to the MIME body for return m, plainBody, attReaders, nil
// signed/encrypted external recipients. It's not important for it to be }
// collected as an attachment; that's already done when we upload the draft.
if key != "" {
attachPublicKey(p.Root(), key, keyName)
}
// BuildMIMEBody builds mime body from the parser returned by NewParser.
func BuildMIMEBody(p *parser.Parser) (mimeBody string, err error) {
mimeBodyBuffer := new(bytes.Buffer) mimeBodyBuffer := new(bytes.Buffer)
if err = p.NewWriter().Write(mimeBodyBuffer); err != nil { if err = p.NewWriter().Write(mimeBodyBuffer); err != nil {
@ -91,7 +104,7 @@ func Parse(r io.Reader, key, keyName string) (m *pmapi.Message, mimeBody, plainB
return return
} }
return m, mimeBodyBuffer.String(), plainBody, attReaders, nil return mimeBodyBuffer.String(), nil
} }
// convertEncodedTransferEncoding decodes any RFC2047-encoded content transfer encodings. // convertEncodedTransferEncoding decodes any RFC2047-encoded content transfer encodings.
@ -381,14 +394,14 @@ func getPlainBody(part *parser.Part) []byte {
} }
} }
func attachPublicKey(p *parser.Part, key, keyName string) { func AttachPublicKey(p *parser.Parser, key, keyName string) {
h := message.Header{} h := message.Header{}
h.Set("Content-Type", fmt.Sprintf(`application/pgp-keys; name="%v.asc"; filename="%v.asc"`, keyName, keyName)) h.Set("Content-Type", fmt.Sprintf(`application/pgp-keys; name="%v.asc"; filename="%v.asc"`, keyName, keyName))
h.Set("Content-Disposition", fmt.Sprintf(`attachment; name="%v.asc"; filename="%v.asc"`, keyName, keyName)) h.Set("Content-Disposition", fmt.Sprintf(`attachment; name="%v.asc"; filename="%v.asc"`, keyName, keyName))
h.Set("Content-Transfer-Encoding", "base64") h.Set("Content-Transfer-Encoding", "base64")
p.AddChild(&parser.Part{ p.Root().AddChild(&parser.Part{
Header: h, Header: h,
Body: []byte(key), Body: []byte(key),
}) })

View File

@ -25,6 +25,7 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/ProtonMail/proton-bridge/pkg/message/parser"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"golang.org/x/text/encoding/charmap" "golang.org/x/text/encoding/charmap"
@ -33,7 +34,7 @@ import (
func TestParseTextPlain(t *testing.T) { func TestParseTextPlain(t *testing.T) {
f := getFileReader("text_plain.eml") f := getFileReader("text_plain.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -48,7 +49,7 @@ func TestParseTextPlain(t *testing.T) {
func TestParseTextPlainUTF8(t *testing.T) { func TestParseTextPlainUTF8(t *testing.T) {
f := getFileReader("text_plain_utf8.eml") f := getFileReader("text_plain_utf8.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -63,7 +64,7 @@ func TestParseTextPlainUTF8(t *testing.T) {
func TestParseTextPlainLatin1(t *testing.T) { func TestParseTextPlainLatin1(t *testing.T) {
f := getFileReader("text_plain_latin1.eml") f := getFileReader("text_plain_latin1.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -78,7 +79,7 @@ func TestParseTextPlainLatin1(t *testing.T) {
func TestParseTextPlainUTF8Subject(t *testing.T) { func TestParseTextPlainUTF8Subject(t *testing.T) {
f := getFileReader("text_plain_utf8_subject.eml") f := getFileReader("text_plain_utf8_subject.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -94,7 +95,7 @@ func TestParseTextPlainUTF8Subject(t *testing.T) {
func TestParseTextPlainLatin2Subject(t *testing.T) { func TestParseTextPlainLatin2Subject(t *testing.T) {
f := getFileReader("text_plain_latin2_subject.eml") f := getFileReader("text_plain_latin2_subject.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -110,7 +111,7 @@ func TestParseTextPlainLatin2Subject(t *testing.T) {
func TestParseTextPlainUnknownCharsetIsActuallyLatin1(t *testing.T) { func TestParseTextPlainUnknownCharsetIsActuallyLatin1(t *testing.T) {
f := getFileReader("text_plain_unknown_latin1.eml") f := getFileReader("text_plain_unknown_latin1.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -125,7 +126,7 @@ func TestParseTextPlainUnknownCharsetIsActuallyLatin1(t *testing.T) {
func TestParseTextPlainUnknownCharsetIsActuallyLatin2(t *testing.T) { func TestParseTextPlainUnknownCharsetIsActuallyLatin2(t *testing.T) {
f := getFileReader("text_plain_unknown_latin2.eml") f := getFileReader("text_plain_unknown_latin2.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -146,7 +147,7 @@ func TestParseTextPlainUnknownCharsetIsActuallyLatin2(t *testing.T) {
func TestParseTextPlainAlready7Bit(t *testing.T) { func TestParseTextPlainAlready7Bit(t *testing.T) {
f := getFileReader("text_plain_7bit.eml") f := getFileReader("text_plain_7bit.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -161,7 +162,7 @@ func TestParseTextPlainAlready7Bit(t *testing.T) {
func TestParseTextPlainWithOctetAttachment(t *testing.T) { func TestParseTextPlainWithOctetAttachment(t *testing.T) {
f := getFileReader("text_plain_octet_attachment.eml") f := getFileReader("text_plain_octet_attachment.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -177,7 +178,7 @@ func TestParseTextPlainWithOctetAttachment(t *testing.T) {
func TestParseTextPlainWithOctetAttachmentGoodFilename(t *testing.T) { func TestParseTextPlainWithOctetAttachmentGoodFilename(t *testing.T) {
f := getFileReader("text_plain_octet_attachment_good_2231_filename.eml") f := getFileReader("text_plain_octet_attachment_good_2231_filename.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -194,7 +195,7 @@ func TestParseTextPlainWithOctetAttachmentGoodFilename(t *testing.T) {
func TestParseTextPlainWithOctetAttachmentBadFilename(t *testing.T) { func TestParseTextPlainWithOctetAttachmentBadFilename(t *testing.T) {
f := getFileReader("text_plain_octet_attachment_bad_2231_filename.eml") f := getFileReader("text_plain_octet_attachment_bad_2231_filename.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -211,7 +212,7 @@ func TestParseTextPlainWithOctetAttachmentBadFilename(t *testing.T) {
func TestParseTextPlainWithPlainAttachment(t *testing.T) { func TestParseTextPlainWithPlainAttachment(t *testing.T) {
f := getFileReader("text_plain_plain_attachment.eml") f := getFileReader("text_plain_plain_attachment.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -227,7 +228,7 @@ func TestParseTextPlainWithPlainAttachment(t *testing.T) {
func TestParseTextPlainEmptyAddresses(t *testing.T) { func TestParseTextPlainEmptyAddresses(t *testing.T) {
f := getFileReader("text_plain_empty_addresses.eml") f := getFileReader("text_plain_empty_addresses.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -242,7 +243,7 @@ func TestParseTextPlainEmptyAddresses(t *testing.T) {
func TestParseTextPlainWithImageInline(t *testing.T) { func TestParseTextPlainWithImageInline(t *testing.T) {
f := getFileReader("text_plain_image_inline.eml") f := getFileReader("text_plain_image_inline.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -262,7 +263,7 @@ func TestParseTextPlainWithImageInline(t *testing.T) {
func TestParseTextPlainWithDuplicateCharset(t *testing.T) { func TestParseTextPlainWithDuplicateCharset(t *testing.T) {
f := getFileReader("text_plain_duplicate_charset.eml") f := getFileReader("text_plain_duplicate_charset.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -277,7 +278,7 @@ func TestParseTextPlainWithDuplicateCharset(t *testing.T) {
func TestParseWithMultipleTextParts(t *testing.T) { func TestParseWithMultipleTextParts(t *testing.T) {
f := getFileReader("multiple_text_parts.eml") f := getFileReader("multiple_text_parts.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -292,7 +293,7 @@ func TestParseWithMultipleTextParts(t *testing.T) {
func TestParseTextHTML(t *testing.T) { func TestParseTextHTML(t *testing.T) {
f := getFileReader("text_html.eml") f := getFileReader("text_html.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -307,7 +308,7 @@ func TestParseTextHTML(t *testing.T) {
func TestParseTextHTMLAlready7Bit(t *testing.T) { func TestParseTextHTMLAlready7Bit(t *testing.T) {
f := getFileReader("text_html_7bit.eml") f := getFileReader("text_html_7bit.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -322,7 +323,7 @@ func TestParseTextHTMLAlready7Bit(t *testing.T) {
func TestParseTextHTMLWithOctetAttachment(t *testing.T) { func TestParseTextHTMLWithOctetAttachment(t *testing.T) {
f := getFileReader("text_html_octet_attachment.eml") f := getFileReader("text_html_octet_attachment.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -338,7 +339,7 @@ func TestParseTextHTMLWithOctetAttachment(t *testing.T) {
func TestParseTextHTMLWithPlainAttachment(t *testing.T) { func TestParseTextHTMLWithPlainAttachment(t *testing.T) {
f := getFileReader("text_html_plain_attachment.eml") f := getFileReader("text_html_plain_attachment.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -355,7 +356,7 @@ func TestParseTextHTMLWithPlainAttachment(t *testing.T) {
func TestParseTextHTMLWithImageInline(t *testing.T) { func TestParseTextHTMLWithImageInline(t *testing.T) {
f := getFileReader("text_html_image_inline.eml") f := getFileReader("text_html_image_inline.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -375,7 +376,10 @@ func TestParseTextHTMLWithImageInline(t *testing.T) {
func TestParseWithAttachedPublicKey(t *testing.T) { func TestParseWithAttachedPublicKey(t *testing.T) {
f := getFileReader("text_plain.eml") f := getFileReader("text_plain.eml")
m, _, plainBody, attReaders, err := Parse(f, "publickey", "publickeyname") p, err := parser.New(f)
require.NoError(t, err)
m, plainBody, attReaders, err := ParserWithParser(p)
AttachPublicKey(p, "publickey", "publickeyname")
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -392,7 +396,7 @@ func TestParseWithAttachedPublicKey(t *testing.T) {
func TestParseTextHTMLWithEmbeddedForeignEncoding(t *testing.T) { func TestParseTextHTMLWithEmbeddedForeignEncoding(t *testing.T) {
f := getFileReader("text_html_embedded_foreign_encoding.eml") f := getFileReader("text_html_embedded_foreign_encoding.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "") m, _, plainBody, attReaders, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
@ -407,7 +411,7 @@ func TestParseTextHTMLWithEmbeddedForeignEncoding(t *testing.T) {
func TestParseMultipartAlternative(t *testing.T) { func TestParseMultipartAlternative(t *testing.T) {
f := getFileReader("multipart_alternative.eml") f := getFileReader("multipart_alternative.eml")
m, _, plainBody, _, err := Parse(f, "", "") m, _, plainBody, _, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"schizofrenic" <schizofrenic@pm.me>`, m.Sender.String()) assert.Equal(t, `"schizofrenic" <schizofrenic@pm.me>`, m.Sender.String())
@ -428,7 +432,7 @@ func TestParseMultipartAlternative(t *testing.T) {
func TestParseMultipartAlternativeNested(t *testing.T) { func TestParseMultipartAlternativeNested(t *testing.T) {
f := getFileReader("multipart_alternative_nested.eml") f := getFileReader("multipart_alternative_nested.eml")
m, _, plainBody, _, err := Parse(f, "", "") m, _, plainBody, _, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"schizofrenic" <schizofrenic@pm.me>`, m.Sender.String()) assert.Equal(t, `"schizofrenic" <schizofrenic@pm.me>`, m.Sender.String())
@ -449,7 +453,7 @@ func TestParseMultipartAlternativeNested(t *testing.T) {
func TestParseMultipartAlternativeLatin1(t *testing.T) { func TestParseMultipartAlternativeLatin1(t *testing.T) {
f := getFileReader("multipart_alternative_latin1.eml") f := getFileReader("multipart_alternative_latin1.eml")
m, _, plainBody, _, err := Parse(f, "", "") m, _, plainBody, _, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"schizofrenic" <schizofrenic@pm.me>`, m.Sender.String()) assert.Equal(t, `"schizofrenic" <schizofrenic@pm.me>`, m.Sender.String())
@ -470,7 +474,7 @@ func TestParseMultipartAlternativeLatin1(t *testing.T) {
func TestParseWithTrailingEndOfMailIndicator(t *testing.T) { func TestParseWithTrailingEndOfMailIndicator(t *testing.T) {
f := getFileReader("text_html_trailing_end_of_mail.eml") f := getFileReader("text_html_trailing_end_of_mail.eml")
m, _, plainBody, _, err := Parse(f, "", "") m, _, plainBody, _, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@sender.com>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@sender.com>`, m.Sender.String())
@ -483,7 +487,7 @@ func TestParseWithTrailingEndOfMailIndicator(t *testing.T) {
func TestParseEncodedContentType(t *testing.T) { func TestParseEncodedContentType(t *testing.T) {
f := getFileReader("rfc2047-content-transfer-encoding.eml") f := getFileReader("rfc2047-content-transfer-encoding.eml")
m, _, plainBody, _, err := Parse(f, "", "") m, _, plainBody, _, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@sender.com>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@sender.com>`, m.Sender.String())
@ -495,7 +499,7 @@ func TestParseEncodedContentType(t *testing.T) {
func TestParseNonEncodedContentType(t *testing.T) { func TestParseNonEncodedContentType(t *testing.T) {
f := getFileReader("non-encoded-content-transfer-encoding.eml") f := getFileReader("non-encoded-content-transfer-encoding.eml")
m, _, plainBody, _, err := Parse(f, "", "") m, _, plainBody, _, err := Parse(f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@sender.com>`, m.Sender.String()) assert.Equal(t, `"Sender" <sender@sender.com>`, m.Sender.String())
@ -507,7 +511,7 @@ func TestParseNonEncodedContentType(t *testing.T) {
func TestParseEncodedContentTypeBad(t *testing.T) { func TestParseEncodedContentTypeBad(t *testing.T) {
f := getFileReader("rfc2047-content-transfer-encoding-bad.eml") f := getFileReader("rfc2047-content-transfer-encoding-bad.eml")
_, _, _, _, err := Parse(f, "", "") // nolint[dogsled] _, _, _, _, err := Parse(f) // nolint[dogsled]
require.Error(t, err) require.Error(t, err)
} }

View File

@ -211,7 +211,7 @@ func (api *FakePMAPI) Import(importMessageRequests []*pmapi.ImportMsgReq) ([]*pm
} }
func (api *FakePMAPI) generateMessageFromImportRequest(msgReq *pmapi.ImportMsgReq) (*pmapi.Message, error) { func (api *FakePMAPI) generateMessageFromImportRequest(msgReq *pmapi.ImportMsgReq) (*pmapi.Message, error) {
m, _, _, _, err := message.Parse(bytes.NewReader(msgReq.Body), "", "") // nolint[dogsled] m, _, _, _, err := message.Parse(bytes.NewReader(msgReq.Body)) // nolint[dogsled]
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -17,7 +17,7 @@ Feature: SMTP initiation
Given there is connected user "user" Given there is connected user "user"
When SMTP client authenticates "user" When SMTP client authenticates "user"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me>" When SMTP client sends "MAIL FROM:<[userAddress]>"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<user@pm.me>" When SMTP client sends "RCPT TO:<user@pm.me>"
Then SMTP response is "OK" Then SMTP response is "OK"
@ -37,7 +37,7 @@ Feature: SMTP initiation
Given there is connected user "user" Given there is connected user "user"
When SMTP client authenticates "user" When SMTP client authenticates "user"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me>" When SMTP client sends "MAIL FROM:<[userAddress]>"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "DATA" When SMTP client sends "DATA"
Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command." Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command."
@ -53,13 +53,13 @@ Feature: SMTP initiation
When SMTP client sends "DATA" When SMTP client sends "DATA"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "hello\r\n." When SMTP client sends "hello\r\n."
Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: missing sender" Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: missing return path"
Scenario: Send with empty TO Scenario: Send with empty TO
Given there is connected user "user" Given there is connected user "user"
When SMTP client authenticates "user" When SMTP client authenticates "user"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me>" When SMTP client sends "MAIL FROM:<[userAddress]>"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<>" When SMTP client sends "RCPT TO:<>"
Then SMTP response is "OK" Then SMTP response is "OK"
@ -72,12 +72,19 @@ Feature: SMTP initiation
Given there is connected user "user" Given there is connected user "user"
When SMTP client authenticates "user" When SMTP client authenticates "user"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me> BODY=7BIT" When SMTP client sends "MAIL FROM:<[userAddress]> BODY=7BIT"
Then SMTP response is "OK" Then SMTP response is "OK"
Scenario: Allow AUTH parameter of MAIL FROM command Scenario: Allow AUTH parameter of MAIL FROM command
Given there is connected user "user" Given there is connected user "user"
When SMTP client authenticates "user" When SMTP client authenticates "user"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me> AUTH=<>" When SMTP client sends "MAIL FROM:<[userAddress]> AUTH=<>"
Then SMTP response is "OK" Then SMTP response is "OK"
Scenario: FROM not owned by user
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.test>"
Then SMTP response is "SMTP error: 451 4.0.0 backend: invalid return path: not owned by user"

View File

@ -7,7 +7,7 @@ Feature: SMTP with bcc
When SMTP client sends message with bcc "bridgetest2@protonmail.com" When SMTP client sends message with bcc "bridgetest2@protonmail.com"
""" """
Subject: hello Subject: hello
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
hello hello
@ -43,7 +43,7 @@ Feature: SMTP with bcc
When SMTP client sends message with bcc "bridgetest@protonmail.com" When SMTP client sends message with bcc "bridgetest@protonmail.com"
""" """
Subject: hello Subject: hello
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
hello hello

View File

@ -6,7 +6,7 @@ Feature: SMTP wrong messages
Scenario: Message with attachment and wrong boundaries Scenario: Message with attachment and wrong boundaries
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: With attachment (wrong boundaries) Subject: With attachment (wrong boundaries)
Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606 Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606
@ -39,3 +39,14 @@ Feature: SMTP wrong messages
""" """
Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: failed to create new parser: unexpected EOF" Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: failed to create new parser: unexpected EOF"
Scenario: Invalid from
When SMTP client sends message
"""
From: Bridge Test <bridgetest@pm.test>
To: Internal Bridge <bridgetest@protonmail.com>
hello
"""
Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: backend: invalid email address: not owned by user"

View File

@ -6,7 +6,7 @@ Feature: SMTP sending of HTML messages
Scenario: HTML message to external account Scenario: HTML message to external account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: HTML text external Subject: HTML text external
Content-Disposition: inline Content-Disposition: inline
@ -45,7 +45,7 @@ Feature: SMTP sending of HTML messages
Scenario: HTML message with inline image to external account Scenario: HTML message with inline image to external account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: Html Inline External Subject: Html Inline External
Content-Disposition: inline Content-Disposition: inline
@ -120,7 +120,7 @@ Feature: SMTP sending of HTML messages
Scenario: HTML message with alternative inline to internal account Scenario: HTML message with alternative inline to internal account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: Html Inline Alternative Internal Subject: Html Inline Alternative Internal
Content-Disposition: inline Content-Disposition: inline
@ -209,7 +209,7 @@ Feature: SMTP sending of HTML messages
Scenario: HTML message with alternative inline to external account Scenario: HTML message with alternative inline to external account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: Html Inline Alternative External Subject: Html Inline Alternative External
Content-Disposition: inline Content-Disposition: inline

View File

@ -6,7 +6,7 @@ Feature: SMTP sending of HTML messages with attachments
Scenario: HTML message with attachment to internal account Scenario: HTML message with attachment to internal account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: HTML with attachment internal Subject: HTML with attachment internal
Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606 Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606
@ -65,7 +65,7 @@ Feature: SMTP sending of HTML messages with attachments
Scenario: HTML message with attachment to external account Scenario: HTML message with attachment to external account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: HTML with attachment external PGP Subject: HTML with attachment external PGP
Content-Type: multipart/mixed; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606 Content-Type: multipart/mixed; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606

View File

@ -6,7 +6,7 @@ Feature: SMTP sending of plain messages
Scenario: Only from and to headers to internal account Scenario: Only from and to headers to internal account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
hello hello
@ -40,7 +40,7 @@ Feature: SMTP sending of plain messages
Scenario: Only from and to headers to external account Scenario: Only from and to headers to external account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
hello hello
@ -74,7 +74,7 @@ Feature: SMTP sending of plain messages
Scenario: Basic message to internal account Scenario: Basic message to internal account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: Plain text internal Subject: Plain text internal
Content-Disposition: inline Content-Disposition: inline
@ -111,7 +111,7 @@ Feature: SMTP sending of plain messages
Scenario: Basic message to external account Scenario: Basic message to external account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: Plain text external Subject: Plain text external
Content-Disposition: inline Content-Disposition: inline
@ -148,7 +148,7 @@ Feature: SMTP sending of plain messages
Scenario: Message without charset is utf8 Scenario: Message without charset is utf8
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: Plain text no charset external Subject: Plain text no charset external
Content-Disposition: inline Content-Disposition: inline
@ -185,7 +185,7 @@ Feature: SMTP sending of plain messages
Scenario: Message without charset is base64-encoded latin1 Scenario: Message without charset is base64-encoded latin1
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: Plain text no charset external Subject: Plain text no charset external
Content-Disposition: inline Content-Disposition: inline
@ -225,7 +225,7 @@ Feature: SMTP sending of plain messages
Scenario: Message without charset and content is detected as HTML Scenario: Message without charset and content is detected as HTML
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: Plain, no charset, no content, external Subject: Plain, no charset, no content, external
Content-Disposition: inline Content-Disposition: inline

View File

@ -6,7 +6,7 @@ Feature: SMTP sending of plain messages with attachments
Scenario: Basic message with attachment to internal account Scenario: Basic message with attachment to internal account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: Plain with attachment Subject: Plain with attachment
Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606 Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606
@ -65,7 +65,7 @@ Feature: SMTP sending of plain messages with attachments
Scenario: Plain message with attachment to external account Scenario: Plain message with attachment to external account
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge <pm.bridge.qa@gmail.com> To: External Bridge <pm.bridge.qa@gmail.com>
Subject: Plain with attachment external Subject: Plain with attachment external
Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606 Content-Type: multipart/related; boundary=bc5bd30245232f31b6c976adcd59bb0069c9b13f986f9e40c2571bb80aa16606
@ -124,7 +124,7 @@ Feature: SMTP sending of plain messages with attachments
Scenario: Plain message with attachment to two external accounts Scenario: Plain message with attachment to two external accounts
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: External Bridge 1 <pm.bridge.qa@gmail.com> To: External Bridge 1 <pm.bridge.qa@gmail.com>
CC: External Bridge 2 <bridgeqa@seznam.cz> CC: External Bridge 2 <bridgeqa@seznam.cz>
Subject: Plain with attachment external PGP and external CC Subject: Plain with attachment external PGP and external CC

View File

@ -4,7 +4,7 @@ Feature: SMTP sending the same message twice
And there is SMTP client logged in as "user" And there is SMTP client logged in as "user"
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: Hello Subject: Hello
@ -16,7 +16,7 @@ Feature: SMTP sending the same message twice
Scenario: The exact same message is not sent twice Scenario: The exact same message is not sent twice
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: Hello Subject: Hello
@ -31,7 +31,7 @@ Feature: SMTP sending the same message twice
Scenario: Slight change means different message and is sent twice Scenario: Slight change means different message and is sent twice
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
Subject: Hello. Subject: Hello.

View File

@ -4,7 +4,7 @@ Feature: SMTP sending two messages
And there is SMTP client logged in as "user" And there is SMTP client logged in as "user"
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
hello hello
@ -13,7 +13,7 @@ Feature: SMTP sending two messages
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends message When SMTP client sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
world world
@ -28,7 +28,7 @@ Feature: SMTP sending two messages
And there is SMTP client "smtp2" logged in as "userMoreAddresses" with address "secondary" And there is SMTP client "smtp2" logged in as "userMoreAddresses" with address "secondary"
When SMTP client "smtp1" sends message When SMTP client "smtp1" sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
hello hello
@ -37,7 +37,7 @@ Feature: SMTP sending two messages
Then SMTP response to "smtp1" is "OK" Then SMTP response to "smtp1" is "OK"
When SMTP client "smtp2" sends message When SMTP client "smtp2" sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
world world
@ -53,7 +53,7 @@ Feature: SMTP sending two messages
When SMTP client "smtp1" sends message When SMTP client "smtp1" sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
hello hello
@ -62,7 +62,7 @@ Feature: SMTP sending two messages
Then SMTP response to "smtp1" is "OK" Then SMTP response to "smtp1" is "OK"
When SMTP client "smtp2" sends message When SMTP client "smtp2" sends message
""" """
From: Bridge Test <bridgetest@pm.test> From: Bridge Test <[userAddress]>
To: Internal Bridge <bridgetest@protonmail.com> To: Internal Bridge <bridgetest@protonmail.com>
world world

View File

@ -74,6 +74,8 @@ func (c *SMTPClient) SendCommands(commands ...string) *SMTPResponse {
smtpResponse := &SMTPResponse{t: c.t} smtpResponse := &SMTPResponse{t: c.t}
for _, command := range commands { for _, command := range commands {
command = strings.ReplaceAll(command, "[userAddress]", c.address)
tstart := time.Now() tstart := time.Now()
c.debug.printReq(command) c.debug.printReq(command)

View File

@ -17,3 +17,6 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
### Changed ### Changed
* GODT-858 Bump go-rfc5322 dependency to v0.4.0 to handle some invalid RFC5322 groups. * GODT-858 Bump go-rfc5322 dependency to v0.4.0 to handle some invalid RFC5322 groups.
* GODT-923 Fix listener locking. * GODT-923 Fix listener locking.
### Changed
* GODT-389 Prefer `From` header instead of `MAIL FROM` address.