[fix] Use Bulk Email status as Delivery Status of a Communication
This commit is contained in:
parent
54f9632206
commit
c427de108c
10 changed files with 1075 additions and 970 deletions
|
|
@ -318,7 +318,7 @@ def sendmail(recipients=(), sender="", subject="No Subject", message="No Message
|
|||
unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None,
|
||||
attachments=None, content=None, doctype=None, name=None, reply_to=None,
|
||||
cc=(), show_as_cc=(), message_id=None, in_reply_to=None, as_bulk=False, send_after=None, expose_recipients=False,
|
||||
bulk_priority=1):
|
||||
bulk_priority=1, communication=None):
|
||||
"""Send email using user's default **Email Account** or global default **Email Account**.
|
||||
|
||||
|
||||
|
|
@ -339,6 +339,7 @@ def sendmail(recipients=(), sender="", subject="No Subject", message="No Message
|
|||
:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To.
|
||||
:param send_after: Send after the given datetime.
|
||||
:param expose_recipients: Display all recipients in the footer message - "This email was sent to"
|
||||
:param communication: Communication link to be set in Bulk Email record
|
||||
"""
|
||||
|
||||
if bulk or as_bulk:
|
||||
|
|
@ -348,7 +349,7 @@ def sendmail(recipients=(), sender="", subject="No Subject", message="No 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, message_id=message_id, in_reply_to=in_reply_to,
|
||||
send_after=send_after, expose_recipients=expose_recipients, bulk_priority=bulk_priority)
|
||||
send_after=send_after, expose_recipients=expose_recipients, bulk_priority=bulk_priority, communication=communication)
|
||||
else:
|
||||
import frappe.email
|
||||
if as_markdown:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,7 @@ from frappe.model.db_schema import add_column
|
|||
from frappe.core.doctype.communication.comment import validate_comment, notify_mentions, update_comment_in_doc
|
||||
from frappe.core.doctype.communication.email import validate_email, notify, _notify, update_parent_status
|
||||
from email.utils import parseaddr
|
||||
from collections import Counter
|
||||
|
||||
exclude_from_linked_with = True
|
||||
|
||||
|
|
@ -174,6 +175,35 @@ class Communication(Document):
|
|||
|
||||
_notify(self, print_html, print_format, attachments, recipients, cc)
|
||||
|
||||
def set_delivery_status(self, commit=False):
|
||||
'''Look into the status of Bulk Email linked to this Communication and set the Delivery Status of this Communication'''
|
||||
delivery_status = None
|
||||
status_counts = Counter(frappe.db.sql_list('''select status from `tabBulk Email` where communication=%s''', self.name))
|
||||
|
||||
if status_counts.get('Not Sent') or status_counts.get('Sending'):
|
||||
delivery_status = 'Sending'
|
||||
|
||||
elif status_counts.get('Error'):
|
||||
delivery_status = 'Error'
|
||||
|
||||
elif status_counts.get('Expired'):
|
||||
delivery_status = 'Expired'
|
||||
|
||||
elif status_counts.get('Sent'):
|
||||
delivery_status = 'Sent'
|
||||
|
||||
if delivery_status:
|
||||
self.db_set('delivery_status', delivery_status)
|
||||
|
||||
frappe.publish_realtime('update_communication', self.as_dict(),
|
||||
doctype=self.reference_doctype, docname=self.reference_name, after_commit=True)
|
||||
|
||||
# for list views and forms
|
||||
self.notify_update()
|
||||
|
||||
if commit:
|
||||
frappe.db.commit()
|
||||
|
||||
def on_doctype_update():
|
||||
"""Add index in `tabCommunication` for `(reference_doctype, reference_name)`"""
|
||||
frappe.db.add_index("Communication", ["reference_doctype", "reference_name"])
|
||||
|
|
|
|||
|
|
@ -131,7 +131,8 @@ def _notify(doc, print_html=None, print_format=None, attachments=None,
|
|||
attachments=doc.attachments,
|
||||
message_id=doc.name,
|
||||
unsubscribe_message=_("Leave this conversation"),
|
||||
bulk=True
|
||||
bulk=True,
|
||||
communication=doc.name
|
||||
)
|
||||
|
||||
def update_parent_status(doc):
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class BulkLimitCrossedError(frappe.ValidationError): pass
|
|||
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):
|
||||
expose_recipients=False, bulk_priority=1, communication=None):
|
||||
"""Add email to sending queue (Bulk Email)
|
||||
|
||||
:param recipients: List of recipients.
|
||||
|
|
@ -34,6 +34,7 @@ def send(recipients=None, sender=None, subject=None, message=None, reference_doc
|
|||
: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"
|
||||
|
|
@ -101,12 +102,15 @@ def send(recipients=None, sender=None, subject=None, message=None, reference_doc
|
|||
|
||||
# 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)
|
||||
reference_name, attachments, reply_to, cc, message_id, in_reply_to, send_after, bulk_priority,
|
||||
email_account=email_account, communication=communication)
|
||||
|
||||
def add(email, sender, subject, formatted, text_content=None,
|
||||
reference_doctype=None, reference_name=None, attachments=None, reply_to=None,
|
||||
cc=(), message_id=None, in_reply_to=None, send_after=None, bulk_priority=1, email_account=None):
|
||||
cc=(), message_id=None, in_reply_to=None, send_after=None, bulk_priority=1,
|
||||
email_account=None, communication=None):
|
||||
"""add to bulk mail queue"""
|
||||
|
||||
e = frappe.new_doc('Bulk Email')
|
||||
e.recipient = email
|
||||
e.priority = bulk_priority
|
||||
|
|
@ -130,12 +134,13 @@ def add(email, sender, subject, formatted, text_content=None,
|
|||
|
||||
e.reference_doctype = reference_doctype
|
||||
e.reference_name = reference_name
|
||||
e.communication = communication
|
||||
e.send_after = send_after
|
||||
e.insert(ignore_permissions=True)
|
||||
|
||||
def check_bulk_limit(recipients):
|
||||
# get count of mails sent this month
|
||||
this_month = frappe.db.sql("""select count(*) from `tabBulk Email` where
|
||||
this_month = frappe.db.sql("""select count(name) from `tabBulk Email` where
|
||||
status='Sent' and MONTH(creation)=MONTH(CURDATE())""")[0][0]
|
||||
|
||||
# if using settings from site_config.json, check bulk limit
|
||||
|
|
@ -261,6 +266,10 @@ def flush(from_test=False):
|
|||
|
||||
frappe.db.sql("""update `tabBulk Email` set status='Sending' where name=%s""",
|
||||
(email["name"],), auto_commit=auto_commit)
|
||||
|
||||
if email.communication:
|
||||
frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)
|
||||
|
||||
try:
|
||||
if not from_test:
|
||||
smtpserver.setup_email_account(email.reference_doctype)
|
||||
|
|
@ -269,6 +278,9 @@ def flush(from_test=False):
|
|||
frappe.db.sql("""update `tabBulk Email` set status='Sent' where name=%s""",
|
||||
(email["name"],), auto_commit=auto_commit)
|
||||
|
||||
if email.communication:
|
||||
frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)
|
||||
|
||||
except (smtplib.SMTPServerDisconnected,
|
||||
smtplib.SMTPConnectError,
|
||||
smtplib.SMTPHeloError,
|
||||
|
|
@ -278,6 +290,9 @@ def flush(from_test=False):
|
|||
frappe.db.sql("""update `tabBulk Email` set status='Not Sent' where name=%s""",
|
||||
(email["name"],), auto_commit=auto_commit)
|
||||
|
||||
if email.communication:
|
||||
frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)
|
||||
|
||||
# no need to attempt further
|
||||
return
|
||||
|
||||
|
|
@ -285,6 +300,9 @@ def flush(from_test=False):
|
|||
frappe.db.sql("""update `tabBulk Email` set status='Error', error=%s
|
||||
where name=%s""", (unicode(e), email["name"]), auto_commit=auto_commit)
|
||||
|
||||
if email.communication:
|
||||
frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)
|
||||
|
||||
# NOTE: removing commit here because we pass auto_commit
|
||||
# finally:
|
||||
# frappe.db.commit()
|
||||
|
|
|
|||
|
|
@ -183,6 +183,32 @@
|
|||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "communication",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Communication",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Communication",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
|
|
@ -245,8 +271,8 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-02-26 06:44:01.199764",
|
||||
"modified_by": "anand@erpnext.com",
|
||||
"modified": "2016-04-18 05:13:07.741981",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Email",
|
||||
"name": "Bulk Email",
|
||||
"owner": "Administrator",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// MIT License. See license.txt
|
||||
|
||||
frappe.provide('frappe.timeline');
|
||||
|
||||
frappe.ui.form.Timeline = Class.extend({
|
||||
init: function(opts) {
|
||||
$.extend(this, opts);
|
||||
|
|
@ -551,3 +553,71 @@ frappe.ui.form.Timeline = Class.extend({
|
|||
frappe.ui.setup_like_popover(this.wrapper, ".comment-likes");
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(frappe.timeline, {
|
||||
new_communication: function(communication) {
|
||||
var docinfo = frappe.model.get_docinfo(communication.reference_doctype, communication.reference_name);
|
||||
if (docinfo && docinfo.communications) {
|
||||
var communications = docinfo.communications;
|
||||
var communication_exists = false;
|
||||
for (var i=0, l=communications.length; i<l; i++) {
|
||||
if (communications[i].name==communication.name) {
|
||||
communication_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!communication_exists) {
|
||||
docinfo.communications = communications.concat([communication]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cur_frm.doctype === communication.reference_doctype && cur_frm.docname === communication.reference_name) {
|
||||
cur_frm.timeline && cur_frm.timeline.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
delete_communication: function(communication) {
|
||||
var docinfo = frappe.model.get_docinfo(communication.reference_doctype, communication.reference_name);
|
||||
var index = frappe.timeline.index_of_communication(communication, docinfo);
|
||||
if (index !== -1) {
|
||||
// remove it from communications list
|
||||
docinfo.communications.splice(index, 1);
|
||||
}
|
||||
|
||||
if (cur_frm.doctype === communication.reference_doctype && cur_frm.docname === communication.reference_name) {
|
||||
cur_frm.timeline && cur_frm.timeline.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
update_communication: function(communication) {
|
||||
var docinfo = frappe.model.get_docinfo(communication.reference_doctype, communication.reference_name);
|
||||
var index = frappe.timeline.index_of_communication(communication, docinfo);
|
||||
|
||||
if (index !== -1) {
|
||||
// update
|
||||
$.extend(docinfo.communications[index], communication);
|
||||
}
|
||||
|
||||
if (cur_frm.doctype === communication.reference_doctype && cur_frm.docname === communication.reference_name) {
|
||||
cur_frm.timeline && cur_frm.timeline.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
index_of_communication: function(communication, docinfo) {
|
||||
var index = -1;
|
||||
|
||||
if (docinfo && docinfo.communications) {
|
||||
var communications = docinfo.communications;
|
||||
|
||||
for (var i=0, l=communications.length; i<l; i++) {
|
||||
if (communications[i].name==communication.name) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
{% if (data.delivery_status) {
|
||||
if (in_list(["Sent", "Opened", "Clicked"], data.delivery_status)) {
|
||||
var indicator_class = "green";
|
||||
} else if (data.delivery_status === "Sending") {
|
||||
var indicator_class = "orange";
|
||||
} else {
|
||||
var indicator_class = "red";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,53 +160,6 @@ $.extend(frappe.model, {
|
|||
}
|
||||
},
|
||||
|
||||
new_communication: function(communication) {
|
||||
var docinfo = frappe.model.get_docinfo(communication.reference_doctype, communication.reference_name);
|
||||
if (docinfo && docinfo.communications) {
|
||||
var communications = docinfo.communications;
|
||||
var communication_exists = false;
|
||||
for (var i=0, l=communications.length; i<l; i++) {
|
||||
if (communications[i].name==communication.name) {
|
||||
communication_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!communication_exists) {
|
||||
docinfo.communications = communications.concat([communication]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cur_frm.doctype === communication.reference_doctype && cur_frm.docname === communication.reference_name) {
|
||||
cur_frm.timeline && cur_frm.timeline.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
delete_communication: function(communication) {
|
||||
var docinfo = frappe.model.get_docinfo(communication.reference_doctype, communication.reference_name);
|
||||
if (docinfo && docinfo.communications) {
|
||||
var communications = docinfo.communications;
|
||||
|
||||
var index = -1;
|
||||
for (var i=0, l=communications.length; i<l; i++) {
|
||||
if (communications[i].name==communication.name) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index !== -1) {
|
||||
// remove it from communications list
|
||||
docinfo.communications.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (cur_frm.doctype === communication.reference_doctype && cur_frm.docname === communication.reference_name) {
|
||||
cur_frm.timeline && cur_frm.timeline.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
get_shared: function(doctype, name) {
|
||||
return frappe.model.get_docinfo(doctype, name).shared;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,11 +26,15 @@ frappe.views.FormFactory = frappe.views.Factory.extend({
|
|||
});
|
||||
|
||||
frappe.realtime.on("new_communication", function(data) {
|
||||
frappe.model.new_communication(data);
|
||||
frappe.timeline.new_communication(data);
|
||||
});
|
||||
|
||||
frappe.realtime.on("delete_communication", function(data) {
|
||||
frappe.model.delete_communication(data);
|
||||
frappe.timeline.delete_communication(data);
|
||||
});
|
||||
|
||||
frappe.realtime.on('update_communication', function(data) {
|
||||
frappe.timeline.update_communication(data);
|
||||
});
|
||||
|
||||
frappe.realtime.on("doc_viewers", function(data) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue