@@ -388,22 +388,17 @@ def sendmail(recipients=(), sender="", subject="No Subject", message="No Message | |||||
from markdown2 import markdown | from markdown2 import markdown | ||||
message = markdown(message) | message = markdown(message) | ||||
if now!=None: | |||||
delayed = not now | |||||
import email | |||||
if delayed: | |||||
import email.queue | |||||
email.queue.send(recipients=recipients, sender=sender, | |||||
subject=subject, message=message, | |||||
reference_doctype = doctype or reference_doctype, reference_name = name or reference_name, | |||||
unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message, | |||||
attachments=attachments, reply_to=reply_to, cc=cc, show_as_cc=show_as_cc, in_reply_to=in_reply_to, | |||||
send_after=send_after, expose_recipients=expose_recipients, send_priority=send_priority, communication=communication) | |||||
else: | |||||
email.sendmail(recipients, sender=sender, | |||||
subject=subject, msg=content or message, attachments=attachments, reply_to=reply_to, | |||||
cc=cc, in_reply_to=in_reply_to, retry=retry) | |||||
if not delayed: | |||||
now = True | |||||
import email.queue | |||||
email.queue.send(recipients=recipients, sender=sender, | |||||
subject=subject, message=message, | |||||
reference_doctype = doctype or reference_doctype, reference_name = name or reference_name, | |||||
unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message, | |||||
attachments=attachments, reply_to=reply_to, cc=cc, show_as_cc=show_as_cc, in_reply_to=in_reply_to, | |||||
send_after=send_after, expose_recipients=expose_recipients, send_priority=send_priority, | |||||
communication=communication, now=now) | |||||
whitelisted = [] | whitelisted = [] | ||||
guest_methods = [] | guest_methods = [] | ||||
@@ -5,7 +5,7 @@ from __future__ import unicode_literals | |||||
import frappe | import frappe | ||||
from frappe.utils import (getdate, cint, add_months, date_diff, add_days, | from frappe.utils import (getdate, cint, add_months, date_diff, add_days, | ||||
nowdate, get_datetime_str, cstr, get_datetime) | |||||
nowdate, get_datetime_str, cstr, get_datetime, now_datetime) | |||||
from frappe.model.document import Document | from frappe.model.document import Document | ||||
from frappe.utils.user import get_enabled_system_users | from frappe.utils.user import get_enabled_system_users | ||||
@@ -13,6 +13,9 @@ weekdays = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", | |||||
class Event(Document): | class Event(Document): | ||||
def validate(self): | def validate(self): | ||||
if not self.starts_on: | |||||
self.starts_on = now_datetime() | |||||
if self.starts_on and self.ends_on and get_datetime(self.starts_on) > get_datetime(self.ends_on): | if self.starts_on and self.ends_on and get_datetime(self.starts_on) > get_datetime(self.ends_on): | ||||
frappe.msgprint(frappe._("Event end must be after start"), raise_exception=True) | frappe.msgprint(frappe._("Event end must be after start"), raise_exception=True) | ||||
@@ -365,20 +365,17 @@ class EmailAccount(Document): | |||||
def find_parent_from_in_reply_to(self, communication, email): | def find_parent_from_in_reply_to(self, communication, email): | ||||
'''Returns parent reference if embedded in In-Reply-To header | '''Returns parent reference if embedded in In-Reply-To header | ||||
Message-ID is formatted as `{random}.{doctype}.{name}@{site}`''' | |||||
Message-ID is formatted as `{message_id}@{site}`''' | |||||
parent = None | parent = None | ||||
in_reply_to = (email.mail.get("In-Reply-To") or "").strip(" <>") | in_reply_to = (email.mail.get("In-Reply-To") or "").strip(" <>") | ||||
if in_reply_to and "@{0}".format(frappe.local.site) in in_reply_to: | if in_reply_to and "@{0}".format(frappe.local.site) in in_reply_to: | ||||
# reply to a communication sent from the system | # reply to a communication sent from the system | ||||
reference, domain = in_reply_to.split("@", 1) | |||||
if '.' in reference: | |||||
t, parent_doctype, parent_name = reference.split('.', 2) | |||||
# parent doctype has '-' instead of ' ' and '--' instead of '-' | |||||
parent_doctype = parent_doctype.replace('--', '%').replace('-', ' ').replace('%', '-') | |||||
email_queue = frappe.db.get_value('Email Queue', dict(message_id=in_reply_to), ['reference_doctype', 'reference_name']) | |||||
if email_queue: | |||||
parent_doctype, parent_name = email_queue | |||||
else: | else: | ||||
reference, domain = in_reply_to.split("@", 1) | |||||
parent_doctype, parent_name = 'Communication', reference | parent_doctype, parent_name = 'Communication', reference | ||||
if frappe.db.exists(parent_doctype, parent_name): | if frappe.db.exists(parent_doctype, parent_name): | ||||
@@ -170,5 +170,30 @@ class TestEmailAccount(unittest.TestCase): | |||||
self.assertEquals(comm_list[0].reference_doctype, comm_list[1].reference_doctype) | self.assertEquals(comm_list[0].reference_doctype, comm_list[1].reference_doctype) | ||||
self.assertEquals(comm_list[0].reference_name, comm_list[1].reference_name) | self.assertEquals(comm_list[0].reference_name, comm_list[1].reference_name) | ||||
def test_threading_by_message_id(self): | |||||
frappe.db.sql("""delete from tabCommunication""") | |||||
frappe.db.sql("""delete from `tabEmail Queue`""") | |||||
# reference document for testing | |||||
event = frappe.get_doc(dict(doctype='Event', subject='test-message')).insert() | |||||
# send a mail against this | |||||
frappe.sendmail(recipients='test@example.com', subject='test message for threading', | |||||
message='testing', reference_doctype=event.doctype, reference_name=event.name) | |||||
last_mail = frappe.get_doc('Email Queue', dict(reference_name=event.name)) | |||||
# get test mail with message-id as in-reply-to | |||||
with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-4.raw"), "r") as f: | |||||
test_mails = [f.read().replace('{{ message_id }}', last_mail.message_id)] | |||||
# pull the mail | |||||
email_account = frappe.get_doc("Email Account", "_Test Email Account 1") | |||||
email_account.receive(test_mails=test_mails) | |||||
comm_list = frappe.get_all("Communication", filters={"sender":"test_sender@example.com"}, | |||||
fields=["name", "reference_doctype", "reference_name"]) | |||||
# check if threaded correctly | |||||
self.assertEquals(comm_list[0].reference_doctype, event.doctype) | |||||
self.assertEquals(comm_list[0].reference_name, event.name) |
@@ -0,0 +1,75 @@ | |||||
From: <test_sender@example.com> | |||||
Content-Type: multipart/alternative; | |||||
boundary="Apple-Mail=_29597CF7-20DD-4184-B3FA-85582C5C4361" | |||||
Message-Id: <07D687F6-10AA-4B9F-82DE-27753096164E@gmail.com> | |||||
Mime-Version: 1.0 (Mac OS X Mail 9.3 \(3124\)) | |||||
X-Smtp-Server: 73CC8281-7E8F-4B47-8324-D5DA86EEDD4F | |||||
Subject: Re: What did you work on today? | |||||
Date: Thu, 10 Nov 2016 16:04:43 +0530 | |||||
X-Universally-Unique-Identifier: A4D9669F-179C-42D8-A3D3-AA6A8C49A6F2 | |||||
References: {{ message_id }} | |||||
To: test_in@iwebnotes.com | |||||
In-Reply-To: {{ message_id }} | |||||
--Apple-Mail=_29597CF7-20DD-4184-B3FA-85582C5C4361 | |||||
Content-Transfer-Encoding: quoted-printable | |||||
Content-Type: text/plain; | |||||
charset=us-ascii | |||||
Testing another reply! | |||||
> On 10-Nov-2016, at 3:20 PM, Frappe <test@erpnext.com> wrote: | |||||
>=20 | |||||
> Please share what did you do today. If you reply by midnight, your = | |||||
response will be recorded! | |||||
>=20 | |||||
> This email was sent to rmehta@gmail.com | |||||
> Unsubscribe from this list = | |||||
<http://demo-test.erpnext.com.dev/api/method/frappe.email.queue.unsubscrib= | |||||
e?email=3Drmehta%40gmail.com&name=3D26cc3e5a5d&doctype=3DDaily+Work+Summar= | |||||
y&_signature=3D2c7ab37e6d775e5a481e9b4376154a41> | |||||
> Sent via ERPNext <https://erpnext.com/?source=3Dvia_email_footer> | |||||
--Apple-Mail=_29597CF7-20DD-4184-B3FA-85582C5C4361 | |||||
Content-Transfer-Encoding: 7bit | |||||
Content-Type: text/html; | |||||
charset=us-ascii | |||||
<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Testing another reply!<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 10-Nov-2016, at 3:20 PM, Frappe <<a href="mailto:test@erpnext.com" class="">test@erpnext.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""> | |||||
<meta name="viewport" content="width=device-width" class=""> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" class=""> | |||||
<title class="">What did you work on today?</title> | |||||
<div style="line-height: 1.5; color: #36414C;" class=""> | |||||
<!-- body --> | |||||
<div style="font-family: -apple-system, BlinkMacSystemFont, | |||||
" segoe="" ui",="" "roboto",="" "oxygen",="" "ubuntu",="" "cantarell",="" "fira="" sans",="" "droid="" "helvetica="" neue",="" sans-serif;="" font-size:="" 14px;="" padding:="" 10px;"="" class=""><p class="">Please share what did you do today. If you reply by midnight, your response will be recorded!</p> | |||||
</div> | |||||
<!-- footer --> | |||||
<div style="margin-top: 30px; font-family: Helvetica, Arial, sans-serif; font-size: 11px; | |||||
margin-bottom: 15px; border-top: 1px solid #d1d8dd;" data-email-footer="true" class=""> | |||||
<div style="margin: 15px auto; padding: 0px 7px; text-align: center; color: #8d99a6;" class=""> | |||||
This email was sent to <a href="mailto:rmehta@gmail.com" class="">rmehta@gmail.com</a> | |||||
<p style="margin: 15px auto;" class=""> | |||||
<a href="http://demo-test.erpnext.com.dev/api/method/frappe.email.queue.unsubscribe?email=rmehta%40gmail.com&name=26cc3e5a5d&doctype=Daily+Work+Summary&_signature=2c7ab37e6d775e5a481e9b4376154a41" style="color: #8d99a6; text-decoration: underline; | |||||
target=" _blank"="" class="">Unsubscribe from this list | |||||
</a> | |||||
</p> | |||||
</div><div style="margin: 15px auto;" class=""><div style="text-align: center;" class=""> | |||||
<a href="https://erpnext.com/?source=via_email_footer" target="_blank" style="color: #8d99a6;" class=""> | |||||
Sent via ERPNext | |||||
</a> | |||||
</div></div> | |||||
</div> | |||||
<!-- /footer --> | |||||
<div class="print-html"></div> | |||||
</div> | |||||
</div></blockquote></div><br class=""></div></body></html> | |||||
--Apple-Mail=_29597CF7-20DD-4184-B3FA-85582C5C4361-- |
@@ -24,6 +24,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Sender", | "label": "Sender", | ||||
@@ -52,6 +53,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Recipient", | "label": "Recipient", | ||||
@@ -80,6 +82,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Message", | "label": "Message", | ||||
@@ -108,6 +111,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 1, | "in_standard_filter": 1, | ||||
"label": "Status", | "label": "Status", | ||||
@@ -136,6 +140,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Error", | "label": "Error", | ||||
@@ -152,6 +157,35 @@ | |||||
"set_only_once": 0, | "set_only_once": 0, | ||||
"unique": 0 | "unique": 0 | ||||
}, | }, | ||||
{ | |||||
"allow_on_submit": 0, | |||||
"bold": 0, | |||||
"collapsible": 0, | |||||
"columns": 0, | |||||
"fieldname": "message_id", | |||||
"fieldtype": "Data", | |||||
"hidden": 0, | |||||
"ignore_user_permissions": 0, | |||||
"ignore_xss_filter": 0, | |||||
"in_filter": 0, | |||||
"in_global_search": 0, | |||||
"in_list_view": 0, | |||||
"in_standard_filter": 0, | |||||
"label": "Message ID", | |||||
"length": 0, | |||||
"no_copy": 0, | |||||
"permlevel": 0, | |||||
"precision": "", | |||||
"print_hide": 0, | |||||
"print_hide_if_no_value": 0, | |||||
"read_only": 1, | |||||
"remember_last_selected_value": 0, | |||||
"report_hide": 0, | |||||
"reqd": 0, | |||||
"search_index": 1, | |||||
"set_only_once": 0, | |||||
"unique": 0 | |||||
}, | |||||
{ | { | ||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
@@ -163,6 +197,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Reference DocType", | "label": "Reference DocType", | ||||
@@ -191,6 +226,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Reference DocName", | "label": "Reference DocName", | ||||
@@ -218,6 +254,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Communication", | "label": "Communication", | ||||
@@ -247,6 +284,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Send After", | "label": "Send After", | ||||
@@ -276,6 +314,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Priority", | "label": "Priority", | ||||
@@ -305,7 +344,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 0, | "istable": 0, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2016-11-07 05:29:46.316408", | |||||
"modified": "2016-11-17 16:45:02.296617", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Email", | "module": "Email", | ||||
"name": "Email Queue", | "name": "Email Queue", | ||||
@@ -59,6 +59,7 @@ class EMail: | |||||
self.html_set = False | self.html_set = False | ||||
self.email_account = email_account or get_outgoing_email_account() | self.email_account = email_account or get_outgoing_email_account() | ||||
self.set_message_id() | |||||
def set_html(self, message, text_content = None, footer=None, print_html=None, formatted=None): | def set_html(self, message, text_content = None, footer=None, print_html=None, formatted=None): | ||||
"""Attach message in the html portion of multipart/alternative""" | """Attach message in the html portion of multipart/alternative""" | ||||
@@ -182,10 +183,8 @@ class EMail: | |||||
sender_name, sender_email = email.utils.parseaddr(self.sender) | sender_name, sender_email = email.utils.parseaddr(self.sender) | ||||
self.sender = email.utils.formataddr((sender_name or self.email_account.name, self.email_account.email_id)) | self.sender = email.utils.formataddr((sender_name or self.email_account.name, self.email_account.email_id)) | ||||
def set_message_id(self, doctype, name): | |||||
message_id = "<{random}.{doctype}.{name}@{site}>".format( | |||||
doctype=doctype.replace('-', '--').replace(' ', '-'), name=name, site=frappe.local.site, random=random_string(10)) | |||||
self.msg_root["Message-Id"] = message_id | |||||
def set_message_id(self): | |||||
self.msg_root["Message-Id"] = get_message_id() | |||||
def set_in_reply_to(self, in_reply_to): | def set_in_reply_to(self, in_reply_to): | ||||
"""Used to send the Message-Id of a received email back as In-Reply-To""" | """Used to send the Message-Id of a received email back as In-Reply-To""" | ||||
@@ -241,6 +240,12 @@ def get_formatted_html(subject, message, footer=None, print_html=None, email_acc | |||||
return scrub_urls(rendered_email) | return scrub_urls(rendered_email) | ||||
def get_message_id(): | |||||
'''Returns Message ID created from doctype and name''' | |||||
return "<{unique}@{site}>".format( | |||||
site=frappe.local.site, | |||||
unique=email.utils.make_msgid(random_string(10)).split('@')[0].split('<')[1]) | |||||
def get_signature(email_account): | def get_signature(email_account): | ||||
if email_account and email_account.add_signature and email_account.signature: | if email_account and email_account.add_signature and email_account.signature: | ||||
return "<br><br>" + email_account.signature | return "<br><br>" + email_account.signature | ||||
@@ -19,7 +19,7 @@ class EmailLimitCrossedError(frappe.ValidationError): pass | |||||
def send(recipients=None, sender=None, subject=None, message=None, reference_doctype=None, | 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, | reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None, | ||||
attachments=None, reply_to=None, cc=(), show_as_cc=(), in_reply_to=None, send_after=None, | attachments=None, reply_to=None, cc=(), show_as_cc=(), in_reply_to=None, send_after=None, | ||||
expose_recipients=False, send_priority=1, communication=None): | |||||
expose_recipients=False, send_priority=1, communication=None, now=False): | |||||
"""Add email to sending queue (Email Queue) | """Add email to sending queue (Email Queue) | ||||
:param recipients: List of recipients. | :param recipients: List of recipients. | ||||
@@ -36,6 +36,7 @@ def send(recipients=None, sender=None, subject=None, message=None, reference_doc | |||||
:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To. | :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 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 communication: Communication link to be set in Email Queue record | ||||
:param now: Send immediately (don't send in the background) | |||||
""" | """ | ||||
if not unsubscribe_method: | if not unsubscribe_method: | ||||
unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe" | unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe" | ||||
@@ -101,9 +102,13 @@ def send(recipients=None, sender=None, subject=None, message=None, reference_doc | |||||
email_content = email_content.replace("<!-- cc message -->", cc_message) | email_content = email_content.replace("<!-- cc message -->", cc_message) | ||||
email_text_context = cc_message + "\n" + email_text_context | email_text_context = cc_message + "\n" + email_text_context | ||||
# add to queue | # add to queue | ||||
add(email, sender, subject, email_content, email_text_context, reference_doctype, | |||||
email_queue = add(email, sender, subject, email_content, email_text_context, reference_doctype, | |||||
reference_name, attachments, reply_to, cc, in_reply_to, send_after, send_priority, email_account=email_account, communication=communication) | reference_name, attachments, reply_to, cc, in_reply_to, send_after, send_priority, email_account=email_account, communication=communication) | ||||
if now: | |||||
send_one(email_queue.name, now=True) | |||||
def add(email, sender, subject, formatted, text_content=None, | def add(email, sender, subject, formatted, text_content=None, | ||||
reference_doctype=None, reference_name=None, attachments=None, reply_to=None, | reference_doctype=None, reference_name=None, attachments=None, reply_to=None, | ||||
cc=(), in_reply_to=None, send_after=None, send_priority=1, email_account=None, | cc=(), in_reply_to=None, send_after=None, send_priority=1, email_account=None, | ||||
@@ -118,12 +123,10 @@ def add(email, sender, subject, formatted, text_content=None, | |||||
text_content=text_content, attachments=attachments, reply_to=reply_to, | text_content=text_content, attachments=attachments, reply_to=reply_to, | ||||
cc=cc, email_account=email_account) | cc=cc, email_account=email_account) | ||||
if reference_doctype and reference_name: | |||||
mail.set_message_id(reference_doctype, reference_name) | |||||
if in_reply_to: | if in_reply_to: | ||||
mail.set_in_reply_to(in_reply_to) | mail.set_in_reply_to(in_reply_to) | ||||
e.message_id = mail.msg_root["Message-Id"].strip(" <>") | |||||
e.message = cstr(mail.as_string()) | e.message = cstr(mail.as_string()) | ||||
e.sender = mail.sender | e.sender = mail.sender | ||||
@@ -137,6 +140,8 @@ def add(email, sender, subject, formatted, text_content=None, | |||||
e.send_after = send_after | e.send_after = send_after | ||||
e.db_insert() | e.db_insert() | ||||
return e | |||||
def check_email_limit(recipients): | def check_email_limit(recipients): | ||||
# if using settings from site_config.json, check email limit | # if using settings from site_config.json, check email limit | ||||
# No limit for own email settings | # No limit for own email settings | ||||
@@ -347,8 +352,10 @@ def send_one(email, smtpserver=None, auto_commit=True, now=False): | |||||
log('frappe.email.queue.flush', unicode(e)) | log('frappe.email.queue.flush', unicode(e)) | ||||
def clear_outbox(): | def clear_outbox(): | ||||
"""Remove mails older than 31 days in Outbox. Called daily via scheduler.""" | |||||
frappe.db.sql("""delete from `tabEmail Queue` where | |||||
"""Remove low priority older than 31 days in Outbox and expire mails not sent for 7 days. | |||||
Called daily via scheduler.""" | |||||
frappe.db.sql("""delete from `tabEmail Queue` where priority=0 | |||||
datediff(now(), modified) > 31""") | datediff(now(), modified) > 31""") | ||||
frappe.db.sql("""update `tabEmail Queue` set status='Expired' | frappe.db.sql("""update `tabEmail Queue` set status='Expired' | ||||