Skip to content
AI & Agents
Skill

/frappe-core-notifications

Use when implementing email notifications, system alerts, Assignment Rules, Auto Repeat, or ToDo items. Prevents misconfigured Email Accounts, broken notification templates, and silent delivery failures. Covers frappe.sendmail, Notification DocType, Email Account setup, Jinja

From plugin
frappe-claude-skill-package
20061 skills

Claude Code

$ npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-core-notifications --agent claude-code

SKILL.md

frappe-core-notifications.SKILL.md
name: frappe-core-notifications
description: >
  Use when implementing email notifications, system alerts, Assignment Rules, Auto Repeat, or ToDo items.
  Prevents misconfigured Email Accounts, broken notification templates, and silent delivery failures.
  Covers frappe.sendmail, Notification DocType, Email Account setup, Jinja email templates, Assignment Rules, Auto Repeat scheduling, ToDo API.
  Keywords: notification, email, sendmail, Email Account, Assignment Rule, Auto Repeat, ToDo, alert, template, notify on approval, email when status changes, alert, email not sending, notification not working..
license: MIT
compatibility: "Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16."
metadata:
  author: OpenAEC-Foundation
  version: "2.0"

Frappe Notification System

Quick Reference

| Channel | Method | Use Case | |---------|--------|----------| | Email | `frappe.sendmail()` | Programmatic email with full control | | Email | Notification DocType (Email) | No-code email on document events | | System | `frappe.publish_realtime()` | In-app real-time alerts via socket.io | | System | Notification DocType (System) | No-code in-app alerts | | SMS | Notification DocType (SMS) | No-code SMS on document events | | Slack | Notification DocType (Slack) | No-code Slack webhook messages | | Assignment | `frappe.desk.form.assign_to.add()` | Assign document to user (creates ToDo) | | ToDo | `frappe.get_doc({"doctype": "ToDo", ...})` | Direct task creation | | Comment | `doc.add_comment("Comment", text)` | Timeline comment on document | | Tag | `doc.add_tag("tag_name")` | Document tagging for filtering |

---

Decision Tree

What notification mechanism do you need?
│
├─ Email on document event (no code)?
│  └─ Notification DocType → Channel: Email
│
├─ Programmatic email with custom logic?
│  └─ frappe.sendmail() in server script or hook
│
├─ Real-time in-app notification?
│  ├─ No-code → Notification DocType → Channel: System Notification
│  └─ Programmatic → frappe.publish_realtime()
│
├─ SMS on document event?
│  └─ Notification DocType → Channel: SMS (requires SMS Settings)
│
├─ Assign document to user?
│  ├─ No-code → Assignment Rule DocType
│  └─ Programmatic → frappe.desk.form.assign_to.add()
│
├─ Recurring document creation?
│  └─ Auto Repeat DocType
│
└─ Add comment or tag?
   ├─ Comment → doc.add_comment("Comment", text="...")
   └─ Tag → doc.add_tag("tag_name")

---

Notification DocType

The Notification DocType enables no-code alerts across four channels.

Event Triggers

| Event | Fires When | |-------|------------| | New | Document is created | | Save | Document is saved | | Submit | Document is submitted | | Cancel | Document is cancelled | | Value Change | Specific field value changes | | Days Before | N days before a date field value | | Days After | N days after a date field value | | Method | Custom Python method is called |

Condition Syntax

ALWAYS use Python expressions in the Condition field:

# Status-based
doc.status == "Open"

# Date-based
doc.due_date == nowdate()

# Threshold-based
doc.grand_total > 40000

# Combined
doc.status == "Overdue" and doc.grand_total > 10000

Available context: `doc`, `nowdate()`, `frappe.utils.*`.

Recipient Configuration

| Source | Description | |--------|-------------| | Document Field | Email/phone field on the document | | Role | All users with specified role | | Custom | Hard-coded email address | | All Assignees | All users assigned to the document | | Condition | Jinja expression to filter recipients |

Jinja Message Template

<h3>Order Overdue</h3>
<p>Transaction {{ doc.name }} has exceeded its due date.</p>

{% if comments %}
Last comment: {{ comments[-1].comment }} by {{ comments[-1].by }}
{% endif %}

<ul>
  <li>Customer: {{ doc.customer }}</li>
  <li>Amount: {{ doc.grand_total }}</li>
</ul>

Template variables: `{{ doc }}`, `{{ doc.fieldname }}`, `{{ comments }}`, `{{ nowdate() }}`.

Attach Print

Set **Attach Print** to include a PDF of the document. Select a **Print Format** for custom layout.

---

frappe.sendmail(): Programmatic Email

frappe.sendmail(
    recipients=["user@example.com"],       # list of email addresses
    subject="Invoice Due",                  # email subject
    message="<p>Your invoice is due.</p>",  # HTML body
    template="invoice_reminder",            # Jinja template name (optional)
    args={"customer": "ACME"},              # template context variables
    attachments=[{"fname": "inv.pdf", "fcontent": pdf_bytes}],
    reference_doctype="Sales Invoice",      # links email to document
    reference_name="SINV-00001",
    delayed=True,                           # queue via Email Queue (default)
    now=False,                              # True = send immediately, skip queue
    sender="noreply@example.com",           # override sender
    cc=["manager@example.com"],
    bcc=["audit@example.com"],
    reply_to="support@example.com",
    expose_recipients="header",             # show recipients in email header
)

**Rules**:

  • ALWAYS set `reference_doctype` and `reference_name` when the email relates to a document — this links the email in the document timeline.
  • NEVER set `now=True` in production — it blocks the request. Use `delayed=True` (default) to queue via Email Queue.
  • ALWAYS ensure an Email Account with "Enable Outgoing" is configured before calling `frappe.sendmail`.

Email Queue

Emails are queued in the **Email Queue** DocType and sent by the scheduler. Check queue status:

# Check pending emails
pending = frappe.get_all("Email Queue", filters={"status": "Not Sent"}, limit=10)

---

frappe.publish_realtime(): System Notifications

frappe.publish_realtime(
    event="msgprint",                      # event name
    message={"msg": "Task completed!"},    # dict payload
    user="user@example.com",               # target specific user
    doctype="Sales Invoice",
Read more
@impertio-studio
Ships withfrappe-claude-skill-package

60 deterministic Claude AI skills for Frappe Framework & ERPNext v14-v16 development and operations

Stars on GitHub

Momentum

stars in total
200
Star history of Impertio-Studio/Frappe_Claude_Skill_Package on GitHub, a chart by star-history.com

More skills from other plugins.

1password

1password

Set up and use 1Password CLI for sign-in, desktop integration, and reading or injecting secrets.

openclaw13d393k
@openclaw@openclawInstall Skill

Questions about frappe-core-notifications.

Which coding agents can use frappe-core-notifications?
frappe-core-notifications installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.