def save(self, *args, **kwargs): # Sanitize the post body. self.html = html.parse_html(self.content) # Must add tags with instance method. This is just for safety. self.tag_val = html.strip_tags(self.tag_val) # Posts other than a question also carry the same tag if self.is_toplevel and self.type != Post.QUESTION: required_tag = self.get_type_display() if required_tag not in self.tag_val: self.tag_val += "," + required_tag 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.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) # bail on zimbra auto-replies if msg.has_key("Auto-Submitted") and \ msg['Auto-Submitted'] == "auto-replied (zimbra; vacation)": data = dict(status="error", msg="discarding zimbra vacation notification") data = json.dumps(data) return HttpResponse(data, content_type="application/json") # 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) error = traceback.format_exc() import smtplib from email.mime.text import MIMEText emailbody = "Error was:\n%s\n\nBody was:\n%s" % (error, body) msg = MIMEText(emailbody) msg['Subject'] = 'message emailed to biostar failed to go through' msg['From'] = os.environ['DEFAULT_FROM_EMAIL'] msg['To'] = os.environ['BIOSTAR_ADMIN_EMAIL'] s = smtplib.SMTP(os.environ['EMAIL_HOST']) if not "hub.nih.gov" in body and not "*****@*****.**" in body: s.sendmail(msg['From'], [msg['To']], msg.as_string()) s.quit() data = dict(status="error", msg=str(output.getvalue()))
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()))
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 as 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 as exc: output = StringIO.StringIO() traceback.print_exc(file=output) data = dict(status="error", msg=str(output.getvalue())) data = json.dumps(data) return HttpResponse(data, content_type="application/json")
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) # 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. 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 text = EmailReplyParser.parse_reply(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: data = dict(status="error", msg=str(exc))