$npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-core-notificationsUse 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 ema
| 1 | # Frappe Notification System |
| 2 | |
| 3 | ## Quick Reference |
| 4 | |
| 5 | | Channel | Method | Use Case | |
| 6 | |---------|--------|----------| |
| 7 | | Email | `frappe.sendmail()` | Programmatic email with full control | |
| 8 | | Email | Notification DocType (Email) | No-code email on document events | |
| 9 | | System | `frappe.publish_realtime()` | In-app real-time alerts via socket.io | |
| 10 | | System | Notification DocType (System) | No-code in-app alerts | |
| 11 | | SMS | Notification DocType (SMS) | No-code SMS on document events | |
| 12 | | Slack | Notification DocType (Slack) | No-code Slack webhook messages | |
| 13 | | Assignment | `frappe.desk.form.assign_to.add()` | Assign document to user (creates ToDo) | |
| 14 | | ToDo | `frappe.get_doc({"doctype": "ToDo", ...})` | Direct task creation | |
| 15 | | Comment | `doc.add_comment("Comment", text)` | Timeline comment on document | |
| 16 | | Tag | `doc.add_tag("tag_name")` | Document tagging for filtering | |
| 17 | |
| 18 | --- |
| 19 | |
| 20 | ## Decision Tree |
| 21 | |
| 22 | ``` |
| 23 | What notification mechanism do you need? |
| 24 | │ |
| 25 | ├─ Email on document event (no code)? |
| 26 | │ └─ Notification DocType → Channel: Email |
| 27 | │ |
| 28 | ├─ Programmatic email with custom logic? |
| 29 | │ └─ frappe.sendmail() in server script or hook |
| 30 | │ |
| 31 | ├─ Real-time in-app notification? |
| 32 | │ ├─ No-code → Notification DocType → Channel: System Notification |
| 33 | │ └─ Programmatic → frappe.publish_realtime() |
| 34 | │ |
| 35 | ├─ SMS on document event? |
| 36 | │ └─ Notification DocType → Channel: SMS (requires SMS Settings) |
| 37 | │ |
| 38 | ├─ Assign document to user? |
| 39 | │ ├─ No-code → Assignment Rule DocType |
| 40 | │ └─ Programmatic → frappe.desk.form.assign_to.add() |
| 41 | │ |
| 42 | ├─ Recurring document creation? |
| 43 | │ └─ Auto Repeat DocType |
| 44 | │ |
| 45 | └─ Add comment or tag? |
| 46 | ├─ Comment → doc.add_comment("Comment", text="...") |
| 47 | └─ Tag → doc.add_tag("tag_name") |
| 48 | ``` |
| 49 | |
| 50 | --- |
| 51 | |
| 52 | ## Notification DocType |
| 53 | |
| 54 | The Notification DocType enables no-code alerts across four channels. |
| 55 | |
| 56 | ### Event Triggers |
| 57 | |
| 58 | | Event | Fires When | |
| 59 | |-------|------------| |
| 60 | | New | Document is created | |
| 61 | | Save | Document is saved | |
| 62 | | Submit | Document is submitted | |
| 63 | | Cancel | Document is cancelled | |
| 64 | | Value Change | Specific field value changes | |
| 65 | | Days Before | N days before a date field value | |
| 66 | | Days After | N days after a date field value | |
| 67 | | Method | Custom Python method is called | |
| 68 | |
| 69 | ### Condition Syntax |
| 70 | |
| 71 | ALWAYS use Python expressions in the Condition field: |
| 72 | |
| 73 | ```python |
| 74 | # Status-based |
| 75 | doc.status == "Open" |
| 76 | |
| 77 | # Date-based |
| 78 | doc.due_date == nowdate() |
| 79 | |
| 80 | # Threshold-based |
| 81 | doc.grand_total > 40000 |
| 82 | |
| 83 | # Combined |
| 84 | doc.status == "Overdue" and doc.grand_total > 10000 |
| 85 | ``` |
| 86 | |
| 87 | Available context: `doc`, `nowdate()`, `frappe.utils.*`. |
| 88 | |
| 89 | ### Recipient Configuration |
| 90 | |
| 91 | | Source | Description | |
| 92 | |--------|-------------| |
| 93 | | Document Field | Email/phone field on the document | |
| 94 | | Role | All users with specified role | |
| 95 | | Custom | Hard-coded email address | |
| 96 | | All Assignees | All users assigned to the document | |
| 97 | | Condition | Jinja expression to filter recipients | |
| 98 | |
| 99 | ### Jinja Message Template |
| 100 | |
| 101 | ```html |
| 102 | <h3>Order Overdue</h3> |
| 103 | <p>Transaction {{ doc.name }} has exceeded its due date.</p> |
| 104 | |
| 105 | {% if comments %} |
| 106 | Last comment: {{ comments[-1].comment }} by {{ comments[-1].by }} |
| 107 | {% endif %} |
| 108 | |
| 109 | <ul> |
| 110 | <li>Customer: {{ doc.customer }}</li> |
| 111 | <li>Amount: {{ doc.grand_total }}</li> |
| 112 | </ul> |
| 113 | ``` |
| 114 | |
| 115 | Template variables: `{{ doc }}`, `{{ doc.fieldname }}`, `{{ comments }}`, `{{ nowdate() }}`. |
| 116 | |
| 117 | ### Attach Print |
| 118 | |
| 119 | Set **Attach Print** to include a PDF of the document. Select a **Print Format** for custom layout. |
| 120 | |
| 121 | --- |
| 122 | |
| 123 | ## frappe.sendmail(): Programmatic Email |
| 124 | |
| 125 | ```python |
| 126 | frappe.sendmail( |
| 127 | recipients=["user@example.com"], # list of email addresses |
| 128 | subject="Invoice Due", # email subject |
| 129 | message="<p>Your invoice is due.</p>", # HTML body |
| 130 | template="invoice_reminder", # Jinja template name (optional) |
| 131 | args={"customer": "ACME"}, # template context variables |
| 132 | attachments=[{"fname": "inv.pdf", "fcontent": pdf_bytes}], |
| 133 | reference_doctype="Sales Invoice", # links email to document |
| 134 | reference_name="SINV-00001", |
| 135 | delayed=True, # queue via Email Queue (default) |
| 136 | now=False, # True = send immediately, skip queue |
| 137 | sender="noreply@example.com", # override sender |
| 138 | cc=["manager@example.com"], |
| 139 | bcc=["audit@example.com"], |
| 140 | reply_to="support@example.com" |