From f6c8d5e0387a677ac2e51917e8b647a81d5d388c Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 10:55:07 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`fix/ema?= =?UTF-8?q?il-campaign-timeout`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstrings generation was requested by @pratikb64. * https://github.com/frappe/erpnext/pull/51994#issuecomment-3783742931 The following files were modified: * `erpnext/crm/doctype/email_campaign/email_campaign.py` --- .../doctype/email_campaign/email_campaign.py | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/erpnext/crm/doctype/email_campaign/email_campaign.py b/erpnext/crm/doctype/email_campaign/email_campaign.py index a5a2132dc0c..8fc72ee0d5e 100644 --- a/erpnext/crm/doctype/email_campaign/email_campaign.py +++ b/erpnext/crm/doctype/email_campaign/email_campaign.py @@ -100,6 +100,16 @@ def send_email_to_leads_or_contacts(): def send_mail(entry, email_campaign): + """ + Send the rendered email template to the recipients defined by the campaign, creating one communication per batch. + + Parameters: + entry (dict): Campaign schedule entry containing at least the `email_template` reference and `send_after_days`. + email_campaign (Document): Email Campaign document that provides recipient selection, sender, campaign name, start/end dates and related context. + + Returns: + comm (Document or None): The last created communication Document for the final recipient batch, or `None` if no recipients were found. + """ recipient_list = [] if email_campaign.email_campaign_for == "Email Group": for member in frappe.db.get_list( @@ -116,19 +126,29 @@ def send_mail(entry, email_campaign): email_template = frappe.get_doc("Email Template", entry.get("email_template")) sender = frappe.db.get_value("User", email_campaign.get("sender"), "email") context = {"doc": frappe.get_doc(email_campaign.email_campaign_for, email_campaign.recipient)} - # send mail and link communication to document - comm = make( - doctype="Email Campaign", - name=email_campaign.name, - subject=frappe.render_template(email_template.get("subject"), context), - content=frappe.render_template(email_template.response_, context), - sender=sender, - bcc=recipient_list, - communication_medium="Email", - sent_or_received="Sent", - send_email=True, - email_template=email_template.name, - ) + subject = frappe.render_template(email_template.get("subject"), context) + content = frappe.render_template(email_template.response_, context) + + # Batch recipients to avoid timeout when processing large email groups + BATCH_SIZE = 100 + comm = None + + for i in range(0, len(recipient_list), BATCH_SIZE): + batch = recipient_list[i : i + BATCH_SIZE] + + comm = make( + doctype="Email Campaign", + name=email_campaign.name, + subject=subject, + content=content, + sender=sender, + bcc=batch, + communication_medium="Email", + sent_or_received="Sent", + send_email=True, + email_template=email_template.name, + ) + return comm @@ -143,4 +163,4 @@ def set_email_campaign_status(): email_campaigns = frappe.get_all("Email Campaign", filters={"status": ("!=", "Unsubscribed")}) for entry in email_campaigns: email_campaign = frappe.get_doc("Email Campaign", entry.name) - email_campaign.update_status() + email_campaign.update_status() \ No newline at end of file