Skip to content

Commit

Permalink
Merge pull request #4 from abligh/imap4flags
Browse files Browse the repository at this point in the history
Add support for Imap4flags
  • Loading branch information
foxcpp authored Jan 27, 2024
2 parents 44be6d3 + 006cbb3 commit 2e76e3e
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 4 deletions.
2 changes: 2 additions & 0 deletions cmd/sieve-run/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"log"
"net/textproto"
"os"
"strings"
"time"

"github.com/foxcpp/go-sieve"
Expand Down Expand Up @@ -76,4 +77,5 @@ func main() {
fmt.Println("redirect:", data.RedirectAddr)
fmt.Println("fileinfo:", data.Mailboxes)
fmt.Println("keep:", data.ImplicitKeep || data.Keep)
fmt.Printf("flags: %s\n", strings.Join(data.Flags, " "))
}
126 changes: 126 additions & 0 deletions execute_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package sieve

import (
"bufio"
"context"
"net/textproto"
"reflect"
"strings"
"testing"

"github.com/foxcpp/go-sieve/interp"
)

var eml string = `Date: Tue, 1 Apr 1997 09:06:31 -0800 (PST)
From: [email protected]
To: [email protected]
Subject: I have a present for you
Look, I'm sorry about the whole anvil thing, and I really
didn't mean to try and drop it on you from the top of the
cliff. I want to try to make it up to you. I've got some
great birdseed over here at my place--top of the line
stuff--and if you come by, I'll have it all wrapped up
for you. I'm really sorry for all the problems I've caused
for you over the years, but I know we can work this out.
--
Wile E. Coyote "Super Genius" [email protected]
`

type result struct {
redirect []string
fileinto []string
implicitKeep bool
keep bool
flags []string
}

func testExecute(t *testing.T, in string, eml string, intendedResult result) {
t.Run("case", func(t *testing.T) {

msgHdr, err := textproto.NewReader(bufio.NewReader(strings.NewReader(eml))).ReadMIMEHeader()
if err != nil {
t.Fatal(err)
}

script := bufio.NewReader(strings.NewReader(in))

loadedScript, err := Load(script, DefaultOptions())
if err != nil {
t.Fatal(err)
}
data := interp.NewRuntimeData(loadedScript, interp.Callback{
RedirectAllowed: func(ctx context.Context, d *interp.RuntimeData, addr string) (bool, error) {
return true, nil
},
HeaderGet: func(key string) (string, bool, error) {
vals, ok := msgHdr[key]
if !ok {
return "", false, nil
}
return vals[0], true, nil
},
})
data.MessageSize = len(eml)
data.SMTP.From = "[email protected]"
data.SMTP.To = "[email protected]"

ctx := context.Background()
if err := loadedScript.Execute(ctx, data); err != nil {
t.Fatal(err)
}

r := result{
redirect: data.RedirectAddr,
fileinto: data.Mailboxes,
keep: data.Keep,
implicitKeep: data.ImplicitKeep,
flags: data.Flags,
}

if !reflect.DeepEqual(r, intendedResult) {
t.Log("Wrong Execute output")
t.Log("Actual: ", r)
t.Log("Expected:", intendedResult)
t.Fail()
}
})
}

func TestFileinto(t *testing.T) {
testExecute(t, `require ["fileinto"];
fileinto "test";
`, eml,
result{
fileinto: []string{"test"},
})
testExecute(t, `require ["fileinto"];
fileinto "test";
fileinto "test2";
`, eml,
result{
fileinto: []string{"test", "test2"},
})
}

func TestFlags(t *testing.T) {
testExecute(t, `require ["fileinto", "imap4flags"];
setflag ["flag1", "flag2"];
addflag ["flag2", "flag3"];
removeflag ["flag1"];
fileinto "test";
`, eml,
result{
fileinto: []string{"test"},
flags: []string{"flag2", "flag3"},
})
testExecute(t, `require ["fileinto", "imap4flags"];
addflag ["flag2", "flag3"];
removeflag ["flag3", "flag4"];
fileinto "test";
`, eml,
result{
fileinto: []string{"test"},
flags: []string{"flag2"},
})
}
52 changes: 51 additions & 1 deletion interp/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func (c CmdStop) Execute(ctx context.Context, d *RuntimeData) error {

type CmdFileInto struct {
Mailbox string
Flags *Flags
}

func (c CmdFileInto) Execute(ctx context.Context, d *RuntimeData) error {
Expand All @@ -27,6 +28,9 @@ func (c CmdFileInto) Execute(ctx context.Context, d *RuntimeData) error {
}
d.Mailboxes = append(d.Mailboxes, c.Mailbox)
d.ImplicitKeep = false
if c.Flags != nil {
d.Flags = *canonicalFlags(make([]string, len(*c.Flags)), nil, d.FlagAliases)
}
return nil
}

Expand All @@ -53,16 +57,62 @@ func (c CmdRedirect) Execute(ctx context.Context, d *RuntimeData) error {
return nil
}

type CmdKeep struct{}
type CmdKeep struct {
Flags *Flags
}

func (c CmdKeep) Execute(_ context.Context, d *RuntimeData) error {
d.Keep = true
if c.Flags != nil {
d.Flags = *canonicalFlags(make([]string, len(*c.Flags)), nil, d.FlagAliases)
}
return nil
}

type CmdDiscard struct{}

func (c CmdDiscard) Execute(_ context.Context, d *RuntimeData) error {
d.ImplicitKeep = false
d.Flags = make([]string, 0)
return nil
}

type CmdSetFlag struct {
Flags *Flags
}

func (c CmdSetFlag) Execute(_ context.Context, d *RuntimeData) error {
if c.Flags != nil {
d.Flags = *canonicalFlags(*c.Flags, nil, d.FlagAliases)
}
return nil
}

type CmdAddFlag struct {
Flags *Flags
}

func (c CmdAddFlag) Execute(_ context.Context, d *RuntimeData) error {
if c.Flags != nil {
if d.Flags == nil {
d.Flags = make([]string, len(*c.Flags))
copy(d.Flags, *c.Flags)
} else {
// Use canonicalFlags to remove duplicates
d.Flags = *canonicalFlags(append(d.Flags, *c.Flags...), nil, d.FlagAliases)
}
}
return nil
}

type CmdRemoveFlag struct {
Flags *Flags
}

func (c CmdRemoveFlag) Execute(_ context.Context, d *RuntimeData) error {
if c.Flags != nil {
// Use canonicalFlags to remove duplicates
d.Flags = *canonicalFlags(d.Flags, c.Flags, d.FlagAliases)
}
return nil
}
9 changes: 7 additions & 2 deletions interp/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
)

var supportedExtensions = map[string]struct{}{
"fileinto": {},
"envelope": {},
"fileinto": {},
"envelope": {},
"imap4flags": {},
}

var (
Expand All @@ -32,6 +33,10 @@ func init() {
"redirect": loadRedirect,
"keep": loadKeep,
"discard": loadDiscard,
// RFC 5232 Actions
"setflag": loadSetFlag, // imap4flags extension
"addflag": loadAddFlag, // imap4flags extension
"removeflag": loadRemoveFlag, // imap4flags extension
}
tests = map[string]func(*Script, parser.Test) (Test, error){
// RFC 5228 Tests
Expand Down
Loading

0 comments on commit 2e76e3e

Please sign in to comment.