- attachment:darcs-messages_as_mbox.py of MessagesAsMbox
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.You are not allowed to attach a file to this page.