mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
Other: Bump liteapi and clean up tests a bit
This commit is contained in:
3
Makefile
3
Makefile
@ -231,9 +231,6 @@ bench:
|
||||
coverage: test
|
||||
go tool cover -html=/tmp/coverage.out -o=coverage.html
|
||||
|
||||
integration-test-bridge:
|
||||
${MAKE} -C test test-bridge
|
||||
|
||||
mocks:
|
||||
mockgen --package mocks github.com/ProtonMail/proton-bridge/v2/internal/bridge TLSReporter,ProxyController,Autostarter > internal/bridge/mocks/mocks.go
|
||||
mockgen --package mocks github.com/ProtonMail/proton-bridge/v2/internal/updater Downloader,Installer > internal/updater/mocks/mocks.go
|
||||
|
||||
2
go.mod
2
go.mod
@ -39,7 +39,7 @@ require (
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/urfave/cli/v2 v2.16.3
|
||||
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221019124718-218de25bbfd6
|
||||
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221020085018-bbcf03261c80
|
||||
golang.org/x/exp v0.0.0-20220921164117-439092de6870
|
||||
golang.org/x/net v0.1.0
|
||||
golang.org/x/sys v0.1.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -401,8 +401,8 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0=
|
||||
github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
|
||||
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221019124718-218de25bbfd6 h1:D6tMRUg6C1VtnDVjqJkm10QHZJG5TLOPAslegS46nVg=
|
||||
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221019124718-218de25bbfd6/go.mod h1:VCEA83UCi9f3XCP9W/XUIFnJKwokGB46lKUHBNzPWsQ=
|
||||
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221020085018-bbcf03261c80 h1:fxmLKxf1xsNAu6EBj+BPU1ChyZagXYhLHiqb7Jy1yOA=
|
||||
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221020085018-bbcf03261c80/go.mod h1:VCEA83UCi9f3XCP9W/XUIFnJKwokGB46lKUHBNzPWsQ=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
|
||||
@ -357,7 +357,7 @@ func TestBridge_MissingGluonDir(t *testing.T) {
|
||||
|
||||
// withEnv creates the full test environment and runs the tests.
|
||||
func withEnv(t *testing.T, tests func(context.Context, *server.Server, *liteapi.NetCtl, bridge.Locator, []byte)) {
|
||||
server := server.NewTLS()
|
||||
server := server.New()
|
||||
defer server.Close()
|
||||
|
||||
withEnvServer(t, server, func(ctx context.Context, netCtl *liteapi.NetCtl, locator bridge.Locator, vaultKey []byte) {
|
||||
|
||||
@ -22,10 +22,13 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
"github.com/bradenaw/juniper/iterator"
|
||||
"github.com/bradenaw/juniper/stream"
|
||||
"github.com/emersion/go-imap/client"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
@ -48,11 +51,44 @@ func TestBridge_Sync(t *testing.T) {
|
||||
literal, err := os.ReadFile(filepath.Join("testdata", "text-plain.eml"))
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := 0; i < numMsg; i++ {
|
||||
messageID, err := s.CreateMessage(userID, addrID, literal, liteapi.MessageFlagReceived, false, false)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.LabelMessage(userID, messageID, labelID))
|
||||
}
|
||||
c, _, err := liteapi.New(
|
||||
liteapi.WithHostURL(s.GetHostURL()),
|
||||
liteapi.WithTransport(liteapi.InsecureTransport()),
|
||||
).NewClientWithLogin(ctx, "imap", password)
|
||||
require.NoError(t, err)
|
||||
|
||||
user, err := c.GetUser(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
addr, err := c.GetAddresses(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, addrID, addr[0].ID)
|
||||
|
||||
salt, err := c.GetSalts(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
keyPass, err := salt.SaltForKey(password, user.Keys.Primary().ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, addrKRs, err := liteapi.Unlock(user, addr, keyPass)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, getErr(stream.Collect(ctx, c.ImportMessages(
|
||||
ctx,
|
||||
addrKRs[addr[0].ID],
|
||||
runtime.NumCPU(),
|
||||
runtime.NumCPU(),
|
||||
iterator.Collect(iterator.Map(iterator.Counter(numMsg), func(i int) liteapi.ImportReq {
|
||||
return liteapi.ImportReq{
|
||||
Metadata: liteapi.ImportMetadata{
|
||||
AddressID: addr[0].ID,
|
||||
LabelIDs: []string{labelID},
|
||||
Flags: liteapi.MessageFlagReceived,
|
||||
},
|
||||
Message: literal,
|
||||
}
|
||||
}))...,
|
||||
))))
|
||||
|
||||
var read uint64
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ func TestTLSPinBackup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTLSPinInvalid(t *testing.T) {
|
||||
s := server.NewTLS()
|
||||
s := server.New()
|
||||
defer s.Close()
|
||||
|
||||
called, _, _, _, cm := createClientWithPinningDialer(s.GetHostURL())
|
||||
|
||||
@ -213,13 +213,15 @@ func (conn *imapConnector) GetMessage(ctx context.Context, messageID imap.Messag
|
||||
}
|
||||
|
||||
// CreateMessage creates a new message on the remote.
|
||||
//
|
||||
// nolint:funlen
|
||||
func (conn *imapConnector) CreateMessage(
|
||||
ctx context.Context,
|
||||
mailboxID imap.MailboxID,
|
||||
literal []byte,
|
||||
flags imap.FlagSet,
|
||||
date time.Time,
|
||||
) (imap.Message, []byte, error) { // nolint:funlen
|
||||
) (imap.Message, []byte, error) {
|
||||
var msgFlags liteapi.MessageFlag
|
||||
|
||||
if mailboxID != liteapi.DraftsLabel {
|
||||
|
||||
@ -100,7 +100,10 @@ func withAPI(_ *testing.T, ctx context.Context, fn func(context.Context, *server
|
||||
server := server.New()
|
||||
defer server.Close()
|
||||
|
||||
fn(ctx, server, liteapi.New(liteapi.WithHostURL(server.GetHostURL())))
|
||||
fn(ctx, server, liteapi.New(
|
||||
liteapi.WithHostURL(server.GetHostURL()),
|
||||
liteapi.WithTransport(liteapi.InsecureTransport()),
|
||||
))
|
||||
}
|
||||
|
||||
func withAccount(t *testing.T, s *server.Server, username, password string, emails []string, fn func(string, []string)) {
|
||||
|
||||
@ -26,7 +26,6 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/ProtonMail/gluon/rfc822"
|
||||
"github.com/emersion/go-message"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
@ -38,7 +37,6 @@ import (
|
||||
func init() {
|
||||
rfc822.ParseMediaType = ParseMediaType
|
||||
liteapi.CharsetReader = CharsetReader
|
||||
message.CharsetReader = CharsetReader
|
||||
}
|
||||
|
||||
func CharsetReader(charset string, input io.Reader) (io.Reader, error) {
|
||||
|
||||
@ -19,7 +19,6 @@ package tests
|
||||
|
||||
import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"gitlab.protontech.ch/go/liteapi/server"
|
||||
)
|
||||
|
||||
@ -30,12 +29,10 @@ type API interface {
|
||||
AddCallWatcher(func(server.Call), ...string)
|
||||
|
||||
CreateUser(username, address string, password []byte) (string, string, error)
|
||||
CreateAddress(userID, address string, password []byte) (string, error)
|
||||
RemoveAddress(userID, addrID string) error
|
||||
RevokeUser(userID string) error
|
||||
|
||||
GetLabels(userID string) ([]liteapi.Label, error)
|
||||
CreateLabel(userID, name string, labelType liteapi.LabelType) (string, error)
|
||||
CreateAddress(userID, address string, password []byte) (string, error)
|
||||
RemoveAddress(userID, addrID string) error
|
||||
|
||||
Close()
|
||||
}
|
||||
@ -46,6 +43,6 @@ type fakeAPI struct {
|
||||
|
||||
func newFakeAPI() *fakeAPI {
|
||||
return &fakeAPI{
|
||||
Server: server.NewTLS(),
|
||||
Server: server.New(),
|
||||
}
|
||||
}
|
||||
|
||||
87
tests/ctx_helper_test.go
Normal file
87
tests/ctx_helper_test.go
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/bradenaw/juniper/stream"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
)
|
||||
|
||||
func (t *testCtx) withClient(ctx context.Context, username string, fn func(context.Context, *liteapi.Client) error) error {
|
||||
c, _, err := liteapi.New(
|
||||
liteapi.WithHostURL(t.api.GetHostURL()),
|
||||
liteapi.WithTransport(liteapi.InsecureTransport()),
|
||||
).NewClientWithLogin(ctx, username, []byte(t.getUserPass(t.getUserID(username))))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := fn(ctx, c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.AuthDelete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Close()
|
||||
}
|
||||
|
||||
func (t *testCtx) createMessages(ctx context.Context, username, addrID string, req []liteapi.ImportReq) error {
|
||||
return t.withClient(ctx, username, func(ctx context.Context, c *liteapi.Client) error {
|
||||
user, err := c.GetUser(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := c.GetAddresses(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
salt, err := c.GetSalts(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyPass, err := salt.SaltForKey([]byte(t.getUserPass(t.getUserID(username))), user.Keys.Primary().ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, addrKRs, err := liteapi.Unlock(user, addr, keyPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := stream.Collect(ctx, c.ImportMessages(
|
||||
ctx,
|
||||
addrKRs[addrID],
|
||||
runtime.NumCPU(),
|
||||
runtime.NumCPU(),
|
||||
req...,
|
||||
)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@ -125,6 +125,16 @@ func (t *testCtx) beforeStep() {
|
||||
t.errors = append(t.errors, nil)
|
||||
}
|
||||
|
||||
func (t *testCtx) getName(wantUserID string) string {
|
||||
for name, userID := range t.userIDByName {
|
||||
if userID == wantUserID {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unknown user ID %q", wantUserID))
|
||||
}
|
||||
|
||||
func (t *testCtx) getUserID(username string) string {
|
||||
return t.userIDByName[username]
|
||||
}
|
||||
@ -174,20 +184,33 @@ func (t *testCtx) setUserBridgePass(userID string, pass []byte) {
|
||||
}
|
||||
|
||||
func (t *testCtx) getMBoxID(userID string, name string) string {
|
||||
labels, err := t.api.GetLabels(userID)
|
||||
if err != nil {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var labelID string
|
||||
|
||||
if err := t.withClient(ctx, t.getName(userID), func(ctx context.Context, client *liteapi.Client) error {
|
||||
labels, err := client.GetLabels(ctx, liteapi.LabelTypeLabel, liteapi.LabelTypeFolder, liteapi.LabelTypeSystem)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
idx := xslices.IndexFunc(labels, func(label liteapi.Label) bool {
|
||||
return label.Name == name
|
||||
})
|
||||
|
||||
if idx < 0 {
|
||||
panic(fmt.Errorf("label %q not found", name))
|
||||
}
|
||||
|
||||
labelID = labels[idx].ID
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
idx := xslices.IndexFunc(labels, func(label liteapi.Label) bool {
|
||||
return label.Name == name
|
||||
})
|
||||
|
||||
if idx < 0 {
|
||||
panic(fmt.Errorf("label %q not found", name))
|
||||
}
|
||||
|
||||
return labels[idx].ID
|
||||
return labelID
|
||||
}
|
||||
|
||||
func (t *testCtx) getLastCall(method, path string) (server.Call, error) {
|
||||
|
||||
@ -68,9 +68,7 @@ func (msg Message) Build() []byte {
|
||||
b = append(b, "Subject: "+msg.Subject+"\r\n"...)
|
||||
}
|
||||
|
||||
if msg.Body != "" {
|
||||
b = append(b, "\r\n"+msg.Body+"\r\n"...)
|
||||
}
|
||||
b = append(b, "\r\n"+msg.Body+"\r\n"...)
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@ -22,6 +22,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/bradenaw/juniper/iterator"
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"github.com/cucumber/godog"
|
||||
"github.com/google/uuid"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
@ -74,26 +76,45 @@ func (s *scenario) theAccountNoLongerHasAdditionalAddress(username, address stri
|
||||
}
|
||||
|
||||
func (s *scenario) theAccountHasCustomFolders(username string, count int) error {
|
||||
for idx := 0; idx < count; idx++ {
|
||||
if _, err := s.t.api.CreateLabel(s.t.getUserID(username), uuid.NewString(), liteapi.LabelTypeFolder); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
return nil
|
||||
return s.t.withClient(ctx, username, func(ctx context.Context, client *liteapi.Client) error {
|
||||
for idx := 0; idx < count; idx++ {
|
||||
if _, err := client.CreateLabel(ctx, liteapi.CreateLabelReq{
|
||||
Name: uuid.NewString(),
|
||||
Type: liteapi.LabelTypeFolder,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *scenario) theAccountHasCustomLabels(username string, count int) error {
|
||||
for idx := 0; idx < count; idx++ {
|
||||
if _, err := s.t.api.CreateLabel(s.t.getUserID(username), uuid.NewString(), liteapi.LabelTypeLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
return nil
|
||||
return s.t.withClient(ctx, username, func(ctx context.Context, client *liteapi.Client) error {
|
||||
for idx := 0; idx < count; idx++ {
|
||||
if _, err := client.CreateLabel(ctx, liteapi.CreateLabelReq{
|
||||
Name: uuid.NewString(),
|
||||
Type: liteapi.LabelTypeLabel,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *scenario) theAccountHasTheFollowingCustomMailboxes(username string, table *godog.Table) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
type CustomMailbox struct {
|
||||
Name string `bdd:"name"`
|
||||
Type string `bdd:"type"`
|
||||
@ -104,26 +125,34 @@ func (s *scenario) theAccountHasTheFollowingCustomMailboxes(username string, tab
|
||||
return err
|
||||
}
|
||||
|
||||
for _, wantMailbox := range wantMailboxes {
|
||||
var labelType liteapi.LabelType
|
||||
return s.t.withClient(ctx, username, func(ctx context.Context, client *liteapi.Client) error {
|
||||
for _, wantMailbox := range wantMailboxes {
|
||||
var labelType liteapi.LabelType
|
||||
|
||||
switch wantMailbox.Type {
|
||||
case "folder":
|
||||
labelType = liteapi.LabelTypeFolder
|
||||
switch wantMailbox.Type {
|
||||
case "folder":
|
||||
labelType = liteapi.LabelTypeFolder
|
||||
|
||||
case "label":
|
||||
labelType = liteapi.LabelTypeLabel
|
||||
case "label":
|
||||
labelType = liteapi.LabelTypeLabel
|
||||
}
|
||||
|
||||
if _, err := client.CreateLabel(ctx, liteapi.CreateLabelReq{
|
||||
Name: wantMailbox.Name,
|
||||
Type: labelType,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := s.t.api.CreateLabel(s.t.getUserID(username), wantMailbox.Name, labelType); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address, username, mailbox string, table *godog.Table) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
userID := s.t.getUserID(username)
|
||||
addrID := s.t.getUserAddrID(userID, address)
|
||||
mboxID := s.t.getMBoxID(userID, mailbox)
|
||||
@ -133,42 +162,42 @@ func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address,
|
||||
return err
|
||||
}
|
||||
|
||||
for _, wantMessage := range wantMessages {
|
||||
messageID, err := s.t.api.CreateMessage(userID, addrID, wantMessage.Build(), liteapi.MessageFlagReceived, wantMessage.Unread, false)
|
||||
if err != nil {
|
||||
return err
|
||||
return s.t.createMessages(ctx, username, addrID, xslices.Map(wantMessages, func(message Message) liteapi.ImportReq {
|
||||
return liteapi.ImportReq{
|
||||
Metadata: liteapi.ImportMetadata{
|
||||
AddressID: addrID,
|
||||
LabelIDs: []string{mboxID},
|
||||
Unread: liteapi.Bool(message.Unread),
|
||||
Flags: liteapi.MessageFlagReceived,
|
||||
},
|
||||
Message: message.Build(),
|
||||
}
|
||||
|
||||
if err := s.t.api.LabelMessage(userID, messageID, mboxID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *scenario) theAddressOfAccountHasMessagesInMailbox(address, username string, count int, mailbox string) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
userID := s.t.getUserID(username)
|
||||
addrID := s.t.getUserAddrID(userID, address)
|
||||
mboxID := s.t.getMBoxID(userID, mailbox)
|
||||
|
||||
for idx := 0; idx < count; idx++ {
|
||||
messageID, err := s.t.api.CreateMessage(userID, addrID, Message{
|
||||
Subject: fmt.Sprintf("%d", idx),
|
||||
To: fmt.Sprintf("%d@pm.me", idx),
|
||||
From: fmt.Sprintf("%d@pm.me", idx),
|
||||
Body: fmt.Sprintf("body %d", idx),
|
||||
}.Build(), liteapi.MessageFlagReceived, idx%2 == 0, false)
|
||||
if err != nil {
|
||||
return err
|
||||
return s.t.createMessages(ctx, username, addrID, iterator.Collect(iterator.Map(iterator.Counter(count), func(idx int) liteapi.ImportReq {
|
||||
return liteapi.ImportReq{
|
||||
Metadata: liteapi.ImportMetadata{
|
||||
AddressID: addrID,
|
||||
LabelIDs: []string{mboxID},
|
||||
Flags: liteapi.MessageFlagReceived,
|
||||
},
|
||||
Message: Message{
|
||||
Subject: fmt.Sprintf("%d", idx),
|
||||
To: fmt.Sprintf("%d@pm.me", idx),
|
||||
From: fmt.Sprintf("%d@pm.me", idx),
|
||||
Body: fmt.Sprintf("body %d", idx),
|
||||
}.Build(),
|
||||
}
|
||||
|
||||
if err := s.t.api.LabelMessage(userID, messageID, mboxID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})))
|
||||
}
|
||||
|
||||
func (s *scenario) userLogsInWithUsernameAndPassword(username, password string) error {
|
||||
|
||||
Reference in New Issue
Block a user