From b8299cdb1934627120bc1a44b36933eb7ecf1a0d Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 15 Nov 2024 10:28:23 +0530 Subject: [PATCH 1/2] fix: validate duplicate mail domain --- mail_client/mail_client/doctype/mail_domain/mail_domain.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mail_client/mail_client/doctype/mail_domain/mail_domain.py b/mail_client/mail_client/doctype/mail_domain/mail_domain.py index 7e23fa8a..b5c3ff93 100644 --- a/mail_client/mail_client/doctype/mail_domain/mail_domain.py +++ b/mail_client/mail_client/doctype/mail_domain/mail_domain.py @@ -18,6 +18,7 @@ def validate(self) -> None: self.validate_newsletter_retention() if self.is_new(): + self.validate_duplicate() self.access_token = generate_access_token() self.dkim_private_key, self.dkim_public_key = generate_dkim_keys() self.add_or_update_domain_in_mail_server() @@ -50,6 +51,12 @@ def validate_newsletter_retention(self) -> None: "Mail Client Settings", "default_newsletter_retention", cache=True ) + def validate_duplicate(self) -> None: + """Validate if the Mail Domain already exists.""" + + if frappe.db.exists("Mail Domain", {"domain_name": self.domain_name}): + frappe.throw(_("Mail Domain {0} already exists.").format(frappe.bold(self.domain_name))) + def add_or_update_domain_in_mail_server(self) -> None: """Adds or Updates the Domain in the Mail Server.""" From 485d9b094543e201549dbd9a549eb84d1f744a72 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 15 Nov 2024 11:33:04 +0530 Subject: [PATCH 2/2] feat: rotate DKIM keys and access token --- .../doctype/mail_domain/mail_domain.js | 63 ++++++++++++++++++- .../doctype/mail_domain/mail_domain.py | 20 ++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/mail_client/mail_client/doctype/mail_domain/mail_domain.js b/mail_client/mail_client/doctype/mail_domain/mail_domain.js index d4080e11..683368c2 100644 --- a/mail_client/mail_client/doctype/mail_domain/mail_domain.js +++ b/mail_client/mail_client/doctype/mail_domain/mail_domain.js @@ -19,8 +19,37 @@ frappe.ui.form.on("Mail Domain", { frm.add_custom_button( __("Refresh DNS Records"), () => { - frappe.confirm(__("Are you certain you wish to proceed?"), () => - frm.trigger("refresh_dns_records") + frappe.confirm( + __( + "Are you sure you want to refresh the DNS records? If there are any changes, you'll need to update the DNS settings with your DNS provider accordingly." + ), + () => frm.trigger("refresh_dns_records") + ); + }, + __("Actions") + ); + + frm.add_custom_button( + __("Rotate DKIM Keys"), + () => { + frappe.confirm( + __( + "Are you sure you want to rotate the DKIM keys? This will generate new keys for email signing and may take up to 10 minutes to propagate across DNS servers. Emails sent during this period may be blocked due to a DKIM signature mismatch." + ), + () => frm.trigger("rotate_dkim_keys") + ); + }, + __("Actions") + ); + + frm.add_custom_button( + __("Rotate Access Token"), + () => { + frappe.confirm( + __( + "Are you sure you want to rotate the access token? This will replace the current token with a new one, potentially interrupting any active sessions using the old token." + ), + () => frm.trigger("rotate_access_token") ); }, __("Actions") @@ -57,4 +86,34 @@ frappe.ui.form.on("Mail Domain", { }, }); }, + + rotate_dkim_keys(frm) { + frappe.call({ + doc: frm.doc, + method: "rotate_dkim_keys", + args: {}, + freeze: true, + freeze_message: __("Rotating DKIM Keys..."), + callback: (r) => { + if (!r.exc) { + frm.refresh(); + } + }, + }); + }, + + rotate_access_token(frm) { + frappe.call({ + doc: frm.doc, + method: "rotate_access_token", + args: {}, + freeze: true, + freeze_message: __("Rotating Access Token..."), + callback: (r) => { + if (!r.exc) { + frm.refresh(); + } + }, + }); + }, }); diff --git a/mail_client/mail_client/doctype/mail_domain/mail_domain.py b/mail_client/mail_client/doctype/mail_domain/mail_domain.py index b5c3ff93..f1ef551a 100644 --- a/mail_client/mail_client/doctype/mail_domain/mail_domain.py +++ b/mail_client/mail_client/doctype/mail_domain/mail_domain.py @@ -101,6 +101,26 @@ def verify_dns_records(self, do_not_save: bool = False) -> None: if not do_not_save: self.save() + @frappe.whitelist() + def rotate_dkim_keys(self) -> None: + """Rotates the DKIM Keys.""" + + frappe.only_for(["System Manager", "Administrator"]) + self.dkim_private_key, self.dkim_public_key = generate_dkim_keys() + self.add_or_update_domain_in_mail_server() + self.save() + frappe.msgprint(_("DKIM Keys rotated successfully."), indicator="green", alert=True) + + @frappe.whitelist() + def rotate_access_token(self) -> None: + """Rotates the Access Token.""" + + frappe.only_for(["System Manager", "Administrator"]) + self.access_token = generate_access_token() + self.add_or_update_domain_in_mail_server() + self.save() + frappe.msgprint(_("Access Token rotated successfully."), indicator="green", alert=True) + def generate_access_token() -> str: """Generates and returns the Access Token."""