]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Enhancement: option to stop processing further mail rules feature-mailrule-stop-processing-4314
authorshamoon <4887959+shamoon@users.noreply.github.com>
Mon, 24 Feb 2025 16:53:20 +0000 (08:53 -0800)
committershamoon <4887959+shamoon@users.noreply.github.com>
Mon, 24 Feb 2025 17:00:47 +0000 (09:00 -0800)
12 files changed:
src-ui/messages.xlf
src-ui/src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html
src-ui/src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.ts
src-ui/src/app/data/mail-rule.ts
src-ui/src/app/services/rest/mail-rule.service.spec.ts
src/documents/tests/test_migration_workflows.py
src/locale/en_US/LC_MESSAGES/django.po
src/paperless_mail/mail.py
src/paperless_mail/migrations/0030_mailrule_stop_processing.py [new file with mode: 0644]
src/paperless_mail/models.py
src/paperless_mail/serialisers.py
src/paperless_mail/tests/test_mail.py

index ae9abe84710618c8709ecdfb74c0d67930983e64..149ebb7a8c68274f683e77821bd46a00112b29d1 100644 (file)
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">76</context>
+          <context context-type="linenumber">81</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">75</context>
+          <context context-type="linenumber">80</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">83</context>
+          <context context-type="linenumber">87</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">79</context>
+          <context context-type="linenumber">83</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
           <context context-type="linenumber">113</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="220550782947016929" datatype="html">
-        <source>Order</source>
-        <context-group purpose="location">
-          <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">19</context>
-        </context-group>
-      </trans-unit>
       <trans-unit id="4816216590591222133" datatype="html">
         <source>Enabled</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">22</context>
+          <context context-type="linenumber">19</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
           <context context-type="linenumber">41</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="220550782947016929" datatype="html">
+        <source>Order</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
+          <context context-type="linenumber">24</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1504364192557145528" datatype="html">
+        <source>Stop further processing</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
+          <context context-type="linenumber">27</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="6164556674897067551" datatype="html">
+        <source>Stop processing further rules if this rule queues any document(s).</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
+          <context context-type="linenumber">27</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="4348351765075925931" datatype="html">
         <source>Paperless will only process mails that match <x id="START_EMPHASISED_TEXT" ctype="x-em" equiv-text="&lt;em&gt;"/>all<x id="CLOSE_EMPHASISED_TEXT" ctype="x-em" equiv-text="&lt;/em&gt;"/> of the criteria specified below.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">27</context>
+          <context context-type="linenumber">32</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7046259383943324039" datatype="html">
         <source>Folder</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">29</context>
+          <context context-type="linenumber">34</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1391527525114848695" datatype="html">
         <source>Subfolders must be separated by a delimiter, often a dot (&apos;.&apos;) or slash (&apos;/&apos;), but it varies by mail server.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">29</context>
+          <context context-type="linenumber">34</context>
         </context-group>
       </trans-unit>
       <trans-unit id="101686279614365671" datatype="html">
         <source>Maximum age (days)</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">30</context>
+          <context context-type="linenumber">35</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6925928412364847639" datatype="html">
         <source>Filter from</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">33</context>
+          <context context-type="linenumber">38</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8977094263269822022" datatype="html">
         <source>Filter to</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">34</context>
+          <context context-type="linenumber">39</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8497813481090627874" datatype="html">
         <source>Filter subject</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">35</context>
+          <context context-type="linenumber">40</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7314357616097563149" datatype="html">
         <source>Filter body</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">36</context>
+          <context context-type="linenumber">41</context>
         </context-group>
       </trans-unit>
       <trans-unit id="559099472394646919" datatype="html">
         <source>Consumption scope</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">42</context>
+          <context context-type="linenumber">47</context>
         </context-group>
       </trans-unit>
       <trans-unit id="56643687972548912" datatype="html">
         <source>See docs for .eml processing requirements</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">42</context>
+          <context context-type="linenumber">47</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7093509971705471817" datatype="html">
         <source>Attachment type</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">43</context>
+          <context context-type="linenumber">48</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3842519365862452117" datatype="html">
         <source>PDF layout</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">44</context>
+          <context context-type="linenumber">49</context>
         </context-group>
       </trans-unit>
       <trans-unit id="2873939123535615966" datatype="html">
         <source>Include only files matching</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">47</context>
+          <context context-type="linenumber">52</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7233407036155150477" datatype="html">
         <source>Optional. Wildcards e.g. *.pdf or *invoice* allowed. Can be comma-separated list. Case insensitive.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">47</context>
+          <context context-type="linenumber">52</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">48</context>
+          <context context-type="linenumber">53</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1546332577833742677" datatype="html">
         <source>Exclude files matching</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">48</context>
+          <context context-type="linenumber">53</context>
         </context-group>
       </trans-unit>
       <trans-unit id="9216117865911519658" datatype="html">
         <source>Action</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">54</context>
+          <context context-type="linenumber">59</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7841986067387421166" datatype="html">
         <source>Only performed if the mail is processed.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">54</context>
+          <context context-type="linenumber">59</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1261794314435932203" datatype="html">
         <source>Action parameter</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">56</context>
+          <context context-type="linenumber">61</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6093797930511670257" datatype="html">
         <source>Assign title from</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">58</context>
+          <context context-type="linenumber">63</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5232720756589450549" datatype="html">
         <source>Assign owner from rule</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">59</context>
+          <context context-type="linenumber">64</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6695990587380209737" datatype="html">
         <source>Assign document type</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">63</context>
+          <context context-type="linenumber">68</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
         <source>Assign correspondent from</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">64</context>
+          <context context-type="linenumber">69</context>
         </context-group>
       </trans-unit>
       <trans-unit id="4875491778188965469" datatype="html">
         <source>Assign correspondent</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">66</context>
+          <context context-type="linenumber">71</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
         <source>Error</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
-          <context context-type="linenumber">73</context>
+          <context context-type="linenumber">78</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">125</context>
+          <context context-type="linenumber">129</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
           <context context-type="linenumber">72</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="235571817610183244" datatype="html">
+        <source>Web UI</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
+          <context context-type="linenumber">76</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="3553216189604488439" datatype="html">
         <source>Modified</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">87</context>
+          <context context-type="linenumber">91</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/data/document.ts</context>
         <source>Custom Field</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">91</context>
+          <context context-type="linenumber">95</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8696908693776094667" datatype="html">
         <source>Consumption Started</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">98</context>
+          <context context-type="linenumber">102</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7858311467093621703" datatype="html">
         <source>Document Added</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">102</context>
+          <context context-type="linenumber">106</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7955486237346046731" datatype="html">
         <source>Document Updated</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">106</context>
+          <context context-type="linenumber">110</context>
         </context-group>
       </trans-unit>
       <trans-unit id="9172233176401579786" datatype="html">
         <source>Scheduled</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">110</context>
+          <context context-type="linenumber">114</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5502398334173581061" datatype="html">
         <source>Assignment</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">117</context>
+          <context context-type="linenumber">121</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6234812824772766804" datatype="html">
         <source>Removal</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">121</context>
+          <context context-type="linenumber">125</context>
         </context-group>
       </trans-unit>
       <trans-unit id="4206419737792796794" datatype="html">
         <source>Webhook</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">129</context>
+          <context context-type="linenumber">133</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3138206142174978019" datatype="html">
         <source>Create new workflow</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">225</context>
+          <context context-type="linenumber">229</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5996779210524133604" datatype="html">
         <source>Edit workflow</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">229</context>
+          <context context-type="linenumber">233</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7376342558017986274" datatype="html">
         <source>Connecting...</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">42</context>
+          <context context-type="linenumber">43</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1245343823699368872" datatype="html">
         <source>Uploading...</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">54</context>
+          <context context-type="linenumber">55</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7446520539098045935" datatype="html">
         <source>Upload complete, waiting...</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">57</context>
+          <context context-type="linenumber">58</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1405142710727603568" datatype="html">
         <source>HTTP error: <x id="PH" equiv-text="error.status"/> <x id="PH_1" equiv-text="error.statusText"/></source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">70</context>
+          <context context-type="linenumber">71</context>
         </context-group>
       </trans-unit>
       <trans-unit id="2119857572761283468" datatype="html">
index afe6c2ab93f2e4b9d1d9abbd9ff7a9305d92f818..0b06616fb54539fdc9695b5aaf7545cdec9e1459 100644 (file)
@@ -9,19 +9,24 @@
   </div>
   <div class="modal-body">
     <div class="row">
-      <div class="col-md-4">
+      <div class="col-md-6">
         <pngx-input-text [horizontal]="true" i18n-title title="Name" formControlName="name" [error]="error?.name" autocomplete="off"></pngx-input-text>
       </div>
-      <div class="col-md-3">
+      <div class="col-md-4">
         <pngx-input-select [horizontal]="true" i18n-title title="Account" [items]="accounts" formControlName="account"></pngx-input-select>
       </div>
-      <div class="col-md-3">
-        <pngx-input-number [horizontal]="true" i18n-title title="Order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
-      </div>
       <div class="col-md-2 pt-2">
         <pngx-input-switch [horizontal]="true" i18n-title title="Enabled" formControlName="enabled"></pngx-input-switch>
       </div>
     </div>
+    <div class="row">
+      <div class="col-md-6">
+        <pngx-input-number [horizontal]="true" i18n-title title="Order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
+      </div>
+      <div class="col-md-6">
+        <pngx-input-switch [horizontal]="true" i18n-title title="Stop further processing" formControlName="stop_processing" i18n-hint hint="Stop processing further rules if this rule queues any document(s)."></pngx-input-switch>
+      </div>
+    </div>
     <hr class="mt-0"/>
     <div class="row">
       <p class="small" i18n>Paperless will only process mails that match <em>all</em> of the criteria specified below.</p>
index 3d4924c0b67ed778fa6d57fe772a5f6c4b22174b..c6766b6c02f315f2b8da6d90f67d12f828cb5f18 100644 (file)
@@ -221,6 +221,7 @@ export class MailRuleEditDialogComponent extends EditDialogComponent<MailRule> {
       ),
       assign_correspondent: new FormControl(null),
       assign_owner_from_rule: new FormControl(true),
+      stop_processing: new FormControl(false),
     })
   }
 
index 4c47b65006d5f679400658d327375f0636483be8..6609810ddf789559206cfa02ae5fb449c1300794 100644 (file)
@@ -84,4 +84,6 @@ export interface MailRule extends ObjectWithPermissions {
   assign_correspondent?: number // PaperlessCorrespondent.id
 
   assign_owner_from_rule: boolean
+
+  stop_processing: boolean
 }
index f2016d7978cd0fc7cf627d0741f98ca0167c6ecf..f5bef1ec00e9805a408b5e91165126933fe54a6a 100644 (file)
@@ -33,6 +33,7 @@ const mail_rules = [
     action: MailAction.MarkRead,
     assign_title_from: MailMetadataTitleOption.FromSubject,
     assign_owner_from_rule: true,
+    stop_processing: false,
   },
   {
     name: 'Mail Rule 2',
@@ -52,6 +53,7 @@ const mail_rules = [
     action: MailAction.Delete,
     assign_title_from: MailMetadataTitleOption.FromSubject,
     assign_owner_from_rule: true,
+    stop_processing: false,
   },
   {
     name: 'Mail Rule 3',
@@ -71,6 +73,7 @@ const mail_rules = [
     action: MailAction.Flag,
     assign_title_from: MailMetadataTitleOption.FromSubject,
     assign_owner_from_rule: false,
+    stop_processing: false,
   },
 ]
 
index 9895188188a4e42c4169fe7640824ec546b76e68..1e9aa3bf5bca67fce984e7c83f72834a2068e1a9 100644 (file)
@@ -8,7 +8,7 @@ class TestMigrateWorkflow(TestMigrations):
     dependencies = (
         (
             "paperless_mail",
-            "0029_mailrule_pdf_layout",
+            "0030_mailrule_stop_processing",
         ),
     )
 
index 32d60ac196abd3bd10224e7ac657111b1ddade30..045d79726b8f933fd122b475cd32eacec8e93d19 100644 (file)
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: paperless-ngx\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-02-11 18:43-0800\n"
+"POT-Creation-Date: 2025-02-24 09:00-0800\n"
 "PO-Revision-Date: 2022-02-17 04:17\n"
 "Last-Translator: \n"
 "Language-Team: English\n"
@@ -89,20 +89,20 @@ msgstr ""
 msgid "Automatic"
 msgstr ""
 
-#: documents/models.py:67 documents/models.py:433 documents/models.py:1498
+#: documents/models.py:67 documents/models.py:433 documents/models.py:1502
 #: paperless_mail/models.py:23 paperless_mail/models.py:143
 msgid "name"
 msgstr ""
 
-#: documents/models.py:69 documents/models.py:1085
+#: documents/models.py:69 documents/models.py:1086
 msgid "match"
 msgstr ""
 
-#: documents/models.py:72 documents/models.py:1088
+#: documents/models.py:72 documents/models.py:1089
 msgid "matching algorithm"
 msgstr ""
 
-#: documents/models.py:77 documents/models.py:1093
+#: documents/models.py:77 documents/models.py:1094
 msgid "is insensitive"
 msgstr ""
 
@@ -256,7 +256,7 @@ msgid "The position of this document in your physical document archive."
 msgstr ""
 
 #: documents/models.py:295 documents/models.py:737 documents/models.py:791
-#: documents/models.py:1541
+#: documents/models.py:1545
 msgid "document"
 msgstr ""
 
@@ -276,7 +276,7 @@ msgstr ""
 msgid "warning"
 msgstr ""
 
-#: documents/models.py:387 paperless_mail/models.py:363
+#: documents/models.py:387 paperless_mail/models.py:371
 msgid "error"
 msgstr ""
 
@@ -320,11 +320,11 @@ msgstr ""
 msgid "Title"
 msgstr ""
 
-#: documents/models.py:420 documents/models.py:1037
+#: documents/models.py:420 documents/models.py:1038
 msgid "Created"
 msgstr ""
 
-#: documents/models.py:421 documents/models.py:1036
+#: documents/models.py:421 documents/models.py:1037
 msgid "Added"
 msgstr ""
 
@@ -812,377 +812,381 @@ msgstr ""
 msgid "Mail Fetch"
 msgstr ""
 
-#: documents/models.py:1038
-msgid "Modified"
+#: documents/models.py:1034
+msgid "Web UI"
 msgstr ""
 
 #: documents/models.py:1039
+msgid "Modified"
+msgstr ""
+
+#: documents/models.py:1040
 msgid "Custom Field"
 msgstr ""
 
-#: documents/models.py:1042
+#: documents/models.py:1043
 msgid "Workflow Trigger Type"
 msgstr ""
 
-#: documents/models.py:1054
+#: documents/models.py:1055
 msgid "filter path"
 msgstr ""
 
-#: documents/models.py:1059
+#: documents/models.py:1060
 msgid ""
 "Only consume documents with a path that matches this if specified. Wildcards "
 "specified as * are allowed. Case insensitive."
 msgstr ""
 
-#: documents/models.py:1066
+#: documents/models.py:1067
 msgid "filter filename"
 msgstr ""
 
-#: documents/models.py:1071 paperless_mail/models.py:200
+#: documents/models.py:1072 paperless_mail/models.py:200
 msgid ""
 "Only consume documents which entirely match this filename if specified. "
 "Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
 msgstr ""
 
-#: documents/models.py:1082
+#: documents/models.py:1083
 msgid "filter documents from this mail rule"
 msgstr ""
 
-#: documents/models.py:1098
+#: documents/models.py:1099
 msgid "has these tag(s)"
 msgstr ""
 
-#: documents/models.py:1106
+#: documents/models.py:1107
 msgid "has this document type"
 msgstr ""
 
-#: documents/models.py:1114
+#: documents/models.py:1115
 msgid "has this correspondent"
 msgstr ""
 
-#: documents/models.py:1118
+#: documents/models.py:1119
 msgid "schedule offset days"
 msgstr ""
 
-#: documents/models.py:1121
+#: documents/models.py:1122
 msgid "The number of days to offset the schedule trigger by."
 msgstr ""
 
-#: documents/models.py:1126
+#: documents/models.py:1127
 msgid "schedule is recurring"
 msgstr ""
 
-#: documents/models.py:1129
+#: documents/models.py:1130
 msgid "If the schedule should be recurring."
 msgstr ""
 
-#: documents/models.py:1134
+#: documents/models.py:1135
 msgid "schedule recurring delay in days"
 msgstr ""
 
-#: documents/models.py:1138
+#: documents/models.py:1139
 msgid "The number of days between recurring schedule triggers."
 msgstr ""
 
-#: documents/models.py:1143
+#: documents/models.py:1144
 msgid "schedule date field"
 msgstr ""
 
-#: documents/models.py:1148
+#: documents/models.py:1149
 msgid "The field to check for a schedule trigger."
 msgstr ""
 
-#: documents/models.py:1157
+#: documents/models.py:1158
 msgid "schedule date custom field"
 msgstr ""
 
-#: documents/models.py:1161
+#: documents/models.py:1162
 msgid "workflow trigger"
 msgstr ""
 
-#: documents/models.py:1162
+#: documents/models.py:1163
 msgid "workflow triggers"
 msgstr ""
 
-#: documents/models.py:1170
+#: documents/models.py:1171
 msgid "email subject"
 msgstr ""
 
-#: documents/models.py:1174
+#: documents/models.py:1175
 msgid ""
 "The subject of the email, can include some placeholders, see documentation."
 msgstr ""
 
-#: documents/models.py:1180
+#: documents/models.py:1181
 msgid "email body"
 msgstr ""
 
-#: documents/models.py:1183
+#: documents/models.py:1184
 msgid ""
 "The body (message) of the email, can include some placeholders, see "
 "documentation."
 msgstr ""
 
-#: documents/models.py:1189
+#: documents/models.py:1190
 msgid "emails to"
 msgstr ""
 
-#: documents/models.py:1192
+#: documents/models.py:1193
 msgid "The destination email addresses, comma separated."
 msgstr ""
 
-#: documents/models.py:1198
+#: documents/models.py:1199
 msgid "include document in email"
 msgstr ""
 
-#: documents/models.py:1207
+#: documents/models.py:1210
 msgid "webhook url"
 msgstr ""
 
-#: documents/models.py:1209
+#: documents/models.py:1213
 msgid "The destination URL for the notification."
 msgstr ""
 
-#: documents/models.py:1214
+#: documents/models.py:1218
 msgid "use parameters"
 msgstr ""
 
-#: documents/models.py:1219
+#: documents/models.py:1223
 msgid "send as JSON"
 msgstr ""
 
-#: documents/models.py:1223
+#: documents/models.py:1227
 msgid "webhook parameters"
 msgstr ""
 
-#: documents/models.py:1226
+#: documents/models.py:1230
 msgid "The parameters to send with the webhook URL if body not used."
 msgstr ""
 
-#: documents/models.py:1230
+#: documents/models.py:1234
 msgid "webhook body"
 msgstr ""
 
-#: documents/models.py:1233
+#: documents/models.py:1237
 msgid "The body to send with the webhook URL if parameters not used."
 msgstr ""
 
-#: documents/models.py:1237
+#: documents/models.py:1241
 msgid "webhook headers"
 msgstr ""
 
-#: documents/models.py:1240
+#: documents/models.py:1244
 msgid "The headers to send with the webhook URL."
 msgstr ""
 
-#: documents/models.py:1245
+#: documents/models.py:1249
 msgid "include document in webhook"
 msgstr ""
 
-#: documents/models.py:1256
+#: documents/models.py:1260
 msgid "Assignment"
 msgstr ""
 
-#: documents/models.py:1260
+#: documents/models.py:1264
 msgid "Removal"
 msgstr ""
 
-#: documents/models.py:1264 documents/templates/account/password_reset.html:15
+#: documents/models.py:1268 documents/templates/account/password_reset.html:15
 msgid "Email"
 msgstr ""
 
-#: documents/models.py:1268
+#: documents/models.py:1272
 msgid "Webhook"
 msgstr ""
 
-#: documents/models.py:1272
+#: documents/models.py:1276
 msgid "Workflow Action Type"
 msgstr ""
 
-#: documents/models.py:1278
+#: documents/models.py:1282
 msgid "assign title"
 msgstr ""
 
-#: documents/models.py:1283
+#: documents/models.py:1287
 msgid ""
 "Assign a document title, can include some placeholders, see documentation."
 msgstr ""
 
-#: documents/models.py:1292 paperless_mail/models.py:274
+#: documents/models.py:1296 paperless_mail/models.py:274
 msgid "assign this tag"
 msgstr ""
 
-#: documents/models.py:1301 paperless_mail/models.py:282
+#: documents/models.py:1305 paperless_mail/models.py:282
 msgid "assign this document type"
 msgstr ""
 
-#: documents/models.py:1310 paperless_mail/models.py:296
+#: documents/models.py:1314 paperless_mail/models.py:296
 msgid "assign this correspondent"
 msgstr ""
 
-#: documents/models.py:1319
+#: documents/models.py:1323
 msgid "assign this storage path"
 msgstr ""
 
-#: documents/models.py:1328
+#: documents/models.py:1332
 msgid "assign this owner"
 msgstr ""
 
-#: documents/models.py:1335
+#: documents/models.py:1339
 msgid "grant view permissions to these users"
 msgstr ""
 
-#: documents/models.py:1342
+#: documents/models.py:1346
 msgid "grant view permissions to these groups"
 msgstr ""
 
-#: documents/models.py:1349
+#: documents/models.py:1353
 msgid "grant change permissions to these users"
 msgstr ""
 
-#: documents/models.py:1356
+#: documents/models.py:1360
 msgid "grant change permissions to these groups"
 msgstr ""
 
-#: documents/models.py:1363
+#: documents/models.py:1367
 msgid "assign these custom fields"
 msgstr ""
 
-#: documents/models.py:1370
+#: documents/models.py:1374
 msgid "remove these tag(s)"
 msgstr ""
 
-#: documents/models.py:1375
+#: documents/models.py:1379
 msgid "remove all tags"
 msgstr ""
 
-#: documents/models.py:1382
+#: documents/models.py:1386
 msgid "remove these document type(s)"
 msgstr ""
 
-#: documents/models.py:1387
+#: documents/models.py:1391
 msgid "remove all document types"
 msgstr ""
 
-#: documents/models.py:1394
+#: documents/models.py:1398
 msgid "remove these correspondent(s)"
 msgstr ""
 
-#: documents/models.py:1399
+#: documents/models.py:1403
 msgid "remove all correspondents"
 msgstr ""
 
-#: documents/models.py:1406
+#: documents/models.py:1410
 msgid "remove these storage path(s)"
 msgstr ""
 
-#: documents/models.py:1411
+#: documents/models.py:1415
 msgid "remove all storage paths"
 msgstr ""
 
-#: documents/models.py:1418
+#: documents/models.py:1422
 msgid "remove these owner(s)"
 msgstr ""
 
-#: documents/models.py:1423
+#: documents/models.py:1427
 msgid "remove all owners"
 msgstr ""
 
-#: documents/models.py:1430
+#: documents/models.py:1434
 msgid "remove view permissions for these users"
 msgstr ""
 
-#: documents/models.py:1437
+#: documents/models.py:1441
 msgid "remove view permissions for these groups"
 msgstr ""
 
-#: documents/models.py:1444
+#: documents/models.py:1448
 msgid "remove change permissions for these users"
 msgstr ""
 
-#: documents/models.py:1451
+#: documents/models.py:1455
 msgid "remove change permissions for these groups"
 msgstr ""
 
-#: documents/models.py:1456
+#: documents/models.py:1460
 msgid "remove all permissions"
 msgstr ""
 
-#: documents/models.py:1463
+#: documents/models.py:1467
 msgid "remove these custom fields"
 msgstr ""
 
-#: documents/models.py:1468
+#: documents/models.py:1472
 msgid "remove all custom fields"
 msgstr ""
 
-#: documents/models.py:1477
+#: documents/models.py:1481
 msgid "email"
 msgstr ""
 
-#: documents/models.py:1486
+#: documents/models.py:1490
 msgid "webhook"
 msgstr ""
 
-#: documents/models.py:1490
+#: documents/models.py:1494
 msgid "workflow action"
 msgstr ""
 
-#: documents/models.py:1491
+#: documents/models.py:1495
 msgid "workflow actions"
 msgstr ""
 
-#: documents/models.py:1500 paperless_mail/models.py:145
+#: documents/models.py:1504 paperless_mail/models.py:145
 msgid "order"
 msgstr ""
 
-#: documents/models.py:1506
+#: documents/models.py:1510
 msgid "triggers"
 msgstr ""
 
-#: documents/models.py:1513
+#: documents/models.py:1517
 msgid "actions"
 msgstr ""
 
-#: documents/models.py:1516 paperless_mail/models.py:154
+#: documents/models.py:1520 paperless_mail/models.py:154
 msgid "enabled"
 msgstr ""
 
-#: documents/models.py:1527
+#: documents/models.py:1531
 msgid "workflow"
 msgstr ""
 
-#: documents/models.py:1531
+#: documents/models.py:1535
 msgid "workflow trigger type"
 msgstr ""
 
-#: documents/models.py:1545
+#: documents/models.py:1549
 msgid "date run"
 msgstr ""
 
-#: documents/models.py:1551
+#: documents/models.py:1555
 msgid "workflow run"
 msgstr ""
 
-#: documents/models.py:1552
+#: documents/models.py:1556
 msgid "workflow runs"
 msgstr ""
 
-#: documents/serialisers.py:127
+#: documents/serialisers.py:128
 #, python-format
 msgid "Invalid regular expression: %(error)s"
 msgstr ""
 
-#: documents/serialisers.py:553
+#: documents/serialisers.py:554
 msgid "Invalid color."
 msgstr ""
 
-#: documents/serialisers.py:1554
+#: documents/serialisers.py:1570
 #, python-format
 msgid "File type %(type)s not supported"
 msgstr ""
 
-#: documents/serialisers.py:1643
+#: documents/serialisers.py:1659
 msgid "Invalid variable detected."
 msgstr ""
 
@@ -1402,17 +1406,23 @@ msgstr ""
 msgid "As a final step, please complete the following form:"
 msgstr ""
 
-#: documents/validators.py:17
+#: documents/validators.py:24
 #, python-brace-format
 msgid "Unable to parse URI {value}, missing scheme"
 msgstr ""
 
-#: documents/validators.py:22
+#: documents/validators.py:29
 #, python-brace-format
 msgid "Unable to parse URI {value}, missing net location or path"
 msgstr ""
 
-#: documents/validators.py:27
+#: documents/validators.py:36
+msgid ""
+"URI scheme '{parts.scheme}' is not allowed. Allowed schemes: {', '."
+"join(allowed_schemes)}"
+msgstr ""
+
+#: documents/validators.py:45
 #, python-brace-format
 msgid "Unable to parse URI {value}"
 msgstr ""
@@ -1701,7 +1711,7 @@ msgstr ""
 msgid "Chinese Traditional"
 msgstr ""
 
-#: paperless/urls.py:364
+#: paperless/urls.py:369
 msgid "Paperless-ngx administration"
 msgstr ""
 
@@ -1933,7 +1943,7 @@ msgstr ""
 msgid "account"
 msgstr ""
 
-#: paperless_mail/models.py:157 paperless_mail/models.py:318
+#: paperless_mail/models.py:157 paperless_mail/models.py:326
 msgid "folder"
 msgstr ""
 
@@ -2025,22 +2035,32 @@ msgstr ""
 msgid "Assign the rule owner to documents"
 msgstr ""
 
-#: paperless_mail/models.py:326
-msgid "uid"
+#: paperless_mail/models.py:305
+msgid "Stop processing further rules"
+msgstr ""
+
+#: paperless_mail/models.py:308
+msgid ""
+"If True, no further rules will be processed after this one if any document "
+"is queued."
 msgstr ""
 
 #: paperless_mail/models.py:334
-msgid "subject"
+msgid "uid"
 msgstr ""
 
 #: paperless_mail/models.py:342
+msgid "subject"
+msgstr ""
+
+#: paperless_mail/models.py:350
 msgid "received"
 msgstr ""
 
-#: paperless_mail/models.py:349
+#: paperless_mail/models.py:357
 msgid "processed"
 msgstr ""
 
-#: paperless_mail/models.py:355
+#: paperless_mail/models.py:363
 msgid "status"
 msgstr ""
index cf35ea6cbbf031c3bd4cb4aa2f5b7d6a42416b08..642049e77df270499f5424efbc32c8a8190ca8d4 100644 (file)
@@ -571,6 +571,11 @@ class MailAccountHandler(LoggingMixin):
                             rule,
                             supports_gmail_labels=supports_gmail_labels,
                         )
+                        if total_processed_files > 0 and rule.stop_processing:
+                            self.log.debug(
+                                f"Rule {rule}: Stopping processing rules due to stop_processing flag",
+                            )
+                            break
                     except Exception as e:
                         self.log.exception(
                             f"Rule {rule}: Error while processing rule: {e}",
diff --git a/src/paperless_mail/migrations/0030_mailrule_stop_processing.py b/src/paperless_mail/migrations/0030_mailrule_stop_processing.py
new file mode 100644 (file)
index 0000000..323634c
--- /dev/null
@@ -0,0 +1,22 @@
+# Generated by Django 5.1.6 on 2025-02-24 16:07
+
+from django.db import migrations
+from django.db import models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("paperless_mail", "0029_mailrule_pdf_layout"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="mailrule",
+            name="stop_processing",
+            field=models.BooleanField(
+                default=False,
+                help_text="If True, no further rules will be processed after this one if any document is consumed.",
+                verbose_name="Stop processing further rules",
+            ),
+        ),
+    ]
index cf33a056b6508cf02841cd427651a37c604edb7c..1502f3f39fb443f2aaeda0a37534fa4a81b2d424 100644 (file)
@@ -301,6 +301,14 @@ class MailRule(document_models.ModelWithOwner):
         default=True,
     )
 
+    stop_processing = models.BooleanField(
+        _("Stop processing further rules"),
+        default=False,
+        help_text=_(
+            "If True, no further rules will be processed after this one if any document is queued.",
+        ),
+    )
+
     def __str__(self):
         return f"{self.account.name}.{self.name}"
 
index c7a20acbf93bd04977d63dbfa3435f410cf35691..e723b3222d4aa67a3ae0c7ba0e738cb1b5c6906f 100644 (file)
@@ -101,6 +101,7 @@ class MailRuleSerializer(OwnedObjectSerializer):
             "user_can_change",
             "permissions",
             "set_permissions",
+            "stop_processing",
         ]
 
     def update(self, instance, validated_data):
index a73f9cf34e532600004c55c04d26a852cfc68c1a..e9523382ab21e801755bd48fe0a0d0327aa4fbd2 100644 (file)
@@ -1671,6 +1671,39 @@ class TestTasks(TestCase):
         result = tasks.process_mail_accounts(account_ids=[account_b.id])
         self.assertIn("No new", result)
 
+    @mock.patch("paperless_mail.tasks.MailAccountHandler.handle_mail_account")
+    def test_rule_with_stop_processing(self, m):
+        """
+        GIVEN:
+            - Mail account with a rule with stop_processing=True
+        WHEN:
+            - Mail account is processed
+        THEN:
+            - Should only process the first rule
+        """
+        m.side_effect = lambda account: 6
+
+        account = MailAccount.objects.create(
+            name="A",
+            imap_server="A",
+            username="A",
+            password="A",
+        )
+        MailRule.objects.create(
+            name="A",
+            account=account,
+            stop_processing=True,
+        )
+        MailRule.objects.create(
+            name="B",
+            account=account,
+        )
+
+        result = tasks.process_mail_accounts()
+
+        self.assertEqual(m.call_count, 1)
+        self.assertIn("Added 6", result)
+
 
 class TestMailAccountTestView(APITestCase):
     def setUp(self):