mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-11 13:16:53 +00:00
GODT-1817: Restore missing SMTP feature tests
Requires update to GPA to set disabled state on addresses.
This commit is contained in:
@ -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"
|
||||
@ -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"
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user