def save(self, *args, **kwargs): # Sanitize the post body. self.html = html.parse_html(self.content) if not self.id: # Set the titles if self.parent and not self.title: self.title = self.parent.title if self.parent and self.parent.type in (Post.ANSWER, Post.COMMENT): # Only comments may be added to a parent that is answer or comment. self.type = Post.COMMENT if self.type is None: # Set post type if it was left empty. self.type = self.COMMENT if self.parent else self.FORUM # This runs only once upon object creation. self.title = self.parent.title if self.parent else self.title self.lastedit_user = self.author self.status = self.status or Post.PENDING self.creation_date = self.creation_date or now() self.lastedit_date = self.creation_date # Set the timestamps on the parent if self.parent and self.type == Post.ANSWER: self.parent.lastedit_date = self.lastedit_date self.parent.lastedit_user = self.lastedit_user self.parent.save() # Recompute post reply count self.update_reply_count() super(Post, self).save(*args, **kwargs)
def email_handler(request): key = request.POST.get("key") if key != settings.EMAIL_REPLY_SECRET_KEY: data = dict(status="error", msg="key does not match") else: body = request.POST.get("body") body = smart_text(body, errors="ignore") # This is for debug only #fname = "%s/email-debug.txt" % settings.LIVE_DIR #fp = file(fname, "wt") #fp.write(body.encode("utf-8")) #fp.close() try: # Parse the incoming email. # Emails can be malformed in which case we will force utf8 on them before parsing try: msg = pyzmail.PyzMessage.factory(body) except Exception, exc: body = body.encode('utf8', errors='ignore') msg = pyzmail.PyzMessage.factory(body) # Extract the address from the address tuples. address = msg.get_addresses('to')[0][1] # Parse the token from the address. start, token, rest = address.split('+') # Verify that the token exists. token = ReplyToken.objects.get(token=token) # Find the post that the reply targets post, author = token.post, token.user # Extract the body of the email. part = msg.text_part or msg.html_part text = part.get_payload() # Remove the reply related content if settings.EMAIL_REPLY_REMOVE_QUOTED_TEXT: text = EmailReplyParser.parse_reply(text) else: text = text.decode("utf8", errors='replace') text = u"<div class='preformatted'>%s</div>" % text # Apply server specific formatting text = html.parse_html(text) # Apply the markdown on the text text = markdown.markdown(text) # Rate-limit sanity check, potentially a runaway process since = const.now() - timedelta(days=1) if Post.objects.filter(author=author, creation_date__gt=since).count() > settings.MAX_POSTS_TRUSTED_USER: raise Exception("too many posts created %s" % author.id) # Create the new post. post_type = Post.ANSWER if post.is_toplevel else Post.COMMENT obj = Post.objects.create(type=post_type, parent=post, content=text, author=author) # Delete the token. Disabled for now. # Old token should be deleted in the data pruning #token.delete() # Form the return message. data = dict(status="ok", id=obj.id) except Exception, exc: output = StringIO.StringIO() traceback.print_exc(file=output) data = dict(status="error", msg=str(output.getvalue()))