diff -rN -u old-upstream-buildbot-mirror/buildbot/status/mail.py new-upstream-buildbot-mirror/buildbot/status/mail.py
--- old-upstream-buildbot-mirror/buildbot/status/mail.py	2008-04-29 15:02:10.000000000 -0400
+++ new-upstream-buildbot-mirror/buildbot/status/mail.py	2008-04-29 15:02:10.000000000 -0400
@@ -63,7 +63,8 @@
                  addLogs=False, relayhost="localhost",
                  subject="buildbot %(result)s in %(projectName)s on %(builder)s",
                  lookup=None, extraRecipients=[],
-                 sendToInterestedUsers=True):
+                 sendToInterestedUsers=True,
+                 messageGenerator=None):
         """
         @type  fromaddr: string
         @param fromaddr: the email address to be used in the 'From' header.
@@ -127,6 +128,17 @@
                           example, lookup='twistedmatrix.com' will allow mail
                           to be sent to all developers whose SVN usernames
                           match their twistedmatrix.com account names.
+        @type  messageGenerator: callable
+        @param messageGenerator: Normally the message sent with a MailNotifier
+                                 is built with MailNotifier.buildMessageBody.
+                                 You may optionally use an alternative function.
+                                 The signature of it should be as follows:
+                                  func(builderName, mailNotifierMode,
+                                       results, IBuildStatus, IStatus)
+                                 where results is one of (SUCCESS, WARNINGS,
+                                 FAILURE, SKIPPED, EXCEPTION). It should return
+                                 a string that will be used as the body of the
+                                 message sent by MailNotifier.
         """
 
         base.StatusReceiverMultiService.__init__(self)
@@ -151,6 +163,8 @@
         self.lookup = lookup
         self.watched = []
         self.status = None
+        assert messageGenerator is None or callable(messageGenerator)
+        self.messageGenerator = messageGenerator
 
         # you should either limit on builders or categories, not both
         if self.builders != None and self.categories != None:
@@ -216,31 +230,30 @@
         # rearrange this.
         return self.buildMessage(name, build, results)
 
-    def buildMessage(self, name, build, results):
+    def buildMessageBody(self, name, mode, results, build, masterStatus):
         projectName = self.status.getProjectName()
         text = ""
-        if self.mode == "all":
+        if mode == "all":
             text += "The Buildbot has finished a build"
-        elif self.mode == "failing":
+        elif mode == "failing":
             text += "The Buildbot has detected a failed build"
         elif self.mode == "passing":
             text += "The Buildbot has detected a passing build"
         else:
             text += "The Buildbot has detected a new failure"
         text += " of %s on %s.\n" % (name, projectName)
-        buildurl = self.status.getURLForThing(build)
+        buildurl = masterStatus.getURLForThing(build)
         if buildurl:
             text += "Full details are available at:\n %s\n" % buildurl
         text += "\n"
 
-        url = self.status.getBuildbotURL()
+        url = masterStatus.getBuildbotURL()
         if url:
             text += "Buildbot URL: %s\n\n" % urllib.quote(url, '/:')
 
         text += "Buildslave for this Build: %s\n\n" % build.getSlavename()
         text += "Build Reason: %s\n" % build.getReason()
 
-        patch = None
         ss = build.getSourceStamp()
         if ss is None:
             source = "unavailable"
@@ -254,7 +267,6 @@
                 source += "HEAD"
             if ss.patch is not None:
                 source += " (plus patch)"
-                patch = ss.patch
         text += "Build Source Stamp: %s\n" % source
 
         text += "Blamelist: %s\n" % ",".join(build.getResponsibleUsers())
@@ -270,16 +282,10 @@
 
         if results == SUCCESS:
             text += "Build succeeded!\n"
-            res = "success"
         elif results == WARNINGS:
             text += "Build Had Warnings%s\n" % t
-            res = "warnings"
         else:
             text += "BUILD FAILED%s\n" % t
-            res = "failure"
-
-        if self.addLogs and build.getLogs():
-            text += "Logs are attached.\n"
 
         # TODO: it would be nice to provide a URL for the specific build
         # here. That involves some coordination with html.Waterfall .
@@ -293,6 +299,35 @@
         text += " -The Buildbot\n"
         text += "\n"
 
+        return text
+
+    def buildMessage(self, name, build, results):
+        projectName = self.status.getProjectName()
+
+        text = ""
+        if self.messageGenerator:
+            text = self.messageGenerator(name, self.mode, results, build,
+                                         self.status)
+        else:
+            text = self.buildMessageBody(name, self.mode, results, build,
+                                         self.status)
+
+        if self.addLogs and build.getLogs():
+            text += "P.S. Logs are attached"
+
+        patch = None
+        ss = build.getSourceStamp()
+        if ss and ss.patch:
+            patch = ss.patch
+
+        res = ""
+        if results == SUCCESS:
+            res = "success"
+        elif results == WARNINGS:
+            res = "warnings"
+        else:
+            res = "failure"
+
         haveAttachments = False
         if patch or self.addLogs:
             haveAttachments = True


