Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
openaec-foundation avatar

Frappe Core Notifications

  • 1 installs
  • 159 repo stars
  • Updated July 8, 2026
  • openaec-foundation/erpnext_anthropic_claude_development_skill_package

Covers Frappe notifications including frappe.sendmail, Notification DocType, email templates, Assignment Rules, Auto Repeat, and ToDo items.

About

A reference skill for building email notifications, system alerts, assignment rules, and ToDo items in Frappe. A developer uses it to configure notifications and avoid silent email delivery failures.

  • frappe.sendmail, Notification DocType, and Jinja email templates
  • Assignment Rules, Auto Repeat scheduling, and ToDo API

Frappe Core Notifications by the numbers

  • 1 all-time installs (skills.sh)
  • Ranked #3,836 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill frappe-core-notifications

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1
repo stars159
Last updatedJuly 8, 2026
Repositoryopenaec-foundation/erpnext_anthropic_claude_development_skill_package

What it does

Covers Frappe notifications including frappe.sendmail, Notification DocType, email templates, Assignment Rules, Auto Repeat, and ToDo items.

Files

SKILL.mdMarkdownGitHub ↗

Frappe Notification System

Quick Reference

ChannelMethodUse Case
Emailfrappe.sendmail()Programmatic email with full control
EmailNotification DocType (Email)No-code email on document events
Systemfrappe.publish_realtime()In-app real-time alerts via socket.io
SystemNotification DocType (System)No-code in-app alerts
SMSNotification DocType (SMS)No-code SMS on document events
SlackNotification DocType (Slack)No-code Slack webhook messages
Assignmentfrappe.desk.form.assign_to.add()Assign document to user (creates ToDo)
ToDofrappe.get_doc({"doctype": "ToDo", ...})Direct task creation
Commentdoc.add_comment("Comment", text)Timeline comment on document
Tagdoc.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

EventFires When
NewDocument is created
SaveDocument is saved
SubmitDocument is submitted
CancelDocument is cancelled
Value ChangeSpecific field value changes
Days BeforeN days before a date field value
Days AfterN days after a date field value
MethodCustom 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

SourceDescription
Document FieldEmail/phone field on the document
RoleAll users with specified role
CustomHard-coded email address
All AssigneesAll users assigned to the document
ConditionJinja 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",               # broadcast to doctype room
    docname="SINV-00001",                  # broadcast to document room
    after_commit=True,                     # emit after transaction commits
)

Room Types

RoomAudience
user:{email}Single user (set user=)
doctype:{dt}All users viewing that list
doc:{dt}/{dn}All users viewing that document
allAll Desk users site-wide
task_progress:{id}Background task progress

Built-in Events

EventPurpose
msgprintShow message dialog to user
list_updateRefresh document list view
docinfo_updateRefresh document info sidebar
progressShow progress bar

ALWAYS set after_commit=True when publishing from within a database transaction — otherwise the event fires before data is committed and the client may read stale data.

---

Assignment Rules

Auto-assign documents to users based on conditions (no code).

Configuration Fields

FieldPurpose
Document TypeWhich DocType triggers the rule
Assign ConditionPython expression (same as Notification)
Assignment DaysLimit to specific weekdays
UsersList of users to assign to
Assignment RuleRound Robin, Load Balancing, or Based on Field

Programmatic Assignment

from frappe.desk.form.assign_to import add, remove, close, clear

# Assign
add({
    "assign_to": ["user@example.com"],
    "doctype": "Task",
    "name": "TASK-00001",
    "description": "Please review this task",
    "priority": "High",
    "date": "2025-12-31",
})

# Remove assignment (cancels ToDo)
remove("Task", "TASK-00001", "user@example.com")

# Close assignment (only assignee can close)
close("Task", "TASK-00001", "user@example.com")

# Clear all assignments
clear("Task", "TASK-00001")

NEVER call close() as a different user than the assignee — it raises a permission error.

---

Auto Repeat

Creates recurring copies of documents on a schedule.

FieldPurpose
Reference DocTypeWhich DocType to repeat
Reference DocumentSource document to copy
FrequencyDaily, Weekly, Monthly, Quarterly, Half-yearly, Yearly
Start Date / End DateSchedule window
Notify By EmailSend notification on creation

ALWAYS set an End Date on Auto Repeat — open-ended schedules create documents indefinitely and are difficult to debug.

---

ToDo API

# Create ToDo directly
todo = frappe.get_doc({
    "doctype": "ToDo",
    "allocated_to": "user@example.com",
    "assigned_by": frappe.session.user,
    "description": "Review the quarterly report",
    "priority": "Medium",
    "date": "2025-12-31",
    "status": "Open",
    "reference_type": "Task",
    "reference_name": "TASK-00001",
}).insert(ignore_permissions=True)

ToDo statuses: Open, Closed, Cancelled.

---

Comments and Tags

# Add comment (appears in document timeline)
doc.add_comment("Comment", text="Reviewed and approved")
doc.add_comment("Edit", "Values changed")

# Add/get tags
doc.add_tag("urgent")
tags = doc.get_tags()  # returns list of tag strings

---

Version Differences

Featurev14v15v16
Notification DocTypeAll 4 channelsAll 4 channelsAll 4 channels
Minutes Before/AfterNot availableAvailableAvailable
frappe.publish_realtimeAvailableAvailableAvailable
Assignment RulesAvailableAvailableAvailable

---

See Also

  • references/email-system.md — Email Account, Email Queue, Communication linking, Newsletter, Notification Log
  • references/examples.md — Full notification workflow examples
  • references/anti-patterns.md — Common mistakes and fixes
  • references/api-reference.md — Complete API signatures
  • frappe-core-database — Database operations referenced in notifications
  • frappe-core-permissions — Permission model for notification access

Related skills

Backend & APIsbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.