Roundup Tracker

Attachment 'darcs-messages_as_mbox.py'

Download

   1 from roundup.cgi.actions import Action
   2 from email.message import Message
   3 from email.mime.text import MIMEText
   4 from email.mime.multipart import MIMEMultipart
   5 from email.encoders import encode_base64
   6 
   7 class MboxAction(Action):
   8     ## These get set in handle() by a dirty hack (see "setattr").
   9     activity = None             # issue / patch
  10     actor = None                # issue / patch
  11     assignedto = None           # issue / patch (used)
  12     creation = None             # issue / patch
  13     creator = None              # issue / patch
  14     darcswatchurl = None        # patch
  15     messages = None             # issue / patch (used)
  16     nosy = None                 # issue / patch (used)
  17     priority = None             # issue (used)
  18     status = None               # issue / patch (used)
  19     title = None                # issue / patch (used)
  20     topic = None                # issue (used)
  21 
  22     def handle(self):
  23         if self.classname != "issue" and self.classname != "patch":
  24             raise ValueError, "Only an issue or patch can become an mbox."
  25         if self.nodeid is None:
  26             raise ValueError, "Cannot iterate over multiple issues at once."
  27 
  28         ## This saves typing later.  It's naughty, because AFAICT
  29         ## self.db.issue.get() does some extra magic that isn't
  30         ## reproduced here.
  31         for (key, val) in self.db.getnode (self.classname, self.nodeid).items ():
  32             setattr (self, key, val)
  33 
  34         if not self.messages:
  35             raise ValueError, "Can't make an mbox without messages."
  36         self.client.additional_headers ["Content-Type"] = "application/mbox"
  37         self.client.header ()
  38         if self.client.env["REQUEST_METHOD"] == "HEAD":
  39             return None      # Stop now, as the mbox wasn't requested.
  40 
  41         mbox = []               # The accumulator.
  42         for message_id in self.messages:
  43             message = MIMEText (self.db.msg.get (message_id, "content"),
  44                                 "plain", "utf-8") # hard-code as UTF-8 for now.
  45             files = self.db.msg.get (message_id, "files")
  46             if files:
  47                 message_body = message
  48                 message_body ["Content-Disposition"] = "inline"
  49                 message = MIMEMultipart ()
  50                 message.attach (message_body)
  51                 for it in files:
  52                     attachment = Message ()
  53                     attachment.add_header ("Content-Disposition", "attachment",
  54                                            filename=self.db.file.get (it, "name"))
  55                     attachment ["Content-Type"] = self.db.file.get (it, "type")
  56                     attachment.set_payload (self.db.file.get (it, "content"))
  57                     encode_base64 (attachment) # bloated, but reliable.
  58                     message.attach (attachment)
  59 
  60             message ["Date"] = self.db.msg.get (message_id, "date").pretty ("%a, %d %b %Y %H:%M:%S +0000")
  61             message ["From"] = self.address (self.db.msg.get (message_id, "author"))
  62             it = self.db.msg.get (message_id, "recipients")
  63             if it: message ["CC"] = ", ".join ([self.address (recipient) for recipient in it])
  64             message ["Message-ID"] = self.db.msg.get(message_id, "messageid") or None
  65             message ["In-Reply-To"] = self.db.msg.get(message_id, "inreplyto") or None
  66 
  67             ## The remaining header fields are identical for all
  68             ## messages in the mbox, at least until such time as I
  69             ## work out how to reconcile the "journal" with the list
  70             ## of messages.
  71             message ["Reply-To"] = self.db.config.TRACKER_EMAIL
  72             message ["Subject"] = "[" + self.classname + self.nodeid + "] " + self.title
  73             if self.priority:
  74                 message ["X-Roundup-Priority"] = self.db.priority.get (self.priority, "name")
  75             if self.status:
  76                 message ["X-Roundup-Status"] = self.db.status.get (self.status, "name")
  77             if self.assignedto:
  78                 message ["X-Roundup-Assigned-To"] = self.db.user.get (self.assignedto, "username")
  79             if self.nosy:
  80                 message ["X-Roundup-Nosy-List"] = ", ".join([self.db.user.get (nose, "username")
  81                                                              for nose in self.nosy])
  82             if self.topic:
  83                 message ["X-Roundup-Topics"] = ", ".join([self.db.keyword.get (topic, "name")
  84                                                              for topic in self.topic])
  85 
  86             mbox.append (message)
  87 
  88         return "\n".join ([str (message) for message in mbox])
  89 
  90     def address(self, x):
  91         get = self.db.user.get
  92         return (get(x, "realname") or get(x, "username")) + ":;"
  93 
  94 def init(tracker):
  95     tracker.registerAction("mbox", MboxAction)

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2018-06-11 01:02:30, 4.7 KB) [[attachment:darcs-messages_as_mbox.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.