नियम बनाएँ
एक ओर शर्तें, दूसरी ओर कार्रवाइयाँ। जब तक आप न कहें, सक्षम।
असली कॉल आपकी अपनी कुंजी से आपके वर्कस्पेस पर चलाता है।
POST /rules
एक ओर शर्तें, दूसरी ओर कार्रवाइयाँ। जब तक आप न कहें, सक्षम।
उदाहरण
rules:write चाहिए। 201 लौटाता है। position स्वीकार नहीं किया जाता। नया नियम सूची के अंत में जुड़ता है, और उसे हिलाना POST /rules/reorder है।
curl -X POST "$OE/rules" -H "$AUTH" -H "Content-Type: application/json" \ -d '{ "name": "Receipts to their own label", "match": "all", "conditions": [ { "field": "from_domain", "op": "matches", "value": "*.stripe.com" }, { "field": "subject", "op": "contains", "value": "receipt" } ], "actions": [ { "type": "label", "value": "USER_RECEIPTS" }, { "type": "archive" } ], "stopProcessing": true }'{ "object": "rule", "id": "rul_7f3a1c94e05d3862c1f0a44b", "name": "Receipts to their own label", "description": null, "enabled": true, "position": 3, "match": "all", "conditions": [ { "field": "from_domain", "op": "matches", "value": "*.stripe.com", "negate": false }, { "field": "subject", "op": "contains", "value": "receipt", "negate": false } ], "actions": [ { "type": "label", "value": "USER_RECEIPTS" }, { "type": "archive" } ], "stopProcessing": true, "lastMatchedAt": null, "matchCount": 0, "createdAt": "2026-08-30T10:41:02.000Z", "updatedAt": "2026-08-30T10:41:02.000Z"}यहाँ बनाया गया नियम चालू होता है, और अगले संदेश से असर करना शुरू कर देता है। जानबूझकर की गई कॉल के लिए यही सही डिफ़ॉल्ट है, और यह MCP के createRule टूल के उलट है, जो वही नियम अक्षम लिखता है — क्योंकि मेल आर्काइव करने का फ़ैसला लेने वाला मॉडल किसी व्यक्ति के नियम पढ़ने से पहले आर्काइव करना शुरू न कर दे।
एक ही कनेक्शन पर दोहरा name rule_name_taken, एक 409 है। नाम ही वह तरीका है जिससे नियम run लॉग में और सेटिंग्स स्क्रीन पर पहचाना जाता है, इसलिए "Newsletters" नाम के दो नियम ऐसी रिपोर्ट हैं जिसे कोई पढ़ नहीं सकता।
101वाँ नियम rule_limit_reached, एक 422 है। यह सीमा लेखा-जोखा की हद नहीं, लूप में फँसी स्क्रिप्ट से बचाव है, और वह लॉक नहीं है। 99 पर दौड़ती दो creates दोनों सफल हो सकती हैं।
शर्त क्या पूछ सकती है
शर्त { field, op, value } होती है, साथ में वैकल्पिक header जो बताता है कौन-सा header पढ़ना है, और वैकल्पिक negate। value तार पर हमेशा string होता है। संख्यात्मक फ़ील्ड Number(value) के बाद संख्या की तरह तुलना किए जाते हैं, और दोनों बूलियन फ़ील्ड शाब्दिक स्ट्रिंग "true" और "false" लेते हैं, क्योंकि एक टाइप वाला एक फ़ील्ड ऐसा स्कीमा है जिसे OpenAPI जनरेटर वर्णित कर सकता है और तीन का union नहीं।
| फ़ील्ड | क्या पढ़ता है | ऑपरेटर |
|---|---|---|
| `from` | From: header, उसी तरह सामान्यीकृत जैसे blocklist उसे सामान्यीकृत करती है। | text |
| `from_domain` | From: का डोमेन और उसके पैरेंट, दो लेबल तक नीचे: mail.corp.example.com से आया संदेश corp.example.com और example.com से भी मेल खाता है, और com के लिए कुछ भी मेल नहीं खाता। | text |
| `envelope_from` | SMTP MAIL FROM। हर मेलिंग सूची पर यह from से अलग होता है, और यही इकलौती पहचान है जिसके विरुद्ध reject लिखा जा सकता है। | text |
| `to`, `cc`, `bcc` | उस header का कोई भी एक पता। | text |
| `recipient` | to, cc या bcc का कोई भी पता: तीनों के लिए संक्षेप। | text |
| `reply_to` | Reply-To header। | text |
| `delivered_to` | वह विहित पता जिस पर यह प्रति डिलीवर हुई, plus-tag हटाकर और लोअर-केस में — catch-all उपनाम इसी तरह मिलाया जाता है। | text |
| `subject` | विषय पंक्ति, जैसी आई थी। | text |
| `body` | टेक्स्ट भाग, या HTML को टेक्स्ट में घटाकर। सीमित, इसलिए 20 MB की बॉडी पूरी स्कैन नहीं होती। | text |
| `header` | कोई भी header, जिसका नाम शर्त के अपने header फ़ील्ड में दिया जाता है। वहाँ आवश्यक है और तुलना से पहले लोअर-केस किया जाता है। | text |
| `list_id` | List-Id header: वह पहचान जिससे मेलिंग सूची खुद को बताती है। | text |
| `attachment_name` | किसी भी अटैचमेंट का फ़ाइल नाम। | text |
| `attachment_type` | किसी भी अटैचमेंट का MIME टाइप, जैसे application/pdf। | text |
| `has_attachment` | कोई अटैचमेंट है भी या नहीं। | equals "true" / "false" |
| `spam` | आपके नियम चलने से पहले डिलीवरी पथ जिस स्पैम निर्णय पर पहुँचा। | equals "true" / "false" |
| `attachment_size` | किसी अटैचमेंट का आकार, bytes में। तुलना तब मेल खाती है जब कोई एक अटैचमेंट उसे पूरा करता है। | gt, lt, equals |
| `message_size` | तार पर पूरा संदेश, bytes में। | gt, lt, equals |
| `hour` | आगमन का घंटा, 0–23, UTC। | gt, lt, equals |
| `weekday` | आगमन का दिन, 0–6, रविवार 0 है, UTC। | gt, lt, equals |
| ऑपरेटर | यह क्या करता है |
|---|---|
| `matches` | एक glob, और केवल glob: किसी भी लंबाई के अक्षरों के लिए *, एक अक्षर के लिए ?। कोई regular expression नहीं। API क्लाइंट से आया पैटर्न डिलीवरी पथ पर चलता है, और वहाँ विनाशकारी रूप से backtrack करता पैटर्न ऐसा मेलबॉक्स है जो मेल पाना बंद कर देता है। |
| `contains` | सबस्ट्रिंग, केस-असंवेदनशील। |
| `equals` | पूरा मान, केस-असंवेदनशील। संख्यात्मक फ़ील्ड पर, संख्यात्मक समानता। |
| `starts_with` | उपसर्ग, केस-असंवेदनशील। |
| `ends_with` | प्रत्यय, केस-असंवेदनशील। |
| `gt`, `lt` | संख्यात्मक, केवल चार संख्यात्मक फ़ील्ड पर। gt वाला टेक्स्ट फ़ील्ड कभी मेल नहीं खाता। |
matches पैटर्न में अपने कम से कम दो अल्फ़ान्यूमेरिक अक्षर होने चाहिए, वही कसौटी जो blocklist लगाती है। अकेला * लिखे जाते समय ही मना कर दिया जाता है, बजाय इसके कि उसे स्वीकार करके चुपचाप हर आने वाले संदेश से मिलाया जाए — वह नियम नहीं, एक आउटेज है।
जिस शर्त का जवाब इंजन दे ही नहीं सकता (किसी नए क्लाइंट से आया अनजान फ़ील्ड, ऐसा पैटर्न जो कंपाइल नहीं होगा, contains "") उसे false नहीं, बल्कि ऐसा सवाल माना जाता है जो कभी पूछा ही नहीं गया, और negate उसे उलटता नहीं। यह भेद भार उठाता है: टूटी हुई निषेधित शर्त को false मानने पर उसका नियम मेलबॉक्स के हर संदेश पर चल जाता। equals "" को माना जाता है, क्योंकि "विषय पंक्ति खाली है" एक असली सवाल है।
नियम क्या कर सकता है
| कार्रवाई | `value` | क्या होता है |
|---|---|---|
| `label` | एक लेबल id | लेबल जोड़ता है। USER_… ids GET /labels से आती हैं। |
| `remove_label` | एक लेबल id | उसे हटाता है। दोनों में एक ही लेबल का नाम लेने पर यह संदेश फ़ाइल होने से पहले सुलझा लिया जाता है, न कि इस पर छोड़ा जाता है कि आख़िर में कौन चला। |
| `archive` | कोई नहीं | उसे इनबॉक्स से बाहर फ़ाइल कर देता है। |
| `mark_read` | कोई नहीं | UNREAD हटाता है। |
| `star` | कोई नहीं | STARRED जोड़ता है। |
| `spam` | कोई नहीं | उसे Spam के नीचे फ़ाइल करता है। |
| `trash` | कोई नहीं | उसे Trash के नीचे फ़ाइल करता है, और वे लेबल हटा देता है जो trash किया संदेश नहीं रखता। |
| `forward` | एक पता | एक प्रति आगे भेजता है। इस्तेमाल करने से पहले नीचे की टिप्पणी पढ़ें। |
| `reply` | एक template id या slug | प्रकाशित टेम्पलेट से स्वतः उत्तर देता है, नीचे दिए लूप-गार्ड के अधीन। |
| `block_sender` | कोई नहीं | भेजने वाले को blocklist में डाल देता है, ताकि अगला संदेश दरवाज़े पर ही मना हो जाए। |
| `reject` | कोई नहीं | SMTP के समय ही संदेश को 550 5.7.1 Message refused by the recipient के साथ मना करता है। केवल envelope। नीचे देखें। |
reject लिखे जाते समय ही मना कर दिया जाता है, जब तक कि उसी नियम में कम से कम एक envelope_from शर्त न हो: reject_needs_envelope, एक 422। 550 उसे जवाब देता है जिसने हमें संदेश थमाया, और मेलिंग सूची पर वह स्वयं सूची होती है, जो उस अस्वीकरण को उछलता हुआ सब्सक्राइबर समझकर पाठक को उस चीज़ से हटा देती है जिससे वे बस एक व्यक्ति का पोस्ट करना रुकवाना चाहते थे। शर्त लिखी होने पर भी, वह मिलान जो केवल header पहचानों से आया हो, घटकर Spam में फ़ाइल करने पर आ जाता है, क्योंकि envelope ही इकलौती पहचान है जिस पर अस्वीकरण ईमानदारी से निशाना साध सकता है।
नियम से चला forward भेजने के पथ से जाता है, जो संदेश को फिर से बनाता है: मूल DKIM हस्ताक्षर नहीं बचता, और न ही असामान्य भाग, असामान्य headers या आउटबाउंड आकार-सीमा से आगे की कोई चीज़ — जिसे अटैचमेंट वाला 25 MB का संदेश पार कर जाएगा। यह जो आया उसकी प्रति है, वह संदेश नहीं जो आया था। पता तभी जाँचा जाता है जब नियम लिखा जाता है, इसलिए अप्रमाणित गंतव्य कॉल पर 422 है, न कि ऐसा नियम जो चुपचाप हर दसवाँ संदेश गिरा दे।
reply किसी मशीन को जवाब नहीं देगा। यह तब दबा दिया जाता है जब संदेश में Auto-Submitted (no के अलावा), Precedence: bulk|list|junk, List-Id, List-Unsubscribe, X-Autoreply या X-Autorespond हो, जब envelope भेजने वाला खाली हो (हर bounce का यही रूप होता है), और जब headers पढ़े ही न जा सके हों। इसके ऊपर, किसी एक भेजने वाले को दिए गए मेलबॉक्स से 24 घंटे में अधिकतम एक स्वतः-उत्तर मिलता है। reply नियम वाले दो मेलबॉक्स, बिना किसी गार्ड के, तब तक एक-दूसरे को मेल करते रहते हैं जब तक किसी की नज़र न पड़े।