diff --git a/entity/BulkMailAddRecipients_entity/BulkMailAddRecipients_entity.aod b/entity/BulkMailAddRecipients_entity/BulkMailAddRecipients_entity.aod
index e120f312fe5e0fabaa1906dcf24fce187a7037f5..6aaedae300b335d1cdc279657ee3f4c28dde3dbd 100644
--- a/entity/BulkMailAddRecipients_entity/BulkMailAddRecipients_entity.aod
+++ b/entity/BulkMailAddRecipients_entity/BulkMailAddRecipients_entity.aod
@@ -84,6 +84,10 @@
       <name>Parameters_param</name>
       <expose v="true" />
     </entityParameter>
+    <entityParameter>
+      <name>RecordsRecipe_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <datalessRecordContainer>
diff --git a/entity/BulkMailAddRecipients_entity/entityfields/proposedcontactids/valueProcess.js b/entity/BulkMailAddRecipients_entity/entityfields/proposedcontactids/valueProcess.js
index a865018d80dc98523a354ff97ae305e84008d850..275fb1e0e2553ada7caefedf753095fde91ed94f 100644
--- a/entity/BulkMailAddRecipients_entity/entityfields/proposedcontactids/valueProcess.js
+++ b/entity/BulkMailAddRecipients_entity/entityfields/proposedcontactids/valueProcess.js
@@ -1,3 +1,4 @@
+import("system.neonFilter");
 import("Context_lib");
 import("system.entities");
 import("Sql_lib");
@@ -14,12 +15,29 @@ if (bulkMailId)
     var filter = vars.get("$param.Filter_param");
     var context = vars.getString("$param.ObjectType_param");
     var parameters = vars.get("$param.Parameters_param");
+    var recordsRecipe = vars.get("$param.RecordsRecipe_param");
     
     
+    if(!Utils.isNullOrEmptyString(recordsRecipe))
+    {
+        
+        var loadConfig = entities.createConfigForLoadingRows()
+        .fromEntityRecordsRecipe(recordsRecipe);
+        context = ContextUtils.getContextId(JSON.parse(recordsRecipe).entityName);  
+    }
+    
     switch(context)
     {
         case "CampaignParticipant":
-            if (Utils.isNullOrEmpty(ids) && filter)
+            if (!Utils.isNullOrEmpty(recordsRecipe))
+            {
+                loadConfig.fields(["CONTACT_ID"]);
+                proposedRecipients = entities.getRows(loadConfig).map(function (row)
+                {
+                    return row["CONTACT_ID"];
+                });
+            }
+            else if (Utils.isNullOrEmpty(ids) && filter)
             {
                 var filterObject = Utils.isString(filter) ? JSON.parse(filter) : filter;
                 
@@ -55,14 +73,36 @@ if (bulkMailId)
             }    
             break;
         case "CampaignStep":
-            var proposedIds = FilterViewActionUtils.getUidsBySelectionOrFilter(context, ids, filter, parameters);
+            if (!Utils.isNullOrEmpty(recordsRecipe))
+            {
+                loadConfig.fields(["CAMPAIGNSTEPID"]);
+                proposedIds = entities.getRows(loadConfig).map(function (row)
+                {
+                    return row["CAMPAIGNSTEPID"];
+                });
+            }
+            else
+            {
+                var proposedIds = FilterViewActionUtils.getUidsBySelectionOrFilter(context, ids, filter, parameters);
+            }
             proposedRecipients = newSelect("CAMPAIGNPARTICIPANT.CONTACT_ID")
                                 .from("CAMPAIGNPARTICIPANT")
                                 .where("CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID", proposedIds, SqlBuilder.IN())
                                 .arrayColumn();
             break;
         default:
-            proposedRecipients = FilterViewActionUtils.getUidsBySelectionOrFilter(context, ids, filter, parameters);
+            if(!Utils.isNullOrEmpty(recordsRecipe))
+            {
+                loadConfig.fields(["CONTACTID"]);
+                proposedRecipients = entities.getRows(loadConfig).map(function (row)
+                {
+                    return row["CONTACTID"];
+                });
+            }
+            else
+            {
+               proposedRecipients = FilterViewActionUtils.getUidsBySelectionOrFilter(context, ids, filter, parameters);
+            }
     }
   
 }
diff --git a/entity/BulkMailAddRecipients_entity/entityfields/validcontactids/valueProcess.js b/entity/BulkMailAddRecipients_entity/entityfields/validcontactids/valueProcess.js
index 2f2efb1a8dcc5ae9296a2d3f91a4cac8c6c3f329..2197f059fce9fe77ca8a6647ddf4f12334ce71ef 100644
--- a/entity/BulkMailAddRecipients_entity/entityfields/validcontactids/valueProcess.js
+++ b/entity/BulkMailAddRecipients_entity/entityfields/validcontactids/valueProcess.js
@@ -1,3 +1,4 @@
+import("system.neonFilter");
 import("Util_lib");
 import("system.result");
 import("Bulkmail_lib");
@@ -8,6 +9,7 @@ var bulkMailId = vars.get("$field.BULKMAIL_ID");
 var filter = vars.get("$param.Filter_param");
 var ids = Utils.parseJSON(vars.get("$param.Ids_param"));
 var context = vars.getString("$param.ObjectType_param");
+var recordsRecipe = vars.get("$param.RecordsRecipe_param");
 
 if (Utils.isString(filter))
 {
@@ -17,13 +19,17 @@ var validRecipients = [];
 
 if (bulkMailId)
 {
-    if (Utils.isNullOrEmpty(ids) && filter && filter.condition)
+    if (!Utils.isNullOrEmptyString(recordsRecipe))
+    {
+        validRecipients = BulkMailUtils.filterNewRecipientsByRecordsRecipe(bulkMailId, recordsRecipe);
+    }
+    else if (Utils.isNullOrEmpty(ids) && filter && filter.condition)
     {
         validRecipients = BulkMailUtils.filterNewRecipientsByCondition(bulkMailId, filter.condition, context)
     }
     else if (context == "CampaignStep")
     {
-        validRecipients = BulkMailUtils.filterNewRecipientsByCondition(bulkMailId, newWhere("CAMPAIGNSTEP.CAMPAIGNSTEPID", pIds, SqlBuilder.IN()), context);
+        validRecipients = BulkMailUtils.filterNewRecipientsByCondition(bulkMailId, newWhere("CAMPAIGNSTEP.CAMPAIGNSTEPID", ids, SqlBuilder.IN()), context);
     }
     else
     {
diff --git a/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod b/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod
index ce1dcd2d2b93817595ec64e9fb98930a9641e821..6edeeec6b8c14f0cf28450a7cab6e12d826aad27 100644
--- a/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod
+++ b/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod
@@ -8,6 +8,7 @@
   <siblings>
     <element>Communication_entity</element>
   </siblings>
+  <recordsRecipeSupported v="true" />
   <titlePlural>Recipients</titlePlural>
   <recordContainer>db</recordContainer>
   <entityFields>
diff --git a/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/removetestrecipient/onActionProcess.js b/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/removetestrecipient/onActionProcess.js
index b19f093933f83c39b3bca1779f28b1a9240aacd3..99d9e298b993952b4c08ad84f8025c28dc6b947e 100644
--- a/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/removetestrecipient/onActionProcess.js
+++ b/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/removetestrecipient/onActionProcess.js
@@ -1,9 +1,21 @@
 import("Sql_lib");
 import("system.vars");
 import("system.neon");
+import("system.entities");
+
+var loadConfig = entities.createConfigForLoadingRows()
+                .fields(["#UID"])
+                .fromEntityRecordsRecipe(vars.get("$sys.selectionsRecordsRecipe"));
+
+var selectedRecords = entities.getRows(loadConfig);
+                 
+var selectedUids = selectedRecords.map(function (pRecord)
+{
+    return pRecord["#UID"]
+});
+
+newWhere("BULKMAILRECIPIENT.BULKMAILRECIPIENTID",selectedUids,SqlBuilder.IN())
+.updateFields({"IS_TEST_RECIPIENT": 0});
 
-newWhereIfSet("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", vars.get("$sys.selection"), SqlBuilder.IN())
-        .updateData(true, "BULKMAILRECIPIENT", ["IS_TEST_RECIPIENT"], null, [0]);
-        
 neon.refreshAll();
     
\ No newline at end of file
diff --git a/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/settestrecipient/onActionProcess.js b/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/settestrecipient/onActionProcess.js
index 69f831c2f7a1a5dfca2708c9fbee266e552f6773..afda3d26c0b1eaedbf151bce94744b2bf01ccadb 100644
--- a/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/settestrecipient/onActionProcess.js
+++ b/entity/BulkMailRecipient_entity/entityfields/testrunactions/children/settestrecipient/onActionProcess.js
@@ -1,9 +1,22 @@
 import("Sql_lib");
 import("system.vars");
 import("system.neon");
+import("system.entities");
+
+var loadConfig = entities.createConfigForLoadingRows()
+                .fields(["#UID"])
+                .fromEntityRecordsRecipe(vars.get("$sys.selectionsRecordsRecipe"));
+
+var selectedRecords = entities.getRows(loadConfig);
+       
+
+var selectedUids = selectedRecords.map(function (pRecord)
+{
+    return pRecord["#UID"]
+});
+
+newWhere("BULKMAILRECIPIENT.BULKMAILRECIPIENTID",selectedUids,SqlBuilder.IN())
+.updateFields({"IS_TEST_RECIPIENT": 1});
 
-newWhereIfSet("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", vars.get("$sys.selection"), SqlBuilder.IN())
-        .updateData(true, "BULKMAILRECIPIENT", ["IS_TEST_RECIPIENT"], null, [1]);
-        
 neon.refreshAll();
     
\ No newline at end of file
diff --git a/entity/BulkMailRecipient_entity/entityfields/testrunactions/stateProcess.js b/entity/BulkMailRecipient_entity/entityfields/testrunactions/stateProcess.js
index 0d630e347774ced0b5ea0c83e85ae75c66da1b4a..ce0b4a9880b0510ff70206712e32835462cb7a52 100644
--- a/entity/BulkMailRecipient_entity/entityfields/testrunactions/stateProcess.js
+++ b/entity/BulkMailRecipient_entity/entityfields/testrunactions/stateProcess.js
@@ -1,8 +1,10 @@
+import("system.logging");
 import("system.result");
 import("system.vars");
 import("system.neon");
 
-if (vars.get("$sys.selection").length > 0)
+logging.log(vars.get("$sys.selectionsRecordsRecipe"))
+if (vars.get("$sys.selectionsRecordsRecipe"))
 {
     result.string(neon.COMPONENTSTATE_EDITABLE);
 }
diff --git a/entity/BulkMailTestRecipient_entity/BulkMailTestRecipient_entity.aod b/entity/BulkMailTestRecipient_entity/BulkMailTestRecipient_entity.aod
index d8793c1e6f941850bedaed48e1f0beb418eece39..4b92afe629e8f874dbf56a112bbcd38d31857cfc 100644
--- a/entity/BulkMailTestRecipient_entity/BulkMailTestRecipient_entity.aod
+++ b/entity/BulkMailTestRecipient_entity/BulkMailTestRecipient_entity.aod
@@ -4,6 +4,7 @@
   <title>Test Recipient</title>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/BulkMailTestRecipient_entity/documentation.adoc</documentation>
+  <recordsRecipeSupported v="true" />
   <titlePlural>Test Recipients</titlePlural>
   <recordContainer>db</recordContainer>
   <entityFields>
diff --git a/entity/BulkMail_entity/BulkMail_entity.aod b/entity/BulkMail_entity/BulkMail_entity.aod
index c91cdcca4a5efb196f0c9d442aead91a284f0c4e..dc0a44bec39e969515ac367a7a2e748c4de2a988 100644
--- a/entity/BulkMail_entity/BulkMail_entity.aod
+++ b/entity/BulkMail_entity/BulkMail_entity.aod
@@ -642,6 +642,10 @@
         <fieldName>ISO3Name</fieldName>
       </dependency>
     </entityConsumer>
+    <entityParameter>
+      <name>PresetRecipientsRecordsRecipe_param</name>
+      <expose v="true" />
+    </entityParameter>
     <entityConsumer>
       <name>SenderAddressKeyword</name>
       <dependency>
diff --git a/entity/BulkMail_entity/recordcontainers/db/onDBInsert.js b/entity/BulkMail_entity/recordcontainers/db/onDBInsert.js
index 54931b06e7104406b1df9fa48a117170497f7b17..0fcb3e3f16afbaa4c7be3b0c9fae3fa58a08042f 100644
--- a/entity/BulkMail_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/BulkMail_entity/recordcontainers/db/onDBInsert.js
@@ -100,6 +100,11 @@ else if (vars.getString("$param.PresetRecipientsContext_param") && vars.getStrin
     contactIds = contactIds.concat(BulkMailUtils.filterNewRecipientsByCondition(bulkMailId, JSON.parse(vars.getString("$param.PresetRecipientsFilter_param")).condition, vars.getString("$param.PresetRecipientsContext_param")));
 }
 
+if (vars.get("$param.PresetRecipientsRecordsRecipe_param"))
+{
+    contactIds = contactIds.concat(BulkMailUtils.filterNewRecipientsByRecordsRecipe(bulkMailId, vars.get("$param.PresetRecipientsRecordsRecipe_param")));
+}
+
 
 if (contactIds && contactIds.length > 0)
     BulkMailUtils.addRecipients(bulkMailId, contactIds);
diff --git a/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod b/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod
index c14bbf77c06c95747866b02fbaf05a51884d91b9..0c1140dc3ad3a5beb96084aa66cae04e39eafc11 100644
--- a/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod
+++ b/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod
@@ -168,6 +168,10 @@
       <name>#PROVIDER_AGGREGATES</name>
       <useAggregates v="true" />
     </entityProvider>
+    <entityParameter>
+      <name>campaignParticipantsRecordsRecipe_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
diff --git a/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js b/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js
index 6511d5abbe134859e02af1b780da968a76fdd7ba..086f3dd9662482bdbe652235527ef530eaae6ea2 100644
--- a/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js
+++ b/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js
@@ -5,7 +5,8 @@ import("system.vars");
 import("system.neon");
 import("FilterViewAction_lib");
 import("Campaign_lib");
-
+import("system.neonFilter");
+import("system.entities");
 
 if(vars.get("$field.CAMPAIGN_ID") && vars.get("$field.CAMPAIGNSTEP_ID"))
 {
@@ -13,7 +14,8 @@ if(vars.get("$field.CAMPAIGN_ID") && vars.get("$field.CAMPAIGNSTEP_ID"))
     var isUpdate = Utils.toBoolean(vars.get("$param.isUpdate_param"));
     var comingfrom = vars.getString("$param.dataSourceTableName_param");
     var selection = JSON.parse(vars.getString("$param.campaignParticipantsRowIds_param"));
-    
+    var recordsRecipe = neonFilter.createEntityRecordsRecipeBuilder(vars.get("$param.campaignParticipantsRecordsRecipe_param"));
+
     if(vars.exists("$param.campaignParticipantsCondition_param") && vars.get("$param.campaignParticipantsCondition_param") && !isUpdate)
     {
         selection = JSON.parse(vars.getString("$param.campaignParticipantsCondition_param")).condition;
@@ -27,18 +29,42 @@ if(vars.get("$field.CAMPAIGN_ID") && vars.get("$field.CAMPAIGNSTEP_ID"))
     }
     else if(isUpdate)
     {
-        if (vars.get("$param.campaignParticipantsCondition_param"))
+        if (vars.get("$param.campaignParticipantsRecordsRecipe_param"))
+        {
+            let parameters = recordsRecipe.getParameters();
+            parameters["$param.OnlyNotInCampaignStepId_param"] = vars.get("$field.CAMPAIGNSTEP_ID");
+            recordsRecipe.parameters(parameters);
+            var loadConfig = entities.createConfigForLoadingRows()
+                             .fromEntityRecordsRecipe(recordsRecipe)
+                             .fields(["CONTACT_ID"]);
+            contactIds = entities.getRows(loadConfig).map(function (row)
+            {
+                return row["CONTACT_ID"]
+            });
+        }
+        else if (vars.get("$param.campaignParticipantsCondition_param"))
         {
-            
             var contactFilterCondition = JSON.parse(vars.get("$param.campaignParticipantsCondition_param")).condition;
             contactIds = CampaignUtils.GetContactIdsNotInCampaignStepByCondition(vars.get("$field.CAMPAIGNSTEP_ID"),vars.get("$field.CAMPAIGN_ID"), contactFilterCondition);
-        } 
+        }
+        
         else
         {
             contactIds = CampaignUtils.GetContactIdsNotInCampaignStepByRowIds(vars.get("$field.CAMPAIGNSTEP_ID"), selection);
         }
     }
-    else 
+    else if (vars.get("$param.campaignParticipantsRecordsRecipe_param"))
+    {
+        recordsRecipe.parameters({"$param.OnlyNotInCampaignId_param": vars.get("$field.CAMPAIGN_ID")});
+        let loadConfig = entities.createConfigForLoadingRows()
+                         .fromEntityRecordsRecipe(recordsRecipe)
+                         .fields(["#UID"]);
+        contactIds = entities.getRows(loadConfig).map(function (row)
+        {
+            return row["#UID"]
+        });
+    }
+    else
     {
         contactIds = CampaignUtils.GetContactIdsNotInCampaignByRowIds(vars.get("$field.CAMPAIGN_ID"), selection);
     }
diff --git a/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantmessage/valueProcess.js b/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantmessage/valueProcess.js
index 50b80a7140e7174360fc74fd7532e1ae3c65d0a2..e6e773d9bc760b3bb1f325fb6d616db622b5abc0 100644
--- a/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantmessage/valueProcess.js
+++ b/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantmessage/valueProcess.js
@@ -5,6 +5,7 @@ import("system.vars");
 import("Campaign_lib");
 import("FilterViewAction_lib");
 import("Util_lib");
+import("system.entities");
 
 var res = "";
 var resNotAdded = "\n";
@@ -21,8 +22,14 @@ if(vars.get("$field.CAMPAIGN_ID") && vars.get("$field.campaignparticipantContact
         if (validCount != 0)
         {
             res = translate.withArguments("%0 new participants will be added to the campaign.", [validCount]);
-            
-            if(vars.exists("$param.campaignParticipantsRowIds_param") && vars.getString("$param.campaignParticipantsRowIds_param"))
+            if (vars.get("$param.campaignParticipantsRecordsRecipe_param"))
+            {
+                var loadConfig = entities.createConfigForLoadingRows()
+                                 .fromEntityRecordsRecipe(vars.get("$param.campaignParticipantsRecordsRecipe_param"))
+                                 .fields(["#UID"]);
+                selectedIds = entities.getRowCount(loadConfig);
+            }
+            else if(vars.exists("$param.campaignParticipantsRowIds_param") && vars.getString("$param.campaignParticipantsRowIds_param"))
                 selectedIds = JSON.parse(vars.getString("$param.campaignParticipantsRowIds_param")).length;
             else
             {
diff --git a/entity/CampaignParticipant_entity/CampaignParticipant_entity.aod b/entity/CampaignParticipant_entity/CampaignParticipant_entity.aod
index 56099308c728313324d1b2b7d2fad60c7c578c77..8d752e3755b7dc4c2433777c54b289f5c57100a6 100644
--- a/entity/CampaignParticipant_entity/CampaignParticipant_entity.aod
+++ b/entity/CampaignParticipant_entity/CampaignParticipant_entity.aod
@@ -10,6 +10,7 @@
     <element>Campaign_entity</element>
   </siblings>
   <usePermissions v="false" />
+  <recordsRecipeSupported v="true" />
   <titlePlural>Participants</titlePlural>
   <recordContainer>db</recordContainer>
   <entityFields>
@@ -181,12 +182,14 @@
           <title>Add to Bulkmail</title>
           <onActionProcess>%aditoprj%/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/onActionProcess.js</onActionProcess>
           <iconId>VAADIN:AT</iconId>
+          <stateProcess>%aditoprj%/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/stateProcess.js</stateProcess>
         </entityActionField>
         <entityActionField>
           <name>newBulkMail</name>
           <title>Write bulk mail</title>
           <onActionProcess>%aditoprj%/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/onActionProcess.js</onActionProcess>
           <iconId>VAADIN:AT</iconId>
+          <stateProcess>%aditoprj%/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/stateProcess.js</stateProcess>
         </entityActionField>
       </children>
     </entityActionGroup>
@@ -306,6 +309,10 @@
         </entityParameter>
       </children>
     </entityConsumer>
+    <entityParameter>
+      <name>OnlyNotInCampaignStepId_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/onActionProcess.js b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/onActionProcess.js
index c5e06bc71d9e0872e5ba270940a124d90da8fc2f..5cc017ccec50eef7265bca9ca800100d7cfa69cc 100644
--- a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/onActionProcess.js
+++ b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/onActionProcess.js
@@ -1,5 +1,4 @@
 import("Bulkmail_lib");
 import("system.vars");
 
-var parameters = {"CampaignId_param":vars.get("$param.CampaignId_param")};
-BulkMailUtils.openAddRecipientView(vars.get("$sys.currentcontextname"), vars.get("$sys.selection"), vars.get("$sys.filter"), parameters);
\ No newline at end of file
+BulkMailUtils.openAddRecipientViewWithRecipe(vars.get("$sys.selectionsRecordsRecipe"));
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/stateProcess.js b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..339c5c0f0416e7d0dcb6159597e334dcbd197795
--- /dev/null
+++ b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/addtobulkmail/stateProcess.js
@@ -0,0 +1,13 @@
+import("system.vars");
+import("system.neon");
+import("system.result");
+
+
+if(vars.get("$sys.selectionsRecordsRecipe"))
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_DISABLED);
+}
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/onActionProcess.js b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/onActionProcess.js
index 7bca6ed54c3f9d4dfc5aa1c56556d2bac6832ed6..290409f7de4e7ea14f511bbabd412b88db3fdc9f 100644
--- a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/onActionProcess.js
+++ b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/onActionProcess.js
@@ -1,21 +1,4 @@
 import("system.vars");
-import("Sql_lib");
-import("system.db");
 import("Bulkmail_lib");
 
-
-var selection = vars.get("$sys.selection");
-var filter = vars.get("$sys.filter");
-var recipientsSql = newSelect("CONTACT_ID")
-                        .from("CAMPAIGNPARTICIPANT")
-                     
-if(selection.length > 0)
-{
-    recipientsSql.where("CAMPAIGNPARTICIPANT.CAMPAIGNPARTICIPANTID",selection,SqlBuilder.IN());
-    BulkMailUtils.newBulkMail(recipientsSql.arrayColumn());
-}
-else
-{
-    BulkMailUtils.newBulkMail(null,vars.getString("$sys.currentcontextname"),filter);
-}
-
+BulkMailUtils.newBulkMailWithRecordsRecipe(vars.get("$sys.selectionsRecordsRecipe"));
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/stateProcess.js b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..339c5c0f0416e7d0dcb6159597e334dcbd197795
--- /dev/null
+++ b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/newbulkmail/stateProcess.js
@@ -0,0 +1,13 @@
+import("system.vars");
+import("system.neon");
+import("system.result");
+
+
+if(vars.get("$sys.selectionsRecordsRecipe"))
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_DISABLED);
+}
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/onActionProcess.js b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/onActionProcess.js
index fbba2db18aa37636d3d3ca5097cccd1c29df51e7..da52348277398320e399c41f241bc67b201c8a46 100644
--- a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/onActionProcess.js
+++ b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/onActionProcess.js
@@ -1,17 +1,9 @@
 import("system.vars");
-import("system.neon");
 import("Campaign_lib");
 
 
-var sysSelection = vars.get("$sys.selection");
+var sysSelectionsRecordsRecipe = vars.get("$sys.selectionsRecordsRecipe");
 var campaignId = vars.get("$field.CAMPAIGN_ID");
-var campaignStepId = vars.get("$field.CAMPAIGNSTEP_ID")
+var campaignStepId = vars.get("$field.CAMPAIGNSTEP_ID");
 
-if(sysSelection.length > 0) //selektierte IDs als Array
-{
-    CampaignUtils.openSetCampaignStepViewByRowIds(JSON.stringify(vars.get("$sys.selection")), campaignId, campaignStepId);
-}
-else
-{
-    CampaignUtils.openSetCampaignStepViewByCondition(JSON.stringify(vars.get("$sys.filter")), campaignId, campaignStepId);
-}
\ No newline at end of file
+CampaignUtils.openSetCampaignStepViewByRecordsRecipe(sysSelectionsRecordsRecipe, campaignId, campaignStepId)
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/stateProcess.js b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/stateProcess.js
index 78eb0e84628e8dd7122682d803a8e555c24594a5..339c5c0f0416e7d0dcb6159597e334dcbd197795 100644
--- a/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/stateProcess.js
+++ b/entity/CampaignParticipant_entity/entityfields/filterviewactiongroup/children/setsteptoparticipantselection/stateProcess.js
@@ -1,11 +1,9 @@
-import("Campaign_lib");
 import("system.vars");
 import("system.neon");
 import("system.result");
 
-var participantCount = vars.get("$sys.datarowcountfull");
 
-if(participantCount > 0)
+if(vars.get("$sys.selectionsRecordsRecipe"))
 {
     result.string(neon.COMPONENTSTATE_EDITABLE);
 }
diff --git a/entity/CampaignParticipant_entity/recordcontainers/db/conditionProcess.js b/entity/CampaignParticipant_entity/recordcontainers/db/conditionProcess.js
index 67d5159a7b988831992b8af18bbaad5ed190c03e..e3f25c18cd7dd6513cced1e3fe52fa11502ff6be 100644
--- a/entity/CampaignParticipant_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/CampaignParticipant_entity/recordcontainers/db/conditionProcess.js
@@ -5,6 +5,7 @@ import("system.vars");
 var condition = newWhere()
     .andIfSet("CAMPAIGNPARTICIPANT.CAMPAIGN_ID", "$param.CampaignId_param")
     .andIfSet("CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID", "$param.CampaignStepId_param")
-    .andIfSet("CAMPAIGNPARTICIPANT.CONTACT_ID", "$param.ContactId_param");
+    .andIfSet("CAMPAIGNPARTICIPANT.CONTACT_ID", "$param.ContactId_param")
+    .andIfSet("CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID","$param.OnlyNotInCampaignStepId_param",SqlBuilder.NOT_EQUAL());
 
 result.string(condition.toString());
diff --git a/entity/CampaignStep_entity/CampaignStep_entity.aod b/entity/CampaignStep_entity/CampaignStep_entity.aod
index 3d40d3531edc1d25041c2b33f962aaf35eef07d3..bbf180554c656100f88929c9f66e3bcae35d0b9d 100644
--- a/entity/CampaignStep_entity/CampaignStep_entity.aod
+++ b/entity/CampaignStep_entity/CampaignStep_entity.aod
@@ -403,6 +403,7 @@
           <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/onActionProcess.js</onActionProcess>
           <isObjectAction v="false" />
           <iconId>VAADIN:AT</iconId>
+          <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/stateProcess.js</stateProcess>
         </entityActionField>
         <entityActionField>
           <name>newBulkMail</name>
@@ -410,6 +411,7 @@
           <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/onActionProcess.js</onActionProcess>
           <isObjectAction v="false" />
           <iconId>VAADIN:AT</iconId>
+          <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/stateProcess.js</stateProcess>
         </entityActionField>
       </children>
     </entityActionGroup>
diff --git a/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/onActionProcess.js b/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/onActionProcess.js
index 3a56d448a8c9b338e7b99dcf92ab7e08d202c6d0..5cc017ccec50eef7265bca9ca800100d7cfa69cc 100644
--- a/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/onActionProcess.js
+++ b/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/onActionProcess.js
@@ -1,5 +1,4 @@
 import("Bulkmail_lib");
 import("system.vars");
 
-var parameters = {"campaignId_param":vars.get("$param.campaignId_param")};
-BulkMailUtils.openAddRecipientView(vars.get("$sys.currentcontextname"), vars.get("$sys.selection"), vars.get("$sys.filter"), parameters);
\ No newline at end of file
+BulkMailUtils.openAddRecipientViewWithRecipe(vars.get("$sys.selectionsRecordsRecipe"));
\ No newline at end of file
diff --git a/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/stateProcess.js b/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..a1b04fd98874d704e41d93d9ce32daca0c5405ac
--- /dev/null
+++ b/entity/CampaignStep_entity/entityfields/group/children/addtobulkmail/stateProcess.js
@@ -0,0 +1,13 @@
+import("system.result");
+import("system.vars");
+import("system.neon")
+
+
+if (!vars.get("$sys.selectionsRecordsRecipe"))
+{
+    result.string(neon.COMPONENTSTATE_DISABLED);
+}
+else
+{   
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/onActionProcess.js b/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/onActionProcess.js
index 548f568aebb826bfa906f7ba752f12b1a51ad638..290409f7de4e7ea14f511bbabd412b88db3fdc9f 100644
--- a/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/onActionProcess.js
+++ b/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/onActionProcess.js
@@ -1,7 +1,4 @@
 import("system.vars");
-import("Sql_lib");
-import("system.db");
 import("Bulkmail_lib");
 
-
-BulkMailUtils.newBulkMail(null,vars.get("$sys.currentcontextname"),{"condition":newWhere("CAMPAIGNSTEP.CAMPAIGNSTEPID","$field.CAMPAIGNSTEPID").toString()});
\ No newline at end of file
+BulkMailUtils.newBulkMailWithRecordsRecipe(vars.get("$sys.selectionsRecordsRecipe"));
\ No newline at end of file
diff --git a/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/stateProcess.js b/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..a1b04fd98874d704e41d93d9ce32daca0c5405ac
--- /dev/null
+++ b/entity/CampaignStep_entity/entityfields/group/children/newbulkmail/stateProcess.js
@@ -0,0 +1,13 @@
+import("system.result");
+import("system.vars");
+import("system.neon")
+
+
+if (!vars.get("$sys.selectionsRecordsRecipe"))
+{
+    result.string(neon.COMPONENTSTATE_DISABLED);
+}
+else
+{   
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/EmailFilterHandlingSetWorkflow_entity/EmailFilterHandlingSetWorkflow_entity.aod b/entity/EmailFilterHandlingSetWorkflow_entity/EmailFilterHandlingSetWorkflow_entity.aod
index e395e37ec6c1f4cc81394011b1962de7700eebd6..df3a2e2f557d0038901b78b39203793d999579a9 100644
--- a/entity/EmailFilterHandlingSetWorkflow_entity/EmailFilterHandlingSetWorkflow_entity.aod
+++ b/entity/EmailFilterHandlingSetWorkflow_entity/EmailFilterHandlingSetWorkflow_entity.aod
@@ -30,20 +30,16 @@
         <fieldName>#PROVIDER</fieldName>
       </dependency>
     </entityConsumer>
-    <entityParameter>
-      <name>Selection_param</name>
-      <expose v="true" />
-    </entityParameter>
-    <entityParameter>
-      <name>Filter_param</name>
-      <expose v="true" />
-    </entityParameter>
     <entityActionField>
       <name>SetWorkflow</name>
       <title>Set workflow</title>
       <onActionProcess>%aditoprj%/entity/EmailFilterHandlingSetWorkflow_entity/entityfields/setworkflow/onActionProcess.js</onActionProcess>
       <tooltipProcess>%aditoprj%/entity/EmailFilterHandlingSetWorkflow_entity/entityfields/setworkflow/tooltipProcess.js</tooltipProcess>
     </entityActionField>
+    <entityParameter>
+      <name>RecordsRecipe_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <datalessRecordContainer>
diff --git a/entity/EmailFilterHandlingSetWorkflow_entity/entityfields/emailfilterhandling_ids/valueProcess.js b/entity/EmailFilterHandlingSetWorkflow_entity/entityfields/emailfilterhandling_ids/valueProcess.js
index 3e11a5f4ad618b1476e572870a2eeb6b60380aee..7b03969847eb3c2262da852414f874e53b0711a0 100644
--- a/entity/EmailFilterHandlingSetWorkflow_entity/entityfields/emailfilterhandling_ids/valueProcess.js
+++ b/entity/EmailFilterHandlingSetWorkflow_entity/entityfields/emailfilterhandling_ids/valueProcess.js
@@ -1,15 +1,14 @@
-import("Util_lib");
-import("FilterViewAction_lib");
 import("system.result");
 import("system.vars");
+import("system.entities");
 
-var emailFilterHandlingIds = [];
-
-var selection = Utils.parseJSON(vars.get("$param.Selection_param"));
-var filter = vars.get("$param.Filter_param");
-var context = "EmailFilterHandling";
-
-emailFilterHandlingIds = FilterViewActionUtils.getUidsBySelectionOrFilter(context, selection, filter);
+var loadConfig = entities.createConfigForLoadingRows()
+    .fromEntityRecordsRecipe(vars.get("$param.RecordsRecipe_param"))
+    .fields(["#UID"]);
 
+var emailFilterHandlingIds = entities.getRows(loadConfig).map(function (row)
+{
+    return row["#UID"];
+});
 
 result.string(JSON.stringify(emailFilterHandlingIds));
\ No newline at end of file
diff --git a/entity/EmailFilterHandling_entity/EmailFilterHandling_entity.aod b/entity/EmailFilterHandling_entity/EmailFilterHandling_entity.aod
index c19d078351c9e6797a7dfd3e210001eae9021dc9..53f1200d7116fa19d98f4d3812371c82c7c8fca5 100644
--- a/entity/EmailFilterHandling_entity/EmailFilterHandling_entity.aod
+++ b/entity/EmailFilterHandling_entity/EmailFilterHandling_entity.aod
@@ -5,6 +5,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/EmailFilterHandling_entity/documentation.adoc</documentation>
   <iconId>VAADIN:INBOX</iconId>
+  <recordsRecipeSupported v="true" />
   <titlePlural>Email Filter</titlePlural>
   <recordContainer>db</recordContainer>
   <entityFields>
@@ -123,6 +124,7 @@
           <title>Set workflow</title>
           <onActionProcess>%aditoprj%/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/onActionProcess.js</onActionProcess>
           <iconId>VAADIN:PLAY</iconId>
+          <stateProcess>%aditoprj%/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/stateProcess.js</stateProcess>
           <tooltipProcess>%aditoprj%/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/tooltipProcess.js</tooltipProcess>
         </entityActionField>
       </children>
diff --git a/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/increasepriority/stateProcess.js b/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/increasepriority/stateProcess.js
index feaf9fc2c6832f235d8f3425eb23854ebccb34f3..46ef593de432a6d610b40dd32f93abf4d98f68ae 100644
--- a/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/increasepriority/stateProcess.js
+++ b/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/increasepriority/stateProcess.js
@@ -5,12 +5,13 @@ import("system.neon");
 
 var priority = parseInt(vars.get("$field.PRIORITY"));
 
-
-if (priority != 1)
+if (vars.get("$sys.selectionsRecordsRecipe") && priority != 1)
 {
+
     result.string(neon.COMPONENTSTATE_EDITABLE);
 }
 else
 {
+
     result.string(neon.COMPONENTSTATE_DISABLED);
 }
\ No newline at end of file
diff --git a/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/onActionProcess.js b/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/onActionProcess.js
index 535c3584bb352512b843f264d4ddcc40b700f16b..973fbf9adccfed92dab5e9f393059ed7945b1176 100644
--- a/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/onActionProcess.js
+++ b/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/onActionProcess.js
@@ -2,11 +2,9 @@ import("system.neonFilter");
 import("system.vars");
 import("system.neon");
 
-var selection = JSON.stringify(vars.get("$sys.selection"));
-var filter = JSON.stringify(vars.get("$sys.filter"));
+var recordsRecipe = vars.get("$sys.selectionsRecordsRecipe")
 
 var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters({
-    "Selection_param": selection,
-    "Filter_param": filter
+    "RecordsRecipe_param": recordsRecipe
 }).toString();
 neon.openContextWithRecipe("EmailFilterHandlingSetWorkflow", "EmailFilterHandlingSetWorkflowEdit_view", recipe, neon.OPERATINGSTATE_VIEW);
diff --git a/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/stateProcess.js b/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..221f0d1a3171a6a9ac80e629edb140fa8c78d884
--- /dev/null
+++ b/entity/EmailFilterHandling_entity/entityfields/filterviewactiongroup/children/setworkflow/stateProcess.js
@@ -0,0 +1,12 @@
+import("system.vars");
+import("system.result");
+import("system.neon");
+
+if(vars.get("$sys.selectionsRecordsRecipe"))
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_DISABLED);
+}
\ No newline at end of file
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index 6c66d90b9193913044811aa5b08ec3225e1661fd..373a1c7ca8f6cb5a2bccdc3f0b6e26c5cfda53b9 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -1477,6 +1477,10 @@
       <name>IsQuickEntry_param</name>
       <expose v="true" />
     </entityParameter>
+    <entityParameter>
+      <name>OnlyNotInCampaignId_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js b/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js
index 328ef725e8d1c646a39e15a2dfaa78a626b2a424..0f92e5c7591e73ac10824c67c770ef9bac2f92aa 100644
--- a/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js
+++ b/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js
@@ -1,4 +1,11 @@
 import("Bulkmail_lib");
 import("system.vars");
 
-BulkMailUtils.openAddRecipientView(vars.get("$sys.currentcontextname"), vars.get("$sys.selection"), vars.get("$sys.filter"));
\ No newline at end of file
+if(vars.get("$sys.selectionsRecordsRecipe"))
+{
+    BulkMailUtils.openAddRecipientViewWithRecipe(vars.get("$sys.selectionsRecordsRecipe"));
+}
+else
+{
+    BulkMailUtils.openAddRecipientView(vars.get("$sys.currentcontextname"), vars.get("$sys.selection"), vars.get("$sys.filter"));
+}
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js b/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js
index d2b26e842b85f3da742191e8163d45b5078e3317..502b816a33188e51a2dead147cef66751ce19108 100644
--- a/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js
+++ b/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js
@@ -2,11 +2,11 @@ import("system.vars");
 import("system.neon");
 import("Campaign_lib");
 
-var sysSelection = vars.get("$sys.selection");
+var selectionsRecordsRecipe = vars.get("$sys.selectionsRecordsRecipe");
 
-if(sysSelection.length > 0)     //if data selected -> use selected data
+if(selectionsRecordsRecipe)     //if data selected -> use selected data
 {
-    CampaignUtils.addParticipantsByRowIds(JSON.stringify(sysSelection), vars.get("$sys.currentcontextname"));
+    CampaignUtils.addParticipantsByRecordsRecipe(selectionsRecordsRecipe, vars.get("$sys.currentcontextname"));
 }
 else                            //else -> use Filtercondition
 {
diff --git a/entity/Organisation_entity/recordcontainers/db/conditionProcess.js b/entity/Organisation_entity/recordcontainers/db/conditionProcess.js
index 2d3417abfe5d5281f33a0b8ae7fffa39676ff853..c890b789cc923bfcc43a22af3ba89a4ab352cf24 100644
--- a/entity/Organisation_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Organisation_entity/recordcontainers/db/conditionProcess.js
@@ -61,4 +61,14 @@ if (vars.exists("$param.OnlyOwnSupervised_param") && vars.get("$param.OnlyOwnSup
         SqlBuilder.EXISTS()
     );
 }
+
+if (vars.get("$param.OnlyNotInCampaignId_param"))
+{
+    cond.and(null,newSelect("1")
+        .from("CAMPAIGNPARTICIPANT")
+        .where("CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
+        .and("CAMPAIGNPARTICIPANT.CAMPAIGN_ID","$param.OnlyNotInCampaignId_param"),
+        SqlBuilder.NOT_EXISTS()
+        );        
+}
 result.string(cond.toString());
\ No newline at end of file
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index 0a84080c9f8896c00a574db0773b24eb31f3db2b..fd872f181de16c40f5b33b709fb5b3c995eee094 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -1393,6 +1393,10 @@
       <name>contenttitle</name>
       <valueProcess>%aditoprj%/entity/Person_entity/entityfields/contenttitle/valueProcess.js</valueProcess>
     </entityField>
+    <entityParameter>
+      <name>OnlyNotInCampaignId_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Person_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js
index 328ef725e8d1c646a39e15a2dfaa78a626b2a424..7584ac5f5fc439abe65a7deddfdffa92ef354bdd 100644
--- a/entity/Person_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js
+++ b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtobulkmailfromtable/onActionProcess.js
@@ -1,4 +1,11 @@
 import("Bulkmail_lib");
 import("system.vars");
 
-BulkMailUtils.openAddRecipientView(vars.get("$sys.currentcontextname"), vars.get("$sys.selection"), vars.get("$sys.filter"));
\ No newline at end of file
+if(vars.get("$sys.selectionsRecordsRecipe"))
+{
+    BulkMailUtils.openAddRecipientViewWithRecipe(vars.get("$sys.selectionsRecordsRecipe"));
+}
+else
+{
+    BulkMailUtils.openAddRecipientView(vars.get("$sys.currentcontextname"), vars.get("$sys.selection"), vars.get("$sys.filter"));
+}
diff --git a/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js
index dec741db1e10a5a36746e87da2b3496c02665940..44e828e62b4d1a991ddc4b8ba805ec44db8d64b8 100644
--- a/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js
+++ b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocampaignfromtable/onActionProcess.js
@@ -2,13 +2,11 @@ import("system.vars");
 import("system.neon");
 import("Campaign_lib");
 
-var sysSelection = vars.get("$sys.selection");
-
-if(sysSelection.length > 0)     //if data selected -> use selected data
+if (vars.get("$sys.selectionsRecordsRecipe"))
 {
-    CampaignUtils.addParticipantsByRowIds(JSON.stringify(sysSelection), vars.get("$sys.currentcontextname"));
+    CampaignUtils.addParticipantsByRecordsRecipe(vars.get("$sys.selectionsRecordsRecipe"));
 }
-else                            //else -> use Filtercondition
+else
 {
     let sysFilter = vars.get("$sys.filter");//todo change name
     CampaignUtils.addParticipantsByCondition(JSON.stringify(sysFilter), vars.get("$sys.currentcontextname"));
diff --git a/entity/Person_entity/recordcontainers/db/conditionProcess.js b/entity/Person_entity/recordcontainers/db/conditionProcess.js
index c24eb7b7e0e4ffb85e6660796fabfe866ec6129d..3947bd9538e6db4495a9f9627b3ff477a746ff70 100644
--- a/entity/Person_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Person_entity/recordcontainers/db/conditionProcess.js
@@ -8,6 +8,9 @@ import("system.vars");
 import("system.db");
 import("system.result");
 import("Sql_lib");
+import("system.neonFilter");
+
+var myEntityRecordsRecipe = neonFilter.createEntityRecordsRecipeBuilder()
 
 var cond = newWhereIfSet("CONTACT.ORGANISATION_ID", "$param.OrgId_param")
 .andIfSet("CONTACT.CONTACTID", "$param.ContactId_param");    
@@ -45,4 +48,14 @@ if (vars.exists("$param.OnlyOwnSupervised_param") && vars.get("$param.OnlyOwnSup
         );
 }
 
+if (vars.get("$param.OnlyNotInCampaignId_param"))
+{
+    cond.and(null,newSelect("1")
+        .from("CAMPAIGNPARTICIPANT")
+        .where("CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
+        .and("CAMPAIGNPARTICIPANT.CAMPAIGN_ID","$param.OnlyNotInCampaignId_param"),
+        SqlBuilder.NOT_EXISTS()
+        );        
+}
+
 result.string(cond.toString());
\ No newline at end of file
diff --git a/process/Bulkmail_lib/process.js b/process/Bulkmail_lib/process.js
index 776a7ed0a7059ba01d8a1feff7b542fcb15c540c..d370120e78b240e3e205d610aaf253b554dcc233 100644
--- a/process/Bulkmail_lib/process.js
+++ b/process/Bulkmail_lib/process.js
@@ -428,6 +428,21 @@ BulkMailUtils.openAddRecipientView = function (pContext, pIds, pFilter, pParamet
     neon.openContextWithRecipe("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", recipe, neon.OPERATINGSTATE_VIEW);
 }
 
+/**
+ * Opens a context to select a bulk mail to add recipients to.<br>
+ * 
+ * @param {String} pRecordsRecipe       RecordsRecipe for the selection that should be added
+  */
+BulkMailUtils.openAddRecipientViewWithRecipe = function (pRecordsRecipe)
+{
+    logging.log(pRecordsRecipe);
+
+    var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters({
+        "RecordsRecipe_param": pRecordsRecipe
+    }).toString();
+    neon.openContextWithRecipe("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", recipe, neon.OPERATINGSTATE_VIEW);
+}
+
 /**
  * Deletes all bulk mail recipients that have a commrestriction for emails.<br>
  * 
@@ -583,6 +598,26 @@ BulkMailUtils.newBulkMail = function (pRecipients, pContext, pFilter)
     neon.openContextWithRecipe("BulkMail", "BulkMailEdit_view", recipe, neon.OPERATINGSTATE_NEW);
 }
 
+/**
+ * Opens the BulkMail context in new mode.<br>
+ * 
+ * @param {String}   pRecordsRecipe            <p>
+ *                                                  Recordsrecipe containing the recipients for the new Bulkmail.
+ *                                                  Currently supported Contexts are campaignstep, campaignparticipant, person and <br>                                                  sys.filter of selection that should be added to new bulkmail<br>                                                                                                
+ */
+BulkMailUtils.newBulkMailWithRecordsRecipe = function (pRecordsRecipe)
+{
+    if (!Utils.isString(pRecordsRecipe))
+    {
+        pRecordsRecipe = JSON.stringify(pRecordsRecipe);
+    }
+    var params = {
+        "PresetRecipientsRecordsRecipe_param": pRecordsRecipe
+    };
+    var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters(params).toString();
+    neon.openContextWithRecipe("BulkMail", "BulkMailEdit_view", recipe, neon.OPERATINGSTATE_NEW);
+}
+
 /**
  * Filters the given contactIds if they can be added as new recipients.
  * Checks if a contact is already a recipient or if there is a advertising ban.
@@ -661,6 +696,76 @@ BulkMailUtils.filterNewRecipientsByCondition = function (pBulkMailId, pCondition
     return  condition.arrayColumn();
 }
 
+/**
+ * Filters the given contactIds if they can be added as new recipients.
+ * Checks if a contact is already a recipient or if there is a advertising ban.
+ * 
+ * @param {String} pBulkMailId id of the bulk mail the contacts should be added to
+ * @param {String} pRecordsRecipe recordsrecipe for the selection that should be filtered.
+ * @return {String[]} contacts that can be added as recipients
+ */
+BulkMailUtils.filterNewRecipientsByRecordsRecipe = function (pBulkMailId, pRecordsRecipe)
+{
+    var recipients = [];
+    
+    var entity = JSON.parse(pRecordsRecipe).entityName;
+    
+    var loadConfig = entities.createConfigForLoadingRows()
+                    .fromEntityRecordsRecipe(pRecordsRecipe)
+                    .fields(["#UID"]);
+    var rows = entities.getRows(loadConfig);
+
+    while (rows.length > 0)
+    {
+        var currentIds = rows.splice(0,1000).map(function (row)
+        {
+            return row["#UID"];
+        });
+        var sql = newSelect("CONTACTID")
+                    .from("CONTACT")
+                    .join("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID")
+                    .join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID")
+                    // only add contacts that aren't already recipients
+                    .where(null, newSelect("BULKMAILRECIPIENTID")
+                                    .from("BULKMAILRECIPIENT")
+                                    .where("BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
+                                    .and("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
+                            , SqlBuilder.NOT_EXISTS())
+                    // check if there's a commrestriction
+                    .and(new CommunicationSettingsCondition()
+                        .emails(CommUtil.getStandardSubSqlMail())
+                        .rejected()
+                        .existNoSettings()
+                        .buildCondition());
+        if (entity == "Person_entity")
+        {
+            sql.join("PERSON", "PERSON.PERSONID = CONTACT.PERSON_ID")
+            .and("CONTACT.CONTACTID",currentIds,SqlBuilder.IN());
+        }
+        if (entity == "Organisation_entity")
+        {
+            sql.and("CONTACT.PERSON_ID is null")
+            .and("CONTACT.CONTACTID",currentIds,SqlBuilder.IN());
+        }
+
+        if (entity == "CampaignParticipant_entity")
+        {
+           sql.join("CAMPAIGNPARTICIPANT","CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
+           .and("CAMPAIGNPARTICIPANT.CAMPAIGNPARTICIPANTID",currentIds,SqlBuilder.IN());
+        }
+
+        if (entity == "CampaignStep_entity")
+        {
+           sql.join("CAMPAIGNPARTICIPANT","CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
+           .join("CAMPAIGNSTEP","CAMPAIGNSTEP.CAMPAIGNSTEPID = CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID")
+           .and("CAMPAIGNSTEP.CAMPAIGNSTEPID",currentIds,SqlBuilder.IN());
+        }
+        recipients = recipients.concat(sql.arrayColumn());
+    }
+
+    return  recipients;
+}
+
 /**
  * Opens the given bulk mail.
  * 
diff --git a/process/Campaign_lib/process.js b/process/Campaign_lib/process.js
index 58bdffc44102983beea08ff21599faa982748d66..b42cd51a90d0882b32916d2beebc572c1b4e124b 100644
--- a/process/Campaign_lib/process.js
+++ b/process/Campaign_lib/process.js
@@ -48,6 +48,20 @@ CampaignUtils.addParticipantsByCondition = function(pCondition, pSourceTableName
     "campaignParticipantsCondition_param", "CampaignAddParticipantsEdit_view", pSourceTableName);
 }
 
+/**
+ * Add many contacts (person or organistaion) to a campaign.<br>
+ * 
+ * @param {String} pRecordsRecipe           <p>
+ *                                      RecordsRecipe
+ * @param {String} pSourceTableName     <p>
+ *                                      The source table.<br>                                  
+ */
+CampaignUtils.addParticipantsByRecordsRecipe = function(pRecordsRecipe, pSourceTableName)
+{
+    _CampaignUtils._openAddParticipantContext("CampaignAddParticipants", pRecordsRecipe, 
+    "campaignParticipantsRecordsRecipe_param", "CampaignAddParticipantsEdit_view", pSourceTableName);
+}
+
 /**
  * Gets the campaign name per id.<br>
  * 
@@ -257,6 +271,29 @@ CampaignUtils.openSetCampaignStepViewByCondition = function(pCondition, pCampaig
     neon.openContextWithRecipe("CampaignAddParticipants", "CampaignAddParticipantsEdit_view", recipe, neon.OPERATINGSTATE_VIEW);
 }
 
+/**
+ * Opens the CampaignAddParticipants context in new mode.<br>
+ * 
+ * @param {String} pRecordsRecipe                       <p>
+ *                                                  The records recipe which will be used to select the specific<br>
+ *                                                  participants, which campaign step shall be updated.<br>
+ * @param {String} pCampaignId                      <p>
+ *                                                  The id of the campaign.<br>
+ * @param {String} pCampaignStepId                  <p>
+ *                                                  The id of the new campaign step.<br>                                                                                                  
+ */
+CampaignUtils.openSetCampaignStepViewByRecordsRecipe = function(pRecordsRecipe, pCampaignId, pCampaignStepId)
+{
+    var params = {
+        "campaignParticipantsRecordsRecipe_param": pRecordsRecipe,
+        "currentCampaignId_param": pCampaignId,
+        "currentCampaignStepId_param": pCampaignStepId,
+        "isUpdate_param": true
+    };
+    var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters(params).toString();
+    neon.openContextWithRecipe("CampaignAddParticipants", "CampaignAddParticipantsEdit_view", recipe, neon.OPERATINGSTATE_VIEW);
+}
+
 /**
  * Opens the CampaignStep context in new mode.<br>
  *