From 8f71135af0e0d68554246c55a6290d37c471c5db Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 15 Jan 2013 12:29:42 +0530 Subject: [PATCH 1/5] cleaned up support email --- webnotes/utils/__init__.py | 25 +++++------------ webnotes/utils/email_lib/receive.py | 43 +++++++++++------------------ 2 files changed, 23 insertions(+), 45 deletions(-) diff --git a/webnotes/utils/__init__.py b/webnotes/utils/__init__.py index e12f5f9502..0f5bd8f166 100644 --- a/webnotes/utils/__init__.py +++ b/webnotes/utils/__init__.py @@ -59,19 +59,7 @@ def get_fullname(profile): return profile -# TODO: deprecate it -def decode_email_header(s): - import email.header - - # replace double quotes with blank - # double quotes in header prohibit decoding of header - decoded_header_tuple = email.header.decode_header(s.replace('"', '')) - - decoded_list = map(lambda h: unicode(h[0], encoding=h[1] or 'utf-8'), decoded_header_tuple) - - return " ".join(decoded_list) - -def get_email_id(user): +def get_formatted_email(user): """get email id of user formatted as: John Doe """ if user == "Administrator": return user @@ -81,14 +69,15 @@ def get_email_id(user): def extract_email_id(email): """fetch only the email part of the email id""" - import re - sender_email = re.findall("<([^>]*)>", email) - return sender_email and sender_email[0] or "" + from email.utils import parseaddr + if ',' in email and email.count("@")==1: + email = email.split(",")[-1] + fullname, email_id = parseaddr(email) + return email_id def validate_email_add(email_str): """Validates the email string""" - from email.utils import parseaddr - real_name, email = parseaddr(email_str) + email = extract_email_id(email_str) import re return re.match("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", email.lower()) diff --git a/webnotes/utils/email_lib/receive.py b/webnotes/utils/email_lib/receive.py index 3fbad5f48e..8d0248e9f0 100644 --- a/webnotes/utils/email_lib/receive.py +++ b/webnotes/utils/email_lib/receive.py @@ -21,9 +21,7 @@ # from __future__ import unicode_literals -""" - This module contains classes for managing incoming emails -""" +from webnotes.utils import extract_email_id class IncomingMail: """ @@ -41,18 +39,21 @@ class IncomingMail: self.html_content = '' self.attachments = [] self.parse() + self.set_content_and_type() + self.from_email = extract_email_id(self.mail["From"]) def parse(self): - """ - Extracts text, html and attachments from the mail - """ for part in self.mail.walk(): self.process_part(part) + def set_content_and_type(self): + self.content, self.content_type = '[Blank Email]', 'text/plain' + if self.text_content: + self.content, self.content_type = self.text_content, 'text/plain' + else: + self.content, self.content_type = self.html_content, 'text/html' + def process_part(self, part): - """ - Process a single part of an email - """ content_type = part.get_content_type() charset = part.get_content_charset() if not charset: charset = self.get_charset(part) @@ -67,15 +68,9 @@ class IncomingMail: self.get_attachment(part, charset) def get_text_content(self): - """ - Returns the text parts of the email. If None, then HTML parts - """ return self.text_content or self.html_content def get_charset(self, part): - """ - Guesses character set - """ charset = part.get_content_charset() if not charset: import chardet @@ -84,33 +79,27 @@ class IncomingMail: return charset def get_payload(self, part, charset): - """ - get utf-8 encoded part content - """ try: return unicode(part.get_payload(decode=True),str(charset),"ignore") except LookupError, e: return part.get_payload() def get_attachment(self, part, charset): - """ - Extracts an attachment - """ self.attachments.append({ 'content-type': part.get_content_type(), 'filename': part.get_filename(), 'content': part.get_payload(decode=True), }) - + + def save_attachments_in_doc(self, doc): + from webnotes.utils.file_manager import save_file, add_file_list + for attachment in self.attachments: + fid = save_file(attachment['filename'], attachment['content']) + status = add_file_list(doc.doctype, doc.name, fid, fid) def get_thread_id(self): - """ - Extracts thread id of the message between first [] - from the subject - """ import re subject = self.mail.get('Subject', '') - return re.findall('(?<=\[)[\w/-]+', subject) class POP3Mailbox: From 870cbdc68030b8ba0806fc7b963c80ed4975df2e Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 15 Jan 2013 12:44:26 +0530 Subject: [PATCH 2/5] scheduler log now a standard doctype --- core/doctype/doctype/doctype.py | 4 +- core/doctype/scheduler_log/__init__.py | 0 core/doctype/scheduler_log/scheduler_log.py | 8 +++ core/doctype/scheduler_log/scheduler_log.txt | 58 ++++++++++++++++++++ webnotes/utils/scheduler.py | 6 +- 5 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 core/doctype/scheduler_log/__init__.py create mode 100644 core/doctype/scheduler_log/scheduler_log.py create mode 100644 core/doctype/scheduler_log/scheduler_log.txt diff --git a/core/doctype/doctype/doctype.py b/core/doctype/doctype/doctype.py index 2fe2895b91..9fb4a07a29 100644 --- a/core/doctype/doctype/doctype.py +++ b/core/doctype/doctype/doctype.py @@ -226,7 +226,7 @@ def validate_permissions(permissions, for_remove=False): issubmittable = webnotes.conn.get_value("DocType", doctype, "is_submittable") def get_txt(d): - return "For %s (level %s) in %s:" % (d.role, d.permlevel, d.parent) + return "For %s (level %s) in %s row %s:" % (d.role, d.permlevel, d.parent, d.idx) def check_atleast_one_set(d): if not d.read and not d.write and not d.submit and not d.cancel and not d.create: @@ -245,7 +245,7 @@ def validate_permissions(permissions, for_remove=False): raise_exception=True) def check_level_zero_is_set(d): - if d.permlevel > 0 and d.role != 'All': + if cint(d.permlevel) > 0 and d.role != 'All': if not permissions.get({"role": d.role, "permlevel": 0}): webnotes.msgprint(get_txt(d) + " Higher level permissions are meaningless if level 0 permission is not set.", raise_exception=True) diff --git a/core/doctype/scheduler_log/__init__.py b/core/doctype/scheduler_log/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/doctype/scheduler_log/scheduler_log.py b/core/doctype/scheduler_log/scheduler_log.py new file mode 100644 index 0000000000..928aa9ff9f --- /dev/null +++ b/core/doctype/scheduler_log/scheduler_log.py @@ -0,0 +1,8 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl \ No newline at end of file diff --git a/core/doctype/scheduler_log/scheduler_log.txt b/core/doctype/scheduler_log/scheduler_log.txt new file mode 100644 index 0000000000..e7bc7bc49d --- /dev/null +++ b/core/doctype/scheduler_log/scheduler_log.txt @@ -0,0 +1,58 @@ +[ + { + "owner": "Administrator", + "docstatus": 0, + "creation": "2013-01-15 12:42:11", + "modified_by": "Administrator", + "modified": "2013-01-15 12:42:31" + }, + { + "autoname": "SCHLOG.#####", + "description": "Log of Scheduler Errors", + "doctype": "DocType", + "module": "Core", + "document_type": "System", + "name": "__common__" + }, + { + "name": "__common__", + "parent": "Scheduler Log", + "doctype": "DocField", + "parenttype": "DocType", + "permlevel": 0, + "parentfield": "fields" + }, + { + "parent": "Scheduler Log", + "read": 1, + "cancel": 1, + "name": "__common__", + "create": 1, + "doctype": "DocPerm", + "submit": 0, + "write": 1, + "parenttype": "DocType", + "role": "System Manager", + "permlevel": 0, + "parentfield": "permissions" + }, + { + "name": "Scheduler Log", + "doctype": "DocType" + }, + { + "doctype": "DocField", + "label": "Method", + "fieldname": "method", + "fieldtype": "Data" + }, + { + "doctype": "DocField", + "label": "Error", + "fieldname": "error", + "fieldtype": "Text" + }, + { + "doctype": "DocPerm" + } +] \ No newline at end of file diff --git a/webnotes/utils/scheduler.py b/webnotes/utils/scheduler.py index 2ddc494cb6..eeeff28d24 100644 --- a/webnotes/utils/scheduler.py +++ b/webnotes/utils/scheduler.py @@ -101,8 +101,10 @@ def log(method): import webnotes.utils webnotes.conn.begin() - webnotes.conn.sql("""insert into __SchedulerLog (`timestamp`, method, error) - values (%s, %s, %s)""", (webnotes.utils.now_datetime(), method, traceback)) + d = webnotes.doc("Scheduler Log") + d.method = method + d.error = traceback + d.save() webnotes.conn.commit() return traceback From 5721a696c0176676ae03784a3bfea1542a5d0c46 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 15 Jan 2013 12:51:01 +0530 Subject: [PATCH 3/5] support fixes --- core/doctype/scheduler_log/scheduler_log.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/doctype/scheduler_log/scheduler_log.txt b/core/doctype/scheduler_log/scheduler_log.txt index e7bc7bc49d..1ff16c15f5 100644 --- a/core/doctype/scheduler_log/scheduler_log.txt +++ b/core/doctype/scheduler_log/scheduler_log.txt @@ -4,7 +4,7 @@ "docstatus": 0, "creation": "2013-01-15 12:42:11", "modified_by": "Administrator", - "modified": "2013-01-15 12:42:31" + "modified": "2013-01-15 12:49:23" }, { "autoname": "SCHLOG.#####", @@ -33,6 +33,7 @@ "write": 1, "parenttype": "DocType", "role": "System Manager", + "report": 1, "permlevel": 0, "parentfield": "permissions" }, From 19815f54d0d167f29c2c0e2d4743fc2bdeccfdcd Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 15 Jan 2013 14:17:30 +0530 Subject: [PATCH 4/5] cleanup get_support_ticket --- public/js/wn/views/communication.js | 6 +++- webnotes/model/wrapper.py | 2 ++ webnotes/utils/email_lib/receive.py | 51 +++++++++-------------------- 3 files changed, 23 insertions(+), 36 deletions(-) diff --git a/public/js/wn/views/communication.js b/public/js/wn/views/communication.js index 40a4375747..2dfa40cc45 100644 --- a/public/js/wn/views/communication.js +++ b/public/js/wn/views/communication.js @@ -75,7 +75,7 @@ wn.views.CommunicationList = Class.extend({ make_line: function(doc) { var me = this; var comm = $(repl('\ - ' + ' +wn._('Show Details')+'\

\ %(_sender)s on %(when)s

\ @@ -83,6 +83,10 @@ wn.views.CommunicationList = Class.extend({ padding: 10px; overflow-x: auto; display: none;">\ ', doc)) .appendTo(this.body); + + if(!doc.name) { + comm.find(".show-details").toggle(false); + } comm.find(".comm-header") .css({"cursor":"pointer"}) diff --git a/webnotes/model/wrapper.py b/webnotes/model/wrapper.py index 81d79a633a..8011c78444 100644 --- a/webnotes/model/wrapper.py +++ b/webnotes/model/wrapper.py @@ -48,6 +48,8 @@ class ModelWrapper: self.load_from_db(dt, dn) elif isinstance(dt, list): self.set_doclist(dt) + elif isinstance(dt, dict): + self.set_doclist([dt]) def load_from_db(self, dt=None, dn=None, prefix='tab'): """ diff --git a/webnotes/utils/email_lib/receive.py b/webnotes/utils/email_lib/receive.py index 8d0248e9f0..a5f1e1719f 100644 --- a/webnotes/utils/email_lib/receive.py +++ b/webnotes/utils/email_lib/receive.py @@ -100,30 +100,27 @@ class IncomingMail: def get_thread_id(self): import re subject = self.mail.get('Subject', '') - return re.findall('(?<=\[)[\w/-]+', subject) + l= re.findall('(?<=\[)[\w/-]+', subject) + return l and l[0] or None class POP3Mailbox: - """ - A simple pop3 mailbox, abstracts connection and mail extraction - To use, subclass it and override method process_message(from, subject, text, thread_id) - """ + def __init__(self): + self.setup() + self.get_messages() - def __init__(self, settings_doc): - """ - settings_doc must contain - use_ssl, host, username, password - (by name or object) - """ - if isinstance(settings_doc, basestring): - from webnotes.model.doc import Document - self.settings = Document(settings_doc, settings_doc) - else: - self.settings = settings_doc + def setup(self): + # overrride + self.settings = webnotes._dict() + def check_mails(self): + # overrride + return True + + def process_message(self, mail): + # overrride + pass + def connect(self): - """ - Connects to the mailbox - """ import poplib if self.settings.use_ssl: @@ -134,10 +131,6 @@ class POP3Mailbox: self.pop.pass_(self.settings.password) def get_messages(self): - """ - Loads messages from the mailbox and calls - process_message for each message - """ import webnotes if not self.check_mails(): @@ -179,15 +172,3 @@ class POP3Mailbox: self.pop.quit() webnotes.conn.begin() - def check_mails(self): - """ - To be overridden - If mailbox is to be scanned, returns true - """ - return True - - def process_message(self, mail): - """ - To be overriden - """ - pass From ace1a516dcab415acfae6af1f1358e97a6db8e0e Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 15 Jan 2013 14:54:45 +0530 Subject: [PATCH 5/5] default time --- public/js/wn/model/create_new.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/wn/model/create_new.js b/public/js/wn/model/create_new.js index 3233a0b3f4..e178664140 100644 --- a/public/js/wn/model/create_new.js +++ b/public/js/wn/model/create_new.js @@ -59,7 +59,7 @@ $.extend(wn.model, { if(def_vals[df["default"]]) return def_vals[df["default"]]; - else if(df.fieldtype=="Time" && !df["default"] && df.reqd) + else if(df.fieldtype=="Time" && (!df["default"])) return dateutil.get_cur_time() else if(df["default"]) return df["default"];