Other(refactor): Use normal value + mutex for user.updateCh
This commit is contained in:
@ -18,21 +18,17 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/gluon/rfc822"
|
||||
"github.com/ProtonMail/go-rfc5322"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/safe"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/vault"
|
||||
"github.com/ProtonMail/proton-bridge/v2/pkg/message"
|
||||
"github.com/ProtonMail/proton-bridge/v2/pkg/message/parser"
|
||||
@ -42,107 +38,6 @@ import (
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
func (user *User) sendMail(authID string, emails []string, from string, to []string, r io.Reader) error { //nolint:funlen
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Read the message to send.
|
||||
b, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read message: %w", err)
|
||||
}
|
||||
|
||||
// Compute the hash of the message (to match it against SMTP messages).
|
||||
hash, err := getMessageHash(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if we already tried to send this message recently.
|
||||
if ok, err := user.sendHash.tryInsertWait(ctx, hash, to, time.Now().Add(90*time.Second)); err != nil {
|
||||
return fmt.Errorf("failed to check send hash: %w", err)
|
||||
} else if !ok {
|
||||
user.log.Warn("A duplicate message was already sent recently, skipping")
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we fail to send this message, we should remove the hash from the send recorder.
|
||||
defer user.sendHash.removeOnFail(hash)
|
||||
|
||||
// Create a new message parser from the reader.
|
||||
parser, err := parser.New(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create parser: %w", err)
|
||||
}
|
||||
|
||||
// If the message contains a sender, use it instead of the one from the return path.
|
||||
if sender, ok := getMessageSender(parser); ok {
|
||||
from = sender
|
||||
}
|
||||
|
||||
// Load the user's mail settings.
|
||||
settings, err := user.client.GetMailSettings(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get mail settings: %w", err)
|
||||
}
|
||||
|
||||
return safe.LockRet(func() error {
|
||||
addrID, err := getAddrID(user.apiAddrs, from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return withAddrKR(user.apiUser, user.apiAddrs[addrID], user.vault.KeyPass(), func(userKR, addrKR *crypto.KeyRing) error {
|
||||
// Use the first key for encrypting the message.
|
||||
addrKR, err := addrKR.FirstKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get first key: %w", err)
|
||||
}
|
||||
|
||||
// If we have to attach the public key, do it now.
|
||||
if settings.AttachPublicKey == liteapi.AttachPublicKeyEnabled {
|
||||
key, err := addrKR.GetKey(0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get sending key: %w", err)
|
||||
}
|
||||
|
||||
pubKey, err := key.GetArmoredPublicKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get public key: %w", err)
|
||||
}
|
||||
|
||||
parser.AttachPublicKey(pubKey, fmt.Sprintf("publickey - %v - %v", addrKR.GetIdentities()[0].Name, key.GetFingerprint()[:8]))
|
||||
}
|
||||
|
||||
// Parse the message we want to send (after we have attached the public key).
|
||||
message, err := message.ParseWithParser(parser)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse message: %w", err)
|
||||
}
|
||||
|
||||
// Send the message using the correct key.
|
||||
sent, err := sendWithKey(
|
||||
ctx,
|
||||
user.client,
|
||||
authID,
|
||||
user.vault.AddressMode(),
|
||||
settings,
|
||||
userKR, addrKR,
|
||||
emails, from, to,
|
||||
message,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send message: %w", err)
|
||||
}
|
||||
|
||||
// If the message was successfully sent, we can update the message ID in the record.
|
||||
user.sendHash.addMessageID(hash, sent.ID)
|
||||
|
||||
return nil
|
||||
})
|
||||
}, &user.apiUserLock, &user.apiAddrsLock)
|
||||
}
|
||||
|
||||
// sendWithKey sends the message with the given address key.
|
||||
func sendWithKey( //nolint:funlen
|
||||
ctx context.Context,
|
||||
|
||||
Reference in New Issue
Block a user