blob: 838d082228b6e012b25020efd640cbbd1a8751c9 [file] [log] [blame]
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dashboard
// This file handles receiving mail.
import (
"net/http"
"net/mail"
"regexp"
"time"
"appengine"
"appengine/datastore"
)
func init() {
http.HandleFunc("/_ah/mail/", handleMail)
}
var subjectRegexp = regexp.MustCompile(`.*code review (\d+):.*`)
func handleMail(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
defer r.Body.Close()
msg, err := mail.ReadMessage(r.Body)
if err != nil {
c.Errorf("mail.ReadMessage: %v", err)
return
}
subj := msg.Header.Get("Subject")
m := subjectRegexp.FindStringSubmatch(subj)
if len(m) != 2 {
c.Debugf("Subject %q did not match /%v/", subj, subjectRegexp)
return
}
c.Infof("Found issue %q", m[1])
// Track the MessageID.
key := datastore.NewKey(c, "CL", m[1], 0, nil)
err = datastore.RunInTransaction(c, func(c appengine.Context) error {
cl := new(CL)
err := datastore.Get(c, key, cl)
if err != nil && err != datastore.ErrNoSuchEntity {
return err
}
if err == datastore.ErrNoSuchEntity {
// Must set sentinel values for time.Time fields
// if this is a new entity.
cl.Created = time.Unix(0, 0)
cl.Modified = time.Unix(0, 0)
}
cl.LastMessageID = msg.Header.Get("Message-ID")
_, err = datastore.Put(c, key, cl)
return err
}, nil)
if err != nil {
c.Errorf("datastore transaction failed: %v", err)
}
// Update the CL after a delay to give Rietveld a chance to catch up.
UpdateCLLater(c, m[1], 10*time.Second)
}