Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions backend/jmap/jmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"github.com/floatpane/matcha/config"
)

const jmapMailboxIds = "mailboxIds"

func init() {
backend.RegisterBackend("jmap", func(account *config.Account) (backend.Provider, error) {
return New(account)
Expand Down Expand Up @@ -167,7 +169,7 @@ func (p *Provider) FetchEmails(_ context.Context, folder string, limit, offset u
},
Properties: []string{
"id", "subject", "from", "to", "replyTo", "receivedAt",
"preview", "keywords", "mailboxIds", "hasAttachment",
"preview", "keywords", jmapMailboxIds, "hasAttachment",
"messageId", "inReplyTo", "references",
},
})
Expand Down Expand Up @@ -220,7 +222,7 @@ func (p *Provider) Search(_ context.Context, folder string, query backend.Search
},
Properties: []string{
"id", "subject", "from", "to", "replyTo", "receivedAt",
"preview", "keywords", "mailboxIds", "hasAttachment",
"preview", "keywords", jmapMailboxIds, "hasAttachment",
"messageId",
},
})
Expand Down Expand Up @@ -356,7 +358,7 @@ func (p *Provider) FetchAttachment(_ context.Context, _ string, _ uint32, partID
if err != nil {
return nil, fmt.Errorf("jmap download: %w", err)
}
defer reader.Close()
defer reader.Close() //nolint:errcheck
return io.ReadAll(reader)
}

Expand Down Expand Up @@ -419,7 +421,7 @@ func (p *Provider) DeleteEmail(_ context.Context, _ string, uid uint32) error {
req.Invoke(&email.Set{
Account: p.accountID,
Update: map[jmapclient.ID]jmapclient.Patch{
jmapID: {"mailboxIds": map[jmapclient.ID]bool{trashID: true}},
jmapID: {jmapMailboxIds: map[jmapclient.ID]bool{trashID: true}},
},
})
_, err = p.client.Do(req)
Expand All @@ -441,7 +443,7 @@ func (p *Provider) ArchiveEmail(_ context.Context, _ string, uid uint32) error {
req.Invoke(&email.Set{
Account: p.accountID,
Update: map[jmapclient.ID]jmapclient.Patch{
jmapID: {"mailboxIds": map[jmapclient.ID]bool{archiveID: true}},
jmapID: {jmapMailboxIds: map[jmapclient.ID]bool{archiveID: true}},
},
})
_, err = p.client.Do(req)
Expand All @@ -463,7 +465,7 @@ func (p *Provider) MoveEmail(_ context.Context, uid uint32, _, dstFolder string)
req.Invoke(&email.Set{
Account: p.accountID,
Update: map[jmapclient.ID]jmapclient.Patch{
jmapID: {"mailboxIds": map[jmapclient.ID]bool{dstID: true}},
jmapID: {jmapMailboxIds: map[jmapclient.ID]bool{dstID: true}},
},
})
_, err = p.client.Do(req)
Expand Down Expand Up @@ -596,7 +598,7 @@ func (p *Provider) SendEmail(_ context.Context, msg *backend.OutgoingEmail) erro
if sentID != "" {
subReq.OnSuccessUpdateEmail = map[jmapclient.ID]jmapclient.Patch{
"#sub": {
"mailboxIds": map[jmapclient.ID]bool{sentID: true},
jmapMailboxIds: map[jmapclient.ID]bool{sentID: true},
"keywords/$draft": nil,
},
}
Expand Down Expand Up @@ -690,7 +692,7 @@ func (p *Provider) lookupJMAPID(uid uint32) (jmapclient.ID, error) {
// jmapIDToUID converts a JMAP string ID to a uint32 hash for use as a UID.
func jmapIDToUID(id jmapclient.ID) uint32 {
h := fnv.New32a()
h.Write([]byte(id))
h.Write([]byte(id)) //nolint:gosec
v := h.Sum32()
if v == 0 {
v = 1
Expand Down
20 changes: 11 additions & 9 deletions backend/maildir/maildir.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package maildir

import (
"context"
"errors"
"fmt"
"io"
"mime"
Expand Down Expand Up @@ -165,7 +166,7 @@ func (p *Provider) readHeader(msg *emaildir.Message) (backend.Email, error) {
if err != nil {
return backend.Email{}, err
}
defer rc.Close()
defer rc.Close() //nolint:errcheck

entity, err := message.Read(rc)
if err != nil && entity == nil {
Expand Down Expand Up @@ -194,7 +195,7 @@ func (p *Provider) FetchEmailBody(_ context.Context, folder string, uid uint32)
if err != nil {
return "", "", nil, fmt.Errorf("maildir open: %w", err)
}
defer rc.Close()
defer rc.Close() //nolint:errcheck

return parseMessageBody(rc)
}
Expand All @@ -209,7 +210,7 @@ func (p *Provider) FetchAttachment(_ context.Context, folder string, uid uint32,
if err != nil {
return nil, fmt.Errorf("maildir open: %w", err)
}
defer rc.Close()
defer rc.Close() //nolint:errcheck

return findAttachmentData(rc, partID)
}
Expand Down Expand Up @@ -348,7 +349,7 @@ func (p *Provider) matchOpen(msg *emaildir.Message) (backend.Email, string, erro
if err != nil {
return backend.Email{}, "", err
}
defer rc.Close()
defer rc.Close() //nolint:errcheck

entity, err := message.Read(rc)
if err != nil && entity == nil {
Expand Down Expand Up @@ -552,7 +553,7 @@ func parseMessageBody(r io.Reader) (string, string, []backend.Attachment, error)

for {
part, err := mr.NextPart()
if err == io.EOF {
if errors.Is(err, io.EOF) {
break
}
if err != nil {
Expand All @@ -568,7 +569,8 @@ func parseMessageBody(r io.Reader) (string, string, []backend.Attachment, error)
continue
}

if disposition == "attachment" || (disposition == "inline" && !strings.HasPrefix(contentType, "text/")) {
switch {
case disposition == "attachment" || (disposition == "inline" && !strings.HasPrefix(contentType, "text/")):
filename := dParams["filename"]
if filename == "" {
_, cp, _ := mime.ParseMediaType(part.Header.Get("Content-Type"))
Expand All @@ -585,9 +587,9 @@ func parseMessageBody(r io.Reader) (string, string, []backend.Attachment, error)
att.ContentID = strings.Trim(cid, "<>")
}
attachments = append(attachments, att)
} else if contentType == "text/html" {
case contentType == "text/html":
htmlBody = string(data)
} else if contentType == "text/plain" && bodyText == "" {
case contentType == "text/plain" && bodyText == "":
bodyText = string(data)
}
}
Expand All @@ -608,7 +610,7 @@ func findAttachmentData(r io.Reader, targetPartID string) ([]byte, error) {
partIdx := 0
for {
part, err := mr.NextPart()
if err == io.EOF {
if errors.Is(err, io.EOF) {
break
}
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions backend/maildir/maildir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package maildir

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -238,15 +239,15 @@ func TestArchiveEmailRequiresArchiveFolder(t *testing.T) {
p := newProvider(t, root)
emails, _ := p.FetchEmails(context.Background(), "INBOX", 10, 0)
err := p.ArchiveEmail(context.Background(), "INBOX", emails[0].UID)
if err != backend.ErrNotSupported {
if !errors.Is(err, backend.ErrNotSupported) {
t.Errorf("want ErrNotSupported, got %v", err)
}
}

func TestSendEmailNotSupported(t *testing.T) {
root := makeMaildir(t)
p := newProvider(t, root)
if err := p.SendEmail(context.Background(), &backend.OutgoingEmail{}); err != backend.ErrNotSupported {
if err := p.SendEmail(context.Background(), &backend.OutgoingEmail{}); !errors.Is(err, backend.ErrNotSupported) {
t.Errorf("want ErrNotSupported, got %v", err)
}
}
Expand Down
22 changes: 12 additions & 10 deletions backend/pop3/pop3.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package pop3

import (
"context"
"errors"
"fmt"
"io"
"mime"
Expand Down Expand Up @@ -78,7 +79,7 @@ func (p *Provider) connect() (*pop3client.Conn, error) {
}

if err := conn.Auth(p.account.Email, p.account.Password); err != nil {
conn.Quit()
_ = conn.Quit()
return nil, fmt.Errorf("pop3 auth: %w", err)
}

Expand All @@ -90,7 +91,7 @@ func (p *Provider) FetchEmails(_ context.Context, _ string, limit, offset uint32
if err != nil {
return nil, err
}
defer conn.Quit()
defer conn.Quit() //nolint:errcheck

// Get message list with UIDs
msgs, err := conn.Uidl(0)
Expand Down Expand Up @@ -139,7 +140,7 @@ func (p *Provider) FetchEmailBody(_ context.Context, _ string, uid uint32) (stri
if err != nil {
return "", "", nil, err
}
defer conn.Quit()
defer conn.Quit() //nolint:errcheck

msgID, err := p.findMessageByUID(conn, uid)
if err != nil {
Expand All @@ -159,7 +160,7 @@ func (p *Provider) FetchAttachment(_ context.Context, _ string, uid uint32, part
if err != nil {
return nil, err
}
defer conn.Quit()
defer conn.Quit() //nolint:errcheck

msgID, err := p.findMessageByUID(conn, uid)
if err != nil {
Expand Down Expand Up @@ -212,7 +213,7 @@ func (p *Provider) DeleteEmails(_ context.Context, _ string, uids []uint32) erro

messageIDsByUID, err := p.buildMessageIDsByUID(conn)
if err != nil {
conn.Quit()
_ = conn.Quit()
return err
}

Expand Down Expand Up @@ -415,7 +416,7 @@ func parseMessageBody(r io.Reader) (string, string, []backend.Attachment, error)

for {
part, err := mr.NextPart()
if err == io.EOF {
if errors.Is(err, io.EOF) {
break
}
if err != nil {
Expand All @@ -431,7 +432,8 @@ func parseMessageBody(r io.Reader) (string, string, []backend.Attachment, error)
continue
}

if disposition == "attachment" || (disposition == "inline" && !strings.HasPrefix(contentType, "text/")) {
switch {
case disposition == "attachment" || (disposition == "inline" && !strings.HasPrefix(contentType, "text/")):
filename := dParams["filename"]
if filename == "" {
_, cp, _ := mime.ParseMediaType(part.Header.Get("Content-Type"))
Expand All @@ -448,9 +450,9 @@ func parseMessageBody(r io.Reader) (string, string, []backend.Attachment, error)
att.ContentID = strings.Trim(cid, "<>")
}
attachments = append(attachments, att)
} else if contentType == "text/html" {
case contentType == "text/html":
htmlBody = string(data)
} else if contentType == "text/plain" && bodyText == "" {
case contentType == "text/plain" && bodyText == "":
bodyText = string(data)
}
}
Expand All @@ -472,7 +474,7 @@ func findAttachmentData(r io.Reader, targetPartID string) ([]byte, error) {
var scanErr error
for {
part, err := mr.NextPart()
if err == io.EOF {
if errors.Is(err, io.EOF) {
break
}
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion calendar/calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func GenerateRSVP(originalData []byte, userEmail, response string) ([]byte, erro
// Attendee not found in original - add ourselves with full parameters
vevent.AddAttendee("mailto:"+userEmail,
ics.WithRSVP(true),
ics.ParticipationStatus(ics.ParticipationStatusNeedsAction),
ics.ParticipationStatusNeedsAction,
ics.CalendarUserTypeIndividual,
ics.ParticipationRoleReqParticipant,
)
Expand Down
4 changes: 2 additions & 2 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
name := args[0]
// Add .lua extension if not present
if filepath.Ext(name) != ".lua" {
name = name + ".lua"
name += ".lua"
}
target = filepath.Join(home, ".config", "matcha", "plugins", name)
}
Expand All @@ -35,7 +35,7 @@
return fmt.Errorf("file not found: %s", target)
}

cmd := exec.Command(editor, target)
cmd := exec.Command(editor, target) //nolint:gosec,noctx

Check failure

Code scanning / gosec

Command injection via taint analysis Error

Command injection via taint analysis
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Expand Down
2 changes: 1 addition & 1 deletion cli/contacts_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func runExportContacts(format, outputPath string, noHeader bool) error {
if outputPath != "" {
dir := filepath.Dir(outputPath)
if dir != "." {
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0750); err != nil {
return fmt.Errorf("failed to create output directory: %w", err)
}
}
Expand Down
8 changes: 4 additions & 4 deletions cli/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") {
// Download from URL
client := httpclient.New(httpclient.InstallTimeout)
resp, err := client.Get(source)
resp, err := client.Get(source) //nolint:noctx
if err != nil {
return fmt.Errorf("failed to download: %w", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("download returned status %d", resp.StatusCode)
Expand Down Expand Up @@ -62,7 +62,7 @@
}

dest := filepath.Join(pluginsDir, filename)
if err := os.WriteFile(dest, data, 0644); err != nil {
if err := os.WriteFile(dest, data, 0644); err != nil { //nolint:gosec

Check failure

Code scanning / gosec

Path traversal via taint analysis Error

Path traversal via taint analysis
return fmt.Errorf("failed to write plugin: %w", err)
}

Expand All @@ -76,7 +76,7 @@
return "", fmt.Errorf("cannot find home directory: %w", err)
}
dir := filepath.Join(home, ".config", "matcha", "plugins")
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0750); err != nil {
return "", fmt.Errorf("cannot create plugins directory: %w", err)
}
return dir, nil
Expand Down
Loading
Loading