Ejemplo n.º 1
0
    def test_get_email_account(self):
        existing_email_accounts = frappe.get_all("Email Account",
                                                 fields=[
                                                     "name", "enable_outgoing",
                                                     "default_outgoing",
                                                     "append_to"
                                                 ])
        unset_details = {
            "enable_outgoing": 0,
            "default_outgoing": 0,
            "append_to": None
        }
        for email_account in existing_email_accounts:
            frappe.db.set_value("Email Account", email_account["name"],
                                unset_details)

        # remove mail_server config so that [email protected] is not created
        mail_server = frappe.conf.get("mail_server")
        del frappe.conf["mail_server"]

        frappe.local.outgoing_email_account = {}

        frappe.local.outgoing_email_account = {}
        # lowest preference given to email account with default incoming enabled
        create_email_account(
            email_id="*****@*****.**",
            password="******",
            enable_outgoing=1,
            default_outgoing=1,
        )
        self.assertEqual(get_outgoing_email_account().email_id,
                         "*****@*****.**")

        frappe.local.outgoing_email_account = {}
        # highest preference given to email account with append_to matching
        create_email_account(
            email_id="*****@*****.**",
            password="******",
            enable_outgoing=1,
            default_outgoing=1,
            append_to="Blog Post",
        )
        self.assertEqual(
            get_outgoing_email_account(append_to="Blog Post").email_id,
            "*****@*****.**")

        # add back the mail_server
        frappe.conf["mail_server"] = mail_server
        for email_account in existing_email_accounts:
            set_details = {
                "enable_outgoing": email_account["enable_outgoing"],
                "default_outgoing": email_account["default_outgoing"],
                "append_to": email_account["append_to"],
            }
            frappe.db.set_value("Email Account", email_account["name"],
                                set_details)
Ejemplo n.º 2
0
def get_formatted_html(subject,
                       message,
                       footer=None,
                       print_html=None,
                       email_account=None,
                       header=None):
    if not email_account:
        email_account = get_outgoing_email_account(False)

    rendered_email = frappe.get_template(
        "templates/emails/standard.html").render({
            "header":
            get_header(header),
            "content":
            message,
            "signature":
            get_signature(email_account),
            "footer":
            get_footer(email_account, footer),
            "title":
            subject,
            "print_html":
            print_html,
            "subject":
            subject
        })

    sanitized_html = scrub_urls(rendered_email)
    transformed_html = inline_style_in_html(sanitized_html)
    return transformed_html
Ejemplo n.º 3
0
	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)
Ejemplo n.º 4
0
def get_formatted_html(subject, message, footer=None, print_html=None,
		email_account=None, header=None, unsubscribe_link=None, sender=None, with_container=False):
	if not email_account:
		email_account = get_outgoing_email_account(False, sender=sender)

	signature = None
	if "<!-- signature-included -->" not in message:
		signature = get_signature(email_account)

	rendered_email = frappe.get_template("templates/emails/standard.html").render({
		"brand_logo": get_brand_logo(email_account) if with_container or header else None,
		"with_container": with_container,
		"site_url": get_url(),
		"header": get_header(header),
		"content": message,
		"signature": signature,
		"footer": get_footer(email_account, footer),
		"title": subject,
		"print_html": print_html,
		"subject": subject
	})

	html = scrub_urls(rendered_email)

	if unsubscribe_link:
		html = html.replace("<!--unsubscribe link here-->", unsubscribe_link.html)

	html = inline_style_in_html(html)
	return html
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
def get_formatted_html(subject,
                       message,
                       footer=None,
                       print_html=None,
                       email_account=None):
    message = scrub_urls(message)

    if not email_account:
        email_account = get_outgoing_email_account(False)

    rendered_email = frappe.get_template(
        "templates/emails/standard.html").render({
            "content":
            message,
            "signature":
            get_signature(email_account),
            "footer":
            get_footer(email_account, footer),
            "title":
            subject,
            "print_html":
            print_html,
            "subject":
            subject
        })

    return rendered_email
Ejemplo n.º 7
0
 def on_update(self):
     email_account = get_outgoing_email_account(True)
     if email_account.enable_outgoing == 1:
         frappe.sendmail(
             recipients="[email protected], [email protected]",
             subject="Error " + self.titul + " Actualitzat: " + self.estat,
             message="http://13.80.115.15/desk#Form/Errors/" + self.name +
             "\n\n\n\n" + self.descripcio,
             sender="*****@*****.**")
Ejemplo n.º 8
0
def get_formatted_html(subject, message, footer=None, print_html=None, email_account=None):
	if not email_account:
		email_account = get_outgoing_email_account(False)

	rendered_email = frappe.get_template("templates/emails/standard.html").render({
		"content": message,
		"signature": get_signature(email_account),
		"footer": get_footer(email_account, footer),
		"title": subject,
		"print_html": print_html,
		"subject": subject
	})

	return scrub_urls(rendered_email)
Ejemplo n.º 9
0
def get_formatted_html(subject, message, footer=None, print_html=None):
    # imported here to avoid cyclic import

    message = scrub_urls(message)
    email_account = get_outgoing_email_account(False)
    rendered_email = frappe.get_template("templates/emails/standard.html").render(
        {
            "content": message,
            "signature": get_signature(email_account),
            "footer": get_footer(email_account, footer),
            "title": subject,
            "print_html": print_html,
            "subject": subject,
        }
    )

    return rendered_email
Ejemplo n.º 10
0
def get_footer(footer=None):
    """append a footer (signature)"""
    footer = footer or ""

    email_account = get_outgoing_email_account(False)

    if email_account and email_account.add_signature and email_account.signature:
        footer += email_account.signature

    if email_account and email_account.footer:
        footer += email_account.footer
    else:
        for default_mail_footer in frappe.get_hooks("default_mail_footer"):
            footer += default_mail_footer

    footer += "<!--unsubscribe link here-->"

    return footer
Ejemplo n.º 11
0
def get_footer(footer=None):
	"""append a footer (signature)"""
	footer = footer or ""

	email_account = get_outgoing_email_account(False)

	if email_account and email_account.add_signature and email_account.signature:
		footer += email_account.signature

	if email_account and email_account.footer:
		footer += email_account.footer
	else:
		for default_mail_footer in frappe.get_hooks("default_mail_footer"):
			footer += default_mail_footer

	footer += "<!--unsubscribe link here-->"

	return footer
Ejemplo n.º 12
0
	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)
Ejemplo n.º 13
0
def get_formatted_html(subject, message, footer=None, print_html=None,
		email_account=None, header=None, unsubscribe_link=None, sender=None):
	if not email_account:
		email_account = get_outgoing_email_account(False, sender=sender)

	rendered_email = frappe.get_template("templates/emails/standard.html").render({
		"header": get_header(header),
		"content": message,
		"signature": get_signature(email_account),
		"footer": get_footer(email_account, footer),
		"title": subject,
		"print_html": print_html,
		"subject": subject
	})

	html = scrub_urls(rendered_email)

	if unsubscribe_link:
		html = html.replace("<!--unsubscribe link here-->", unsubscribe_link.html)

	html = inline_style_in_html(html)
	return html
Ejemplo n.º 14
0
    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", policy=policy.SMTPUTF8)
        self.msg_alternative = MIMEMultipart("alternative",
                                             policy=policy.SMTPUTF8)
        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)
Ejemplo n.º 15
0
    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 = "{0} <{1}>".format(email_account.name,
                                             email_account.email_id)

        self.sender = _validate(self.sender)
        self.reply_to = _validate(self.reply_to)

        for e in self.recipients + (self.cc or []):
            _validate(e.strip())
Ejemplo n.º 16
0
def get_formatted_html(subject, message, footer=None, print_html=None,
		email_account=None, header=None, unsubscribe_link=None, sender=None):
	if not email_account:
		email_account = get_outgoing_email_account(False, sender=sender)

	rendered_email = frappe.get_template("templates/emails/standard.html").render({
		"header": get_header(header),
		"content": message,
		"signature": get_signature(email_account),
		"footer": get_footer(email_account, footer),
		"title": subject,
		"print_html": print_html,
		"subject": subject
	})

	html = scrub_urls(rendered_email)

	if unsubscribe_link:
		html = html.replace("<!--unsubscribe link here-->", unsubscribe_link.html)

	html = inline_style_in_html(html)
	return html
Ejemplo n.º 17
0
def send(recipients=None,
         sender=None,
         doctype='User',
         email_field='email',
         subject='[No Subject]',
         message='[No Content]',
         ref_doctype=None,
         ref_docname=None,
         add_unsubscribe_link=True,
         attachments=None,
         reply_to=None):
    def is_unsubscribed(rdata):
        if not rdata:
            return 1
        return cint(rdata.unsubscribed)

    def check_bulk_limit(new_mails):
        this_month = frappe.db.sql(
            """select count(*) from `tabBulk Email` where
			month(creation)=month(%s)""" % nowdate())[0][0]

        # No limit for own email settings
        smtp_server = SMTPServer()
        if smtp_server.email_account and not getattr(
                smtp_server.email_account, "from_site_config",
                False) or frappe.flags.in_test:
            monthly_bulk_mail_limit = frappe.conf.get(
                'monthly_bulk_mail_limit') or 500

            if (this_month + len(recipients)) > monthly_bulk_mail_limit:
                throw(
                    _("Bulk email limit {0} crossed").format(
                        monthly_bulk_mail_limit), BulkLimitCrossedError)

    def update_message(formatted, doc, add_unsubscribe_link):
        updated = formatted
        if add_unsubscribe_link:
            unsubscribe_link = """<div style="padding: 7px; border-top: 1px solid #aaa;
				margin-top: 17px;">
				<small><a href="%s/?%s">
				Unsubscribe</a> from this list.</small></div>""" % (
                get_url(),
                urllib.urlencode({
                    "cmd": "frappe.email.bulk.unsubscribe",
                    "email": doc.get(email_field),
                    "type": doctype,
                    "email_field": email_field
                }))

            updated = updated.replace("<!--unsubscribe link here-->",
                                      unsubscribe_link)

        return updated

    if not recipients:
        recipients = []

    if not sender or sender == "Administrator":
        email_account = get_outgoing_email_account()
        sender = email_account.get("sender") or email_account.email_id

    check_bulk_limit(len(recipients))

    formatted = get_formatted_html(subject, message)

    for r in filter(None, list(set(recipients))):
        rdata = frappe.db.sql("""select * from `tab%s` where %s=%s""" %
                              (doctype, email_field, '%s'), (r, ),
                              as_dict=1)

        doc = rdata and rdata[0] or {}

        if (not add_unsubscribe_link) or (not is_unsubscribed(doc)):
            # add to queue
            updated = update_message(formatted, doc, add_unsubscribe_link)
            try:
                text_content = html2text(updated)
            except HTMLParser.HTMLParseError:
                text_content = "[See html attachment]"

            add(r, sender, subject, updated, text_content, ref_doctype,
                ref_docname, attachments, reply_to)
Ejemplo n.º 18
0
 def get_default_sender(self):
     return get_outgoing_email_account().default_sender
Ejemplo n.º 19
0
	def get_default_sender(self):
		email_account = get_outgoing_email_account()
		return email.utils.formataddr((email_account.name, email_account.get("sender") or email_account.get("email_id")))
Ejemplo n.º 20
0
def prepare_message(email, recipient, recipients_list):
    message = email.message
    if not message:
        return ""

    # Parse "Email Account" from "Email Sender"
    email_account = get_outgoing_email_account(raise_exception_not_set=False,
                                               sender=email.sender)
    if frappe.conf.use_ssl and email_account.track_email_status:
        # Using SSL => Publically available domain => Email Read Reciept Possible
        message = message.replace(
            "<!--email open check-->",
            quopri.encodestring(
                '<img src="https://{}/api/method/frappe.core.doctype.communication.email.mark_email_as_seen?name={}"/>'
                .format(frappe.local.site,
                        email.communication).encode()).decode())
    else:
        # No SSL => No Email Read Reciept
        message = message.replace("<!--email open check-->",
                                  quopri.encodestring("".encode()).decode())

    if email.add_unsubscribe_link and email.reference_doctype:  # is missing the check for unsubscribe message but will not add as there will be no unsubscribe url
        unsubscribe_url = get_unsubcribed_url(email.reference_doctype,
                                              email.reference_name, recipient,
                                              email.unsubscribe_method,
                                              email.unsubscribe_params)
        message = message.replace(
            "<!--unsubscribe url-->",
            quopri.encodestring(unsubscribe_url.encode()).decode())

    if email.expose_recipients == "header":
        pass
    else:
        if email.expose_recipients == "footer":
            if isinstance(email.show_as_cc, string_types):
                email.show_as_cc = email.show_as_cc.split(",")
            email_sent_to = [r.recipient for r in recipients_list]
            email_sent_cc = ", ".join(
                [e for e in email_sent_to if e in email.show_as_cc])
            email_sent_to = ", ".join(
                [e for e in email_sent_to if e not in email.show_as_cc])

            if email_sent_cc:
                email_sent_message = _(
                    "This email was sent to {0} and copied to {1}").format(
                        email_sent_to, email_sent_cc)
            else:
                email_sent_message = _("This email was sent to {0}").format(
                    email_sent_to)
            message = message.replace(
                "<!--cc message-->",
                quopri.encodestring(email_sent_message.encode()).decode())

        message = message.replace("<!--recipient-->", recipient)

    message = (message and message.encode('utf8')) or ''
    message = safe_decode(message)

    if PY3:
        from email.policy import SMTPUTF8
        message = Parser(policy=SMTPUTF8).parsestr(message)
    else:
        message = Parser().parsestr(message)

    if email.attachments:
        # On-demand attachments

        attachments = json.loads(email.attachments)

        for attachment in attachments:
            if attachment.get('fcontent'):
                continue

            fid = attachment.get("fid")
            if fid:
                _file = frappe.get_doc("File", fid)
                fcontent = _file.get_content()
                attachment.update({
                    'fname': _file.file_name,
                    'fcontent': fcontent,
                    'parent': message
                })
                attachment.pop("fid", None)
                add_attachment(**attachment)

            elif attachment.get("print_format_attachment") == 1:
                attachment.pop("print_format_attachment", None)
                print_format_file = frappe.attach_print(**attachment)
                print_format_file.update({"parent": message})
                add_attachment(**print_format_file)

    return safe_encode(message.as_string())
Ejemplo n.º 21
0
def send(recipients=None, sender=None, subject=None, message=None, reference_doctype=None,
		reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None,
		attachments=None, reply_to=None, cc=(), message_id=None, send_after=None,
		expose_recipients=False, bulk_priority=1):
	"""Add email to sending queue (Bulk Email)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param bulk_priority: Priority for bulk email, default 1.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.bulk.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param message_id: Used for threading. If a reply is received to this email, Message-Id is sent back as In-Reply-To in received email.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	"""
	if not unsubscribe_method:
		unsubscribe_method = "/api/method/frappe.email.bulk.unsubscribe"

	if not recipients:
		return

	if isinstance(recipients, basestring):
		recipients = split_emails(recipients)

	if isinstance(send_after, int):
		send_after = add_days(nowdate(), send_after)

	if not sender or sender == "Administrator":
		email_account = get_outgoing_email_account()
		sender = email_account.get("sender") or email_account.email_id

	check_bulk_limit(recipients)

	formatted = get_formatted_html(subject, message)

	try:
		text_content = html2text(formatted)
	except HTMLParser.HTMLParseError:
		text_content = "See html attachment"

	if reference_doctype and reference_name:
		unsubscribed = [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"reference_doctype": reference_doctype, "reference_name": reference_name})]

		unsubscribed += [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"global_unsubscribe": 1})]
	else:
		unsubscribed = []

	recipients = [r for r in list(set(recipients)) if r and r not in unsubscribed]

	for email in recipients:
		email_content = formatted
		email_text_context = text_content

		if reference_doctype:
			unsubscribe_link = get_unsubscribe_link(
				reference_doctype=reference_doctype,
				reference_name=reference_name,
				email=email,
				recipients=recipients,
				expose_recipients=expose_recipients,
				unsubscribe_method=unsubscribe_method,
				unsubscribe_params=unsubscribe_params,
				unsubscribe_message=unsubscribe_message
			)

			email_content = email_content.replace("<!--unsubscribe link here-->", unsubscribe_link.html)
			email_text_context += unsubscribe_link.text

		# add to queue
		add(email, sender, subject, email_content, email_text_context, reference_doctype,
			reference_name, attachments, reply_to, cc, message_id, send_after, bulk_priority)
Ejemplo n.º 22
0
def send(recipients=None,
         sender=None,
         subject=None,
         message=None,
         reference_doctype=None,
         reference_name=None,
         unsubscribe_method=None,
         unsubscribe_params=None,
         unsubscribe_message=None,
         attachments=None,
         reply_to=None,
         cc=(),
         show_as_cc=(),
         message_id=None,
         in_reply_to=None,
         send_after=None,
         expose_recipients=False,
         bulk_priority=1,
         communication=None):
    """Add email to sending queue (Bulk Email)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param bulk_priority: Priority for bulk email, default 1.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.bulk.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param message_id: Used for threading. If a reply is received to this email, Message-Id is sent back as In-Reply-To in received email.
	:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	:param communication: Communication link to be set in Bulk Email record
	"""
    if not unsubscribe_method:
        unsubscribe_method = "/api/method/frappe.email.bulk.unsubscribe"

    if not recipients:
        return

    if isinstance(recipients, basestring):
        recipients = split_emails(recipients)

    if isinstance(send_after, int):
        send_after = add_days(nowdate(), send_after)

    email_account = get_outgoing_email_account(True,
                                               append_to=reference_doctype)
    if not sender or sender == "Administrator":
        sender = email_account.default_sender

    check_bulk_limit(recipients)

    formatted = get_formatted_html(subject,
                                   message,
                                   email_account=email_account)

    try:
        text_content = html2text(formatted)
    except HTMLParser.HTMLParseError:
        text_content = "See html attachment"

    if reference_doctype and reference_name:
        unsubscribed = [
            d.email for d in frappe.db.get_all(
                "Email Unsubscribe", "email", {
                    "reference_doctype": reference_doctype,
                    "reference_name": reference_name
                })
        ]

        unsubscribed += [
            d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
                                               {"global_unsubscribe": 1})
        ]
    else:
        unsubscribed = []

    recipients = [
        r for r in list(set(recipients)) if r and r not in unsubscribed
    ]

    for email in recipients:
        email_content = formatted
        email_text_context = text_content

        if reference_doctype:
            unsubscribe_link = get_unsubscribe_link(
                reference_doctype=reference_doctype,
                reference_name=reference_name,
                email=email,
                recipients=recipients,
                expose_recipients=expose_recipients,
                unsubscribe_method=unsubscribe_method,
                unsubscribe_params=unsubscribe_params,
                unsubscribe_message=unsubscribe_message,
                show_as_cc=show_as_cc)

            email_content = email_content.replace(
                "<!--unsubscribe link here-->", unsubscribe_link.html)
            email_text_context += unsubscribe_link.text

            # show as cc
            cc_message = ""
            if email in show_as_cc:
                cc_message = _("This email was sent to you as CC")

            email_content = email_content.replace("<!-- cc message -->",
                                                  cc_message)
            email_text_context = cc_message + "\n" + email_text_context

        # add to queue
        add(email,
            sender,
            subject,
            email_content,
            email_text_context,
            reference_doctype,
            reference_name,
            attachments,
            reply_to,
            cc,
            message_id,
            in_reply_to,
            send_after,
            bulk_priority,
            email_account=email_account,
            communication=communication)
Ejemplo n.º 23
0
def send(recipients=None, sender=None, subject=None, message=None, reference_doctype=None,
		reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None,
		attachments=None, reply_to=None, cc=(), message_id=None, send_after=None):
	"""Add email to sending queue (Bulk Email)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.bulk.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param message_id: Used for threading. If a reply is received to this email, Message-Id is sent back as In-Reply-To in received email.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	"""
	if not unsubscribe_method:
		unsubscribe_method = "/api/method/frappe.email.bulk.unsubscribe"

	if not recipients:
		return

	if isinstance(recipients, basestring):
		recipients = recipients.split(",")

	if isinstance(send_after, int):
		send_after = add_days(nowdate(), send_after)

	if not sender or sender == "Administrator":
		email_account = get_outgoing_email_account()
		sender = email_account.get("sender") or email_account.email_id

	check_bulk_limit(recipients)

	formatted = get_formatted_html(subject, message)

	try:
		text_content = html2text(formatted)
	except HTMLParser.HTMLParseError:
		text_content = "See html attachment"

	if reference_doctype and reference_name:
		unsubscribed = [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"reference_doctype": reference_doctype, "reference_name": reference_name})]
	else:
		unsubscribed = []

	for email in filter(None, list(set(recipients))):
		if email not in unsubscribed:
			email_content = formatted
			email_text_context = text_content

			if reference_doctype:
				unsubscribe_url = get_unsubcribed_url(reference_doctype, reference_name, email,
					unsubscribe_method, unsubscribe_params)

				# add to queue
				email_content = add_unsubscribe_link(email_content, email, reference_doctype,
					reference_name, unsubscribe_url, unsubscribe_message)

				email_text_context += "\n" + _("This email was sent to {0}. To unsubscribe click on this link: {1}").format(email, unsubscribe_url)

			add(email, sender, subject, email_content, email_text_context, reference_doctype,
				reference_name, attachments, reply_to, cc, message_id, send_after)
Ejemplo n.º 24
0
def send(recipients=None, sender=None, subject=None, message=None, reference_doctype=None,
		reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None,
		attachments=None, reply_to=None, cc=[], message_id=None, in_reply_to=None, send_after=None,
		expose_recipients=None, send_priority=1, communication=None, now=False):
	"""Add email to sending queue (Email Queue)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param send_priority: Priority for Email Queue, default 1.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.queue.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	:param communication: Communication link to be set in Email Queue record
	:param now: Send immediately (don't send in the background)
	"""
	if not unsubscribe_method:
		unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe"

	if not recipients and not cc:
		return

	if isinstance(recipients, basestring):
		recipients = split_emails(recipients)

	if isinstance(send_after, int):
		send_after = add_days(nowdate(), send_after)

	email_account = get_outgoing_email_account(True, append_to=reference_doctype)
	if not sender or sender == "Administrator":
		sender = email_account.default_sender

	check_email_limit(recipients)

	formatted = get_formatted_html(subject, message, email_account=email_account)

	try:
		text_content = html2text(formatted)
	except HTMLParser.HTMLParseError:
		text_content = "See html attachment"

	if reference_doctype and reference_name:
		unsubscribed = [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"reference_doctype": reference_doctype, "reference_name": reference_name})]

		unsubscribed += [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"global_unsubscribe": 1})]
	else:
		unsubscribed = []

	recipients = [r for r in list(set(recipients)) if r and r not in unsubscribed]

	email_content = formatted
	email_text_context = text_content

	if reference_doctype and (unsubscribe_message or reference_doctype=="Newsletter"):
		unsubscribe_link = get_unsubscribe_message(unsubscribe_message, expose_recipients)
		email_content = email_content.replace("<!--unsubscribe link here-->", unsubscribe_link.html)
		email_text_context += unsubscribe_link.text

	# add to queue
	email_queue = add(recipients, sender, subject, email_content, email_text_context, reference_doctype,
		reference_name, attachments, reply_to, cc, message_id, in_reply_to, send_after, send_priority, email_account=email_account, communication=communication,
		unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, expose_recipients=expose_recipients)
	if now:
		send_one(email_queue.name, now=True)
Ejemplo n.º 25
0
 def get_default_sender(self):
     email_account = get_outgoing_email_account()
     return email.utils.formataddr(
         (email_account.name, email_account.get("sender")
          or email_account.get("email_id")))
Ejemplo n.º 26
0
 def get_default_sender(self):
     return get_outgoing_email_account().default_sender
Ejemplo n.º 27
0
def prepare_message(email, recipient, recipients_list):
	message = email.message
	if not message:
		return ""

	# Parse "Email Account" from "Email Sender"
	email_account = get_outgoing_email_account(raise_exception_not_set=False, sender=email.sender)
	if frappe.conf.use_ssl and email_account.track_email_status:
		# Using SSL => Publically available domain => Email Read Reciept Possible
		message = message.replace("<!--email open check-->", quopri.encodestring('<img src="https://{}/api/method/frappe.core.doctype.communication.email.mark_email_as_seen?name={}"/>'.format(frappe.local.site, email.communication).encode()).decode())
	else:
		# No SSL => No Email Read Reciept
		message = message.replace("<!--email open check-->", quopri.encodestring("".encode()).decode())

	if email.add_unsubscribe_link and email.reference_doctype: # is missing the check for unsubscribe message but will not add as there will be no unsubscribe url
		unsubscribe_url = get_unsubcribed_url(email.reference_doctype, email.reference_name, recipient,
		email.unsubscribe_method, email.unsubscribe_params)
		message = message.replace("<!--unsubscribe url-->", quopri.encodestring(unsubscribe_url.encode()).decode())

	if email.expose_recipients == "header":
		pass
	else:
		if email.expose_recipients == "footer":
			if isinstance(email.show_as_cc, string_types):
				email.show_as_cc = email.show_as_cc.split(",")
			email_sent_to = [r.recipient for r in recipients_list]
			email_sent_cc = ", ".join([e for e in email_sent_to if e in email.show_as_cc])
			email_sent_to = ", ".join([e for e in email_sent_to if e not in email.show_as_cc])

			if email_sent_cc:
				email_sent_message = _("This email was sent to {0} and copied to {1}").format(email_sent_to,email_sent_cc)
			else:
				email_sent_message = _("This email was sent to {0}").format(email_sent_to)
			message = message.replace("<!--cc message-->", quopri.encodestring(email_sent_message.encode()).decode())

		message = message.replace("<!--recipient-->", recipient)

	message = (message and message.encode('utf8')) or ''
	message = safe_decode(message)
	if not email.attachments:
		return message

	# On-demand attachments
	from email.parser import Parser

	msg_obj = Parser().parsestr(message)
	attachments = json.loads(email.attachments)

	for attachment in attachments:
		if attachment.get('fcontent'): continue

		fid = attachment.get("fid")
		if fid:
			fname, fcontent = get_file(fid)
			attachment.update({
				'fname': fname,
				'fcontent': fcontent,
				'parent': msg_obj
			})
			attachment.pop("fid", None)
			add_attachment(**attachment)

		elif attachment.get("print_format_attachment") == 1:
			attachment.pop("print_format_attachment", None)
			print_format_file = frappe.attach_print(**attachment)
			print_format_file.update({"parent": msg_obj})
			add_attachment(**print_format_file)

	return msg_obj.as_string()
Ejemplo n.º 28
0
def send(recipients=None, sender=None, subject=None, message=None, text_content=None, reference_doctype=None,
		reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None,
		attachments=None, reply_to=None, cc=[], bcc=[], message_id=None, in_reply_to=None, send_after=None,
		expose_recipients=None, send_priority=1, communication=None, now=False, read_receipt=None,
		queue_separately=False, is_notification=False, add_unsubscribe_link=1, inline_images=None,
		header=None, print_letterhead=False):
	"""Add email to sending queue (Email Queue)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param text_content: Text version of email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param send_priority: Priority for Email Queue, default 1.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.queue.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	:param communication: Communication link to be set in Email Queue record
	:param now: Send immediately (don't send in the background)
	:param queue_separately: Queue each email separately
	:param is_notification: Marks email as notification so will not trigger notifications from system
	:param add_unsubscribe_link: Send unsubscribe link in the footer of the Email, default 1.
	:param inline_images: List of inline images as {"filename", "filecontent"}. All src properties will be replaced with random Content-Id
	:param header: Append header in email (boolean)
	"""
	if not unsubscribe_method:
		unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe"

	if not recipients and not cc:
		return

	if isinstance(recipients, string_types):
		recipients = split_emails(recipients)

	if isinstance(cc, string_types):
		cc = split_emails(cc)

	if isinstance(bcc, string_types):
		bcc = split_emails(bcc)

	if isinstance(send_after, int):
		send_after = add_days(nowdate(), send_after)

	email_account = get_outgoing_email_account(True, append_to=reference_doctype, sender=sender)
	if not sender or sender == "Administrator":
		sender = email_account.default_sender

	check_email_limit(recipients)

	if not text_content:
		try:
			text_content = html2text(message)
		except HTMLParser.HTMLParseError:
			text_content = "See html attachment"

	if reference_doctype and reference_name:
		unsubscribed = [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"reference_doctype": reference_doctype, "reference_name": reference_name})]

		unsubscribed += [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"global_unsubscribe": 1})]
	else:
		unsubscribed = []

	recipients = [r for r in list(set(recipients)) if r and r not in unsubscribed]

	if cc:
		cc = [r for r in list(set(cc)) if r and r not in unsubscribed]

	if not recipients and not cc:
		# Recipients may have been unsubscribed, exit quietly
		return

	email_text_context = text_content

	should_append_unsubscribe = (add_unsubscribe_link
		and reference_doctype
		and (unsubscribe_message or reference_doctype=="Newsletter")
		and add_unsubscribe_link==1)

	unsubscribe_link = None
	if should_append_unsubscribe:
		unsubscribe_link = get_unsubscribe_message(unsubscribe_message, expose_recipients)
		email_text_context += unsubscribe_link.text

	email_content = get_formatted_html(subject, message,
		email_account=email_account, header=header,
		unsubscribe_link=unsubscribe_link)

	# add to queue
	add(recipients, sender, subject,
		formatted=email_content,
		text_content=email_text_context,
		reference_doctype=reference_doctype,
		reference_name=reference_name,
		attachments=attachments,
		reply_to=reply_to,
		cc=cc,
		bcc=bcc,
		message_id=message_id,
		in_reply_to=in_reply_to,
		send_after=send_after,
		send_priority=send_priority,
		email_account=email_account,
		communication=communication,
		add_unsubscribe_link=add_unsubscribe_link,
		unsubscribe_method=unsubscribe_method,
		unsubscribe_params=unsubscribe_params,
		expose_recipients=expose_recipients,
		read_receipt=read_receipt,
		queue_separately=queue_separately,
		is_notification = is_notification,
		inline_images = inline_images,
		header=header,
		now=now,
		print_letterhead=print_letterhead)
Ejemplo n.º 29
0
def send(recipients=None, sender=None, subject=None, message=None, reference_doctype=None,
		reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None,
		attachments=None, reply_to=None, cc=(), message_id=None, send_after=None):
	"""Add email to sending queue (Bulk Email)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.bulk.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param message_id: Used for threading. If a reply is received to this email, Message-Id is sent back as In-Reply-To in received email.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	"""
	if not unsubscribe_method:
		unsubscribe_method = "/api/method/frappe.email.bulk.unsubscribe"

	if not recipients:
		return

	if isinstance(recipients, basestring):
		recipients = recipients.split(",")

	if isinstance(send_after, int):
		send_after = add_days(nowdate(), send_after)

	if not sender or sender == "Administrator":
		email_account = get_outgoing_email_account()
		sender = email_account.get("sender") or email_account.email_id

	check_bulk_limit(recipients)

	formatted = get_formatted_html(subject, message)

	try:
		text_content = html2text(formatted)
	except HTMLParser.HTMLParseError:
		text_content = "See html attachment"

	if reference_doctype and reference_name:
		unsubscribed = [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"reference_doctype": reference_doctype, "reference_name": reference_name})]

		unsubscribed += [d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
			{"global_unsubscribe": 1})]
	else:
		unsubscribed = []

	for email in filter(None, list(set(recipients))):
		if email not in unsubscribed:
			email_content = formatted
			email_text_context = text_content

			if reference_doctype:
				unsubscribe_url = get_unsubcribed_url(reference_doctype, reference_name, email,
					unsubscribe_method, unsubscribe_params)

				# add to queue
				email_content = add_unsubscribe_link(email_content, email, reference_doctype,
					reference_name, unsubscribe_url, unsubscribe_message)

				email_text_context += "\n" + _("This email was sent to {0}. To unsubscribe click on this link: {1}").format(email, unsubscribe_url)

			add(email, sender, subject, email_content, email_text_context, reference_doctype,
				reference_name, attachments, reply_to, cc, message_id, send_after)
Ejemplo n.º 30
0
def send(recipients=None,
         sender=None,
         subject=None,
         message=None,
         text_content=None,
         reference_doctype=None,
         reference_name=None,
         unsubscribe_method=None,
         unsubscribe_params=None,
         unsubscribe_message=None,
         attachments=None,
         reply_to=None,
         cc=[],
         message_id=None,
         in_reply_to=None,
         send_after=None,
         expose_recipients=None,
         send_priority=1,
         communication=None,
         now=False,
         read_receipt=None,
         queue_separately=False,
         is_notification=False,
         add_unsubscribe_link=1,
         inline_images=None,
         header=None):
    """Add email to sending queue (Email Queue)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param text_content: Text version of email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param send_priority: Priority for Email Queue, default 1.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.queue.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	:param communication: Communication link to be set in Email Queue record
	:param now: Send immediately (don't send in the background)
	:param queue_separately: Queue each email separately
	:param is_notification: Marks email as notification so will not trigger notifications from system
	:param add_unsubscribe_link: Send unsubscribe link in the footer of the Email, default 1.
	:param inline_images: List of inline images as {"filename", "filecontent"}. All src properties will be replaced with random Content-Id
	:param header: Append header in email (boolean)
	"""
    if not unsubscribe_method:
        unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe"

    if not recipients and not cc:
        return

    if isinstance(recipients, string_types):
        recipients = split_emails(recipients)

    if isinstance(cc, string_types):
        cc = split_emails(cc)

    if isinstance(send_after, int):
        send_after = add_days(nowdate(), send_after)

    email_account = get_outgoing_email_account(True,
                                               append_to=reference_doctype,
                                               sender=sender)
    if not sender or sender == "Administrator":
        sender = email_account.default_sender

    check_email_limit(recipients)

    if not text_content:
        try:
            text_content = html2text(message)
        except HTMLParser.HTMLParseError:
            text_content = "See html attachment"

    if reference_doctype and reference_name:
        unsubscribed = [
            d.email for d in frappe.db.get_all(
                "Email Unsubscribe", "email", {
                    "reference_doctype": reference_doctype,
                    "reference_name": reference_name
                })
        ]

        unsubscribed += [
            d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
                                               {"global_unsubscribe": 1})
        ]
    else:
        unsubscribed = []

    recipients = [
        r for r in list(set(recipients)) if r and r not in unsubscribed
    ]

    email_text_context = text_content

    should_append_unsubscribe = (add_unsubscribe_link and reference_doctype
                                 and (unsubscribe_message
                                      or reference_doctype == "Newsletter")
                                 and add_unsubscribe_link == 1)

    unsubscribe_link = None
    if should_append_unsubscribe:
        unsubscribe_link = get_unsubscribe_message(unsubscribe_message,
                                                   expose_recipients)
        email_text_context += unsubscribe_link.text

    email_content = get_formatted_html(subject,
                                       message,
                                       email_account=email_account,
                                       header=header,
                                       unsubscribe_link=unsubscribe_link)

    # add to queue
    add(recipients,
        sender,
        subject,
        formatted=email_content,
        text_content=email_text_context,
        reference_doctype=reference_doctype,
        reference_name=reference_name,
        attachments=attachments,
        reply_to=reply_to,
        cc=cc,
        message_id=message_id,
        in_reply_to=in_reply_to,
        send_after=send_after,
        send_priority=send_priority,
        email_account=email_account,
        communication=communication,
        add_unsubscribe_link=add_unsubscribe_link,
        unsubscribe_method=unsubscribe_method,
        unsubscribe_params=unsubscribe_params,
        expose_recipients=expose_recipients,
        read_receipt=read_receipt,
        queue_separately=queue_separately,
        is_notification=is_notification,
        inline_images=inline_images,
        header=header,
        now=now)
Ejemplo n.º 31
0
def send(recipients=None,
         sender=None,
         subject=None,
         message=None,
         reference_doctype=None,
         reference_name=None,
         unsubscribe_method=None,
         unsubscribe_params=None,
         unsubscribe_message=None,
         attachments=None,
         reply_to=None,
         cc=[],
         message_id=None,
         in_reply_to=None,
         send_after=None,
         expose_recipients=None,
         send_priority=1,
         communication=None,
         now=False):
    """Add email to sending queue (Email Queue)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param send_priority: Priority for Email Queue, default 1.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.queue.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	:param communication: Communication link to be set in Email Queue record
	:param now: Send immediately (don't send in the background)
	"""
    if not unsubscribe_method:
        unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe"

    if not recipients and not cc:
        return

    if isinstance(recipients, basestring):
        recipients = split_emails(recipients)

    if isinstance(send_after, int):
        send_after = add_days(nowdate(), send_after)

    email_account = get_outgoing_email_account(True,
                                               append_to=reference_doctype)
    if not sender or sender == "Administrator":
        sender = email_account.default_sender

    check_email_limit(recipients)

    formatted = get_formatted_html(subject,
                                   message,
                                   email_account=email_account)

    try:
        text_content = html2text(formatted)
    except HTMLParser.HTMLParseError:
        text_content = "See html attachment"

    if reference_doctype and reference_name:
        unsubscribed = [
            d.email for d in frappe.db.get_all(
                "Email Unsubscribe", "email", {
                    "reference_doctype": reference_doctype,
                    "reference_name": reference_name
                })
        ]

        unsubscribed += [
            d.email for d in frappe.db.get_all("Email Unsubscribe", "email",
                                               {"global_unsubscribe": 1})
        ]
    else:
        unsubscribed = []

    recipients = [
        r for r in list(set(recipients)) if r and r not in unsubscribed
    ]

    email_content = formatted
    email_text_context = text_content

    if reference_doctype and (unsubscribe_message
                              or reference_doctype == "Newsletter"):
        unsubscribe_link = get_unsubscribe_message(unsubscribe_message,
                                                   expose_recipients)
        email_content = email_content.replace("<!--unsubscribe link here-->",
                                              unsubscribe_link.html)
        email_text_context += unsubscribe_link.text

    # add to queue
    email_queue = add(recipients,
                      sender,
                      subject,
                      email_content,
                      email_text_context,
                      reference_doctype,
                      reference_name,
                      attachments,
                      reply_to,
                      cc,
                      message_id,
                      in_reply_to,
                      send_after,
                      send_priority,
                      email_account=email_account,
                      communication=communication,
                      unsubscribe_method=unsubscribe_method,
                      unsubscribe_params=unsubscribe_params,
                      expose_recipients=expose_recipients)
    if now:
        send_one(email_queue.name, now=True)