def get_cc(doc, recipients=None, fetched_from_email_account=False): """Build a list of email addresses for CC""" # get a copy of CC list cc = split_emails(doc.cc) if doc.reference_doctype and doc.reference_name: if fetched_from_email_account: # if it is a fetched email, add follows to CC cc.append(get_owner_email(doc)) cc += get_assignees(doc) if getattr(doc, "send_me_a_copy", False) and doc.sender not in cc: cc.append(doc.sender) if cc: # exclude unfollows, recipients and unsubscribes exclude = [] #added to remove account check exclude += [d[0] for d in frappe.db.get_all("User", ["name"], {"thread_notify": 0}, as_list=True)] exclude += [(parse_addr(email)[1] or "").lower() for email in recipients] if fetched_from_email_account: # exclude sender when pulling email exclude += [parse_addr(doc.sender)[1]] if doc.reference_doctype and doc.reference_name: exclude += [d[0] for d in frappe.db.get_all("Email Unsubscribe", ["email"], {"reference_doctype": doc.reference_doctype, "reference_name": doc.reference_name}, as_list=True)] cc = filter_email_list(doc, cc, exclude, is_cc=True) return cc
def get_bcc(doc, recipients=None, fetched_from_email_account=False): """Build a list of email addresses for BCC""" bcc = split_emails(doc.bcc) if doc.reference_doctype and doc.reference_name: if fetched_from_email_account: bcc.append(get_owner_email(doc)) bcc += get_assignees(doc) if bcc: exclude = [] exclude += [d[0] for d in frappe.db.get_all("User", ["name"], {"thread_notify": 0}, as_list=True)] exclude += [(parse_addr(email)[1] or "").lower() for email in recipients] if fetched_from_email_account: # exclude sender when pulling email exclude += [parse_addr(doc.sender)[1]] if doc.reference_doctype and doc.reference_name: exclude += [d[0] for d in frappe.db.get_all("Email Unsubscribe", ["email"], {"reference_doctype": doc.reference_doctype, "reference_name": doc.reference_name}, as_list=True)] bcc = filter_email_list(doc, bcc, exclude, is_bcc=True) return bcc
def get_cc(doc, recipients=None, fetched_from_email_account=False): """Build a list of email addresses for CC""" # get a copy of CC list cc = split_emails(doc.cc) if doc.reference_doctype and doc.reference_name: if fetched_from_email_account: # if it is a fetched email, add follows to CC cc.append(get_owner_email(doc)) cc += get_assignees(doc) if getattr(doc, "send_me_a_copy", False) and doc.sender not in cc: cc.append(doc.sender) if cc: # exclude unfollows, recipients and unsubscribes exclude = [] #added to remove account check exclude += [d[0] for d in frappe.db.get_all("User", ["name"], {"thread_notify": 0}, as_list=True)] exclude += [(parse_addr(email)[1] or "").lower() for email in recipients] if fetched_from_email_account: # exclude sender when pulling email exclude += [parse_addr(doc.sender)[1]] if doc.reference_doctype and doc.reference_name: exclude += [d[0] for d in frappe.db.get_all("Email Unsubscribe", ["email"], {"reference_doctype": doc.reference_doctype, "reference_name": doc.reference_name}, as_list=True)] cc = filter_email_list(doc, cc, exclude, is_cc=True) return cc
def get_bcc(doc, recipients=None, fetched_from_email_account=False): """Build a list of email addresses for BCC""" bcc = split_emails(doc.bcc) if bcc: exclude = [] exclude += [ d[0] for d in frappe.db.get_all("User", ["email"], {"thread_notify": 0}, as_list=True) ] exclude += [(parse_addr(email)[1] or "").lower() for email in recipients] if fetched_from_email_account: # exclude sender when pulling email exclude += [parse_addr(doc.sender)[1]] if doc.reference_doctype and doc.reference_name: exclude += [ d[0] for d in frappe.db.get_all("Email Unsubscribe", ["email"], { "reference_doctype": doc.reference_doctype, "reference_name": doc.reference_name }, as_list=True) ] bcc = filter_email_list(doc, bcc, exclude, is_bcc=True) return bcc
def get_email_with_displayname(self, email_address): """Returns email address after adding displayname. """ display_name, email = parse_addr(email_address) if display_name and display_name != email: return email_address # emailid to emailid with display name map. email_map = {parse_addr(email)[1]: email for email in self.get_all_email_addresses()} return email_map.get(email, email)
def filter_email_list(doc, email_list, exclude, is_cc=False): # temp variables filtered = [] email_address_list = [] for email in list(set(email_list)): email_address = (parse_addr(email)[1] or "").lower() if not email_address: continue # this will be used to eventually find email addresses that aren't sent to doc.all_email_addresses.append(email_address) if (email in exclude) or (email_address in exclude): continue if is_cc: is_user_enabled = frappe.db.get_value("User", email_address, "enabled") if is_user_enabled==0: # don't send to disabled users continue # make sure of case-insensitive uniqueness of email address if email_address not in email_address_list: # append the full email i.e. "Human <*****@*****.**>" filtered.append(email) email_address_list.append(email_address) doc.sent_email_addresses.extend(email_address_list) return filtered
def set_sender_full_name(self): if not self.sender_full_name and self.sender: if self.sender == "Administrator": self.sender_full_name = frappe.db.get_value( "User", "Administrator", "full_name") self.sender = frappe.db.get_value("User", "Administrator", "email") elif self.sender == "Guest": self.sender_full_name = self.sender self.sender = None else: if self.sent_or_received == "Sent": validate_email_address(self.sender, throw=True) sender_name, sender_email = parse_addr(self.sender) if sender_name == sender_email: sender_name = None self.sender = sender_email self.sender_full_name = sender_name if not self.sender_full_name: self.sender_full_name = frappe.db.get_value( "User", self.sender, "full_name") if not self.sender_full_name: first_name, last_name = frappe.db.get_value( "Contact", filters={"email_id": sender_email}, fieldname=["first_name", "last_name"]) or [None, None] self.sender_full_name = (first_name or "") + (last_name or "") if not self.sender_full_name: self.sender_full_name = sender_email
def filter_email_list(doc, email_list, exclude, is_cc=False): # temp variables filtered = [] email_address_list = [] for email in list(set(email_list)): email_address = (parse_addr(email)[1] or "").lower() if not email_address: continue # this will be used to eventually find email addresses that aren't sent to doc.all_email_addresses.append(email_address) if (email in exclude) or (email_address in exclude): continue if is_cc: is_user_enabled = frappe.db.get_value("User", email_address, "enabled") if is_user_enabled==0: # don't send to disabled users continue # make sure of case-insensitive uniqueness of email address if email_address not in email_address_list: # append the full email i.e. "Human <*****@*****.**>" filtered.append(email) email_address_list.append(email_address) doc.sent_email_addresses.extend(email_address_list) return filtered
def replace_sender(self): if cint(self.email_account.always_use_account_email_id_as_sender): self.set_header('X-Original-From', self.sender) sender_name, sender_email = parse_addr(self.sender) self.sender = email.utils.formataddr( (str(Header(sender_name or self.email_account.name, 'utf-8')), self.email_account.email_id))
def import_from(self, doctype): """Extract Email Addresses from given doctype and add them to the current list""" meta = frappe.get_meta(doctype) email_field = [d.fieldname for d in meta.fields if d.fieldtype in ("Data", "Small Text", "Text", "Code") and d.options=="Email"][0] unsubscribed_field = "unsubscribed" if meta.get_field("unsubscribed") else None added = 0 for user in frappe.db.get_all(doctype, [email_field, unsubscribed_field or "name"]): try: email = parse_addr(user.get(email_field))[1] if user.get(email_field) else None if email: frappe.get_doc({ "doctype": "Email Group Member", "email_group": self.name, "email": email, "unsubscribed": user.get(unsubscribed_field) if unsubscribed_field else 0 }).insert(ignore_permissions=True) added += 1 except frappe.UniqueValidationError: pass frappe.msgprint(_("{0} subscribers added").format(added)) return self.update_total_subscribers()
def get_owners(cls, filters=None): """Returns list of owners after applying filters on todo's. """ rows = frappe.get_all(cls.DocType, filters=filters or {}, fields=['owner']) return [parse_addr(row.owner)[1] for row in rows if row.owner]
def import_from(self, doctype): """Extract Email Addresses from given doctype and add them to the current list""" meta = frappe.get_meta(doctype) email_field = [d.fieldname for d in meta.fields if d.fieldtype in ("Data", "Small Text", "Text", "Code") and d.options=="Email"][0] unsubscribed_field = "unsubscribed" if meta.get_field("unsubscribed") else None added = 0 for user in frappe.db.get_all(doctype, [email_field, unsubscribed_field or "name"]): try: email = parse_addr(user.get(email_field))[1] if user.get(email_field) else None if email: frappe.get_doc({ "doctype": "Email Group Member", "email_group": self.name, "email": email, "unsubscribed": user.get(unsubscribed_field) if unsubscribed_field else 0 }).insert(ignore_permissions=True) added += 1 except frappe.UniqueValidationError: pass frappe.msgprint(_("{0} subscribers added").format(added)) return self.update_total_subscribers()
def set_sender_full_name(self): if not self.sender_full_name and self.sender: if self.sender == "Administrator": self.sender_full_name = frappe.db.get_value("User", "Administrator", "full_name") self.sender = frappe.db.get_value("User", "Administrator", "email") elif self.sender == "Guest": self.sender_full_name = self.sender self.sender = None else: if self.sent_or_received=='Sent': validate_email_address(self.sender, throw=True) sender_name, sender_email = parse_addr(self.sender) if sender_name == sender_email: sender_name = None self.sender = sender_email self.sender_full_name = sender_name if not self.sender_full_name: self.sender_full_name = frappe.db.get_value('User', self.sender, 'full_name') if not self.sender_full_name: first_name, last_name = frappe.db.get_value('Contact', filters={'email_id': sender_email}, fieldname=['first_name', 'last_name'] ) or [None, None] self.sender_full_name = (first_name or '') + (last_name or '') if not self.sender_full_name: self.sender_full_name = sender_email
def set_from(self): # gmail mailing-list compatibility # use X-Original-Sender if available, as gmail sometimes modifies the 'From' _from_email = self.decode_email(self.mail.get("X-Original-From") or self.mail["From"]) _reply_to = self.decode_email(self.mail.get("Reply-To")) if _reply_to and not frappe.db.get_value('Email Account', {"email_id":_reply_to}, 'email_id'): self.from_email = extract_email_id(_reply_to) else: self.from_email = extract_email_id(_from_email) if self.from_email: self.from_email = self.from_email.lower() self.from_real_name = parse_addr(_from_email)[0] if "@" in _from_email else _from_email
def _get_emails_list(emails=None, exclude_displayname=False): """Returns list of emails from given email string. * Removes duplicate mailids * Removes display name from email address if exclude_displayname is True """ emails = split_emails(emails) if isinstance(emails, str) else (emails or []) if exclude_displayname: return [ email.lower() for email in set([parse_addr(email)[1] for email in emails]) if email ] return [email.lower() for email in set(emails) if email]
def set_from(self): # gmail mailing-list compatibility # use X-Original-Sender if available, as gmail sometimes modifies the 'From' _from_email = self.decode_email(self.mail.get("X-Original-From") or self.mail["From"]) _reply_to = self.decode_email(self.mail.get("Reply-To")) if _reply_to and not frappe.db.get_value('Email Account', {"email_id":_reply_to}, 'email_id'): self.from_email = extract_email_id(_reply_to) else: self.from_email = extract_email_id(_from_email) if self.from_email: self.from_email = self.from_email.lower() self.from_real_name = parse_addr(_from_email)[0] if "@" in _from_email else _from_email
def update_customer_details(existing_so: str, order: "ShipStationOrder"): existing_so_doc: "SalesOrder" = frappe.get_doc("Sales Order", existing_so) email_id, user_name = parse_addr(existing_so_doc.amazon_customer) if email_id: contact = create_contact(order, email_id) existing_so_doc.contact_person = contact.name existing_so_doc.shipstation_order_id = order.order_id existing_so_doc.has_pii = True if order.bill_to and order.bill_to.street1: if existing_so_doc.customer_address: bill_address = update_address( order.bill_to, existing_so_doc.customer_address, order.customer_email, "Billing", ) else: bill_address = create_address( order.bill_to, existing_so_doc.amazon_customer, order.customer_email, "Billing", ) existing_so_doc.customer_address = bill_address.name if order.ship_to and order.ship_to.street1: if existing_so_doc.shipping_address_name: ship_address = update_address( order.ship_to, existing_so_doc.shipping_address_name, order.customer_email, "Shipping", ) else: ship_address = create_address( order.ship_to, existing_so_doc.amazon_customer, order.customer_email, "Shipping", ) existing_so_doc.shipping_address_name = ship_address.name existing_so_doc.flags.ignore_validate_update_after_submit = True existing_so_doc.run_method("set_customer_address") existing_so_doc.save() return existing_so_doc
def set_sender_full_name(self): if not self.sender_full_name and self.sender: if self.sender == "Administrator": self.sender_full_name = frappe.db.get_value("User", "Administrator", "full_name") self.sender = frappe.db.get_value("User", "Administrator", "email") elif self.sender == "Guest": self.sender_full_name = self.sender self.sender = None else: if self.sent_or_received=='Sent': validate_email_add(self.sender, throw=True) sender_name, sender_email = parse_addr(self.sender) if sender_name == sender_email: sender_name = None self.sender = sender_email self.sender_full_name = sender_name or get_fullname(frappe.session.user) if frappe.session.user!='Administrator' else None
def set_sender_full_name(self): if not self.sender_full_name and self.sender: if self.sender == "Administrator": self.sender_full_name = frappe.db.get_value("User", "Administrator", "full_name") self.sender = frappe.db.get_value("User", "Administrator", "email") elif self.sender == "Guest": self.sender_full_name = self.sender self.sender = None else: if self.sent_or_received=='Sent': validate_email_add(self.sender, throw=True) sender_name, sender_email = parse_addr(self.sender) if sender_name == sender_email: sender_name = None self.sender = sender_email self.sender_full_name = sender_name or frappe.db.exists("Contact", {"email_id": sender_email}) or sender_email
def set_sender_full_name(self): if not self.sender_full_name and self.sender: if self.sender == "Administrator": self.sender_full_name = frappe.db.get_value("User", "Administrator", "full_name") self.sender = frappe.db.get_value("User", "Administrator", "email") elif self.sender == "Guest": self.sender_full_name = self.sender self.sender = None else: if self.sent_or_received=='Sent': validate_email_add(self.sender, throw=True) sender_name, sender_email = parse_addr(self.sender) if sender_name == sender_email: sender_name = None self.sender = sender_email self.sender_full_name = sender_name or get_fullname(frappe.session.user) if frappe.session.user!='Administrator' else None
def get_outgoing_email_account(raise_exception_not_set=True, append_to=None, sender=None): """Returns outgoing email account based on `append_to` or the default outgoing account. If default outgoing account is not found, it will try getting settings from `site_config.json`.""" sender_email_id = None if sender: sender_email_id = parse_addr(sender)[1] if not getattr(frappe.local, "outgoing_email_account", None): frappe.local.outgoing_email_account = {} if not frappe.local.outgoing_email_account.get(append_to) \ or frappe.local.outgoing_email_account.get(sender_email_id) \ or frappe.local.outgoing_email_account.get("default"): email_account = None if append_to: # append_to is only valid when enable_incoming is checked email_account = _get_email_account({"enable_outgoing": 1, "enable_incoming": 1, "append_to": append_to}) if not email_account and sender_email_id: # check if the sender has email account with enable_outgoing email_account = _get_email_account({"enable_outgoing": 1, "email_id": sender_email_id}) if not email_account: # sender don't have the outging email account sender_email_id = None email_account = get_default_outgoing_email_account(raise_exception_not_set=raise_exception_not_set) if not email_account and raise_exception_not_set and cint(frappe.db.get_single_value('System Settings', 'setup_complete')): frappe.throw(_("Please setup default Email Account from Setup > Email > Email Account"), frappe.OutgoingEmailError) if email_account: if email_account.enable_outgoing and not getattr(email_account, 'from_site_config', False): raise_exception = True if email_account.smtp_server in ['localhost','127.0.0.1']: raise_exception = False email_account.password = email_account.get_password(raise_exception=raise_exception) email_account.default_sender = email.utils.formataddr((email_account.name, email_account.get("email_id"))) frappe.local.outgoing_email_account[append_to or sender_email_id or "default"] = email_account return frappe.local.outgoing_email_account.get(append_to) \ or frappe.local.outgoing_email_account.get(sender_email_id) \ or frappe.local.outgoing_email_account.get("default")
def get_outgoing_email_account(raise_exception_not_set=True, append_to=None, sender=None): """Returns outgoing email account based on `append_to` or the default outgoing account. If default outgoing account is not found, it will try getting settings from `site_config.json`.""" sender_email_id = None if sender: sender_email_id = parse_addr(sender)[1] if not getattr(frappe.local, "outgoing_email_account", None): frappe.local.outgoing_email_account = {} if not frappe.local.outgoing_email_account.get(append_to) \ or frappe.local.outgoing_email_account.get(sender_email_id) \ or frappe.local.outgoing_email_account.get("default"): email_account = None if append_to: # append_to is only valid when enable_incoming is checked email_account = _get_email_account({"enable_outgoing": 1, "enable_incoming": 1, "append_to": append_to}) if not email_account and sender_email_id: # check if the sender has email account with enable_outgoing email_account = _get_email_account({"enable_outgoing": 1, "email_id": sender_email_id}) if not email_account: # sender don't have the outging email account sender_email_id = None email_account = get_default_outgoing_email_account(raise_exception_not_set=raise_exception_not_set) if not email_account and raise_exception_not_set and cint(frappe.db.get_single_value('System Settings', 'setup_complete')): frappe.throw(_("Please setup default Email Account from Setup > Email > Email Account"), frappe.OutgoingEmailError) if email_account: if email_account.enable_outgoing and not getattr(email_account, 'from_site_config', False): raise_exception = True if email_account.smtp_server in ['localhost','127.0.0.1']: raise_exception = False email_account.password = email_account.get_password(raise_exception=raise_exception) email_account.default_sender = email.utils.formataddr((email_account.name, email_account.get("email_id"))) frappe.local.outgoing_email_account[append_to or sender_email_id or "default"] = email_account return frappe.local.outgoing_email_account.get(append_to) \ or frappe.local.outgoing_email_account.get(sender_email_id) \ or frappe.local.outgoing_email_account.get("default")
def create_lead(email_id): """create a lead if it does not exist""" from frappe.model.naming import get_default_naming_series full_name, email_id = parse_addr(email_id) if frappe.db.get_value("Lead", {"email_id": email_id}): return lead = frappe.get_doc({ "doctype": "Lead", "email_id": email_id, "lead_name": full_name or email_id, "status": "Lead", "naming_series": get_default_naming_series("Lead"), "company": frappe.db.get_default("Company"), "source": "Email" }) lead.insert()
def create_lead(email_id): """create a lead if it does not exist""" from frappe.model.naming import get_default_naming_series full_name, email_id = parse_addr(email_id) if frappe.db.get_value("Lead", {"email_id": email_id}): return lead = frappe.get_doc({ "doctype": "Lead", "email_id": email_id, "lead_name": full_name or email_id, "status": "Lead", "naming_series": get_default_naming_series("Lead"), "company": frappe.db.get_default("Company"), "source": "Email" }) lead.insert()
def create_customer(order: "ShipStationOrder"): customer_id = (order.customer_id or order.customer_email or order.ship_to.name or frappe.generate_hash("", 10)) customer_name = (order.customer_email or order.customer_id or order.ship_to.name or customer_id) if frappe.db.exists("Customer", customer_name): return frappe.get_doc("Customer", customer_name) cust = frappe.new_doc("Customer") cust.shipstation_customer_id = customer_id cust.customer_name = customer_name cust.customer_type = "Individual" cust.customer_group = "ShipStation" cust.territory = "United States" cust.save() frappe.db.commit() email_id, user_name = parse_addr(customer_name) if email_id: customer_primary_contact = create_contact(order, email_id) if customer_primary_contact: cust.customer_primary_contact = customer_primary_contact.name if order.ship_to.street1: create_address(order.ship_to, customer_name, order.customer_email, "Shipping").name if order.bill_to.street1: create_address(order.bill_to, order.customer_username, order.customer_email, "Billing").name try: cust.save() return cust except Exception as e: frappe.log_error(title="Error saving Shipstation Customer", message=e)
def sender_mailid(self): return parse_addr(self.sender)[1] if self.sender else ""
def replace_sender_name(self): if cint(self.email_account.always_use_account_name_as_sender_name): self.set_header("X-Original-From", self.sender) sender_name, sender_email = parse_addr(self.sender) self.sender = email.utils.formataddr( (str(Header(self.email_account.name, "utf-8")), sender_email))
def get_outgoing_email_account(raise_exception_not_set=True, append_to=None, sender=None): """Returns outgoing email account based on `append_to` or the default outgoing account. If default outgoing account is not found, it will try getting settings from `site_config.json`.""" sender_email_id = None _email_account = None if sender: sender_email_id = parse_addr(sender)[1] if not getattr(frappe.local, "outgoing_email_account", None): frappe.local.outgoing_email_account = {} if not (frappe.local.outgoing_email_account.get(append_to) or frappe.local.outgoing_email_account.get(sender_email_id) or frappe.local.outgoing_email_account.get("default")): email_account = None if sender_email_id: # check if the sender has an email account with enable_outgoing email_account = _get_email_account({ "enable_outgoing": 1, "email_id": sender_email_id }) if not email_account and append_to: # append_to is only valid when enable_incoming is checked email_accounts = frappe.db.get_values( "Email Account", { "enable_outgoing": 1, "enable_incoming": 1, "append_to": append_to, }, cache=True, ) if email_accounts: _email_account = email_accounts[0] else: email_account = _get_email_account({ "enable_outgoing": 1, "enable_incoming": 1, "append_to": append_to }) if not email_account: # sender don't have the outging email account sender_email_id = None email_account = get_default_outgoing_email_account( raise_exception_not_set=raise_exception_not_set) if not email_account and _email_account: # if default email account is not configured then setup first email account based on append to email_account = _email_account if (not email_account and raise_exception_not_set and cint( frappe.db.get_single_value("System Settings", "setup_complete"))): frappe.throw( _("Please setup default Email Account from Setup > Email > Email Account" ), frappe.OutgoingEmailError, ) if email_account: if email_account.enable_outgoing and not getattr( email_account, "from_site_config", False): raise_exception = True if (email_account.smtp_server in ["localhost", "127.0.0.1"] or email_account.no_smtp_authentication): raise_exception = False email_account.password = email_account.get_password( raise_exception=raise_exception) email_account.default_sender = email.utils.formataddr( (email_account.name, email_account.get("email_id"))) frappe.local.outgoing_email_account[append_to or sender_email_id or "default"] = email_account return (frappe.local.outgoing_email_account.get(append_to) or frappe.local.outgoing_email_account.get(sender_email_id) or frappe.local.outgoing_email_account.get("default"))
def replace_sender(self): if cint(self.email_account.always_use_account_email_id_as_sender): self.set_header('X-Original-From', self.sender) sender_name, sender_email = parse_addr(self.sender) self.sender = email.utils.formataddr((str(Header(sender_name or self.email_account.name, 'utf-8')), self.email_account.email_id))