M command.go +8 -3
@@ 116,7 116,12 @@ func ViewPart(dst io.Writer, msg *mail.M
return parse(msg, partPrinter)
}
-func newPlainTextPrinter(dst io.Writer, t transform.Transformer) func(part, int) error {
+func anno(w io.Writer, p part, no int) error {
+ _, err := fmt.Fprintf(w, "[MIME Part %d: %s]\n", no, p.Header.Get("Content-Type"))
+ return err
+}
+
+func newPlainTextPrinter(dst io.Writer, t transform.Transformer, anno func(io.Writer, part, int) error) func(part, int) error {
return func(p part, no int) error {
// todo: if the msg has no content type header, this will return "mime: no media type"
mt, _, err := mime.ParseMediaType(p.Header.Get("Content-Type"))
@@ 131,7 136,7 @@ func newPlainTextPrinter(dst io.Writer,
_, err = io.Copy(dst, transform.NewReader(in, t))
return err
}
- if _, err = fmt.Fprintf(dst, "[MIME Part %d: %s]\n", no, p.Header.Get("Content-Type")); err != nil {
+ if err = anno(dst, p, no); err != nil {
return err
}
// process the stream (by throwing it away), as it is replaced by the string above
@@ 151,7 156,7 @@ func View(dst io.Writer, msg *mail.Messa
if _, err := io.Copy(dst, &b); err != nil {
return err
}
- return parse(msg, newPlainTextPrinter(dst, transform.Nop))
+ return parse(msg, newPlainTextPrinter(dst, transform.Nop, anno))
}
func Send(msg *mail.Message) error {
M edit.go +1 -1
@@ 260,7 260,7 @@ func fmtReply(dst io.Writer, sender stri
parseAddressList(h.Get("From"))); err != nil {
return err
}
- if err := parse(msg, newPlainTextPrinter(dst, "eMessage{true})); err != nil {
+ if err := parse(msg, newPlainTextPrinter(dst, "eMessage{true}, anno)); err != nil {
return err
}
}
M mailbox.go +1 -0
@@ 8,6 8,7 @@ import (
type Message interface {
Id() int64
Header() mail.Header
+ Body() io.Reader
}
type Mailbox interface {
M mh.go +5 -0
@@ 1,6 1,7 @@
package mailbox
import (
+ "io"
"net/mail"
"bitbucket.org/telesto/mailbox/mh"
@@ 27,6 28,10 @@ func (mbox mhMessage) Header() mail.Head
return mbox.Message.Header
}
+func (mbox mhMessage) Body() io.Reader {
+ return mbox.Message.Body
+}
+
func (mb mhMailbox) ReadFolder(folder string) ([]Message, error) {
mhMsgs, err := mb.Mailbox.ReadFolder(folder)
if mhMsgs == nil {
M mh/mh.go +6 -4
@@ 28,7 28,7 @@ const (
type Message struct {
Id int64
- mail.Header
+ *mail.Message
}
type Mailbox struct {
@@ 124,7 124,7 @@ func (mbox Mailbox) ReadFolder(folder st
mails = append(mails, errMail(list[i].Id, err1))
continue
}
- mails = append(mails, &Message{list[i].Id, msg.Header})
+ mails = append(mails, &Message{list[i].Id, msg})
}
return mails, err
}
@@ 154,8 154,10 @@ func (mh *Mailbox) Append(folder string,
}
func errMail(id int64, err error) *Message {
- m := Message{id, make(map[string][]string, 1)}
- m.Header["Subject"] = []string{"Error: " + err.Error()}
+ h := make(map[string][]string, 1)
+ h["Subject"] = []string{"Error: " + err.Error()}
+ b := strings.NewReader("Error: " + err.Error())
+ m := Message{id, &mail.Message{h, b}}
return &m
}
M sequence.go +32 -29
@@ 78,43 78,46 @@ func (s Regexp) Matches(m Message) bool
if !s.matchBody {
return false
}
- return false
+ return s.r.MatchReader(&readRune{reader: m.Body()})
}
func ParseRegexp(s string) (*Regexp, error) {
- ss := strings.Split(s, ":")
- if len(ss) > 2 {
- return nil, errors.New("invalid parameter")
+ i := strings.Index(s, ":")
+ keys := "All"
+ regexp := s
+ if i >= 0 {
+ keys = s[:i]
+ regexp = s[i+1:]
+ }
+ if keys == "All" {
+ // match header and body
+ keys = "Header,Body"
}
- var keys string
- regexp := ss[0]
- if len(ss) == 2 {
- keys = ss[0]
- regexp = ss[1]
+ m := make(map[string]struct{})
+ // todo: don't use closure here
+ hm := func(key string) bool {
+ _, ok := m[key]
+ return ok
+ }
+ var matchBody bool
+ for _, key := range strings.Split(keys, ",") {
+ switch key {
+ case "Body":
+ matchBody = true
+ case "Header":
+ hm = func(string) bool {
+ return true
+ }
+ default:
+ m[key] = struct{}{}
+ }
}
r, err := rgxp.Compile(regexp)
if err != nil {
- return nil, err
- }
- if len(keys) == 0 {
- // match everything
- return &Regexp{func(string) bool {
- return true
- }, true, r}, nil
+ return nil, errors.New(regexp + ": " + err.Error())
}
- m := make(map[string]struct{})
- var matchBody bool
- for _, key := range strings.Split(keys, ",") {
- m[key] = struct{}{}
- if key == "body" {
- matchBody = true
- }
- }
- // todo: don't use closure here
- return &Regexp{func(key string) bool {
- _, ok := m[key]
- return ok
- }, matchBody, r}, nil
+ // todo: decode
+ return &Regexp{hm, matchBody, r}, nil
}
// readRune is a structure to enable reading UTF-8 encoded code points