Merge pull request #24235 from akhilnarang/notification-receiver-language

fix: use receiver's language for some notifications
This commit is contained in:
Akhil Narang 2024-01-11 16:03:23 +05:30 committed by GitHub
commit beac0122b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 32 deletions

View file

@ -29,6 +29,7 @@ class NotificationLog(Document):
read: DF.Check
subject: DF.Text | None
type: DF.Literal["Mention", "Energy Point", "Assignment", "Share", "Alert"]
# end: auto-generated types
def after_insert(self):
frappe.publish_realtime("notification", after_commit=True, user=self.for_user)
@ -115,18 +116,17 @@ def _get_user_ids(user_emails):
return [user for user in user_names if is_notifications_enabled(user)]
def send_notification_email(doc):
def send_notification_email(doc: NotificationLog):
if doc.type == "Energy Point" and doc.email_content is None:
return
from frappe.utils import get_url_to_form, strip_html
email = frappe.db.get_value("User", doc.for_user, "email")
if not email:
user = frappe.db.get_value("User", doc.for_user, fieldname=["email", "language"], as_dict=True)
if not user:
return
header = get_email_header(doc)
header = get_email_header(doc, user.language)
email_subject = strip_html(doc.subject)
args = {
"body_content": doc.subject,
@ -140,7 +140,7 @@ def send_notification_email(doc):
args["doc_link"] = get_url_to_form(doc.document_type, doc.document_name)
frappe.sendmail(
recipients=email,
recipients=user.email,
subject=email_subject,
template="new_notification",
args=args,
@ -149,14 +149,14 @@ def send_notification_email(doc):
)
def get_email_header(doc):
def get_email_header(doc, language: str | None = None):
docname = doc.document_name
header_map = {
"Default": _("New Notification"),
"Mention": _("New Mention on {0}").format(docname),
"Assignment": _("Assignment Update on {0}").format(docname),
"Share": _("New Document Shared {0}").format(docname),
"Energy Point": _("Energy Point Update on {0}").format(docname),
"Default": _("New Notification", lang=language),
"Mention": _("New Mention on {0}", lang=language).format(docname),
"Assignment": _("Assignment Update on {0}", lang=language).format(docname),
"Share": _("New Document Shared {0}", lang=language).format(docname),
"Energy Point": _("Energy Point Update on {0}", lang=language).format(docname),
}
return header_map[doc.type or "Default"]

View file

@ -253,8 +253,10 @@ def notify_assignment(
if not (assigned_by and allocated_to and doc_type and doc_name):
return
assigned_user = frappe.db.get_value("User", allocated_to, ["language", "enabled"], as_dict=True)
# return if self assigned or user disabled
if assigned_by == allocated_to or not frappe.db.get_value("User", allocated_to, "enabled"):
if assigned_by == allocated_to or not assigned_user.enabled:
return
# Search for email address in description -- i.e. assignee
@ -263,14 +265,16 @@ def notify_assignment(
description_html = f"<div>{description}</div>" if description else None
if action == "CLOSE":
subject = _("Your assignment on {0} {1} has been removed by {2}").format(
frappe.bold(_(doc_type)), get_title_html(title), frappe.bold(user_name)
)
subject = _(
"Your assignment on {0} {1} has been removed by {2}", lang=assigned_user.language
).format(frappe.bold(_(doc_type)), get_title_html(title), frappe.bold(user_name))
else:
user_name = frappe.bold(user_name)
document_type = frappe.bold(_(doc_type))
document_type = frappe.bold(_(doc_type, lang=assigned_user.language))
title = get_title_html(title)
subject = _("{0} assigned a new task {1} {2} to you").format(user_name, document_type, title)
subject = _("{0} assigned a new task {1} {2} to you", lang=assigned_user.language).format(
user_name, document_type, title
)
notification_doc = {
"type": "Assignment",

View file

@ -6,7 +6,7 @@ import quopri
import traceback
from contextlib import suppress
from email.parser import Parser
from email.policy import SMTPUTF8, default
from email.policy import SMTP
import frappe
from frappe import _, safe_encode, task
@ -169,7 +169,9 @@ class EmailQueue(Document):
else:
if not frappe.flags.in_test or frappe.flags.testing_email:
ctx.smtp_server.session.sendmail(
from_addr=self.sender, to_addrs=recipient.recipient, msg=message
from_addr=self.sender,
to_addrs=recipient.recipient,
msg=message.decode("utf-8").encode(),
)
ctx.update_recipient_status_to_sent(recipient)
@ -264,7 +266,7 @@ class SendMailContext:
@savepoint(catch=Exception)
def notify_failed_email(self):
# Parse the email body to extract the subject
subject = Parser(policy=default).parsestr(self.queue_doc.message)["Subject"]
subject = Parser(policy=SMTP).parsestr(self.queue_doc.message)["Subject"]
# Construct the notification
notification = frappe.new_doc("Notification Log")
@ -281,7 +283,7 @@ class SendMailContext:
recipient.update_db(status="Sent", commit=True)
def get_message_object(self, message):
return Parser(policy=SMTPUTF8).parsestr(message)
return Parser(policy=SMTP).parsestr(message)
def message_placeholder(self, placeholder_key):
# sourcery skip: avoid-builtin-shadow
@ -293,9 +295,10 @@ class SendMailContext:
}
return map.get(placeholder_key)
def build_message(self, recipient_email):
def build_message(self, recipient_email) -> bytes:
"""Build message specific to the recipient."""
message = self.queue_doc.message
if not message:
return ""

View file

@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
import email.utils
import os
import re
@ -136,8 +135,8 @@ class EMail:
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 = MIMEMultipart("mixed", policy=policy.SMTP)
self.msg_alternative = MIMEMultipart("alternative", policy=policy.SMTP)
self.msg_root.attach(self.msg_alternative)
self.cc = cc or []
self.bcc = bcc or []
@ -186,7 +185,7 @@ class EMail:
"""
from email.mime.text import MIMEText
part = MIMEText(message, "plain", "utf-8", policy=policy.SMTPUTF8)
part = MIMEText(message, "plain", "utf-8", policy=policy.SMTP)
self.msg_alternative.attach(part)
def set_part_html(self, message, inline_images):
@ -199,9 +198,9 @@ class EMail:
message, _inline_images = replace_filename_with_cid(message)
# prepare parts
msg_related = MIMEMultipart("related", policy=policy.SMTPUTF8)
msg_related = MIMEMultipart("related", policy=policy.SMTP)
html_part = MIMEText(message, "html", "utf-8", policy=policy.SMTPUTF8)
html_part = MIMEText(message, "html", "utf-8", policy=policy.SMTP)
msg_related.attach(html_part)
for image in _inline_images:
@ -215,7 +214,7 @@ class EMail:
self.msg_alternative.attach(msg_related)
else:
self.msg_alternative.attach(MIMEText(message, "html", "utf-8", policy=policy.SMTPUTF8))
self.msg_alternative.attach(MIMEText(message, "html", "utf-8", policy=policy.SMTP))
def set_html_as_text(self, html):
"""Set plain text from HTML"""
@ -228,7 +227,7 @@ class EMail:
from email.mime.text import MIMEText
maintype, subtype = mime_type.split("/")
part = MIMEText(message, _subtype=subtype, policy=policy.SMTPUTF8)
part = MIMEText(message, _subtype=subtype, policy=policy.SMTP)
if as_attachment:
part.add_header("Content-Disposition", "attachment", filename=filename)
@ -342,7 +341,7 @@ class EMail:
"""validate, build message and convert to string"""
self.validate()
self.make()
return self.msg_root.as_string(policy=policy.SMTPUTF8)
return self.msg_root.as_string(policy=policy.SMTP)
def get_formatted_html(