def validate(self): """validate the email ids""" from frappe.utils import validate_email_add def _validate(email): """validate an email field""" if email and not validate_email_add(email): throw(_("{0} is not a valid email id").format(email), frappe.InvalidEmailAddressError) return email if not self.sender: self.sender = frappe.db.get_value('Outgoing Email Settings', None, 'auto_email_id') or frappe.conf.get('auto_email_id') or None if not self.sender: msg = _("Please specify 'Auto Email Id' in Setup > Outgoing Email Settings") msgprint(msg) if not "expires_on" in frappe.conf: msgprint(_("Alternatively, you can also specify 'auto_email_id' in site_config.json")) raise frappe.ValidationError, msg self.sender = _validate(strip(self.sender)) self.reply_to = _validate(strip(self.reply_to) or self.sender) self.recipients = [strip(r) for r in self.recipients] self.cc = [strip(r) for r in self.cc] for e in self.recipients + (self.cc or []): _validate(e)
def is_temporary_system_problem(self, e): messages = ( "-ERR [SYS/TEMP] Temporary system problem. Please try again later.", "Connection timed out", ) for message in messages: if message in strip(cstr(e.message)) or message in strip(cstr(getattr(e, 'strerror', ''))): return True return False
def validate(self): """validate the email ids""" from frappe.utils import validate_email_add if not self.sender: self.sender = self.get_default_sender() validate_email_add(strip(self.sender), True) self.reply_to = validate_email_add(strip(self.reply_to) or self.sender, True) self.recipients = [strip(r) for r in self.recipients] self.cc = [strip(r) for r in self.cc] for e in self.recipients + (self.cc or []): validate_email_add(e, True)
def get_web_image(file_url: str) -> Tuple["ImageFile", str, str]: # download file_url = frappe.utils.get_url(file_url) r = requests.get(file_url, stream=True) try: r.raise_for_status() except HTTPError: if r.status_code == 404: frappe.msgprint(_("File '{0}' not found").format(file_url)) else: frappe.msgprint( _("Unable to read file format for {0}").format(file_url)) raise try: image = Image.open(BytesIO(r.content)) except Exception as e: frappe.msgprint(_("Image link '{0}' is not valid").format(file_url), raise_exception=e) try: filename, extn = file_url.rsplit("/", 1)[1].rsplit(".", 1) except ValueError: # the case when the file url doesn't have filename or extension # but is fetched due to a query string. example: https://encrypted-tbn3.gstatic.com/images?q=something filename = get_random_filename() extn = None extn = get_extension(filename, extn, response=r) if extn == "bin": extn = get_extension(filename, extn, content=r.content) or "png" filename = "/files/" + strip(unquote(filename)) return image, filename, extn
def find_parent_based_on_subject_and_sender(self, communication, email): '''Find parent document based on subject and sender match''' parent = None if self.append_to and self.sender_field: if self.subject_field: # try and match by subject and sender # if sent by same sender with same subject, # append it to old coversation subject = frappe.as_unicode(strip(re.sub(r"(^\s*(fw|fwd|wg)[^:]*:|\s*(re|aw)[^:]*:\s*)*", "", email.subject, 0, flags=re.IGNORECASE))) parent = frappe.db.get_all(self.append_to, filters={ self.sender_field: email.from_email, self.subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=60)).strftime(DATE_FORMAT)) }, fields="name") # match only subject field # when the from_email is of a user in the system # and subject is atleast 10 chars long if not parent and len(subject) > 10 and is_system_user(email.from_email): parent = frappe.db.get_all(self.append_to, filters={ self.subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=60)).strftime(DATE_FORMAT)) }, fields="name") if parent: parent = frappe._dict(doctype=self.append_to, name=parent[0].name) return parent
def make(self): """build into msg_root""" headers = { "Subject": strip(self.subject), "From": self.sender, "To": ', '.join(self.recipients) if self.expose_recipients == "header" else "<!--recipient-->", "Date": email.utils.formatdate(), "Reply-To": self.reply_to if self.reply_to else None, "CC": ', '.join(self.cc) if self.cc and self.expose_recipients == "header" else None, 'X-Frappe-Site': get_url(), } # reset headers as values may be changed. for key, val in iteritems(headers): self.set_header(key, val) # call hook to enable apps to modify msg_root before sending for hook in frappe.get_hooks("make_email_body_message"): frappe.get_attr(hook)(self)
def __init__(self, sender='', recipients=(), subject='', alternative=0, reply_to=None, cc=(), email_account=None, expose_recipients=None): from email.mime.multipart import MIMEMultipart from email import Charset Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') if isinstance(recipients, basestring): recipients = recipients.replace(';', ',').replace('\n', '') recipients = split_emails(recipients) # remove null recipients = filter(None, (strip(r) for r in recipients)) self.sender = sender self.reply_to = reply_to or sender self.recipients = recipients self.subject = subject self.expose_recipients = expose_recipients self.msg_root = MIMEMultipart('mixed') self.msg_multipart = MIMEMultipart('alternative') self.msg_root.attach(self.msg_multipart) self.cc = cc or [] self.html_set = False self.email_account = email_account or get_outgoing_email_account()
def __init__(self, sender='', recipients=(), subject='', alternative=0, reply_to=None, cc=(), bcc=(), email_account=None, expose_recipients=None): from email import charset as Charset Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') if isinstance(recipients, string_types): recipients = recipients.replace(';', ',').replace('\n', '') recipients = split_emails(recipients) # remove null recipients = filter(None, (strip(r) for r in recipients)) self.sender = sender self.reply_to = reply_to or sender self.recipients = recipients self.subject = subject self.expose_recipients = expose_recipients if PY3: self.msg_root = MIMEMultipart('mixed', policy=policy.SMTPUTF8) self.msg_alternative = MIMEMultipart('alternative', policy=policy.SMTPUTF8) else: self.msg_root = MIMEMultipart('mixed') self.msg_alternative = MIMEMultipart('alternative') self.msg_root.attach(self.msg_alternative) self.cc = cc or [] self.bcc = bcc or [] self.html_set = False self.email_account = email_account or get_outgoing_email_account(sender=sender)
def get_web_image(file_url): # download file_url = frappe.utils.get_url(file_url) r = requests.get(file_url, stream=True) try: r.raise_for_status() except requests.exceptions.HTTPError as e: if "404" in e.args[0]: frappe.msgprint(_("File '{0}' not found").format(file_url)) else: frappe.msgprint(_("Unable to read file format for {0}").format(file_url)) raise image = Image.open(StringIO(r.content)) try: filename, extn = file_url.rsplit("/", 1)[1].rsplit(".", 1) except ValueError: # the case when the file url doesn't have filename or extension # but is fetched due to a query string. example: https://encrypted-tbn3.gstatic.com/images?q=something filename = get_random_filename() extn = None extn = get_extension(filename, extn, r.content) filename = "/files/" + strip(unquote(filename)) return image, filename, extn
def get_web_image(file_url): # download file_url = frappe.utils.get_url(file_url) r = requests.get(file_url, stream=True) try: r.raise_for_status() except requests.exceptions.HTTPError as e: if "404" in e.args[0]: frappe.msgprint(_("File '{0}' not found").format(file_url)) else: frappe.msgprint( _("Unable to read file format for {0}").format(file_url)) raise image = Image.open(StringIO(frappe.safe_decode(r.content))) try: filename, extn = file_url.rsplit("/", 1)[1].rsplit(".", 1) except ValueError: # the case when the file url doesn't have filename or extension # but is fetched due to a query string. example: https://encrypted-tbn3.gstatic.com/images?q=something filename = get_random_filename() extn = None extn = get_extension(filename, extn, r.content) filename = "/files/" + strip(unquote(filename)) return image, filename, extn
def autoname(self): if frappe.db.get_default("item_naming_by") == "Naming Series": if self.variant_of: if not self.item_code: item_code_suffix = "" for attribute in self.attributes: attribute_abbr = frappe.db.get_value( "Item Attribute Value", { "parent": attribute.attribute, "attribute_value": attribute.attribute_value }, "abbr") item_code_suffix += "-" + str( attribute_abbr or attribute.attribute_value) self.item_code = str(self.variant_of) + item_code_suffix else: from frappe.model.naming import make_autoname self.item_code = make_autoname(self.naming_series + '.#####') elif not self.item_code: msgprint(_( "Item Code is mandatory because Item is not automatically numbered" ), raise_exception=1) self.item_code = strip(self.item_code) self.name = self.item_code
def validate(self): """validate the email ids""" from frappe.utils import validate_email_add if not self.sender: self.sender = self.get_default_sender() validate_email_add(strip(self.sender), True) self.reply_to = validate_email_add( strip(self.reply_to) or self.sender, True) self.recipients = [strip(r) for r in self.recipients] self.cc = [strip(r) for r in self.cc] for e in self.recipients + (self.cc or []): validate_email_add(e, True)
def __init__(self, sender='', recipients=(), subject='', alternative=0, reply_to=None, cc=(), bcc=(), email_account=None, expose_recipients=None): from email import charset as Charset Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') if isinstance(recipients, string_types): recipients = recipients.replace(';', ',').replace('\n', '') recipients = split_emails(recipients) # remove null recipients = filter(None, (strip(r) for r in recipients)) self.sender = sender self.reply_to = reply_to or sender self.recipients = recipients self.subject = subject self.expose_recipients = expose_recipients self.msg_root = MIMEMultipart('mixed') self.msg_alternative = MIMEMultipart('alternative') self.msg_root.attach(self.msg_alternative) self.cc = cc or [] self.bcc = bcc or [] self.html_set = False self.email_account = email_account or get_outgoing_email_account(sender=sender)
def find_parent_based_on_subject_and_sender(self, communication, email): '''Find parent document based on subject and sender match''' parent = None if self.append_to and self.sender_field: if self.subject_field: # try and match by subject and sender # if sent by same sender with same subject, # append it to old coversation subject = strip(re.sub("(^\s*(Fw|FW|fwd)[^:]*:|\s*(Re|RE)[^:]*:\s*)*", "", email.subject)) parent = frappe.db.get_all(self.append_to, filters={ self.sender_field: email.from_email, self.subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") # match only subject field # when the from_email is of a user in the system # and subject is atleast 10 chars long if not parent and len(subject) > 10 and is_system_user(email.from_email): parent = frappe.db.get_all(self.append_to, filters={ self.subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") if parent: parent = frappe.get_doc(self.append_to, parent[0].name) return parent
def write_translations_and_commit(): langs = frappe.db.sql_list("select name from tabLanguage") for app in get_apps_to_be_translated(): for lang in ['ar']: print("Writing for {0}-{1}".format(app, lang)) path = os.path.join(frappe.get_app_path(app, "translations", lang + ".csv")) google_translations = [] user_translations = [] translations = get_translations_for_export(app, lang) for translation in translations: if translation.translated_by_google: google_translations.append(translation) else: user_translations.append(translation) parent = None parent_dict = {} if '-' in lang: # get translation from parent # for example es and es-GT parent = lang.split('-')[0] parent_dict = { t.source_text: t.translated_text for t in get_translations_for_export(app, parent) } with open(path, 'w') as msgfile: w = writer(msgfile, lineterminator='\n') for t in google_translations: # only write if translation is different from parent if not parent or (t.translated_text != parent_dict.get(t.source_text)): position = t.position or '' translated_text = strip(t.translated_text or '') context = strip(t.context or '') w.writerow([position, t.source_text.replace('\n', '\\n'), translated_text.replace('\n', '\\n'), context]) make_a_commit(app, 'chore: Update translation') # commit per user translation for t in user_translations: if not parent or (t.translated_text != parent_dict.get(t.source_text)): position = t.position or '' translated_text = strip(t.translated_text or '') context = strip(t.context or '') with open(path, 'a') as msgfile: w = writer(msgfile, lineterminator='\n') w.writerow([position, t.source_text.replace('\n', '\\n'), translated_text.replace('\n', '\\n'), context]) make_a_commit(app, 'chore: Update translation', t.contributor_name or t.modified_by, t.contributor_email or 'Verifier')
def validate(self): """validate the Email Addresses""" from frappe.utils import validate_email_add if not self.sender: self.sender = self.email_account.default_sender validate_email_add(strip(self.sender), True) self.reply_to = validate_email_add(strip(self.reply_to) or self.sender, True) self.replace_sender() self.recipients = [strip(r) for r in self.recipients] self.cc = [strip(r) for r in self.cc] for e in self.recipients + (self.cc or []): validate_email_add(e, True)
def build_bcc(bcc): if isinstance(bcc, basestring): bcc = bcc.replace(';', ',').replace('\n', '') bcc = bcc.split(',') # remove null bcc = filter(None, (strip(r) for r in bcc)) return bcc
def autoname(self): self.coupon_name = strip(self.coupon_name) self.name = self.coupon_name if not self.coupon_code: if self.coupon_type == "Promotional": self.coupon_code =''.join([i for i in self.coupon_name if not i.isdigit()])[0:8].upper() elif self.coupon_type == "Gift Card": self.coupon_code = frappe.generate_hash()[:10].upper()
def is_temporary_system_problem(self, e): messages = ( "-ERR [SYS/TEMP] Temporary system problem. Please try again later.", "Connection timed out", ) for message in messages: if message in strip(cstr(e.message)): return True return False
def get_translation_dict_from_file(path, lang, app): """load translation dict from given path""" translation_map = {} if os.path.exists(path): csv_content = read_csv_file(path) for item in csv_content: if len(item)==3 and item[2]: key = item[0] + ':' + item[2] translation_map[key] = strip(item[1]) elif len(item) in [2, 3]: translation_map[item[0]] = strip(item[1]) elif item: raise Exception("Bad translation in '{app}' for language '{lang}': {values}".format( app=app, lang=lang, values=repr(item).encode("utf-8") )) return translation_map
def get_translation_dict_from_file(path, lang, app): """load translation dict from given path""" cleaned = {} if os.path.exists(path): csv_content = read_csv_file(path) for item in csv_content: if len(item)==3: # with file and line numbers cleaned[item[1]] = strip(item[2]) elif len(item)==2: cleaned[item[0]] = strip(item[1]) elif item: raise Exception("Bad translation in '{app}' for language '{lang}': {values}".format( app=app, lang=lang, values=repr(item).encode("utf-8") )) return cleaned
def get_context(context): context.javascript = frappe.db.get_single_value('Website Script', 'javascript') or "" theme = get_active_theme() js = strip(theme and theme.js or "") if js: context.javascript += "\n" + js if not frappe.conf.developer_mode: context["google_analytics_id"] = (frappe.db.get_single_value("Website Settings", "google_analytics_id") or frappe.conf.get("google_analytics_id"))
def get_translation_dict_from_file(path, lang, app): """load translation dict from given path""" cleaned = {} if os.path.exists(path): csv_content = read_csv_file(path) for item in csv_content: if len(item)==3: # with file and line numbers cleaned[item[1]] = strip(item[2]) elif len(item)==2: cleaned[item[0]] = strip(item[1]) else: raise Exception("Bad translation in '{app}' for language '{lang}': {values}".format( app=app, lang=lang, values=repr(item).encode("utf-8") )) return cleaned
def import_doc(d, defaults): doc = frappe.new_doc('Item') doc.cas_no = d.get('cas_no') doc.mdl_no = d.get('mdl_no') if doc.cas_no == 'NA': doc.cas_no = None if doc.mdl_no == 'NA': doc.mdl_no = None doc.description = d.get('description') if 'Synonym:' in doc.description: description = doc.description.split('Synonym:') doc.item_name = strip(description[1]) doc.description = strip(description[0]) + '\nSynonym: ' + doc.item_name if not (doc.cas_no and doc.mdl_no): # use synonym as item code for now doc.item_code = doc.item_name else: doc.item_name = doc.description doc.update(defaults) doc.insert() if d.get('image'): file_url = '/files/{0}'.format(d['image']) # attach image frappe.get_doc({ "doctype": "File", "file_url": file_url, "attached_to_doctype": "Item", "attached_to_name": doc.name }).insert() doc.image = file_url doc.save()
def make(self): """build into msg_root""" self.msg_root['Subject'] = strip(self.subject).encode("utf-8") self.msg_root['From'] = self.sender.encode("utf-8") self.msg_root['To'] = ', '.join(self.recipients).encode("utf-8") self.msg_root['Date'] = email.utils.formatdate() self.msg_root['Reply-To'] = self.reply_to.encode("utf-8") if self.cc: self.msg_root['CC'] = ', '.join(self.cc).encode("utf-8") # add frappe site header self.msg_root.add_header(b'X-Frappe-Site', get_url().encode('utf-8'))
def get_translation_dict_from_file(path, lang, app, throw=False): """load translation dict from given path""" translation_map = {} if os.path.exists(path): csv_content = read_csv_file(path) for item in csv_content: if len(item) == 3 and item[2]: key = item[0] + ":" + item[2] translation_map[key] = strip(item[1]) elif len(item) in [2, 3]: translation_map[item[0]] = strip(item[1]) elif item: msg = "Bad translation in '{app}' for language '{lang}': {values}".format( app=app, lang=lang, values=cstr(item)) frappe.log_error(message=msg, title="Error in translation file") if throw: frappe.throw(msg, title="Error in translation file") return translation_map
def validate(self): """validate the email ids""" from frappe.utils import validate_email_add def _validate(email): """validate an email field""" if email and not validate_email_add(email): throw(_("{0} is not a valid email id").format(email), frappe.InvalidEmailAddressError) return email if not self.sender: email_account = get_outgoing_email_account() self.sender = email.utils.formataddr((email_account.name, email_account.get("sender") or email_account.get("email_id"))) self.sender = _validate(strip(self.sender)) self.reply_to = _validate(strip(self.reply_to) or self.sender) self.recipients = [strip(r) for r in self.recipients] self.cc = [strip(r) for r in self.cc] for e in self.recipients + (self.cc or []): _validate(e)
def get_context(context): script_context = { "javascript": frappe.db.get_value('Website Script', None, 'javascript') } theme = get_active_theme() js = strip(theme and theme.js or "") if js: script_context["javascript"] += "\n" + js if not frappe.conf.developer_mode: script_context["google_analytics_id"] = frappe.db.get_value("Website Settings", "Website Settings", "google_analytics_id") return script_context
def get_context(context): context.javascript = frappe.db.get_single_value('Website Script', 'javascript') or "" theme = get_active_theme() js = strip(theme and theme.js or "") if js: context.javascript += "\n" + js if not frappe.conf.developer_mode: context['google_analytics_id'] = get_setting('google_analytics_id') context['google_analytics_anonymize_ip'] = get_setting( 'google_analytics_anonymize_ip')
def validate(self): if self.verified > 0: if frappe.db.get_value("User", frappe.session.user, "karma") < 100: frappe.throw(_("Only user with more than 100 karma can edit verified translations")) self.verified = 0 source_msg = frappe.db.get_value("Source Message", self.source, "message") if get_placeholders_count(source_msg) != get_placeholders_count(self.translated): frappe.throw(_("Number of placehodlers (eg, {0}) do not match the source message")) # strip whitespace and whitespace like characters self.translated = strip(self.translated)
def autoname(self): if frappe.db.get_default("item_naming_by") == "Naming Series": if self.variant_of: if not self.item_code: template_item_name = frappe.db.get_value("Item", self.variant_of, "item_name") self.item_code = make_variant_item_code(self.variant_of, template_item_name, self) else: from frappe.model.naming import set_name_by_naming_series set_name_by_naming_series(self) self.item_code = self.name self.item_code = strip(self.item_code) self.name = self.item_code
def write_csv(app, lang, path): translations = frappe.db.sql("""select source.position, source.message, translated.translated from `tabSource Message` source left join `tabTranslated Message` translated on (source.name=translated.source and translated.language = %s) where translated.name is not null and source.disabled != 1 and source.app = %s""", (lang, app)) with open(path, 'w') as msgfile: w = writer(msgfile, lineterminator='\n') for t in translations: w.writerow([t[0].encode('utf-8') if t[0] else '', t[1].encode('utf-8'), strip(t[2] or '').encode('utf-8')])
def write_csv(app, lang, path): translations = get_translations_for_export(app, lang) parent = None parent_dict = {} if '-' in lang: # get translation from parent # for example es and es-GT parent = lang.split('-')[0] parent_dict = {} for t in get_translations_for_export(app, parent): parent_dict[t.source_text] = t.translated_text with open(path, 'w') as msgfile: w = writer(msgfile, lineterminator='\n') for t in translations: # only write if translation is different from parent if (not parent) or (t.translated_text != parent_dict.get(t.source_text)): position = t.position or '' translated_text = strip(t.translated_text or '') context = strip(t.context or '') w.writerow([t.source_text.replace('\n', '\\n'), translated_text.replace('\n', '\\n'), context])
def autoname(self): if frappe.db.get_default("item_naming_by")=="Naming Series": if self.variant_of: if not self.item_code: self.item_code = make_variant_item_code(self.variant_of, self) else: from frappe.model.naming import make_autoname self.item_code = make_autoname(self.naming_series+'.#####') elif not self.item_code: msgprint(_("Item Code is mandatory because Item is not automatically numbered"), raise_exception=1) self.item_code = strip(self.item_code) self.name = self.item_code
def make_thumbnail(self): if self.file_url: if self.file_url.startswith("/files"): try: image = Image.open( frappe.get_site_path("public", self.file_url.lstrip("/"))) filename, extn = self.file_url.rsplit(".", 1) except IOError: frappe.msgprint( "Unable to read file format for {0}".format( self.file_url)) else: # downlaod file_url = frappe.utils.get_url(self.file_url) r = requests.get(file_url, stream=True) try: r.raise_for_status() except requests.exceptions.HTTPError, e: if "404" in e.args[0]: frappe.throw( _("File '{0}' not found").format(self.file_url)) else: raise image = Image.open(StringIO.StringIO(r.content)) filename, extn = self.file_url.rsplit("/", 1)[1].rsplit(".", 1) mimetype = mimetypes.guess_type(filename + "." + extn)[0] if mimetype is None or not mimetype.startswith("image/"): # detect file extension by reading image header properties extn = imghdr.what(filename + "." + extn, h=r.content) filename = "/files/" + strip(urllib.unquote(filename)) thumbnail = ImageOps.fit(image, (300, 300), Image.ANTIALIAS) thumbnail_url = filename + "_small." + extn path = os.path.abspath( frappe.get_site_path("public", thumbnail_url.lstrip("/"))) try: thumbnail.save(path) self.db_set("thumbnail_url", thumbnail_url) except IOError: frappe.msgprint( "Unable to write file format for {0}".format(path)) return thumbnail_url
def process_args(args): if not args: args = frappe.local.form_dict if isinstance(args, basestring): args = json.loads(args) args = frappe._dict(args) # strip the whitespace for key, value in args.items(): if isinstance(value, basestring): args[key] = strip(value) return args
def load_lang(lang, apps=None): """Combine all translations from `.csv` files in all `apps`""" out = {} for app in (apps or frappe.get_all_apps(True)): path = os.path.join(frappe.get_pymodule_path(app), "translations", lang + ".csv") if os.path.exists(path): csv_content = read_csv_file(path) cleaned = {} for item in csv_content: if len(item)==3: # with file and line numbers cleaned[item[1]] = strip(item[2]) elif len(item)==2: cleaned[item[0]] = strip(item[1]) else: raise Exception("Bad translation in '{app}' for language '{lang}': {values}".format( app=app, lang=lang, values=repr(item).encode("utf-8") )) out.update(cleaned) return out
def autoname(self): if frappe.db.get_default("item_naming_by") == "Naming Series": if self.variant_of: if not self.item_code: template_item_name = frappe.db.get_value("Item", self.variant_of, "item_name") self.item_code = make_variant_item_code(self.variant_of, template_item_name, self) else: from frappe.model.naming import set_name_by_naming_series set_name_by_naming_series(self) self.item_code = self.name elif not self.item_code: msgprint(_("Item Code is mandatory because Item is not automatically numbered"), raise_exception=1) self.item_code = strip(self.item_code) self.name = self.item_code
def make_thumbnail(self): if self.file_url: if self.file_url.startswith("/files"): try: image = Image.open(frappe.get_site_path("public", self.file_url.lstrip("/"))) filename, extn = self.file_url.rsplit(".", 1) except IOError: frappe.msgprint("Unable to read file format for {0}".format(self.file_url)) else: # downlaod file_url = frappe.utils.get_url(self.file_url) r = requests.get(file_url, stream=True) try: r.raise_for_status() except requests.exceptions.HTTPError, e: if "404" in e.args[0]: frappe.throw(_("File '{0}' not found").format(self.file_url)) else: raise image = Image.open(StringIO.StringIO(r.content)) filename, extn = self.file_url.rsplit("/", 1)[1].rsplit(".", 1) mimetype = mimetypes.guess_type(filename + "." + extn)[0] if mimetype is None or not mimetype.startswith("image/"): # detect file extension by reading image header properties extn = imghdr.what(filename + "." + extn, h=r.content) filename = "/files/" + strip(urllib.unquote(filename)) thumbnail = ImageOps.fit( image, (300, 300), Image.ANTIALIAS ) thumbnail_url = filename + "_small." + extn path = os.path.abspath(frappe.get_site_path("public", thumbnail_url.lstrip("/"))) try: thumbnail.save(path) self.db_set("thumbnail_url", thumbnail_url) except IOError: frappe.msgprint("Unable to write file format for {0}".format(path)) return thumbnail_url
def make(self): """build into msg_root""" headers = { "Subject": strip(self.subject).encode("utf-8"), "From": self.sender.encode("utf-8"), "To": ', '.join(self.recipients).encode("utf-8"), "Date": email.utils.formatdate(), "Reply-To": self.reply_to.encode("utf-8") if self.reply_to else None, "CC": ', '.join(self.cc).encode("utf-8") if self.cc else None, b'X-Frappe-Site': get_url().encode('utf-8') } # reset headers as values may be changed. for key, val in headers.iteritems(): if self.msg_root.has_key(key): del self.msg_root[key] self.msg_root[key] = val
def write_csv(app, lang, path): translations = frappe.db.sql( """select source.position, source.message, translated.translated from `tabSource Message` source left join `tabTranslated Message` translated on (source.name=translated.source and translated.language = %s) where translated.name is not null and source.disabled != 1 and source.app = %s""", (lang, app)) with open(path, 'w') as msgfile: w = writer(msgfile, lineterminator='\n') for t in translations: w.writerow([ t[0].encode('utf-8') if t[0] else '', t[1].encode('utf-8'), strip(t[2] or '').encode('utf-8') ])
def autoname(self): if frappe.db.get_default("item_naming_by")=="Naming Series": if self.variant_of: if not self.item_code: item_code_suffix = "" for attribute in self.attributes: attribute_abbr = frappe.db.get_value("Item Attribute Value", {"parent": attribute.attribute, "attribute_value": attribute.attribute_value}, "abbr") item_code_suffix += "-" + str(attribute_abbr or attribute.attribute_value) self.item_code = str(self.variant_of) + item_code_suffix else: from frappe.model.naming import make_autoname self.item_code = make_autoname(self.naming_series+'.#####') elif not self.item_code: msgprint(_("Item Code is mandatory because Item is not automatically numbered"), raise_exception=1) self.item_code = strip(self.item_code) self.name = self.item_code
def make(self): """build into msg_root""" headers = { "Subject": strip(self.subject), "From": self.sender, "To": ', '.join(self.recipients) if self.expose_recipients=="header" else "<!--recipient-->", "Date": email.utils.formatdate(), "Reply-To": self.reply_to if self.reply_to else None, "CC": ', '.join(self.cc) if self.cc and self.expose_recipients=="header" else None, 'X-Frappe-Site': get_url(), } # reset headers as values may be changed. for key, val in iteritems(headers): self.set_header(key, val) # call hook to enable apps to modify msg_root before sending for hook in frappe.get_hooks("make_email_body_message"): frappe.get_attr(hook)(self)
def write_csv(app, lang, path): translations = get_translations_for_export(app, lang) parent = None parent_dict = {} if '-' in lang: # get translation from parent # for example es and es-GT parent = lang.split('-')[0] parent_dict = {} for t in get_translations_for_export(app, parent): parent_dict[t[1]] = t[2] with open(path, 'w') as msgfile: w = writer(msgfile, lineterminator='\n') for t in translations: # only write if translation is different from parent if (not parent) or (t[2] != parent_dict.get(t[1])): w.writerow([t[0] if t[0] else '', t[1], strip(t[2] or '')])
def make(self): """build into msg_root""" headers = { "Subject": strip(self.subject).encode("utf-8"), "From": self.sender.encode("utf-8"), "To": ", ".join(self.recipients).encode("utf-8"), "Date": email.utils.formatdate(), "Reply-To": self.reply_to.encode("utf-8") if self.reply_to else None, "CC": ", ".join(self.cc).encode("utf-8") if self.cc else None, b"X-Frappe-Site": get_url().encode("utf-8"), } # reset headers as values may be changed. for key, val in headers.iteritems(): if self.msg_root.has_key(key): del self.msg_root[key] self.msg_root[key] = val # call hook to enable apps to modify msg_root before sending for hook in frappe.get_hooks("make_email_body_message"): frappe.get_attr(hook)(self)
def __init__(self, sender='', recipients=(), subject='', alternative=0, reply_to=None, cc=()): from email.mime.multipart import MIMEMultipart from email import Charset Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') if isinstance(recipients, basestring): recipients = recipients.replace(';', ',').replace('\n', '') recipients = recipients.split(',') # remove null recipients = filter(None, (strip(r) for r in recipients)) self.sender = sender self.reply_to = reply_to or sender self.recipients = recipients self.subject = subject self.msg_root = MIMEMultipart('mixed') self.msg_multipart = MIMEMultipart('alternative') self.msg_root.attach(self.msg_multipart) self.cc = cc or [] self.html_set = False
def make_thumbnail(self): from PIL import Image, ImageOps import os if self.file_url: if self.file_url.startswith("/files"): try: image = Image.open(frappe.get_site_path("public", self.file_url.lstrip("/"))) filename, extn = self.file_url.rsplit(".", 1) except IOError: frappe.msgprint("Unable to read file format for {0}".format(self.file_url)) else: # downlaod import requests, StringIO file_url = frappe.utils.get_url(self.file_url) r = requests.get(file_url, stream=True) r.raise_for_status() image = Image.open(StringIO.StringIO(r.content)) filename, extn = self.file_url.rsplit("/", 1)[1].rsplit(".", 1) filename = "/files/" + strip(urllib.unquote(filename)) thumbnail = ImageOps.fit( image, (300, 300), Image.ANTIALIAS ) thumbnail_url = filename + "_small." + extn path = os.path.abspath(frappe.get_site_path("public", thumbnail_url.lstrip("/"))) try: thumbnail.save(path) self.db_set("thumbnail_url", thumbnail_url) except IOError: frappe.msgprint("Unable to write file format for {0}".format(path)) return thumbnail_url
def __init__(self, sender="", recipients=(), subject="", alternative=0, reply_to=None, cc=()): from email.mime.multipart import MIMEMultipart from email import Charset Charset.add_charset("utf-8", Charset.QP, Charset.QP, "utf-8") if isinstance(recipients, basestring): recipients = recipients.replace(";", ",").replace("\n", "") recipients = split_emails(recipients) # remove null recipients = filter(None, (strip(r) for r in recipients)) self.sender = sender self.reply_to = reply_to or sender self.recipients = recipients self.subject = subject self.msg_root = MIMEMultipart("mixed") self.msg_multipart = MIMEMultipart("alternative") self.msg_root.attach(self.msg_multipart) self.cc = cc or [] self.html_set = False
def has_login_limit_exceeded(self, e): return "-ERR Exceeded the login limit" in strip(cstr(e.message))
def set_thread(self, communication, email): """Appends communication to parent based on thread ID. Will extract parent communication and will link the communication to the reference of that communication. Also set the status of parent transaction to Open or Replied. If no thread id is found and `append_to` is set for the email account, it will create a new parent transaction (e.g. Issue)""" in_reply_to = (email.mail.get("In-Reply-To") or "").strip(" <>") parent = None if self.append_to: # set subject_field and sender_field meta_module = frappe.get_meta_module(self.append_to) meta = frappe.get_meta(self.append_to) subject_field = getattr(meta_module, "subject_field", "subject") if not meta.get_field(subject_field): subject_field = None sender_field = getattr(meta_module, "sender_field", "sender") if not meta.get_field(sender_field): sender_field = None if in_reply_to: if "@{0}".format(frappe.local.site) in in_reply_to: # reply to a communication sent from the system in_reply_to, domain = in_reply_to.split("@", 1) if frappe.db.exists("Communication", in_reply_to): parent = frappe.get_doc("Communication", in_reply_to) # set in_reply_to of current communication communication.in_reply_to = in_reply_to if parent.reference_name: parent = frappe.get_doc(parent.reference_doctype, parent.reference_name) if not parent and self.append_to and sender_field: if subject_field: # try and match by subject and sender # if sent by same sender with same subject, # append it to old coversation subject = strip(re.sub("^\s*(Re|RE)[^:]*:\s*", "", email.subject)) parent = frappe.db.get_all(self.append_to, filters={ sender_field: email.from_email, subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") # match only subject field # when the from_email is of a user in the system # and subject is atleast 10 chars long if not parent and len(subject) > 10 and is_system_user(email.from_email): parent = frappe.db.get_all(self.append_to, filters={ subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") if parent: parent = frappe.get_doc(self.append_to, parent[0].name) if not parent and self.append_to and self.append_to!="Communication": # no parent found, but must be tagged # insert parent type doc parent = frappe.new_doc(self.append_to) if subject_field: parent.set(subject_field, email.subject) if sender_field: parent.set(sender_field, email.from_email) parent.flags.ignore_mandatory = True try: parent.insert(ignore_permissions=True) except frappe.DuplicateEntryError: # try and find matching parent parent_name = frappe.db.get_value(self.append_to, {sender_field: email.from_email}) if parent_name: parent.name = parent_name else: parent = None # NOTE if parent isn't found and there's no subject match, it is likely that it is a new conversation thread and hence is_first = True communication.is_first = True if parent: communication.reference_doctype = parent.doctype communication.reference_name = parent.name
if "404" in e.args[0]: frappe.msgprint(_("File '{0}' not found").format(file_url)) else: frappe.msgprint("Unable to read file format for {0}".format(file_url)) raise image = Image.open(StringIO.StringIO(r.content)) try: filename, extn = file_url.rsplit("/", 1)[1].rsplit(".", 1) except ValueError: # the case when the file url doesn't have filename or extension # but is fetched due to a query string. example: https://encrypted-tbn3.gstatic.com/images?q=something filename = get_random_filename() extn = None extn = get_extension(filename, extn, r.content) filename = "/files/" + strip(urllib.unquote(filename)) return image, filename, extn def check_file_permission(file_url): for file in frappe.get_all("File", filters={"file_url": file_url, "is_private": 1}, fields=["name", "attached_to_doctype", "attached_to_name"]): if (frappe.has_permission("File", ptype="read", doc=file.name) or frappe.has_permission(file.attached_to_doctype, ptype="read", doc=file.attached_to_name)): return True raise frappe.PermissionError