def get_list_context(context=None): list_context = frappe._dict( template = "templates/includes/blog/blog.html", get_list = get_blog_list, hide_filters = True, children = get_children(), # show_search = True, title = _('Blog') ) category = sanitize_html(frappe.local.form_dict.blog_category or frappe.local.form_dict.category) if category: category_title = get_blog_category(category) list_context.sub_title = _("Posts filed under {0}").format(category_title) list_context.title = category_title elif frappe.local.form_dict.blogger: blogger = frappe.db.get_value("Blogger", {"name": frappe.local.form_dict.blogger}, "full_name") list_context.sub_title = _("Posts by {0}").format(blogger) list_context.title = blogger elif frappe.local.form_dict.txt: list_context.sub_title = _('Filtered by "{0}"').format(sanitize_html(frappe.local.form_dict.txt)) if list_context.sub_title: list_context.parents = [{"name": _("Home"), "route": "/"}, {"name": "Blog", "route": "/blog"}] else: list_context.parents = [{"name": _("Home"), "route": "/"}] list_context.update(frappe.get_doc("Blog Settings", "Blog Settings").as_dict(no_default_fields=True)) return list_context
def get_list_context(context): blog_settings = frappe.get_doc("Website Blog Settings", "Website Blog Settings") context.introduction = blog_settings.blog_introduction or "" context.blog_settings = blog_settings context.get_list = get_blog_list context.parents = [{"name": _("Home"), "route": "/"}] category = sanitize_html(frappe.local.form_dict.blog_category or frappe.local.form_dict.category) if category: category_title = get_blog_category(category) context.sub_title = _("Posts filed under {0}").format(category_title) context.title = category_title elif frappe.local.form_dict.blogger: blogger = frappe.db.get_value("Website Blogger", {"name": frappe.local.form_dict.blogger}, "full_name") context.sub_title = _("Posts by {0}").format(blogger) context.title = blogger elif frappe.local.form_dict.txt: context.sub_title = _('Filtered by "{0}"').format(sanitize_html(frappe.local.form_dict.txt)) if context.sub_title: context.parents = [{"name": _("Home"), "route": "/"}, {"name": "Blog", "route": "/blog"}] else: context.parents = [{"name": _("Home"), "route": "/"}] context.update(frappe.get_doc("Blog Settings", "Blog Settings").as_dict(no_default_fields=True))
def execute(): for product_bundle in frappe.get_all('Product Bundle'): doc = frappe.get_doc('Product Bundle', product_bundle.name) for item in doc.items: if item.description: description = sanitize_html(item.description) item.db_set('description', description, update_modified=False)
def _build_communication_doc(self): data = self.as_dict() data['doctype'] = "Communication" if self.parent_communication(): data['in_reply_to'] = self.parent_communication().name if self.reference_document(): data['reference_doctype'] = self.reference_document().doctype data['reference_name'] = self.reference_document().name elif self.email_account.append_to and self.email_account.append_to != 'Communication': reference_doc = self._create_reference_document(self.email_account.append_to) if reference_doc: data['reference_doctype'] = reference_doc.doctype data['reference_name'] = reference_doc.name data['is_first'] = True if self.is_notification(): # Disable notifications for notification. data['unread_notification_sent'] = 1 if self.seen_status: data['_seen'] = json.dumps(self.get_users_linked_to_account(self.email_account)) communication = frappe.get_doc(data) communication.flags.in_receive = True communication.insert(ignore_permissions=True) # save attachments communication._attachments = self.save_attachments_in_doc(communication) communication.content = sanitize_html(self.replace_inline_images(communication._attachments)) communication.save() return communication
def get_context(context): """Build context for print""" if not ((frappe.form_dict.doctype and frappe.form_dict.name) or frappe.form_dict.doc): return { "body": sanitize_html("""<h1>Error</h1> <p>Parameters doctype and name required</p> <pre>%s</pre>""" % repr(frappe.form_dict)) } if frappe.form_dict.doc: doc = frappe.form_dict.doc else: doc = frappe.get_doc(frappe.form_dict.doctype, frappe.form_dict.name) meta = frappe.get_meta(doc.doctype) print_format = get_print_format_doc(None, meta = meta) make_access_log(doctype=frappe.form_dict.doctype, document=frappe.form_dict.name, file_type='PDF', method='Print') return { "body": get_rendered_template(doc, print_format = print_format, meta=meta, trigger_print = frappe.form_dict.trigger_print, no_letterhead=frappe.form_dict.no_letterhead), "css": get_print_style(frappe.form_dict.style, print_format), "comment": frappe.session.user, "title": doc.get(meta.title_field) if meta.title_field else doc.name, "has_rtl": True if frappe.local.lang in ["ar", "he", "fa"] else False }
def _sanitize_content(self): """Sanitize HTML and Email in field values. Used to prevent XSS. - Ignore if 'Ignore XSS Filter' is checked or fieldtype is 'Code' """ if frappe.flags.in_install: return for fieldname, value in self.get_valid_dict().items(): if not value or not isinstance(value, basestring): continue elif ("<" not in value and ">" not in value): # doesn't look like html so no need continue elif "<!-- markdown -->" in value and not ("<script" in value or "javascript:" in value): # should be handled separately via the markdown converter function continue df = self.meta.get_field(fieldname) sanitized_value = value if df and (df.get("ignore_xss_filter") or (df.get("fieldtype")=="Code" and df.get("options")!="Email") or df.get("fieldtype") in ("Attach", "Attach Image")): continue elif df and df.get("fieldtype") in ("Data", "Code") and df.get("options")=="Email": sanitized_value = sanitize_email(value) else: sanitized_value = sanitize_html(value) self.set(fieldname, sanitized_value)
def get_context(context): context.no_cache = 1 if frappe.form_dict.q: query = str(utils.escape(sanitize_html(frappe.form_dict.q))) context.title = _('Search Results for "{0}"').format(query) context.update(get_search_results(query)) else: context.title = _('Search')
def handle_exception(e): response = None http_status_code = getattr(e, "http_status_code", 500) return_as_message = False if frappe.get_request_header('Accept') and (frappe.local.is_ajax or 'application/json' in frappe.get_request_header('Accept')): # handle ajax responses first # if the request is ajax, send back the trace or error message response = frappe.utils.response.report_error(http_status_code) elif (http_status_code==500 and (frappe.db and isinstance(e, frappe.db.InternalError)) and (frappe.db and (frappe.db.is_deadlocked(e) or frappe.db.is_timedout(e)))): http_status_code = 508 elif http_status_code==401: frappe.respond_as_web_page(_("Session Expired"), _("Your session has expired, please login again to continue."), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code==403: frappe.respond_as_web_page(_("Not Permitted"), _("You do not have enough permissions to complete the action"), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code==404: frappe.respond_as_web_page(_("Not Found"), _("The resource you are looking for is not available"), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 429: response = frappe.rate_limiter.respond() else: traceback = "<pre>" + sanitize_html(frappe.get_traceback()) + "</pre>" if frappe.local.flags.disable_traceback: traceback = "" frappe.respond_as_web_page("Server Error", traceback, http_status_code=http_status_code, indicator_color='red', width=640) return_as_message = True if e.__class__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code >= 500: make_error_snapshot(e) if return_as_message: response = frappe.website.render.render("message", http_status_code=http_status_code) return response
def get_context(context): context.no_cache = 1 if frappe.form_dict.q: query = str(utils.escape(sanitize_html(frappe.form_dict.q))) context.title = _('Search Results for ') context.query = query context.route = '/search' context.update(get_search_results(query, frappe.form_dict.scope)) else: context.title = _('Search')
def get_context(context): context.no_cache = 1 if frappe.form_dict.q: query = str(utils.escape(sanitize_html(frappe.form_dict.q))) context.title = _('Documentation Results for "{0}"').format(query) context.route = '/search_docs' d = frappe._dict() d.results = get_docs_results(query) context.update(d) else: context.title = _('Docs Search')
def get_context(context): """Build context for print""" if not ((frappe.form_dict.doctype and frappe.form_dict.name) or frappe.form_dict.doc): return { "body": sanitize_html("""<h1>Error</h1> <p>Parameters doctype and name required</p> <pre>%s</pre>""" % repr(frappe.form_dict)) } if frappe.form_dict.doc: doc = frappe.form_dict.doc else: doc = frappe.get_doc(frappe.form_dict.doctype, frappe.form_dict.name) settings = frappe.parse_json(frappe.form_dict.settings) letterhead = frappe.form_dict.letterhead or None #For setting print datetime if it's pick_list if doc.doctype=="Pick List": if doc.print_date_time or doc.amended_from: doc.pl_text = "REPRINTED" doc.print_date_time = datetime.datetime.now(timezone('US/Pacific')).strftime("%Y-%m-%d %H:%M:%S") doc.track_print_user = frappe.db.get_value("User", frappe.session.user, "full_name") #Get the doc gain in case it is loaded from frappe.form_dict sdoc = frappe.get_doc(doc.doctype, doc.name) sdoc.update({ "print_date_time": doc.print_date_time, "track_print_user": doc.track_print_user, "pl_text": doc.pl_text, }) sdoc.save() meta = frappe.get_meta(doc.doctype) print_format = get_print_format_doc(None, meta = meta) make_access_log(doctype=frappe.form_dict.doctype, document=frappe.form_dict.name, file_type='PDF', method='Print') return { "body": get_rendered_template(doc, print_format = print_format, meta=meta, trigger_print = frappe.form_dict.trigger_print, no_letterhead=frappe.form_dict.no_letterhead, letterhead=letterhead, settings=settings), "css": get_print_style(frappe.form_dict.style, print_format), "comment": frappe.session.user, "title": doc.get(meta.title_field) if meta.title_field else doc.name, "lang": frappe.local.lang, "layout_direction": "rtl" if is_rtl() else "ltr" }
def get_list_context(context=None): website_settings = frappe.get_doc("Website Settings") featured_blog = None if website_settings.featured_blog: featured_blog = frappe.get_doc("Blog Post", website_settings.featured_blog).as_dict() list_context = frappe._dict( template = "templates/includes/blog/blog.html", get_list = get_blog_list, hide_filters = True, children = get_children(), # show_search = True, title = _('Blog'), page_heading_template = frappe.get_hooks('blogs_page_heading_template') or 'website/doctype/blog_post/templates/blog_post_header.html', featured_blog = featured_blog, background_image = website_settings.blog_header or None ) category = sanitize_html(frappe.local.form_dict.blog_category or frappe.local.form_dict.category) if category: category_title = get_blog_category(category) list_context.sub_title = _("Posts filed under {0}").format(category_title) list_context.title = category_title elif frappe.local.form_dict.blogger: blogger = frappe.db.get_value("Blogger", {"name": frappe.local.form_dict.blogger}, "full_name") list_context.sub_title = _("Posts by {0}").format(blogger) list_context.title = blogger elif frappe.local.form_dict.txt: list_context.sub_title = _('Filtered by "{0}"').format(sanitize_html(frappe.local.form_dict.txt)) if list_context.sub_title: list_context.parents = [{"name": _("Home"), "route": "/"}, {"name": "Blog", "route": "/blog"}] else: list_context.parents = [{"name": _("Home"), "route": "/"}] list_context.update(frappe.get_doc("Blog Settings", "Blog Settings").as_dict(no_default_fields=True)) return list_context
def get_context(context): context.no_cache = 1 if frappe.form_dict.q: query = str(utils.escape(sanitize_html(frappe.form_dict.q))) context.title = _('Help Results for') context.query = query context.route = '/search_help' d = frappe._dict() d.results_sections = get_help_results_sections(query) context.update(d) else: context.title = _('Docs Search')
def insert_communication(self, raw): email = Email(raw) if email.from_email == self.email_id: # gmail shows sent emails in inbox # and we don't want emails sent by us to be pulled back into the system again raise SentEmailInInbox communication = frappe.get_doc({ "doctype": "Communication", "subject": email.subject, "content": email.content, "sent_or_received": "Received", "sender_full_name": email.from_real_name, "sender": email.from_email, "recipients": email.mail.get("To"), "cc": email.mail.get("CC"), "email_account": self.name, "communication_medium": "Email" }) self.set_thread(communication, email) communication.flags.in_receive = True communication.insert(ignore_permissions=1) # save attachments communication._attachments = email.save_attachments_in_doc( communication) # replace inline images dirty = False for file in communication._attachments: if file.name in email.cid_map and email.cid_map[file.name]: dirty = True email.content = email.content.replace( "cid:{0}".format(email.cid_map[file.name]), file.file_url) if dirty: # not sure if using save() will trigger anything communication.db_set("content", sanitize_html(email.content)) # notify all participants of this thread if self.enable_auto_reply and getattr(communication, "is_first", False): self.send_auto_reply(communication, email) return communication
def insert_communication(self, raw): email = Email(raw) if email.from_email == self.email_id: # gmail shows sent emails in inbox # and we don't want emails sent by us to be pulled back into the system again raise SentEmailInInbox communication = frappe.get_doc({ "doctype": "Communication", "subject": email.subject, "content": email.content, 'text_content': email.text_content, "sent_or_received": "Received", "sender_full_name": email.from_real_name, "sender": email.from_email, "recipients": email.mail.get("To"), "cc": email.mail.get("CC"), "email_account": self.name, "communication_medium": "Email" }) self.set_thread(communication, email) communication.flags.in_receive = True communication.insert(ignore_permissions = 1) # save attachments communication._attachments = email.save_attachments_in_doc(communication) # replace inline images dirty = False for file in communication._attachments: if file.name in email.cid_map and email.cid_map[file.name]: dirty = True email.content = email.content.replace("cid:{0}".format(email.cid_map[file.name]), file.file_url) if dirty: # not sure if using save() will trigger anything communication.db_set("content", sanitize_html(email.content)) # notify all participants of this thread if self.enable_auto_reply and getattr(communication, "is_first", False): self.send_auto_reply(communication, email) return communication
def get_context(context): """Build context for print""" if not ((frappe.form_dict.doctype and frappe.form_dict.name) or frappe.form_dict.doc): return { "body": sanitize_html("""<h1>Error</h1> <p>Parameters doctype and name required</p> <pre>%s</pre>""" % repr(frappe.form_dict)) } if frappe.form_dict.doc: doc = frappe.form_dict.doc else: doc = frappe.get_doc(frappe.form_dict.doctype, frappe.form_dict.name) settings = frappe.parse_json(frappe.form_dict.settings) letterhead = frappe.form_dict.letterhead or None meta = frappe.get_meta(doc.doctype) print_format = get_print_format_doc(None, meta=meta) make_access_log(doctype=frappe.form_dict.doctype, document=frappe.form_dict.name, file_type='PDF', method='Print') return { "body": get_rendered_template(doc, print_format=print_format, meta=meta, trigger_print=frappe.form_dict.trigger_print, no_letterhead=frappe.form_dict.no_letterhead, letterhead=letterhead, settings=settings), "css": get_print_style(frappe.form_dict.style, print_format), "comment": frappe.session.user, "title": doc.get(meta.title_field) if meta.title_field else doc.name, "lang": frappe.local.lang, "layout_direction": "rtl" if is_rtl() else "ltr" }
def _sanitize_content(self): """Sanitize HTML and Email in field values. Used to prevent XSS. - Ignore if 'Ignore XSS Filter' is checked or fieldtype is 'Code' """ if frappe.flags.in_install: return for fieldname, value in self.get_valid_dict().items(): if not value or not isinstance(value, string_types): continue value = frappe.as_unicode(value) if (u"<" not in value and u">" not in value): # doesn't look like html so no need continue elif "<!-- markdown -->" in value and not ("<script" in value or "javascript:" in value): # should be handled separately via the markdown converter function continue df = self.meta.get_field(fieldname) sanitized_value = value if df and df.get("fieldtype") in ( "Data", "Code", "Small Text") and df.get("options") == "Email": sanitized_value = sanitize_email(value) elif df and ( df.get("ignore_xss_filter") or (df.get("fieldtype") == "Code" and df.get("options") != "Email") or df.get("fieldtype") in ("Attach", "Attach Image") # cancelled and submit but not update after submit should be ignored or self.docstatus == 2 or (self.docstatus == 1 and not df.get("allow_on_submit"))): continue else: sanitized_value = sanitize_html( value, linkify=df.fieldtype == 'Text Editor') self.set(fieldname, sanitized_value)
def _sanitize_content(self): """Sanitize HTML and Email in field values. Used to prevent XSS. - Ignore if 'Ignore XSS Filter' is checked or fieldtype is 'Code' """ if frappe.flags.in_install: return for fieldname, value in self.get_valid_dict().items(): if not value or not isinstance(value, string_types): continue value = frappe.as_unicode(value) if (u"<" not in value and u">" not in value): # doesn't look like html so no need continue elif "<!-- markdown -->" in value and not ("<script" in value or "javascript:" in value): # should be handled separately via the markdown converter function continue df = self.meta.get_field(fieldname) sanitized_value = value if df and df.get("fieldtype") in ("Data", "Code", "Small Text") and df.get("options")=="Email": sanitized_value = sanitize_email(value) elif df and (df.get("ignore_xss_filter") or (df.get("fieldtype")=="Code" and df.get("options")!="Email") or df.get("fieldtype") in ("Attach", "Attach Image") # cancelled and submit but not update after submit should be ignored or self.docstatus==2 or (self.docstatus==1 and not df.get("allow_on_submit"))): continue else: sanitized_value = sanitize_html(value, linkify=df.fieldtype=='Text Editor') self.set(fieldname, sanitized_value)
def insert_communication(self, msg, args=None): if isinstance(msg, list): raw, uid, seen = msg else: raw = msg uid = -1 seen = 0 if isinstance(args, dict): if args.get("uid", -1): uid = args.get("uid", -1) if args.get("seen", 0): seen = args.get("seen", 0) email = Email(raw) if email.from_email == self.email_id and not email.mail.get( "Reply-To"): # gmail shows sent emails in inbox # and we don't want emails sent by us to be pulled back into the system again # dont count emails sent by the system get those if frappe.flags.in_test: print( 'WARN: Cannot pull email. Sender sames as recipient inbox') raise SentEmailInInbox if email.message_id: # https://stackoverflow.com/a/18367248 names = frappe.db.sql( """SELECT DISTINCT `name`, `creation` FROM `tabCommunication` WHERE `message_id`='{message_id}' ORDER BY `creation` DESC LIMIT 1""".format(message_id=email.message_id), as_dict=True) if names: name = names[0].get("name") # email is already available update communication uid instead frappe.db.set_value("Communication", name, "uid", uid, update_modified=False) return frappe.get_doc("Communication", name) if email.content_type == 'text/html': email.content = clean_email_html(email.content) communication = frappe.get_doc({ "doctype": "Communication", "subject": email.subject, "content": email.content, 'text_content': email.text_content, "sent_or_received": "Received", "sender_full_name": email.from_real_name, "sender": email.from_email, "recipients": email.mail.get("To"), "cc": email.mail.get("CC"), "email_account": self.name, "communication_medium": "Email", "uid": int(uid or -1), "message_id": email.message_id, "communication_date": email.date, "has_attachment": 1 if email.attachments else 0, "seen": seen or 0 }) self.set_thread(communication, email) if communication.seen: # get email account user and set communication as seen users = frappe.get_all("User Email", filters={"email_account": self.name}, fields=["parent"]) users = list(set([user.get("parent") for user in users])) communication._seen = json.dumps(users) communication.flags.in_receive = True communication.insert(ignore_permissions=True) # save attachments communication._attachments = email.save_attachments_in_doc( communication) # replace inline images dirty = False for file in communication._attachments: if file.name in email.cid_map and email.cid_map[file.name]: dirty = True email.content = email.content.replace( "cid:{0}".format(email.cid_map[file.name]), file.file_url) if dirty: # not sure if using save() will trigger anything communication.db_set("content", sanitize_html(email.content)) # notify all participants of this thread if self.enable_auto_reply and getattr(communication, "is_first", False): self.send_auto_reply(communication, email) return communication
def get_blog_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by=None): conditions = [] category = filters.blog_category or sanitize_html( frappe.local.form_dict.blog_category or frappe.local.form_dict.category) if filters: if filters.blogger: conditions.append('t1.blogger=%s' % frappe.db.escape(filters.blogger)) if category: conditions.append('t1.blog_category=%s' % frappe.db.escape(category)) if txt: conditions.append('(t1.content like {0} or t1.title like {0}")'.format( frappe.db.escape('%' + txt + '%'))) if conditions: frappe.local.no_cache = 1 query = """\ select t1.title, t1.name, t1.blog_category, t1.route, t1.published_on, t1.published_on as creation, t1.content as content, t1.content_type as content_type, t1.content_html as content_html, t1.content_md as content_md, ifnull(t1.blog_intro, t1.content) as intro, t2.full_name, t2.avatar, t1.blogger, (select count(name) from `tabComment` where comment_type='Comment' and reference_doctype='Blog Post' and reference_name=t1.name) as comments from `tabBlog Post` t1, `tabBlogger` t2 where ifnull(t1.published,0)=1 and t1.blogger = t2.name %(condition)s order by published_on desc, name asc limit %(start)s, %(page_len)s""" % { "start": limit_start, "page_len": limit_page_length, "condition": (" and " + " and ".join(conditions)) if conditions else "" } posts = frappe.db.sql(query, as_dict=1) for post in posts: post.content = get_html_content_based_on_type(post, 'content', post.content_type) post.cover_image = find_first_image(post.content) post.published = global_date_format(post.creation) post.content = strip_html_tags(post.content) if not post.comments: post.comment_text = _('No comments yet') elif post.comments == 1: post.comment_text = _('1 comment') else: post.comment_text = _('{0} comments').format(str(post.comments)) post.avatar = post.avatar or "" post.category = frappe.db.get_value('Blog Category', post.blog_category, ['route', 'title'], as_dict=True) if post.avatar and (not "http:" in post.avatar and not "https:" in post.avatar ) and not post.avatar.startswith("/"): post.avatar = "/" + post.avatar return posts
def insert_communication(self, msg): if isinstance(msg,list): raw, uid, seen = msg else: raw = msg seen = uid = None email = Email(raw) if email.from_email == self.email_id and not email.mail.get("Reply-To"): # gmail shows sent emails in inbox # and we don't want emails sent by us to be pulled back into the system again # dont count emails sent by the system get those raise SentEmailInInbox communication = frappe.get_doc({ "doctype": "Communication", "subject": email.subject, "content": email.content, "sent_or_received": "Received", "sender_full_name": email.from_real_name, "sender": email.from_email, "recipients": email.To, "cc": email.CC, "email_account": self.name, "communication_medium": "Email", "uid":uid, "message_id":email.message_id, "communication_date":email.date, "has_attachment": 1 if email.attachments else 0, "seen":seen, "unique_id":email.unique_id }) self.set_thread(communication, email) if not self.no_remaining == '0': communication.unread_notification_sent = 1 communication.flags.in_receive = True communication.insert(ignore_permissions = 1) # save attachments communication._attachments = email.save_attachments_in_doc(communication) # replace inline images dirty = False for file in communication._attachments: if file.name in email.cid_map and email.cid_map[file.name]: dirty = True email.content = email.content.replace("cid:{0}".format(email.cid_map[file.name]), file.file_url) if dirty: # not sure if using save() will trigger anything communication.db_set("content", sanitize_html(email.content)) # notify all participants of this thread if self.enable_auto_reply and getattr(communication, "is_first", False): self.send_auto_reply(communication, email) return communication
def insert_communication(self, msg, args={}): if isinstance(msg, list): raw, uid, seen = msg else: raw = msg uid = -1 seen = 0 if args.get("uid", -1): uid = args.get("uid", -1) if args.get("seen", 0): seen = args.get("seen", 0) email = Email(raw) if email.from_email == self.email_id and not email.mail.get( "Reply-To"): # gmail shows sent emails in inbox # and we don't want emails sent by us to be pulled back into the system again # dont count emails sent by the system get those raise SentEmailInInbox if email.message_id: names = frappe.db.sql( """select distinct name from tabCommunication where message_id='{message_id}' order by creation desc limit 1""".format(message_id=email.message_id), as_dict=True) if names: name = names[0].get("name") # email is already available update communication uid instead communication = frappe.get_doc("Communication", name) communication.uid = uid communication.save(ignore_permissions=True) communication._attachments = [] return communication communication = frappe.get_doc({ "doctype": "Communication", "subject": email.subject, "content": email.content, 'text_content': email.text_content, "sent_or_received": "Received", "sender_full_name": email.from_real_name, "sender": email.from_email, "recipients": email.mail.get("To"), "cc": email.mail.get("CC"), "email_account": self.name, "communication_medium": "Email", "uid": int(uid or -1), "message_id": email.message_id, "communication_date": email.date, "has_attachment": 1 if email.attachments else 0, "seen": seen or 0 }) self.set_thread(communication, email) if communication.seen: # get email account user and set communication as seen users = frappe.get_all("User Email", filters={"email_account": self.name}, fields=["parent"]) users = list(set([user.get("parent") for user in users])) communication._seen = json.dumps(users) communication.flags.in_receive = True communication.insert(ignore_permissions=1) # save attachments communication._attachments = email.save_attachments_in_doc( communication) # replace inline images dirty = False for file in communication._attachments: if file.name in email.cid_map and email.cid_map[file.name]: dirty = True email.content = email.content.replace( "cid:{0}".format(email.cid_map[file.name]), file.file_url) if dirty: # not sure if using save() will trigger anything communication.db_set("content", sanitize_html(email.content)) # notify all participants of this thread if self.enable_auto_reply and getattr(communication, "is_first", False): self.send_auto_reply(communication, email) return communication
def handle_exception(e): response = None http_status_code = getattr(e, "http_status_code", 500) return_as_message = False accept_header = frappe.get_request_header("Accept") or "" respond_as_json = ( frappe.get_request_header('Accept') and (frappe.local.is_ajax or 'application/json' in accept_header) or (frappe.local.request.path.startswith("/api/") and not accept_header.startswith("text"))) if frappe.conf.get('developer_mode'): # don't fail silently print(frappe.get_traceback()) if respond_as_json: # handle ajax responses first # if the request is ajax, send back the trace or error message response = frappe.utils.response.report_error(http_status_code) elif (http_status_code == 500 and (frappe.db and isinstance(e, frappe.db.InternalError)) and (frappe.db and (frappe.db.is_deadlocked(e) or frappe.db.is_timedout(e)))): http_status_code = 508 elif http_status_code == 401: frappe.respond_as_web_page( _("Session Expired"), _("Your session has expired, please login again to continue."), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 403: frappe.respond_as_web_page( _("Not Permitted"), _("You do not have enough permissions to complete the action"), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 404: frappe.respond_as_web_page( _("Not Found"), _("The resource you are looking for is not available"), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 429: response = frappe.rate_limiter.respond() else: traceback = "<pre>" + sanitize_html(frappe.get_traceback()) + "</pre>" # disable traceback in production if flag is set if frappe.local.flags.disable_traceback and not frappe.local.dev_server: traceback = "" frappe.respond_as_web_page("Server Error", traceback, http_status_code=http_status_code, indicator_color='red', width=640) return_as_message = True if e.__class__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code >= 500: try: from sentry.utils import capture_exception capture_exception() except: pass frappe.logger().error('Request Error', exc_info=True) make_error_snapshot(e) if return_as_message: response = frappe.website.render.render( "message", http_status_code=http_status_code) return response
def insert_communication(self, msg, args={}): if isinstance(msg, list): raw, uid, seen = msg else: raw = msg uid = -1 seen = 0 if args.get("uid", -1): uid = args.get("uid", -1) if args.get("seen", 0): seen = args.get("seen", 0) email = Email(raw) if email.from_email == self.email_id and not email.mail.get("Reply-To"): # gmail shows sent emails in inbox # and we don't want emails sent by us to be pulled back into the system again # dont count emails sent by the system get those if frappe.flags.in_test: print('WARN: Cannot pull email. Sender sames as recipient inbox') raise SentEmailInInbox if email.message_id: names = frappe.db.sql("""select distinct name from tabCommunication where message_id='{message_id}' order by creation desc limit 1""".format( message_id=email.message_id ), as_dict=True) if names: name = names[0].get("name") # email is already available update communication uid instead frappe.db.set_value("Communication", name, "uid", uid, update_modified=False) return communication = frappe.get_doc({ "doctype": "Communication", "subject": email.subject, "content": email.content, 'text_content': email.text_content, "sent_or_received": "Received", "sender_full_name": email.from_real_name, "sender": email.from_email, "recipients": email.mail.get("To"), "cc": email.mail.get("CC"), "email_account": self.name, "communication_medium": "Email", "uid": int(uid or -1), "message_id": email.message_id, "communication_date": email.date, "has_attachment": 1 if email.attachments else 0, "seen": seen or 0 }) self.set_thread(communication, email) if communication.seen: # get email account user and set communication as seen users = frappe.get_all("User Email", filters={ "email_account": self.name }, fields=["parent"]) users = list(set([ user.get("parent") for user in users ])) communication._seen = json.dumps(users) communication.flags.in_receive = True communication.insert(ignore_permissions = 1) # save attachments communication._attachments = email.save_attachments_in_doc(communication) # replace inline images dirty = False for file in communication._attachments: if file.name in email.cid_map and email.cid_map[file.name]: dirty = True email.content = email.content.replace("cid:{0}".format(email.cid_map[file.name]), file.file_url) if dirty: # not sure if using save() will trigger anything communication.db_set("content", sanitize_html(email.content)) # notify all participants of this thread if self.enable_auto_reply and getattr(communication, "is_first", False): self.send_auto_reply(communication, email) return communication