forked from Silverfish/proton-bridge
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82c388a0dd | |||
| 94ed09b437 | |||
| 57962e5757 | |||
| 8a5c8eaf6e | |||
| 30029f489e |
@ -2,10 +2,16 @@
|
||||
|
||||
Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
||||
|
||||
## [Bridge 3.0.18] Perth Narrows
|
||||
|
||||
### Fixed
|
||||
* GODT-2392: Create message if gluon updateMessage returns `no such message`.
|
||||
* GODT-2391: Create draft if missing during message update on gluon side.
|
||||
|
||||
## [Bridge 3.0.16/17] Perth Narrows
|
||||
|
||||
### Fixed
|
||||
* GODT-2354: Report failed load users.
|
||||
* GODT-2371: Continue, not return, when handling draft.
|
||||
|
||||
## [Bridge 3.0.15] Perth Narrows
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@ -11,7 +11,7 @@ ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
.PHONY: build build-gui build-nogui build-launcher versioner hasher
|
||||
|
||||
# Keep version hardcoded so app build works also without Git repository.
|
||||
BRIDGE_APP_VERSION?=3.0.16+git
|
||||
BRIDGE_APP_VERSION?=3.0.18+git
|
||||
APP_VERSION:=${BRIDGE_APP_VERSION}
|
||||
APP_FULL_NAME:=Proton Mail Bridge
|
||||
APP_VENDOR:=Proton AG
|
||||
|
||||
2
go.mod
2
go.mod
@ -5,7 +5,7 @@ go 1.18
|
||||
require (
|
||||
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557
|
||||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
github.com/ProtonMail/gluon v0.14.2-0.20230207072331-53797c5aa3f6
|
||||
github.com/ProtonMail/gluon v0.14.2-0.20230221144759-b277a90ca303
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
|
||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230209110241-fe7894c4931a
|
||||
github.com/ProtonMail/go-rfc5322 v0.11.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -28,8 +28,8 @@ 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.20230207072331-53797c5aa3f6 h1:HR944ZH7lN6sCA9OJMTdyoH1IRU0dBjxQHc7W0vFVrg=
|
||||
github.com/ProtonMail/gluon v0.14.2-0.20230207072331-53797c5aa3f6/go.mod h1:z2AxLIiBCT1K+0OBHyaDI7AEaO5qI6/BEC2TE42vs4Q=
|
||||
github.com/ProtonMail/gluon v0.14.2-0.20230221144759-b277a90ca303 h1:OTzqa4dcVuo4O4Kkng8rcoKJiKEY9HalQb8Y3OJWNFA=
|
||||
github.com/ProtonMail/gluon v0.14.2-0.20230221144759-b277a90ca303/go.mod h1:z2AxLIiBCT1K+0OBHyaDI7AEaO5qI6/BEC2TE42vs4Q=
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4=
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
|
||||
@ -23,6 +23,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/ProtonMail/gluon"
|
||||
"github.com/ProtonMail/gluon/imap"
|
||||
"github.com/ProtonMail/gluon/queue"
|
||||
"github.com/ProtonMail/gluon/reporter"
|
||||
@ -415,9 +416,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto
|
||||
|
||||
switch event.Action {
|
||||
case proton.EventCreate:
|
||||
updates, err := user.handleCreateMessageEvent(
|
||||
logging.WithLogrusField(ctx, "action", "create message"),
|
||||
event)
|
||||
updates, err := user.handleCreateMessageEvent(logging.WithLogrusField(ctx, "action", "create message"), event.Message)
|
||||
if err != nil {
|
||||
if rerr := user.reporter.ReportMessageWithContext("Failed to apply create message event", reporter.Context{
|
||||
"error": err,
|
||||
@ -446,6 +445,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto
|
||||
}); rerr != nil {
|
||||
user.log.WithError(err).Error("Failed to report update draft message event error")
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to handle update draft event: %w", err)
|
||||
}
|
||||
|
||||
@ -462,7 +462,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto
|
||||
// Issue regular update to handle mailboxes and flag changes.
|
||||
updates, err := user.handleUpdateMessageEvent(
|
||||
logging.WithLogrusField(ctx, "action", "update message"),
|
||||
event,
|
||||
event.Message,
|
||||
)
|
||||
if err != nil {
|
||||
if rerr := user.reporter.ReportMessageWithContext("Failed to apply update message event", reporter.Context{
|
||||
@ -470,10 +470,23 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto
|
||||
}); rerr != nil {
|
||||
user.log.WithError(err).Error("Failed to report update message event error")
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to handle update message event: %w", err)
|
||||
}
|
||||
|
||||
if err := waitOnIMAPUpdates(ctx, updates); err != nil {
|
||||
// If the update fails on the gluon side because it doesn't exist, we try to create the message instead.
|
||||
if err := waitOnIMAPUpdates(ctx, updates); gluon.IsNoSuchMessage(err) {
|
||||
user.log.WithError(err).Error("Failed to handle update message event in gluon, will try creating it")
|
||||
|
||||
updates, err := user.handleCreateMessageEvent(ctx, event.Message)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to handle update message event as create: %w", err)
|
||||
}
|
||||
|
||||
if err := waitOnIMAPUpdates(ctx, updates); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -488,6 +501,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto
|
||||
}); rerr != nil {
|
||||
user.log.WithError(err).Error("Failed to report delete message event error")
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to handle delete message event: %w", err)
|
||||
}
|
||||
|
||||
@ -500,12 +514,17 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto
|
||||
return nil
|
||||
}
|
||||
|
||||
func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.MessageEvent) ([]imap.Update, error) {
|
||||
full, err := user.client.GetFullMessage(ctx, event.Message.ID)
|
||||
func (user *User) handleCreateMessageEvent(ctx context.Context, message proton.MessageMetadata) ([]imap.Update, error) {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"messageID": message.ID,
|
||||
"subject": logging.Sensitive(message.Subject),
|
||||
}).Info("Handling message created event")
|
||||
|
||||
full, err := user.client.GetFullMessage(ctx, message.ID)
|
||||
if err != nil {
|
||||
// If the message is not found, it means that it has been deleted before we could fetch it.
|
||||
if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity {
|
||||
user.log.WithField("messageID", event.Message.ID).Warn("Cannot add new message: full message is missing on API")
|
||||
user.log.WithField("messageID", message.ID).Warn("Cannot create new message: full message is missing on API")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -513,19 +532,15 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes
|
||||
}
|
||||
|
||||
return safe.RLockRetErr(func() ([]imap.Update, error) {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"messageID": event.ID,
|
||||
"subject": logging.Sensitive(event.Message.Subject),
|
||||
}).Info("Handling message created event")
|
||||
|
||||
var update imap.Update
|
||||
if err := withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error {
|
||||
|
||||
if err := withAddrKR(user.apiUser, user.apiAddrs[message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error {
|
||||
res := buildRFC822(user.apiLabels, full, addrKR)
|
||||
|
||||
if res.err != nil {
|
||||
user.log.WithError(err).Error("Failed to build RFC822 message")
|
||||
|
||||
if err := user.vault.AddFailedMessageID(event.ID); err != nil {
|
||||
if err := user.vault.AddFailedMessageID(message.ID); err != nil {
|
||||
user.log.WithError(err).Error("Failed to add failed message ID to vault")
|
||||
}
|
||||
|
||||
@ -539,7 +554,7 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := user.vault.RemFailedMessageID(event.ID); err != nil {
|
||||
if err := user.vault.RemFailedMessageID(message.ID); err != nil {
|
||||
user.log.WithError(err).Error("Failed to remove failed message ID from vault")
|
||||
}
|
||||
|
||||
@ -555,21 +570,21 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes
|
||||
}, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock)
|
||||
}
|
||||
|
||||
func (user *User) handleUpdateMessageEvent(ctx context.Context, event proton.MessageEvent) ([]imap.Update, error) { //nolint:unparam
|
||||
func (user *User) handleUpdateMessageEvent(ctx context.Context, message proton.MessageMetadata) ([]imap.Update, error) { //nolint:unparam
|
||||
return safe.RLockRetErr(func() ([]imap.Update, error) {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"messageID": event.ID,
|
||||
"subject": logging.Sensitive(event.Message.Subject),
|
||||
"messageID": message.ID,
|
||||
"subject": logging.Sensitive(message.Subject),
|
||||
}).Info("Handling message updated event")
|
||||
|
||||
update := imap.NewMessageMailboxesUpdated(
|
||||
imap.MessageID(event.ID),
|
||||
mapTo[string, imap.MailboxID](wantLabels(user.apiLabels, event.Message.LabelIDs)),
|
||||
event.Message.Seen(),
|
||||
event.Message.Starred(),
|
||||
imap.MessageID(message.ID),
|
||||
mapTo[string, imap.MailboxID](wantLabels(user.apiLabels, message.LabelIDs)),
|
||||
message.Seen(),
|
||||
message.Starred(),
|
||||
)
|
||||
|
||||
user.updateCh[event.Message.AddressID].Enqueue(update)
|
||||
user.updateCh[message.AddressID].Enqueue(update)
|
||||
|
||||
return []imap.Update{update}, nil
|
||||
}, user.apiLabelsLock, user.updateChLock)
|
||||
@ -602,7 +617,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa
|
||||
if err != nil {
|
||||
// If the message is not found, it means that it has been deleted before we could fetch it.
|
||||
if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity {
|
||||
user.log.WithField("messageID", event.Message.ID).Warn("Cannot add new draft: full message is missing on API")
|
||||
user.log.WithField("messageID", event.Message.ID).Warn("Cannot update draft: full message is missing on API")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -640,6 +655,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa
|
||||
res.update.Literal,
|
||||
res.update.MailboxIDs,
|
||||
res.update.ParsedMessage,
|
||||
true, // Is the message doesn't exist, silently create it.
|
||||
)
|
||||
|
||||
user.updateCh[full.AddressID].Enqueue(update)
|
||||
|
||||
Reference in New Issue
Block a user