commit - 63edc7a0589cf429104cdf23b74fb7f281501865
commit + e9e55ec0fc4f4626523dc296d3ccec82a3cef5da
blob - /dev/null
blob + 1bea1598d7abd918d1f17ff330fb03fe5695c3d6 (mode 644)
--- /dev/null
+++ src/sieve/sieve.go
+// Package sieve provides a client of the ManageSieve protocol
+// specified in RFC 5804.
+package sieve
+
+import (
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "net/textproto"
+ "os"
+ "strings"
+)
+
+const DefaultPort int = 4190
+
+func Dial(net, addr string) (*textproto.Conn, error) {
+ conn, err := textproto.Dial(net, addr)
+ if err != nil {
+ return nil, err
+ }
+ for i := 0; i <= 10; i++ {
+ line, err := conn.ReadLine()
+ if err != nil {
+ return nil, err
+ }
+ fmt.Fprintln(os.Stderr, line)
+ if strings.HasPrefix(line, "OK") {
+ break
+ }
+ }
+ return conn, nil
+}
+
+// Logout sends the LOGOUT command and closes conn.
+// Implementations should not use conn afterwards.
+func Logout(conn *textproto.Conn) error {
+ id, err := conn.Cmd("LOGOUT")
+ if err != nil {
+ return err
+ }
+ conn.StartResponse(id)
+ defer conn.EndResponse(id)
+ line, err := conn.ReadLine()
+ if err != nil {
+ return err
+ }
+ code, msg, found := strings.Cut(line, " ")
+ if code != "OK" {
+ if !found {
+ return fmt.Errorf("logout failed with no message")
+ }
+ return errors.New(msg)
+ }
+ return conn.Close()
+}
+
+func Noop(conn *textproto.Conn) error {
+ id, err := conn.Cmd("NOOP")
+ if err != nil {
+ return err
+ }
+ conn.StartResponse(id)
+ defer conn.EndResponse(id)
+ line, err := conn.ReadLine()
+ if err != nil {
+ return err
+ }
+ code, msg, found := strings.Cut(line, " ")
+ if code != "OK" {
+ if !found {
+ return fmt.Errorf("noop failed with no message")
+ }
+ return errors.New(msg)
+ }
+ return nil
+}
+
+func StartTLS(conn *textproto.Conn, config *tls.Config) error {
+ id, err := conn.Cmd("STARTTLS")
+ if err != nil {
+ return err
+ }
+ conn.StartResponse(id)
+ defer conn.EndResponse(id)
+ line, err := conn.ReadLine()
+ if err != nil {
+ return err
+ }
+ code, msg, found := strings.Cut(line, " ")
+ if code != "OK" {
+ if !found {
+ return fmt.Errorf("starttls failed with no message")
+ }
+ return errors.New(msg)
+ }
+ return errors.New("TODO not yet implemented")
+}
blob - /dev/null
blob + 7d961d3003d0e78beedd166867bae90bce8ad938 (mode 644)
--- /dev/null
+++ src/sieve/sieve_test.go
+package sieve
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestDial(t *testing.T) {
+ addr := fmt.Sprintf("imap.migadu.com:%d", DefaultPort)
+ conn, err := Dial("tcp", addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ conn.Close()
+}