GODT-1817: Restore missing SMTP feature tests

Requires update to GPA to set disabled state on addresses.
This commit is contained in:
Leander Beernaert
2023-01-09 14:04:04 +01:00
parent 2562d1e77d
commit 0dcd4ca133
8 changed files with 160 additions and 239 deletions

2
go.mod
View File

@ -7,7 +7,7 @@ require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/ProtonMail/gluon v0.14.2-0.20230106095250-7e99ea4da61e
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
github.com/ProtonMail/go-proton-api v0.2.4-0.20230103140323-680d85d1c3f0
github.com/ProtonMail/go-proton-api v0.2.4-0.20230109130302-16194531370b
github.com/ProtonMail/go-rfc5322 v0.11.0
github.com/ProtonMail/gopenpgp/v2 v2.4.10
github.com/PuerkitoBio/goquery v1.8.0

6
go.sum
View File

@ -28,8 +28,6 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo=
github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk=
github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g=
github.com/ProtonMail/gluon v0.14.2-0.20230105101243-675bf5daf3e6 h1:pGom2w5ncRNZf8+Z3IL4DQyTCI2UK8jhb6zkQVbVrLg=
github.com/ProtonMail/gluon v0.14.2-0.20230105101243-675bf5daf3e6/go.mod h1:z2AxLIiBCT1K+0OBHyaDI7AEaO5qI6/BEC2TE42vs4Q=
github.com/ProtonMail/gluon v0.14.2-0.20230106095250-7e99ea4da61e h1://xRNjGTAMXw2U91MtqPc4krUtxQmt2+4z1oYrBaOWU=
github.com/ProtonMail/gluon v0.14.2-0.20230106095250-7e99ea4da61e/go.mod h1:z2AxLIiBCT1K+0OBHyaDI7AEaO5qI6/BEC2TE42vs4Q=
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4=
@ -43,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.2.4-0.20230103140323-680d85d1c3f0 h1:0QzaGMTJsW+LT1+pCG93eYadIwZlgX2aNfwP3O83Mo0=
github.com/ProtonMail/go-proton-api v0.2.4-0.20230103140323-680d85d1c3f0/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos=
github.com/ProtonMail/go-proton-api v0.2.4-0.20230109130302-16194531370b h1:0uoTz1ZBTKpVazsBSt+i2MLupp6xIcv7Ay4KtROQUKU=
github.com/ProtonMail/go-proton-api v0.2.4-0.20230109130302-16194531370b/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=

View File

@ -1,65 +0,0 @@
Feature: SMTP auth
Scenario: Ask EHLO
Given there is connected user "user"
When SMTP client sends "EHLO example.com"
Then SMTP response is "OK"
Scenario: Authenticates successfully and EHLO successfully
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "EHLO example.com"
Then SMTP response is "OK"
Scenario: Authenticates with bad password
Given there is connected user "user"
When SMTP client authenticates "user" with bad password
Then SMTP response is "SMTP error: 454 4.7.0 backend/credentials: incorrect password"
Scenario: Authenticates with disconnected user
Given there is disconnected user "user"
When SMTP client authenticates "user"
Then SMTP response is "SMTP error: 454 4.7.0 account is logged out, use the app to login again"
Scenario: Authenticates with no user
When SMTP client authenticates with username "user@pm.me" and password "bridgepassword"
Then SMTP response is "SMTP error: 454 4.7.0 user user@pm.me not found"
Scenario: Authenticates with capital letter
Given there is connected user "userAddressWithCapitalLetter"
When SMTP client authenticates "userAddressWithCapitalLetter"
Then SMTP response is "OK"
Scenario: Authenticates with more addresses - primary one
Given there is connected user "userMoreAddresses"
When SMTP client authenticates "userMoreAddresses" with address "primary"
Then SMTP response is "OK"
Scenario: Authenticates with more addresses - secondary one
Given there is connected user "userMoreAddresses"
When SMTP client authenticates "userMoreAddresses" with address "secondary"
Then SMTP response is "OK"
Scenario: Authenticates with more addresses - disabled address
Given there is connected user "userMoreAddresses"
When SMTP client authenticates "userMoreAddresses" with address "disabled"
Then SMTP response is "SMTP error: 454 4.7.0 user .* not found"
@ignore-live
Scenario: Authenticates with secondary address of account with disabled primary address
Given there is connected user "userDisabledPrimaryAddress"
When SMTP client authenticates "userDisabledPrimaryAddress" with address "secondary"
Then SMTP response is "OK"
Scenario: Authenticates two users
Given there is connected user "user"
And there is connected user "userMoreAddresses"
When SMTP client "smtp1" authenticates "user"
Then SMTP response to "smtp1" is "OK"
When SMTP client "smtp2" authenticates "userMoreAddresses" with address "primary"
Then SMTP response to "smtp2" is "OK"
Scenario: Logs out user
Given there is connected user "user"
When SMTP client logs out
Then SMTP response is "OK"

View File

@ -1,90 +0,0 @@
Feature: SMTP initiation
Scenario: Empty FROM
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<>"
Then SMTP response is "OK"
Scenario: Send without FROM and TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command."
Scenario: Reset is the same as without FROM and TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<[userAddress]>"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<user@pm.me>"
Then SMTP response is "OK"
When SMTP client sends "RSET"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command"
Scenario: Send without FROM
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<user@pm.me>"
Then SMTP response is "SMTP error: 502 5.5.1 Missing MAIL FROM command."
Scenario: Send without TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<[userAddress]>"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command."
Scenario: Send with empty FROM
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<>"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<user@pm.me>"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "OK"
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 return path"
Scenario: Send with empty TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<[userAddress]>"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<>"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "OK"
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 recipient"
Scenario: Allow BODY parameter of MAIL FROM command
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<[userAddress]> BODY=7BIT"
Then SMTP response is "OK"
Scenario: Allow AUTH parameter of MAIL FROM command
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<[userAddress]> AUTH=<>"
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

@ -110,7 +110,9 @@ func TestFeatures(testingT *testing.T) {
// ==== SETUP ====
ctx.Step(`^there exists an account with username "([^"]*)" and password "([^"]*)"$`, s.thereExistsAnAccountWithUsernameAndPassword)
ctx.Step(`^there exists a disabled account with username "([^"]*)" and password "([^"]*)"$`, s.thereExistsAnAccountWithUsernameAndPasswordWithDisablePrimary)
ctx.Step(`^the account "([^"]*)" has additional address "([^"]*)"$`, s.theAccountHasAdditionalAddress)
ctx.Step(`^the account "([^"]*)" has additional disabled address "([^"]*)"$`, s.theAccountHasAdditionalDisabledAddress)
ctx.Step(`^the account "([^"]*)" has additional address "([^"]*)" without keys$`, s.theAccountHasAdditionalAddressWithoutKeys)
ctx.Step(`^the account "([^"]*)" no longer has additional address "([^"]*)"$`, s.theAccountNoLongerHasAdditionalAddress)
ctx.Step(`^the account "([^"]*)" has (\d+) custom folders$`, s.theAccountHasCustomFolders)
@ -220,6 +222,7 @@ func TestFeatures(testingT *testing.T) {
ctx.Step(`^SMTP client "([^"]*)" sends DATA:$`, s.smtpClientSendsData)
ctx.Step(`^SMTP client "([^"]*)" sends RSET$`, s.smtpClientSendsReset)
ctx.Step(`^SMTP client "([^"]*)" sends the following message from "([^"]*)" to "([^"]*)":$`, s.smtpClientSendsTheFollowingMessageFromTo)
ctx.Step(`^SMTP client "([^"]*)" logs out$`, s.smtpClientLogsOut)
},
Options: &godog.Options{
Format: "pretty",

View File

@ -1,8 +1,15 @@
Feature: A user can authenticate an SMTP client
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user2:user2]" and password "password2"
And there exists a disabled account with username "[user3:user3]" and password "password3"
And the account "[user:user]" has additional address "[alias:alias]@[domain]"
And the account "[user2:user2]" has additional disabled address "[alias2:alias2]@[domain]"
And the account "[user3:user3]" has additional address "[alias3:alias3]@[domain]"
And bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user2:user2]" and password "password2"
And the user logs in with username "[user3:user3]" and password "password3"
Scenario: SMTP client can authenticate successfully
When user "[user:user]" connects SMTP client "1"
@ -19,4 +26,28 @@ Feature: A user can authenticate an SMTP client
Scenario: SMTP client cannot authenticate for disconnected user
When user "[user:user]" logs out
And user "[user:user]" connects SMTP client "1"
Then SMTP client "1" cannot authenticate
Then SMTP client "1" cannot authenticate
Scenario: SMTP client can authenticate successfully with alias
When user "[user:user]" connects and authenticates SMTP client "1" with address "[alias:alias]@[domain]"
Then it succeeds
Scenario: SMTP client can not authenticate with disabled address
When user "[user2:user2]" connects and authenticates SMTP client "1" with address "[alias2:alias2]@[domain]"
Then it fails
Scenario: SMTP Logs out user
Given user "[user:user]" connects SMTP client "1"
When SMTP client "1" logs out
Then it succeeds
Scenario: SMTP client can authenticate two users
When user "[user:user]" connects SMTP client "1"
Then SMTP client "1" can authenticate
When user "[user2:user2]" connects SMTP client "2"
Then SMTP client "2" can authenticate
@ignore-live
Scenario: SMTP Authenticates with secondary address of account with disabled primary address
When user "[user3:user3]" connects and authenticates SMTP client "1" with address "[alias3:alias3]@[domain]"
Then it succeeds

View File

@ -157,3 +157,11 @@ func (s *scenario) smtpClientSendsTheFollowingMessageFromTo(clientID, from, to s
return nil
}
func (s *scenario) smtpClientLogsOut(clientID string) error {
_, client := s.t.getSMTPClient(clientID)
s.t.pushError(client.Quit())
return nil
}

View File

@ -35,89 +35,19 @@ import (
)
func (s *scenario) thereExistsAnAccountWithUsernameAndPassword(username, password string) error {
// Create the user and generate its default address (with keys).
if _, err := s.t.runQuarkCmd(
context.Background(),
"user:create",
"--name", username,
"--password", password,
"--gen-keys", "RSA2048",
); err != nil {
return err
}
return s.createUserAccount(username, password, false)
}
return s.t.withClientPass(context.Background(), username, password, func(ctx context.Context, c *proton.Client) error {
user, err := c.GetUser(ctx)
if err != nil {
return err
}
// Decrypt the user's encrypted ID for use with quark.
userDecID, err := s.t.runQuarkCmd(context.Background(), "encryption:id", "--decrypt", user.ID)
if err != nil {
return err
}
// Upgrade the user to a paid account.
if _, err := s.t.runQuarkCmd(
context.Background(),
"user:create:subscription",
"--planID", "plus",
string(userDecID),
); err != nil {
return err
}
addr, err := c.GetAddresses(ctx)
if err != nil {
return err
}
// Set the ID of the user.
s.t.setUserID(username, user.ID)
// Set the password of the user.
s.t.setUserPass(user.ID, password)
// Set the address of the user.
s.t.setUserAddr(user.ID, addr[0].ID, addr[0].Email)
return nil
})
func (s *scenario) thereExistsAnAccountWithUsernameAndPasswordWithDisablePrimary(username, password string) error {
return s.createUserAccount(username, password, true)
}
func (s *scenario) theAccountHasAdditionalAddress(username, address string) error {
userID := s.t.getUserID(username)
return s.addAdditionalAddressToAccount(username, address, false)
}
// Decrypt the user's encrypted ID for use with quark.
userDecID, err := s.t.runQuarkCmd(context.Background(), "encryption:id", "--decrypt", userID)
if err != nil {
return err
}
// Create the user's additional address.
if _, err := s.t.runQuarkCmd(
context.Background(),
"user:create:address",
"--gen-keys", "RSA2048",
string(userDecID),
s.t.getUserPass(userID),
address,
); err != nil {
return err
}
return s.t.withClient(context.Background(), username, func(ctx context.Context, c *proton.Client) error {
addr, err := c.GetAddresses(ctx)
if err != nil {
return err
}
// Set the new address of the user.
s.t.setUserAddr(userID, addr[len(addr)-1].ID, address)
return nil
})
func (s *scenario) theAccountHasAdditionalDisabledAddress(username, address string) error {
return s.addAdditionalAddressToAccount(username, address, true)
}
func (s *scenario) theAccountHasAdditionalAddressWithoutKeys(username, address string) error {
@ -452,3 +382,109 @@ func (s *scenario) userIsNotListed(username string) error {
func (s *scenario) userFinishesSyncing(username string) error {
return s.bridgeSendsSyncStartedAndFinishedEventsForUser(username)
}
func (s *scenario) addAdditionalAddressToAccount(username, address string, disabled bool) error {
userID := s.t.getUserID(username)
// Decrypt the user's encrypted ID for use with quark.
userDecID, err := s.t.runQuarkCmd(context.Background(), "encryption:id", "--decrypt", userID)
if err != nil {
return err
}
args := []string{
"--gen-keys", "RSA2048",
}
if disabled {
args = append(args, "--status", "1")
}
args = append(args,
string(userDecID),
s.t.getUserPass(userID),
address,
)
// Create the user's additional address.
if _, err := s.t.runQuarkCmd(
context.Background(),
"user:create:address",
args...,
); err != nil {
return err
}
return s.t.withClient(context.Background(), username, func(ctx context.Context, c *proton.Client) error {
addr, err := c.GetAddresses(ctx)
if err != nil {
return err
}
// Set the new address of the user.
s.t.setUserAddr(userID, addr[len(addr)-1].ID, address)
return nil
})
}
func (s *scenario) createUserAccount(username, password string, disabled bool) error {
// Create the user and generate its default address (with keys).
args := []string{
"--name", username,
"--password", password,
"--gen-keys", "RSA2048",
}
if disabled {
args = append(args, "--status", "1")
}
if _, err := s.t.runQuarkCmd(
context.Background(),
"user:create",
args...,
); err != nil {
return err
}
return s.t.withClientPass(context.Background(), username, password, func(ctx context.Context, c *proton.Client) error {
user, err := c.GetUser(ctx)
if err != nil {
return err
}
// Decrypt the user's encrypted ID for use with quark.
userDecID, err := s.t.runQuarkCmd(context.Background(), "encryption:id", "--decrypt", user.ID)
if err != nil {
return err
}
// Upgrade the user to a paid account.
if _, err := s.t.runQuarkCmd(
context.Background(),
"user:create:subscription",
"--planID", "plus",
string(userDecID),
); err != nil {
return err
}
addr, err := c.GetAddresses(ctx)
if err != nil {
return err
}
// Set the ID of the user.
s.t.setUserID(username, user.ID)
// Set the password of the user.
s.t.setUserPass(user.ID, password)
// Set the address of the user.
s.t.setUserAddr(user.ID, addr[0].ID, addr[0].Email)
return nil
})
}