feat: use confirmer in smtp

This commit is contained in:
James Houlahan
2020-07-23 13:44:22 +02:00
parent c8f118a26b
commit 36ef9f20ae
7 changed files with 83 additions and 36 deletions

View File

@ -7,6 +7,8 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
### Changed ### Changed
* GODT-409 Set flags have to replace all flags. * GODT-409 Set flags have to replace all flags.
* GODT-531 Better way to add trusted certificate in macOS. * GODT-531 Better way to add trusted certificate in macOS.
### Fixed
* GODT-454 Fix send on closed channel when receiving unencrypted send confirmation from GUI.
## [v1.3.x] Emma (beta 2020-07-XXX) ## [v1.3.x] Emma (beta 2020-07-XXX)

View File

@ -15,8 +15,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>. // along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
// Code generated by ./credits.sh at Wed Jul 15 13:18:44 CEST 2020. DO NOT EDIT. // Code generated by ./credits.sh at Thu Jul 23 13:43:24 CEST 2020. DO NOT EDIT.
package bridge package bridge
const Credits = "github.com/0xAX/notificator;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/andybalholm/cascadia;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/jhillyerd/enmime;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;" const Credits = "github.com/0xAX/notificator;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/andybalholm/cascadia;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/jhillyerd/enmime;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"

View File

@ -24,8 +24,10 @@ import (
"github.com/ProtonMail/proton-bridge/internal/bridge" "github.com/ProtonMail/proton-bridge/internal/bridge"
"github.com/ProtonMail/proton-bridge/internal/preferences" "github.com/ProtonMail/proton-bridge/internal/preferences"
"github.com/ProtonMail/proton-bridge/pkg/config" "github.com/ProtonMail/proton-bridge/pkg/config"
"github.com/ProtonMail/proton-bridge/pkg/confirmer"
"github.com/ProtonMail/proton-bridge/pkg/listener" "github.com/ProtonMail/proton-bridge/pkg/listener"
goSMTPBackend "github.com/emersion/go-smtp" goSMTPBackend "github.com/emersion/go-smtp"
"github.com/sirupsen/logrus"
) )
type panicHandler interface { type panicHandler interface {
@ -33,12 +35,12 @@ type panicHandler interface {
} }
type smtpBackend struct { type smtpBackend struct {
panicHandler panicHandler panicHandler panicHandler
eventListener listener.Listener eventListener listener.Listener
preferences *config.Preferences preferences *config.Preferences
bridge bridger bridge bridger
shouldSendNoEncChannels map[string]chan bool confirmer *confirmer.Confirmer
sendRecorder *sendRecorder sendRecorder *sendRecorder
} }
// NewSMTPBackend returns struct implementing go-smtp/backend interface. // NewSMTPBackend returns struct implementing go-smtp/backend interface.
@ -58,12 +60,12 @@ func newSMTPBackend(
bridge bridger, bridge bridger,
) *smtpBackend { ) *smtpBackend {
return &smtpBackend{ return &smtpBackend{
panicHandler: panicHandler, panicHandler: panicHandler,
eventListener: eventListener, eventListener: eventListener,
preferences: preferences, preferences: preferences,
bridge: bridge, bridge: bridge,
shouldSendNoEncChannels: make(map[string]chan bool), confirmer: confirmer.New(),
sendRecorder: newSendRecorder(), sendRecorder: newSendRecorder(),
} }
} }
@ -103,7 +105,7 @@ func (sb *smtpBackend) shouldReportOutgoingNoEnc() bool {
} }
func (sb *smtpBackend) ConfirmNoEncryption(messageID string, shouldSend bool) { func (sb *smtpBackend) ConfirmNoEncryption(messageID string, shouldSend bool) {
if ch, ok := sb.shouldSendNoEncChannels[messageID]; ok { if err := sb.confirmer.SetResponse(messageID, shouldSend); err != nil {
ch <- shouldSend logrus.WithError(err).Error("Failed to set confirmation value")
} }
} }

View File

@ -23,11 +23,9 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io" "io"
"math/rand"
"mime" "mime"
"net/mail" "net/mail"
"regexp" "regexp"
"strconv"
"strings" "strings"
"time" "time"
@ -38,6 +36,7 @@ import (
"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"
"github.com/sirupsen/logrus"
) )
type smtpUser struct { type smtpUser struct {
@ -497,28 +496,19 @@ func (su *smtpUser) continueSendingUnencryptedMail(subject string) bool {
return true return true
} }
messageID := strconv.Itoa(rand.Int()) //nolint[gosec] // GUI should always respond in 10 seconds, but let's have safety timeout
ch := make(chan bool) // in case GUI will not respond properly. If GUI didn't respond, we cannot
su.backend.shouldSendNoEncChannels[messageID] = ch // be sure if user even saw the notice: better to not send the e-mail.
su.eventListener.Emit(events.OutgoingNoEncEvent, messageID+":"+subject) req := su.backend.confirmer.NewRequest(15 * time.Second)
log.Debug("Waiting for sendingUnencrypted confirmation for ", messageID) su.eventListener.Emit(events.OutgoingNoEncEvent, req.ID()+":"+subject)
var res bool res, err := req.Result()
select { if err != nil {
case res = <-ch: logrus.WithError(err).Error("Failed to determine whether to send unencrypted, assuming no")
// GUI should always respond in 10 seconds, but let's have safety timeout return false
// in case GUI will not respond properly. If GUI didn't respond, we cannot
// be sure if user even saw the notice: better to not send the e-mail.
log.Debug("Got sendingUnencrypted for ", messageID, ": ", res)
case <-time.After(15 * time.Second):
log.Debug("sendingUnencrypted timeout, not sending ", messageID)
res = false
} }
delete(su.backend.shouldSendNoEncChannels, messageID)
close(ch)
return res return res
} }

View File

@ -1,3 +1,20 @@
// Copyright (c) 2020 Proton Technologies AG
//
// This file is part of ProtonMail Bridge.
//
// ProtonMail 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.
//
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
package confirmer package confirmer
import ( import (
@ -6,6 +23,8 @@ import (
"time" "time"
) )
// NOTE: For now, Confirmer only supports bool values but it could easily be made generic.
type Confirmer struct { type Confirmer struct {
requests map[string]*Request requests map[string]*Request
locker sync.Locker locker sync.Locker

View File

@ -1,3 +1,20 @@
// Copyright (c) 2020 Proton Technologies AG
//
// This file is part of ProtonMail Bridge.
//
// ProtonMail 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.
//
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
package confirmer package confirmer
import ( import (

View File

@ -1,3 +1,20 @@
// Copyright (c) 2020 Proton Technologies AG
//
// This file is part of ProtonMail Bridge.
//
// ProtonMail 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.
//
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
package confirmer package confirmer
import ( import (