aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-07-02 16:08:04 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-07-02 16:08:04 +0200
commiteb1cda04f372c32e5e0765783fad09429138408c (patch)
tree57de9bf53dbf62b9897b8198fac8f41158ab7142 /pkg
parent233bc790fcdf4bc657a5949bd63d0a9db019cf42 (diff)
pkg/email: add function that forms reply to an email
Diffstat (limited to 'pkg')
-rw-r--r--pkg/email/parser.go4
-rw-r--r--pkg/email/reply.go42
-rw-r--r--pkg/email/reply_test.go87
3 files changed, 132 insertions, 1 deletions
diff --git a/pkg/email/parser.go b/pkg/email/parser.go
index 42a890472..a764a5826 100644
--- a/pkg/email/parser.go
+++ b/pkg/email/parser.go
@@ -27,6 +27,8 @@ type Email struct {
CommandArgs []string // arguments for the command
}
+const commandPrefix = "#syzbot "
+
func Parse(r io.Reader, ownEmail string) (*Email, error) {
msg, err := mail.ReadMessage(r)
if err != nil {
@@ -112,7 +114,7 @@ func extractBugID(from, canonical string) string {
// Commands are of the following form:
// ^#syzbot cmd args...
func extractCommand(body []byte) (cmd string, args []string) {
- cmdPos := bytes.Index(append([]byte{'\n'}, body...), []byte("\n#syzbot "))
+ cmdPos := bytes.Index(append([]byte{'\n'}, body...), []byte("\n"+commandPrefix))
if cmdPos == -1 {
return
}
diff --git a/pkg/email/reply.go b/pkg/email/reply.go
new file mode 100644
index 000000000..65aec4509
--- /dev/null
+++ b/pkg/email/reply.go
@@ -0,0 +1,42 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package email
+
+import (
+ "bufio"
+ "bytes"
+ "strings"
+)
+
+func FormReply(email, reply string) string {
+ s := bufio.NewScanner(strings.NewReader(email))
+ out := new(bytes.Buffer)
+ replied := false
+ for s.Scan() {
+ ln := s.Bytes()
+ out.WriteByte('>')
+ if len(ln) != 0 && ln[0] != '>' {
+ out.WriteByte(' ')
+ }
+ out.Write(ln)
+ out.WriteByte('\n')
+ if !replied && bytes.HasPrefix(ln, []byte(commandPrefix)) {
+ replied = true
+ writeReply(out, reply)
+ }
+ }
+ if !replied {
+ writeReply(out, reply)
+ }
+ return out.String()
+}
+
+func writeReply(out *bytes.Buffer, reply string) {
+ out.WriteByte('\n')
+ out.WriteString(reply)
+ if reply != "" && reply[len(reply)-1] != '\n' {
+ out.WriteByte('\n')
+ }
+ out.WriteByte('\n')
+}
diff --git a/pkg/email/reply_test.go b/pkg/email/reply_test.go
new file mode 100644
index 000000000..2dd9d894d
--- /dev/null
+++ b/pkg/email/reply_test.go
@@ -0,0 +1,87 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package email
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestFormReply(t *testing.T) {
+ for i, test := range formReplyTests {
+ t.Run(fmt.Sprint(i), func(t *testing.T) {
+ result := FormReply(test.email, test.reply)
+ if test.result != result {
+ t.Logf("expect:\n%s", test.result)
+ t.Logf("got:\n%s", result)
+ t.Fail()
+ }
+ })
+ }
+}
+
+var formReplyTests = []struct {
+ email string
+ reply string
+ result string
+}{
+ {
+ email: `line1
+line2
+#syzbot foo
+line3
+`,
+ reply: "this is reply",
+ result: `> line1
+> line2
+> #syzbot foo
+
+this is reply
+
+> line3
+`,
+ },
+ {
+ email: `> line1
+> line2
+#syzbot foo
+line3
+`,
+ reply: "this is reply\n",
+ result: `>> line1
+>> line2
+> #syzbot foo
+
+this is reply
+
+> line3
+`,
+ },
+ {
+ email: `line1
+line2
+#syzbot foo`,
+ reply: "this is reply 1\nthis is reply 2",
+ result: `> line1
+> line2
+> #syzbot foo
+
+this is reply 1
+this is reply 2
+
+`,
+ },
+ {
+ email: `line1
+line2
+`,
+ reply: "this is reply",
+ result: `> line1
+> line2
+
+this is reply
+
+`,
+ },
+}