diff --git a/.liquibase/Data_alias/basic/2021.0.0/EwsContactSync/create_ab_synccontact.xml b/.liquibase/Data_alias/basic/2021.0.0/EwsContactSync/create_ab_synccontact.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9de2f01cc35fba70afd6992a3995da9c8e1b7431
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.0/EwsContactSync/create_ab_synccontact.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <changeSet author="A.Riedl" id="9820d74b-1b58-4ffd-9f5d-8c4d670bda47">
+        <createTable tableName="AB_SYNCCONTACT">
+            <column name="SYNCCONTACTID" type="char(36)">
+                <constraints primaryKey="true" primaryKeyName="PK_SYNCCONTACTID"/>
+            </column>
+            <column name="ASYS_FAVORITEID" type="char(36)"/>
+            <column name="EXCHANGEID" type="varchar(254)"/>
+            <column name="USER_ID" type="char(46)"/>            
+            <column name="CONTACT_ID" type="char(36)"/>
+            <column name="DATE_DEL" type="datetime"/>
+            <column name="DATE_EDIT" type="datetime"/>
+            <column name="DATE_NEW" type="datetime"/>
+        </createTable>
+        <createIndex indexName="idx_exchangeId" tableName="AB_SYNCCONTACT">
+            <column name="EXCHANGEID"/>
+        </createIndex>
+        <createIndex tableName="AB_SYNCCONTACT" indexName="idx_UserId">
+            <column name="USER_ID"/>
+        </createIndex>
+        <createIndex tableName="AB_SYNCCONTACT" indexName="idx_ContactId">
+            <column name="CONTACT_ID"/>
+        </createIndex>
+        <addUniqueConstraint 
+            columnNames="ASYS_FAVORITEID"
+            constraintName="const_uniqueFavoriteId"  
+            tableName="AB_SYNCCONTACT"/>  
+    </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2021.0.0/changelog.xml b/.liquibase/Data_alias/basic/2021.0.0/changelog.xml
index 489408fcecc12e61ad7e9f689e82a9aa995e70dd..610a807e257c9da7317a73c9ec0852d04af3956d 100644
--- a/.liquibase/Data_alias/basic/2021.0.0/changelog.xml
+++ b/.liquibase/Data_alias/basic/2021.0.0/changelog.xml
@@ -12,4 +12,5 @@
     <include relativeToChangelogFile="true" file="SalesprojectConversion/changelog.xml"/>
     <include relativeToChangelogFile="true" file="Checklists/changelog.xml"/>
     <include relativeToChangelogFile="true" file="addDateNewToSalesproject.xml"/>
+    <include relativeToChangelogFile="true" file="EwsContactSync/create_ab_synccontact.xml"/>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/entity/EwsSyncAddContacts_entity/EwsSyncAddContacts_entity.aod b/entity/EwsSyncAddContacts_entity/EwsSyncAddContacts_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..332169d840fba95e4b9a7507ede82835e4fda87e
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/EwsSyncAddContacts_entity.aod
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.18" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.18">
+  <name>EwsSyncAddContacts_entity</name>
+  <title>add  contact to ewssync</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <titlePlural></titlePlural>
+  <recordContainer>datalessConfig</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityProvider>
+      <name>#PROVIDER_AGGREGATES</name>
+      <useAggregates v="true" />
+    </entityProvider>
+    <entityField>
+      <name>contactIds</name>
+      <state>EDITABLE</state>
+      <valueProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>countForSync</name>
+      <title>count</title>
+      <state>EDITABLE</state>
+      <valueProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>ContactFilter_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityParameter>
+      <name>ContactIds_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityActionField>
+      <name>syncContacts</name>
+      <title>add to sync</title>
+      <onActionProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:REFRESH</iconId>
+      <stateProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js</stateProcess>
+      <tooltip></tooltip>
+    </entityActionField>
+    <entityParameter>
+      <name>Mode_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityActionField>
+      <name>removeSyncContacts</name>
+      <title>remove from sync</title>
+      <onActionProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js</onActionProcess>
+      <isObjectAction v="true" />
+      <iconId>NEON:RECURRING_APPOINTMENT_MOVED</iconId>
+      <stateProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js</stateProcess>
+    </entityActionField>
+  </entityFields>
+  <recordContainers>
+    <datalessRecordContainer>
+      <name>datalessConfig</name>
+      <alias>Data_alias</alias>
+    </datalessRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..373f61e18faccaead7724225f920d46437148b77
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js
@@ -0,0 +1,10 @@
+import("system.result");
+import("system.vars");
+import("FilterViewAction_lib");
+
+var contactIds = JSON.parse(vars.get("$param.ContactIds_param"));
+var contactFilter = vars.get("$param.ContactFilter_param");
+
+contactIds = FilterViewActionUtils.getUidsBySelectionOrFilter("Person", contactIds, contactFilter);
+
+result.string(JSON.stringify(contactIds));
\ No newline at end of file
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4d01818ca409c8b5746f74b408c7b4456931abe8
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js
@@ -0,0 +1,10 @@
+import("system.vars");
+import("system.result");
+
+var res = "";
+if (vars.get("$field.contactIds"))
+{
+    res = JSON.parse(vars.getString("$field.contactIds")).length;
+}
+
+result.string(res);
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b0a2ce611876352836e323dcd13a38cc97f0a718
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("system.tools");
+import("EwsClientSync_lib");
+import("system.vars");
+
+var contactIds = JSON.parse(vars.get("$field.contactIds"));
+EwsClientSyncUtils.removeFromFavorite(contactIds, tools.getCurrentUser()[tools.NAME]);
+neon.closeImage(vars.get("$sys.currentimage"), true);
\ No newline at end of file
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ae3eef9a8407cd8e4edaee71f77b14a6c233d03
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js
@@ -0,0 +1,11 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+var mode = vars.get("$param.Mode_param");
+var ret = neon.COMPONENTSTATE_INVISIBLE; 
+
+if(mode == "REMOVE")
+    ret = neon.COMPONENTSTATE_EDITABLE;
+
+result.string(ret);
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..34578d4b676914a1e2aa7b8ec83e9277bd82aea1
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js
@@ -0,0 +1,9 @@
+import("system.neon");
+import("EwsClientSync_lib");
+import("system.vars");
+
+var toSncContacts = JSON.parse(vars.get("$field.contactIds"));
+
+//the handling of already Contacts in the Exchange is handeled by the function itself
+EwsClientSyncUtils.addToEwsFavorite(toSncContacts);
+neon.closeImage(vars.get("$sys.currentimage"), true);
\ No newline at end of file
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c10e581fee4f5e13e064bbbb4a8faa11c9470aa3
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js
@@ -0,0 +1,11 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+var mode = vars.get("$param.Mode_param");
+var ret = neon.COMPONENTSTATE_INVISIBLE; 
+
+if(mode == "ADD")
+    ret = neon.COMPONENTSTATE_EDITABLE;
+
+result.string(ret);
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index ac6d2e755a3059859fd1adb11bc724f80856ea89..b5d6a079e7970a57ac684887b51d6c2edda3b287 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -1333,6 +1333,20 @@
           <stateProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/cancelobservation/stateProcess.js</stateProcess>
           <titleProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/cancelobservation/titleProcess.js</titleProcess>
         </entityActionField>
+        <entityActionField>
+          <name>addToContactSync</name>
+          <title>add Contact to Sync</title>
+          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js</onActionProcess>
+          <iconId>NEON:RECURRING_APPOINTMENT</iconId>
+          <state>EDITABLE</state>
+        </entityActionField>
+        <entityActionField>
+          <name>removeFromContactSync</name>
+          <title>remove Contact from Sync</title>
+          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js</onActionProcess>
+          <iconId>NEON:RECURRING_APPOINTMENT_MOVED</iconId>
+          <state>AUTO</state>
+        </entityActionField>
       </children>
     </entityActionGroup>
     <entityActionGroup>
diff --git a/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ba5646790e532ee17f5d19d6fd57fbaece4a4d1
--- /dev/null
+++ b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js
@@ -0,0 +1,4 @@
+import("EwsClientSync_lib");
+import("system.vars");
+
+EwsClientSyncUtils.openEwsSyncAddContactView(vars.get("$sys.selection"), vars.get("$sys.filter"), "ADD");
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js b/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..1c6e00c85cdc5ec2423caf9c9f046f3fb7305168
--- /dev/null
+++ b/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js
@@ -0,0 +1,4 @@
+import("EwsClientSync_lib");
+import("system.vars");
+
+EwsClientSyncUtils.openEwsSyncAddContactView(vars.get("$sys.selection"), vars.get("$sys.filter"), "REMOVE");
\ No newline at end of file
diff --git a/neonContext/EwsSyncAddContacts/EwsSyncAddContacts.aod b/neonContext/EwsSyncAddContacts/EwsSyncAddContacts.aod
new file mode 100644
index 0000000000000000000000000000000000000000..9f9809ee4ab68bc9abc7fd254e23aba11fb0b2c3
--- /dev/null
+++ b/neonContext/EwsSyncAddContacts/EwsSyncAddContacts.aod
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1">
+  <name>EwsSyncAddContacts</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <editView>EwsSyncAddContactsEdit_view</editView>
+  <entity>EwsSyncAddContacts_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>c4d8f240-388e-4a1d-9455-e100a33c4819</name>
+      <view>EwsSyncAddContactsEdit_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonView/EwsSyncAddContactsEdit_view/EwsSyncAddContactsEdit_view.aod b/neonView/EwsSyncAddContactsEdit_view/EwsSyncAddContactsEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..74bbe50bf1c6529cfb43c1c895441220675f604e
--- /dev/null
+++ b/neonView/EwsSyncAddContactsEdit_view/EwsSyncAddContactsEdit_view.aod
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8">
+  <name>EwsSyncAddContactsEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <size>SMALL</size>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <scoreCardViewTemplate>
+      <name>ewsSyncScorecard</name>
+      <fields>
+        <entityFieldLink>
+          <name>bb922a4f-c170-4158-9241-8ba04ae92370</name>
+          <entityField>countForSync</entityField>
+        </entityFieldLink>
+      </fields>
+    </scoreCardViewTemplate>
+    <actionsViewTemplate>
+      <name>syncAction</name>
+      <actions>
+        <element>syncContacts</element>
+        <element>removeSyncContacts</element>
+      </actions>
+    </actionsViewTemplate>
+  </children>
+</neonView>
diff --git a/process/Communication_lib/process.js b/process/Communication_lib/process.js
index 055813cf362081fd583c1d8d2cd33fb0b4c0c4c4..f9e30868d8e9c816f642e8a383504605b2ba4990 100644
--- a/process/Communication_lib/process.js
+++ b/process/Communication_lib/process.js
@@ -31,11 +31,11 @@ CommUtil.getMediumIdsByCategory = function (pCategory)
     var keywordAttr = new KeywordAttribute($KeywordRegistry.communicationMedium(), "category");
     //TODO: use getRows() via JDito
     var mediumIds = newSelect("AB_KEYWORD_ENTRY.KEYID")
-                        .from("AB_KEYWORD_ATTRIBUTERELATION")
-                        .join("AB_KEYWORD_ENTRY", "AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
-                        .where("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", keywordAttr.id)
-                        .and("AB_KEYWORD_ATTRIBUTERELATION." + keywordAttr.dbField, pCategory)
-                        .arrayColumn();
+    .from("AB_KEYWORD_ATTRIBUTERELATION")
+    .join("AB_KEYWORD_ENTRY", "AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
+    .where("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", keywordAttr.id)
+    .and("AB_KEYWORD_ATTRIBUTERELATION." + keywordAttr.dbField, pCategory)
+    .arrayColumn();
     return mediumIds;
 };
 
@@ -73,19 +73,19 @@ CommUtil.setStandardForCategory = function(pAffectedRowId, pNewStandardCommId, p
     
     //set current standard comm-record as non-standard
     var cond = newWhere("ISSTANDARD = 1")
-                .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
-                .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
+    .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
+    .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
     
-     statements.push(["COMMUNICATION", cols, null, ["0"], cond.build()]);
+    statements.push(["COMMUNICATION", cols, null, ["0"], cond.build()]);
 
     //pNewStandardCommId can be an empty string if the standard has to only be removed
     if (pNewStandardCommId != "")
     {
         //set the new standard comm-record
         cond = newWhere("COMMUNICATION.COMMUNICATIONID", pNewStandardCommId)
-            //check communicationid, contactId and medium to prevent data-inconsistency when bad function params are passed by (e.g communicationid of a different category)
-            .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
-            .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
+        //check communicationid, contactId and medium to prevent data-inconsistency when bad function params are passed by (e.g communicationid of a different category)
+        .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
+        .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
             
         statements.push(["COMMUNICATION", cols, null, ["1"], cond.build()]);
     }
@@ -148,8 +148,8 @@ CommUtil.getStandardSubSqlForCategory = function(pCategory, pContactField)
         return "''";
     
     var selectStandardAddr = newSelect("max(COMMUNICATION.ADDR)")
-                                .from("COMMUNICATION")
-                                .where();
+    .from("COMMUNICATION")
+    .where();
                                 
     if (pContactField == undefined)
         selectStandardAddr.and("COMMUNICATION.CONTACT_ID = CONTACT.CONTACTID");
@@ -215,6 +215,41 @@ CommUtil.getStandardMail = function (pContactId)
     return db.cell(query);
 }
 
+/**
+ * Returns a sub sql-string (without brackets) for getting the address of a COMMUNICATION.<br>
+ * 
+ * @param {String} pMediumKey                                                <p>
+ *                                                                          Key of the keyword "COMMUNICATION.MEDIUM".<br>
+ *                                                                          (custom.category; e.g. "PHONE")<br>
+ * @param {String|Object} pContactField=CONTACT.CONTACTID (optional)        <p>
+ *                                                                          SQL-fieldname that shall be used for filtering the CONTACT_ID, <br>
+ *                                                                          this can be a string(fieldname) or an SqlBuilder object.<br>
+ * @return {String}                                                         <p>
+ *                                                                          Sub-sql.<br>
+ */
+CommUtil.getMediumAddrSubSqlByKey = function(pMediumKey, pContactField)
+{
+    var selectAddr = newSelect("max(COMMUNICATION.ADDR)")
+    .from("COMMUNICATION")
+    .where();
+                                
+    if (pContactField == undefined)
+        selectAddr.and("COMMUNICATION.CONTACT_ID = CONTACT.CONTACTID");
+    else if (typeof(pContactField) == "string")
+        selectAddr.and("COMMUNICATION.CONTACT_ID", pContactField);
+    else if (typeof(pContactField) == "object")
+    {
+        //you may want to sepcify a concrete value
+        selectAddr.and(pContactField);
+    }
+    else
+        return "''";
+    
+    selectAddr.andIfSet("COMMUNICATION.MEDIUM_ID", pMediumKey);
+    
+    return selectAddr.toString();    
+}
+
 /**
  * Provides static methods for validation of communication data.<br>
  * <b>Do not create an instance of this!</b>
diff --git a/process/EwsClientSync_lib/EwsClientSync_lib.aod b/process/EwsClientSync_lib/EwsClientSync_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..a53260007b9ecc486117433576e3c03b8723ff43
--- /dev/null
+++ b/process/EwsClientSync_lib/EwsClientSync_lib.aod
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.2">
+  <name>EwsClientSync_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/EwsClientSync_lib/process.js</process>
+  <alias>Data_alias</alias>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/EwsClientSync_lib/process.js b/process/EwsClientSync_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..2366e6b5af77b5ba73399379f2f2d2c14fe88c1b
--- /dev/null
+++ b/process/EwsClientSync_lib/process.js
@@ -0,0 +1,357 @@
+import("system.neon");
+import("Util_lib");
+import("system.translate");
+import("Communication_lib");
+import("Placeholder_lib");
+import("system.SQLTYPES");
+import("system.vars");
+import("system.datetime");
+import("system.util");
+import("system.tools");
+import("system.favorite");
+import("system.logging");
+import("Sql_lib");
+import("system.db");
+import("system.entities")
+
+/**
+ * Provides  methods for handling and interacting with the EWS Plugin
+ * 
+ * @class
+ */
+function EwsClientSyncUtils() {}
+
+/*
+ * Constant which contains the ewsSync Tag
+ * if the tag has to be changed a constant is the better way
+ */
+EwsClientSyncUtils.EWSSYNCTAG = function(){
+    return "ewssync";
+}
+
+/*
+ * prepares the synctable, insert new entries and mark for deletion 
+ * 
+ */
+EwsClientSyncUtils.prepareContactSyncTable = function(){
+    
+    var favoriteDataArray = EwsClientSyncUtils.getEwsFavorites();
+    var ewsSyncData = newSelect("SYNCCONTACTID, ASYS_FAVORITEID, USER_ID, CONTACT_ID")
+    .from("ab_synccontact")
+    .table();
+    
+    var dataIndex = {
+        index: new Map(),
+        add: function (pA, pB)
+        {
+            var idxMap = this.index;
+            if (!idxMap.has(pA))
+                idxMap.set(pA, new Set());
+            idxMap.get(pA).add(pB);
+        },
+        has: function (pA, pB)
+        {
+            return this.index.has(pA) && this.index.get(pA).has(pB);
+        }
+    };
+    
+    //preparing the value for inserting in ewsSync Table
+    var toInsertFavs = []; 
+    for (let i = 0, l = ewsSyncData.length; i < l; i++) 
+    {
+        //3 - contactID     2 userID
+        dataIndex.add(ewsSyncData[i][3], ewsSyncData[i][2]);
+    }
+    ​
+    //we want to insert those which aren't in the sync table yet but which are tagged for sync
+    toInsertFavs = favoriteDataArray.filter(function (row) {
+        return !dataIndex.has(row[1], row[2]);
+    });
+    
+    
+    //preparing values for updating entrys in the ewsSync Table
+    dataIndex.index.clear();
+    
+    var toUpdate = [];
+    
+    for (let i = 0, l = favoriteDataArray.length; i < l; i++) 
+    {
+        dataIndex.add(favoriteDataArray[i][1], favoriteDataArray[i][2]);
+    }
+    
+    ​//dataset which are in the synctable but aren't tagged for sync (favorites ewssync) has to be updated for deletion
+    toUpdate = ewsSyncData.filter(function (row){
+        ​
+        return !dataIndex.has(row[3], row[2]);
+    }
+    ​);
+    
+    
+    let statements = [];
+    let toInsert = [];
+    let cols = ["SYNCCONTACTID", "ASYS_FAVORITEID", "CONTACT_ID", "USER_ID"];
+    let vals = [];
+    let table = "AB_SYNCCONTACT";
+    let updStatements = [];
+    
+    for(let i = 0; i < toInsertFavs.length; i++)
+    {
+        vals = [];
+        vals = [util.getNewUUID(), toInsertFavs[i][0], toInsertFavs[i][1], toInsertFavs[i][2]]
+        
+        statements.push([table, cols, null, vals]);
+    }
+    for(let i = 0; i < toUpdate.length; i++)
+    {
+        updStatements.push([table, ["DATE_DEL"], null, [vars.get("$sys.date")], "ASYS_FAVORITEID = '" + toUpdate[i][1] + "'"  ]);
+    }
+    
+    try{
+        let count = db.inserts(statements, "Data_alias");
+        let updCount = db.updates(updStatements, "Data_alias");
+    }
+    catch(exc){
+        logging.log(exc)
+    }
+}
+
+/*
+ *  get the contact which are marked with the ewssync favorite Tag
+ *   
+ *  @return [Array] favorite Data [[]]
+ */
+EwsClientSyncUtils.getEwsFavorites = function(){
+    
+    
+    //get Favorites which are tagged with the Sync Tag
+    //    var conf = favorite.createGetFavoritesConfig(); 
+    //    conf.setFavoriteGroupTitle(EwsClientSyncUtils.EWSSYNCTAG()); 
+    //    conf.setObjectType("Person");
+    //
+    //    var favoriteData = favorite.getFavorites(conf);
+    //    var favoriteDataArray = [];
+    //    
+    //    for (var temp in favoriteData)
+    //    {
+    //        let favId = favoriteData[temp]["id"];
+    //        let rowId = favoriteData[temp]["rowid"]; 
+    //        let userID = favoriteData[temp]["group"]["groupuser"]; 
+    //        
+    //        favoriteDataArray.push([favId, rowId, userID]);
+    //    }
+    
+    
+    //in the current version it isn't possible to call the favorite API within a Serverprocess this will be implemented in the next RC 
+    
+    var favoriteDataArray = new SqlBuilder("_____SYSTEMALIAS")
+    .selectDistinct("ASYS_RECORD.ID, ASYS_RECORD.ROW_ID, ASYS_RECORDGROUP.USER_ID")
+    .from("ASYS_RECORD")
+    .join("ASYS_RECORDGROUP", "ASYS_RECORDGROUP.ID = ASYS_RECORD.RECORDGROUP_ID")
+    .where("ASYS_RECORD.OBJECT_TYPE", "Person")
+    .and("ASYS_RECORDGROUP.TITLE", EwsClientSyncUtils.EWSSYNCTAG(), "LOWER(#) = ?")
+    .groupBy("ASYS_RECORDGROUP.USER_ID, ASYS_RECORD.ROW_ID, ASYS_RECORD.ID")
+    .table();
+    
+    return favoriteDataArray;
+}
+
+/*
+ * sets the editdate for the entrys in the synctable, in reason to get synced with exchange
+ *
+ * @param {String} pTableName
+ * @param {String} pDataSetID req 
+ * @param {String} pDate req
+ *
+ * @return {void}
+
+ */
+EwsClientSyncUtils.setContactToSync = function(pTableName, pDataSetID, pDate){
+    
+    var affectedTables = ["ORGANISATION" , "PERSON", "CONTACT", "ADDRESS", "COMMUNICATION"];
+    var affectedIDs = [];
+    
+    if (affectedTables.indexOf(pTableName) != -1)
+    {
+        switch(pTableName)
+        {
+            case "ORGANISATION":
+                affectedIDs = newSelect("CONTACT.CONTACTID").from("CONTACT").where("CONTACT.ORGANISATION_ID", pDataSetID).arrayColumn();
+                break;
+            case "PERSON":
+                affectedIDs = newSelect("CONTACT.CONTACTID").from("CONTACT").where("CONTACT.PERSON_ID", pDataSetID).arrayColumn();
+                break;
+            case "CONTACT":
+                affectedIDs = [pDataSetID];
+                break;
+            case "ADDRESS":
+                affectedIDs = newSelect("ADDRESS.CONTACT_ID").from("ADDRESS")
+                .where("ADDRESS.ADDRESSID", pDataSetID)
+                .union(newSelect("CONTACT.CONTACT_ID").from("CONTACT").where("CONTACT.ADDRESS_ID", pDataSetID)).arrayColumn();
+                break;
+            case "COMMUNICATION":
+                affectedIDs = newSelect("COMMUNICATION.CONTACT_ID").from("COMMUNICATION").where("COMMUNICATION.COMMUNICATIONID", pDataSetID).arrayColumn();
+                break;
+        }
+        
+        if (affectedIDs.length > 0)
+        {
+            var upd = db.updateData("AB_SYNCCONTACT", ["DATE_EDIT"], null, [pDate], 
+                "EXCHANGEID is not null and CONTACT_ID in ('" + affectedIDs.join("','") + "')");        
+        }
+    }
+}
+
+
+/*
+ * prepare Placholder for Exchange contacts
+ * 
+ * @param  {String} pUserId
+ */
+EwsClientSyncUtils.getPlaceholders = function(pUserId){
+    var ewsPlaceholders = [];
+    
+    //EWS Sync Placeholder
+    //See EWS API Doc for other placeholder
+    //new Placeholder that has to be synced probably has also to be added in addDataToValueObjects() in the serverprocess
+    _addSqlPart("CONTACTID", "CONTACT.CONTACTID"); 
+    _addSqlPart("EXCHANGEID", "select EXCHANGEID from ab_synccontact where Ab_synccontact.contact_id = contact.contactid and user_id = '"+ pUserId +"'", null, null)
+    
+    _addSqlPart("Givenname", "PERSON.FIRSTNAME");
+    _addSqlPart("Surname", "PERSON.LASTNAME");
+    _addSqlPart("Department", "CONTACT.DEPARTMENT");
+    _addSqlPart("JobTitle", "CONTACT.CONTACTROLE");
+    _addSqlPart("CompanyName", "ORGANISATION.NAME");
+    
+    
+    _addAddressFormat("Business_street", "{street} {buildingno}");
+    _addAddressFormat("Business_postalcode", "{zip}");
+    _addAddressFormat("Business_city", "{city}");
+    _addAddressFormat("Business_state", "{district}");
+    _addAddressFormat("Business_countryorregion", "{country}");
+    
+    _addSqlPart("EmailAddress1", CommUtil.getStandardSubSqlMail()); 
+    
+    _addSqlPart("BusinessPhone", CommUtil.getStandardSubSqlPhone()); 
+    _addSqlPart("BusinessHomepage", CommUtil.getMediumAddrSubSqlByKey("COMMINTERNET"));
+    
+    _addSqlPart("OtherFax", CommUtil.getMediumAddrSubSqlByKey("COMMFAX")); 
+    _addSqlPart("MobilePhone", CommUtil.getMediumAddrSubSqlByKey("COMMMOBIL")); 
+    _addSqlPart("FileAsMapping","case when PERSON_ID is not null then 'SurnameCommaGivenName' else 'Company' end" , null, null);
+    
+    
+    //    _addSqlPart("HomePhone", "''"); 
+    //    _addSqlPart("HomeFax", "''");
+    //    _addSqlPart("EmailAddress2", "''");
+    
+    
+    
+    return ewsPlaceholders;
+    
+    function _addSqlPart (pName, pSqlPart, pTarget, pTitle)
+    {
+        ewsPlaceholders.push(new Placeholder(pName, Placeholder.types.SQLPART, "(" + pSqlPart + ")", pTarget, pTitle));
+    }
+    /**
+     * add an address format placeholder to placeholders
+     */
+    function _addAddressFormat (pName, pFormat, pTarget, pTitle)
+    {
+        ewsPlaceholders.push(new Placeholder(pName, Placeholder.types.ADDRESSFORMAT, pFormat, pTarget, pTitle));
+    }
+}
+
+/*
+ * removes Person favorites with the EWS Tag 
+ * 
+ * @param {Array} pToDelete contains contact_ids for which the favorite should be removed
+ * @param {String} pUserId - User for which the favorites should be removed 
+ * 
+ * @return {Boolean} true if successfull
+ * 
+ */
+EwsClientSyncUtils.removeFromFavorite = function(pToDelete, pUserId ){
+    
+    //maybe in a future version there will be a way to remove favorites on a better way
+ 
+    //all ews related Favorites for the user
+    var config = favorite.createGetFavoritesConfig()
+    .setFavoriteGroupTitle(EwsClientSyncUtils.EWSSYNCTAG())
+    .setGroupType(favorite.FAVORITE_GROUP).setObjectType("Person")
+    .setUserId(pUserId); 
+    
+    var ewsFavorite = favorite.getFavorites(config);
+    var favsToDelete = [];
+    
+    var dataIndex = {
+        index: new Map(),
+        add: function (pA)
+        {
+            var idxMap = this.index;
+            if (!idxMap.has(pA))
+                idxMap.set(pA, new Set());
+        },
+        has: function (pA)
+        {
+            return this.index.has(pA);
+        }
+    };
+
+    for each(let row in pToDelete)
+    {
+        dataIndex.add(row)
+    }
+    
+    // delete those which are in the selection and are also in ewsFavorite 
+    for each (let row in  ewsFavorite)
+    {
+        if(dataIndex.has(row["rowid"]))
+            favsToDelete.push(row["id"]);
+    }
+
+    var delConfig = favorite.createRemoveMultipleByIdConfig().setFavoriteRecordIds(favsToDelete);
+    
+    return favorite.remove(delConfig);
+}
+
+/*
+ * Add contacts to favorites as ewssync group
+ * 
+ * @param {Array} pToInsert         Array with contactIds which should be added to the sync
+ */
+EwsClientSyncUtils.addToEwsFavorite = function(pToInsert){
+    var userID = tools.getCurrentUser()[tools.NAME]
+
+    var config = favorite.createAddFavoriteConfig(); 
+    config.setFavoriteGroupTitle(EwsClientSyncUtils.EWSSYNCTAG()); 
+    config.setObjectType("Person");
+    config.setUserId(userID); 
+    config.setGroupType(favorite.FAVORITE_GROUP) 
+    
+    for(let i = 0, l = pToInsert.length; i < l; i++){
+        config.setRowId(pToInsert[i]);
+        favorite.add(config);
+    }
+}
+
+/**
+ * Opens a context to add or remove contacts from the ewssync<br>
+ * 
+ * @param {String[]} pContactIds        Contacts that should be added.<br>
+ * @param {String|Object} pFilter       the filter for the contacts that should be used if no contact is selected
+ * @param {String} pMode                the mode which should be used ("ADD" or "REMOVE") default ADD
+ */
+EwsClientSyncUtils.openEwsSyncAddContactView = function(pContactIds, pFilter, pMode)
+{
+    if (!Utils.isString(pContactIds))
+        pContactIds = JSON.stringify(pContactIds);
+    if (!Utils.isString(pFilter))
+        pFilter = JSON.stringify(pFilter);
+    
+    var params = {
+        "ContactIds_param": pContactIds,
+        "ContactFilter_param": pFilter, 
+        "Mode_param": pMode
+    }
+    neon.openContext("EwsSyncAddContacts", "EwsSyncAddContactsEdit_view", null, neon.OPERATINGSTATE_VIEW, params);
+}
+    
\ No newline at end of file
diff --git a/process/EwsClient_lib/process.js b/process/EwsClient_lib/process.js
index 2de3addde44d76ac3ad80c4f264e837fc6d90e45..51dd088565b42911b3354abcf3b823cf6c1152f1 100644
--- a/process/EwsClient_lib/process.js
+++ b/process/EwsClient_lib/process.js
@@ -62,7 +62,10 @@ $EwsClientTaskDescriptions.GET_CONTACTS_BY_FOLDERS =            function(){retur
 $EwsClientTaskDescriptions.GET_CONTACTSDEFAULTFOLDER =          function(){return "GET_CONTACTSDEFAULTFOLDER"};
 $EwsClientTaskDescriptions.GET_CONTACTFOLDERS =                 function(){return "GET_CONTACTFOLDERS"};
 $EwsClientTaskDescriptions.UPDATE_CONTACT =                     function(){return "UPDATE_CONTACT"};
-
+$EwsClientTaskDescriptions.INSERT_CONTACT_LIST_TO_FOLDER =      function(){return "INSERT_CONTACT_LIST_TO_FOLDER"}; 
+$EwsClientTaskDescriptions.INSERT_CONTACT_LIST =                function(){return "INSERT_CONTACT_LIST"}; 
+$EwsClientTaskDescriptions.UPDATE_CONTACT_LIST =                function(){return "UPDATE_CONTACT_LIST"};
+$EwsClientTaskDescriptions.DELETE_CONTACT_LIST_BY_IDS =         function(){return "DELETE_CONTACT_LIST_BY_IDS"};
 function $EwsClientImpersonationModes(){}
 /**
  * Impersonation mode NONE should be set if no impersonation user is used and every user is authenticated per user-data
@@ -400,4 +403,394 @@ EwsClientCalendarPermissionUtils._getCalendarPermissionFromResult = function (pP
             + "there exists a write but no read permission");
 
     return retVal;
+}
+
+
+
+/*
+ * provides static methods for the use of the exchange Contact Sync
+ * @class
+ */
+function EwsSyncContactUtils(){}
+
+EwsSyncContactUtils.getEwsSyncTag = function(){
+    return "ewssync";
+}
+
+
+/*
+ * returns the contact Folder for the passed mailbox
+ * requires the EWSClientPlugin
+ * 
+ * @param {String} pAliasName name of the exchange alias 
+ * @param {String} pMailbox mailbox of which the folder should be read
+ * 
+ * @return {Array} array with maps [["id"], ["name"]]
+ */
+EwsSyncContactUtils.getContactFolders = function(pAliasName, pMailbox){
+    
+    let taskDescription = $EwsClientTaskDescriptions.GET_CONTACTFOLDERS();
+    
+    let task = <mailbox>{
+    pMailbox
+    }</mailbox>;
+    
+    let pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    let xmlOutput = EwsClientUtils.callPlugin(pluginInput);
+    let retVal = [];
+    
+    for each (folder in xmlOutput.folders.folder)
+    {
+        let map = {};
+        map["id"] = folder.id;
+        map["name"] = folder.name;
+        retVal.push(map);
+    }
+    return retVal;
+}
+
+
+EwsSyncContactUtils.updateContacts = function(pAliasName, pMailbox, pObjects, doDebug ){
+    let taskDescription = $EwsClientTaskDescriptions.UPDATE_CONTACT_LIST();
+    
+    let tasks = <mailbox>{
+    pMailbox
+    }
+    </mailbox>;
+  
+    let contactsXml = <contacts/>
+     
+    for each(let [pUniqueId, pData, pAddresses] in pObjects)
+    {
+        if(pUniqueId)
+            contactsXml.appendChild(EwsSyncContactXMLUtils.mapContactToXML(pData, pAddresses, pUniqueId, true));
+    } 
+    tasks += contactsXml;
+    
+    let pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, tasks, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    
+    let xmlOutput = EwsClientUtils.callPlugin(pluginInput); 
+
+    return EwsSyncContactUtils.proceedPluginXmlOutput(xmlOutput, 2, doDebug); 
+}
+
+
+/**
+ * Adds a contact in a specific folder
+ * requires EWSClientPlugin 
+ * 
+ * @param {String} pAliasName name of the Alias which contains connectiondata 
+ * @param {String} pMailbox owner of the contact
+ * @param {String} pUniqueId defines folder
+ * @param {[[dataArray, adressArray]]} pObjects
+ * @param {boolean} doDebug
+ * 
+ * @return {String} new unique ID of the contact (ExchangeID)
+ * 
+ * pData array with maps with following structure:
+ * ["key"]
+ * ["value"]
+ * 
+ * pAddresses array with following Maps
+ * ["addressKey"]
+ * ["value"]    -> array with Maps with following structure ["key"]
+ *                                                          ["value]
+ *                                          
+ * existing Key for a exchange Contact:
+ * title, givenname, middlename, surname
+ * jobtitle, officelocation, department, companyname, manager, assistentname, businesshomepage
+ * fileasmapping
+ * messagebody, categories
+ * id, changekey, lastmodifiedtime, datetimecreated (read only)
+ *
+ * - possible phone numbers:
+ * AssistantPhone, BusinessFax, BusinessPhone, BusinessPhone2, Callback, CarPhone, CompanyMainPhone, HomeFax, HomePhone,
+ * HomePhone2, Isdn, MobilePhone, OtherFax, OtherTelephone, Pager, PrimaryPhone, RadioPhone, Telex, TtyTddPhone
+ *
+ * - possible Mailing:
+ * EmailAddress1, EmailAddress2, EmailAddress3
+ *
+ * - possible Instant Messaging:
+ * ImAddress1, ImAddress2, ImAddress3
+ *
+ * - possible Adressen:
+ * Business, Home, Other
+ * - possible values of a adress:
+ * street, postalcode, city, state, countryorregion
+ *
+ * postaladdressindex
+ * - possible value for "postaladdressindex"
+ * None, Business, Home, Other
+ */
+EwsSyncContactUtils.insertContactsToFolder = function(pAliasName, pMailbox, pUniqueId, pObjects, doDebug)
+{
+
+    let taskDescription = $EwsClientTaskDescriptions.INSERT_CONTACT_LIST_TO_FOLDER();
+    
+    let task = <uniqueId>{
+    pUniqueId
+    }</uniqueId>
+
+    task += <mailbox>{
+    pMailbox
+    }</mailbox>
+     
+    let contactsXml = <contacts/>
+     
+    for each(let [pData, pAddresses] in pObjects)
+    {
+        contactsXml.appendChild(EwsSyncContactXMLUtils.mapContactToXML(pData, pAddresses));
+    }
+    task += contactsXml;
+    
+    let pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    let xmlOutput = EwsClientUtils.callPlugin(pluginInput); 
+    
+    return EwsSyncContactUtils.proceedPluginXmlOutput(xmlOutput, 1, doDebug); 
+}
+
+/**
+ * deletes unique Contacts out of EWS
+ * Voraussetzung ist EWSClientPlugin 
+ * 
+ * @param {String} pAliasName Name des Alias aus dem die Verbindungsdaten ausgelesen werden können
+ * @param {String} pUniqueIds Definiert Die Kontakte die 
+ * @param {String} pMailBox opt falls angegen wird der ImpersonatedUser verwendet
+ * @param {boolean} doDebug
+ * 
+ * @return {String[]} Array with results for Structure see Example
+ * @example
+ * Structure of the result from plugin   
+ * [
+ *  [exchangeIdsWithNoError, n],
+ *  [[id, "Error", "errorMsg", "Type"], [idn, "Error", "errorMsg", "Type"] ]    
+ * ]
+ */
+EwsSyncContactUtils.deleteContactByID = function(pAliasName, pUniqueIds, pMailBox, doDebug)
+{
+    let taskDescription = $EwsClientTaskDescriptions.DELETE_CONTACT_LIST_BY_IDS();
+    
+    let task = <uniqueIds/>;
+    
+    for each(let pUniqueId in pUniqueIds)
+    {
+        if(pUniqueId)
+            task.appendChild(<uniqueId>{
+                pUniqueId
+                }</uniqueId>)
+    }
+    
+    let pluginInput;
+    
+    if ( pMailBox == undefined )
+    {
+        pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.NONE(), pAliasName);
+    }
+    else
+    {
+        task += <mailbox>{
+        pMailBox
+        }</mailbox>;
+        pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    }
+
+    var xmlOutput = EwsClientUtils.callPlugin(pluginInput);
+    
+    return EwsSyncContactUtils.proceedPluginXmlOutput(xmlOutput, 3, doDebug); 
+}
+
+/*
+ * proceeds the plugin outputXMl  and returns contactId and ExchangeID,
+ *
+ *  @param {XML} pXmlOutput output of the plugin call
+ *  @param {int} pMode controlls proceeding 1 - insert, 2 - update, 3 - delete
+ *  @param {boolean} doDebug 
+ *  
+ *  @return {Array} 2d Array with contactIds, unigueID(ExchangeID) and ErrorArray
+ *
+ */
+EwsSyncContactUtils.proceedPluginXmlOutput = function(pXmlOutput, pMode, doDebug){
+    
+    var contactRes = [];
+    var failedIds = [];
+    var status, uniqueId, resultMessage, resultCode;
+    
+    //insert and Update
+    if(pMode < 3)
+    {
+        //for every contactResult in the contactResults list
+        for each( contactResult in pXmlOutput.contactResults.contactResult )
+        {
+            var keyValues = contactResult.contact.keyValues.keyValue;
+            var contactid = "";
+        
+            for each( keyValue in keyValues )
+            {
+                if(keyValue.key.toString() == "CONTACTID")//we only need the contactid value
+                {
+                    contactid = keyValue.value.toString();
+                    break;
+                }
+            }
+        
+            status = contactResult.result.toString();
+            resultMessage = contactResult.resultMessage.toString();
+            
+            //during update the xml structure is slightly different
+            uniqueId = (Number(pMode) == 2) ? contactResult.contact.@uniqueId.toString() : contactResult.uniqueId.toString();
+        
+            if(status == "Success" && contactid != "" && uniqueId != "")//only if the action was successfull
+            {
+                if(pMode == 2)//update
+                    contactRes.push(uniqueId);
+                else
+                    contactRes.push([contactid, uniqueId]);//push for update/insert in AB_SYNCCONTACT
+            }
+            else
+            {
+                resultCode = contactResult.resultCode.toString();
+                failedIds.push([contactid, status, resultMessage, resultCode, contactResult.contact.toString()])
+            }
+        }
+        if(doDebug)  logging.log("failedIds: " + failedIds.toSource());
+    }//pMode < 3
+    else 
+    //the delete result xml differs from insert and update  
+    if (pMode == 3)
+    {
+        for each( contactResult in pXmlOutput.resultBundles.resultBundle )
+        {
+            //keyvalues
+            status = contactResult.result.toString();
+            uniqueId = contactResult.uniqueId.toString();
+            
+            if(status == "Success" && uniqueId != "")
+            {
+                contactRes.push(uniqueId);//push for deleting in AB_SYNCCONTACT
+            }
+            else
+            {
+                //get Keyvalues
+                resultMessage = contactResult.resultMessage.toString();
+                resultCode = contactResult.resultCode.toString();
+                
+                failedIds.push([uniqueId, status, resultMessage, resultCode]);
+            }
+        }
+    }
+
+    return [contactRes, failedIds];
+}
+
+/*
+ *Class for handling ews XML
+ *
+ * @class
+ */
+function EwsSyncContactXMLUtils(){}
+
+
+EwsSyncContactXMLUtils.mapContactToXML = function( pData, pAddresses, pExchangeId, isUpdate)
+{
+    var content = <contact>
+                      <keyValues/>
+                      <physicalAddresses/>
+                  </contact>;
+              
+    if(isUpdate)
+    {
+        content = <contact uniqueId={
+        pExchangeId
+        }>
+        <keyValues/>
+        <physicalAddresses/>
+        </contact>;
+    }
+    
+    //add contactData e.g. Name,Lastname, department etc.
+    for each (let map in pData)
+    {  
+        let keyXml = <keyValue/>
+        let mapKey = map["key"]; 
+        let mapVal = map["value"]; 
+
+        keyXml.appendChild(<key>{
+            mapKey
+            }</key>);
+        keyXml.appendChild(<value>{
+            mapVal
+            }</value>);
+        
+        //append contactdata to parent xml
+        content.keyValues.appendChild(keyXml);
+    }
+   
+    //TODO: refactor when for of Loop is available
+    for each( let outerMap in pAddresses )
+    {
+        var adressXml = <physicalAddresse/>
+        var pAdressKey = outerMap["addressKey"];
+    
+        adressXml.appendChild(<addressKey>{
+            pAdressKey
+            }</addressKey>)
+        
+        var list = outerMap["value"];
+       
+        adressXml.appendChild(<keyValues/>)
+        
+            for each( let innerMap in list )
+            {
+                let keyXml = <keyValue/>
+                let innerMapKey =  innerMap["key"];
+                let innerMapValue = innerMap["value"];
+                
+                    
+                keyXml.appendChild(<key>{
+                    innerMapKey
+                    }</key>);
+                keyXml.appendChild(<value>{
+                    innerMapValue
+                    }</value>);
+                
+                adressXml.keyValues.appendChild(keyXml);
+            }
+            //append adressxml to parent
+            content.physicalAddresses.appendChild(adressXml);
+        }
+    return content;
+    }
+    
+EwsSyncContactXMLUtils.mapContactFromXML = function( pContactXML )
+{
+    let retVal = {};
+    let shallow = [];
+
+    for each (keyValue in pContactXML.keyValues.keyValue)
+    {   
+        let map = {};
+        map["key"] = keyValue.key;
+        map["value"] = keyValue.value;
+        shallow.push(map);
+    }
+    retVal["shallow"] = shallow;
+    
+    let addresses = [];
+    for each (physicalAddresse in pContactXML.physicalAddresses.physicalAddresse)
+    {
+
+        let outerMap = {};
+        outerMap["addressKey"] = physicalAddresse.addressKey;
+        let list = [];
+        for each(keyValue in physicalAddresse.keyValues)
+        {
+            let innerMap = {};
+            innerMap["key"] = keyValue.key;
+            outerMap["value"] = keyValue.value;
+            list.push(innerMap);
+        }
+        outerMap["value"] = list;
+    }
+    retVal["addresses"] = addresses;
+    return retVal;
 }
\ No newline at end of file
diff --git a/process/ewsSyncContacts_serverProcess/ewsSyncContacts_serverProcess.aod b/process/ewsSyncContacts_serverProcess/ewsSyncContacts_serverProcess.aod
new file mode 100644
index 0000000000000000000000000000000000000000..fbbe02fc2fff34c845acc1f03e22f34836da4ab6
--- /dev/null
+++ b/process/ewsSyncContacts_serverProcess/ewsSyncContacts_serverProcess.aod
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.2">
+  <name>ewsSyncContacts_serverProcess</name>
+  <title>Sync Exchange Contacts</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/ewsSyncContacts_serverProcess/process.js</process>
+  <alias>Data_alias</alias>
+  <variants>
+    <element>EXECUTABLE</element>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/ewsSyncContacts_serverProcess/process.js b/process/ewsSyncContacts_serverProcess/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..fd420916d9172146ce5f60943ae629bf8578cd82
--- /dev/null
+++ b/process/ewsSyncContacts_serverProcess/process.js
@@ -0,0 +1,588 @@
+import("Util_lib");
+import("system.project");
+import("system.favorite");
+import("system.db");
+import("system.result");
+import("EwsClient_lib");
+import("system.text");
+import("Address_lib");
+import("Communication_lib");
+import("system.vars");
+import("Sql_lib");
+import("system.tools");
+import("system.logging");
+import("EwsClientSync_lib");
+
+//inserting new Data in the asys_synccontact table and deleting those which aren't anymore in the favorite context
+EwsClientSyncUtils.prepareContactSyncTable();
+
+//start Sync with Exchange
+var msg = runSync();
+
+if(msg.length){
+    result.string(msg.join("\n"));
+}
+
+function runSync(){
+    var doDebug = false;
+    var retMsg = [];
+    
+    var syncUser = newSelect("distinct USER_ID").from("AB_SYNCCONTACT").arrayColumn();
+    
+    for (var i= 0 ; i < syncUser.length; i++)
+    {
+        var user = tools.getUserByAttribute(tools.NAME, [syncUser[i]], tools.PROFILE_DEFAULT);
+        if (user)
+        {
+            var mailBox = user[tools.PARAMS][tools.EXCHANGE_EMAIL];
+            
+            if(!mailBox)//use the mail of the user as backup exchangeMail adress
+                mailBox = user[tools.PARAMS][tools.EMAIL];
+            
+            
+            var exAlias = user[tools.PARAMS][tools.CALENDAR_ALIAS]; 
+            
+            if (!exAlias)
+                exAlias = project.getInstanceConfigValue("calendarAlias", null);
+            
+            var login = user[tools.TITLE]; 
+            var lastRunDate = user[tools.PARAMS]["lastEwsSyncContact"];
+            var runDate = vars.get("$sys.date");
+            user[tools.PARAMS]["lastEwsSyncContact"] = runDate;
+            
+            if (mailBox != "" && exAlias != "")
+            {                       
+                if(doDebug) logging.log("ContactSync for User: " + login + " started")         
+  
+                let delContacts = EWSdeleteContactsForUser(syncUser[i], mailBox, exAlias, login, doDebug); 
+                let updateContacts = EWSupdateContactsForUser(syncUser[i], mailBox, exAlias, lastRunDate, login, doDebug);
+                let insertContacts = EWSinsertContactsForUser(syncUser[i], mailBox, exAlias, runDate, login, doDebug);
+                    
+                if(delContacts.length)
+                    retMsg.push(delContacts);
+                if(updateContacts.length)    
+                    retMsg.push(updateContacts);
+                if(insertContacts.length)
+                    retMsg.push(insertContacts);
+
+                tools.updateUser(user);
+ 
+                if(doDebug) logging.log("ContactSync for User: " + login + " completed")                          
+            }
+            else
+            {
+                retMsg.push(["No exchange configuration exists for user " + login]);
+            }
+        }
+    }    
+    if(doDebug) logging.log("EWSContactSync completed");
+    
+    return retMsg;
+}
+
+/**************************************************************************************************/
+
+/*
+ * deletes the Synced Contacts for the passed User
+ * 
+ * @param {String} pUserID ID of the User for which Contact should be removed from sync
+ * @param {String} pMailBox Exchange Mail
+ * @param {String} pAlias name of the Exchange Alias
+ * @param {String} pUser Login of the User
+ * @param {boolean} doDebug 
+ *
+*/
+function EWSdeleteContactsForUser(pUserID, pMailBox, pAlias, pUser, doDebug)
+{
+    //delete all Entrys with a DATE_DEL tag, those were removed between the last import and yet
+    var cond = newWhere("AB_SYNCCONTACT.DATE_DEL is not null").and("AB_SYNCCONTACT.USER_ID", pUserID);
+    
+    var delContacts = newSelect("AB_SYNCCONTACT.EXCHANGEID")
+    .from("AB_SYNCCONTACT")
+    .where(cond)
+    .and("AB_SYNCCONTACT.EXCHANGEID is not null")
+    .arrayColumn();
+    
+    var deletions = Utils.clone(delContacts);
+    
+    var exchangeids = [];
+    while(deletions.length > 0)
+    {
+        let deletionPart = deletions.splice(0, 200);
+        try{
+            exchangeids = exchangeids.concat(EwsSyncContactUtils.deleteContactByID(pAlias, deletionPart, pMailBox, doDebug));
+        }
+        catch(ex)
+        {
+            let errMsg = "Error while calling the plugin: " + logging.toLogString(ex.rhinoException != undefined ? ex.rhinoException : ex, true) + "\r\n"; 
+            logging.log(errMsg);
+            return [errMsg];
+        }                
+    }
+      
+    var errorItems = []; 
+    var notFoundItems = []; 
+    var deletedItems = [];
+    
+    if(exchangeids.length > 0)
+    {
+        //no errors during deletion in Exchange
+        while (exchangeids[0].length > 0) 
+        {
+            let exchangeidsPart = exchangeids[0].splice(0, 30);//max limit 30
+                
+            cond.and("AB_SYNCCONTACT.EXCHANGEID", exchangeidsPart, SqlBuilder.IN()).deleteData();
+            deletedItems = deletedItems.concat(exchangeidsPart);
+        }
+        
+        //exchange Entrys with errors for deleting
+        while (exchangeids[1].length > 0) 
+        {
+            if(doDebug) logging.log("Exchange Entrys with Errors: " + exchangeids[1].length);
+            var deletes = [];
+        
+            let exchangeidsPart = exchangeids[1].splice(0, 30);//max limit 30
+                
+            for (let i = 0; i < exchangeidsPart.length; i++) 
+            {
+                if(exchangeidsPart[i][3] == "ErrorItemNotFound")
+                {
+                    deletes.push(exchangeidsPart[i][0]);
+                    notFoundItems.push(exchangeidsPart[i][0] , pUserID);
+                }
+                else
+                {
+                    errorItems.push(exchangeidsPart[i][0] , pUserID);
+                }
+            }
+            
+            if(deletes.length > 0)
+            {
+                let affectedRows = cond.and("AB_SYNCCONTACT.EXCHANGEID", deletes, SqlBuilder.IN()).deleteData();
+                if(doDebug) logging.log("Anzahl der gelöschten Einträge: " + affectedRows);
+                deletedItems = deletedItems.concat(deletes);
+            }
+            
+            //clearing the where condition and preset it to it's origin condition
+            cond.clearWhere();
+            cond.where("AB_SYNCCONTACT.DATE_DEL is not null").and("AB_SYNCCONTACT.USER_ID", pUserID);
+        }
+        
+        if(doDebug && notFoundItems.length > 0)
+            logging.log("EWSSYnc not found items: " + notFoundItems.toSource());
+        
+        if(errorItems.length > 0)
+            logging.log("EWSSYnc error items: " + errorItems.toSource());
+        
+        if(doDebug && deletedItems.length > 0)
+            logging.log("EWSSYnc deleted items: " + deletedItems.toSource());
+    }
+    return errorItems;
+}
+
+
+
+/*
+ * updates the Synced Contacts for the passed User
+ * 
+ * @param {String} pUserID ID of the User for which Contact should be updated
+ * @param {String} pMailBox Exchange Mail
+ * @param {String} pAlias name of the Exchange Alias
+ * @param {String} pRunDate lastRunDate of the sync
+ * @param {String} pUser Login of the User
+ * @param {boolean} doDebug 
+ *
+*/
+function EWSupdateContactsForUser(pUserID, pMailBox, pAlias, pRunDate, pUser, doDebug) 
+{   
+    var runDate = (!pRunDate) ? 0 : pRunDate;
+       
+    //get Contacts for update 
+    var cond = newWhere("AB_SYNCCONTACT.EXCHANGEID is not null")
+    .and("AB_SYNCCONTACT.USER_ID", pUserID)
+    .and("AB_SYNCCONTACT.DATE_EDIT", runDate, SqlBuilder.GREATER());
+    
+    var contactsData = newSelect("AB_SYNCCONTACT.CONTACT_ID")
+    .from("AB_SYNCCONTACT")
+    .where(cond)
+    .arrayColumn();
+    
+    var retMsg = [];
+    
+    if (contactsData.length > 0)
+    {
+        //get data with config
+        var config = EwsClientSyncUtils.getPlaceholders(pUserID);
+        var data = getAddressData(contactsData, config);
+        
+        //data pos 0 contains column Name - use them as key for the User object
+        var header = [];
+        for (let i = 0; i < data[0].length; i++)
+        {
+            header.push(data[0][i].replace(new RegExp("[{@}]","g"), "")); //replace start and end delimeter which are set in the getAdressData Method
+        }
+        
+        var dataObj, addrObj, addrValueObjBusiness, addrValueObjHome, addrValueObjOther, exchangeId;
+        var objects = [];
+        //loop through array at pos 1, header has been already collected
+        for (let i = 1; i < data.length; i++)
+        {
+            //dataObj at pos data[i][j] will match to the header[j]
+            dataObj = new Object();
+            addrObj = new Object();
+            addrValueObjBusiness = {};
+            addrValueObjHome = {};
+            addrValueObjOther = {};
+            
+            //addressdata will allocated with tags (Business_, Home_, Other_) to each object
+            for (let j = 0; j < header.length; j++)
+            {
+                addDataToValueObjects(header[j], data[i][j], dataObj, addrValueObjBusiness, addrValueObjHome, addrValueObjOther);
+            }
+            
+            //build addr object out of the objects generated above 
+            buildAddrObject(addrObj, addrValueObjHome, addrValueObjBusiness, addrValueObjOther);
+            
+            // Get the exchangeID from the data-object for update
+            let exchangeId = dataObj["EXCHANGEID"].value;
+            objects.push([exchangeId, dataObj, addrObj]);
+        }
+        
+        var errorItems = []; 
+        var notFoundItems = []; 
+        var deletedItems = [];
+        
+        while(objects.length > 0)
+        {
+            let objectsPart = objects.splice(0, 200);//currently max limit: 200
+            try
+            {
+                exchangeIds = EwsSyncContactUtils.updateContacts(pAlias, pMailBox, objectsPart, doDebug);//run plugin
+            }
+            catch(ex)
+            {
+                let errMsg = "Error while calling the plugin: " + logging.toLogString(ex.rhinoException != undefined ? ex.rhinoException : ex, true) + "\r\n"; 
+                logging.log(errMsg);
+                return [errMsg];
+            }
+        
+            //exchangeIDs[1] array for the contacts which got an error
+            while(exchangeIds[1].length > 0) 
+            {
+                var deletes = [];
+                    
+                let exchangeIdsPart = exchangeIds[1].splice(0, 30);
+                
+                for (let i = 0; i < exchangeIdsPart.length; i++) 
+                {
+                    //contact which aren't in Exchange anymore can be deleted out of the sync
+                    if(exchangeIdsPart[i][3] == "ErrorItemNotFound")
+                    {
+                        deletes.push(exchangeIdsPart[i][0]);
+                        notFoundItems.push(exchangeIdsPart[i][0] , pUserID);
+                    }
+                    else
+                    {
+                        errorItems.push(exchangeIdsPart[i].toSource(), pUserID);
+                        retMsg.push( exchangeIDs[1][0] + " : " + exchangeIDs[1][2] + " " + exchangeIDs[1][3] );
+                    }
+                }
+                    
+                if(deletes.length > 0)
+                {
+                    //delete out of sync table
+                    db.deleteData("AB_SYNCCONTACT", " CONTACT_ID in  ('" + deletes.join("', '") + "') and USER_ID = '" + pUserID + "'", "Data_alias", 300000);
+                    
+                    //remove set favorite for those which are delted - otherwise they would appear in the next run as 'new' Contacts
+                    EwsClientSyncUtils.removeFromFavorite(deletes, pUserID);
+                    deletedItems = deletedItems.concat(deletes);
+                }
+            }
+        }//while object > 0
+            
+        if(doDebug && notFoundItems.length > 0)
+            logging.log("EWSSYnc not found items: " + notFoundItems.toSource());
+        
+        if(errorItems.length > 0)
+            logging.log("EWSSYnc error items: " + errorItems.toSource());
+        
+        if(doDebug && deletedItems.length > 0)
+            logging.log("EWSSYnc deleted items: " + deletedItems.toSource());
+    }//contactsData.length > 0 
+    
+    return retMsg; 
+}
+
+/*
+ * updates the Synced Contacts for the passed User
+ * 
+ * @param {String} pUserID ID of the User for which Contact should be updated
+ * @param {String} pMailBox Exchange Mail
+ * @param {String} pAlias name of the Exchange Alias
+ * @param {String} pRunDate lastRunDate of the sync
+ * @param {String} pUser Login of the User
+ * @param {boolean} doDebug 
+ *
+*/
+function EWSinsertContactsForUser(pUserID, pMailBox, pAlias, pRunDate, pUser, doDebug)
+{    
+    var cond = newWhere("AB_SYNCCONTACT.EXCHANGEID is null")
+    .and("AB_SYNCCONTACT.USER_ID", pUserID); 
+    
+    var contactsData = newSelect("AB_SYNCCONTACT.CONTACT_ID")
+    .from("AB_SYNCCONTACT")
+    .where(cond)
+    .arrayColumn();
+    var retMsg = [];
+    if (contactsData.length > 0)
+    {   
+        var config = EwsClientSyncUtils.getPlaceholders(pUserID)
+        var data = getAddressData(contactsData, config);
+        
+        var header  = [];
+        for (let i = 0; i < data[0].length; i++)
+        {
+            header.push(data[0][i].replace(new RegExp("[{@}]","g"), ""))
+        }
+        
+        var dataObj;
+        var addrObj;
+        var objects = [];
+        var addrValueObjHome = {};
+        var addrValueObjBusiness = {};
+        var addrValueObjOther = {};
+       
+        
+        //get ID of the ADITO-Ordners 
+        var folderID = getExchangeFolderID(pAlias, pMailBox, "ADITO");
+        if (folderID != "")
+        {
+            //loop through array at pos 1, header has been already collected
+            for (var i = 1; i < data.length; i++)
+            {
+                dataObj = new Object();
+                addrObj = new Object();
+                addrValueObjBusiness = {};
+                addrValueObjHome = {};
+                addrValueObjOther = {};
+                
+                // The address data gets assigned to the respective object
+                for (let j = 0; j < header.length; j++)
+                {
+                    addDataToValueObjects(header[j], data[i][j], dataObj, addrValueObjBusiness, addrValueObjHome, addrValueObjOther);
+                }
+                
+                buildAddrObject(addrObj, addrValueObjHome, addrValueObjBusiness, addrValueObjOther);
+                objects.push([dataObj, addrObj]);
+            }
+            
+            while(objects.length > 0)
+            {    
+                let objectPart = objects.splice(0, 200); //current limit 200
+                
+
+                let exchangeIDs = EwsSyncContactUtils.insertContactsToFolder(pAlias, pMailBox, folderID, objectPart, doDebug);
+         
+                while(exchangeIDs[0].length > 0) 
+                {
+                    let exchangeIDsPart = exchangeIDs[0].splice(0, 30);//current limit 30
+                    updateADITOContactsAfterAction(exchangeIDsPart, pUserID);
+                }
+                
+                //when errors occured 
+                while(exchangeIDs[1].length > 0)
+                {
+                    retMsg.push( exchangeIDs[1][0] + " : " + exchangeIDs[1][2] + " " + exchangeIDs[1][3] )
+                }
+            }//objects.length > 0 
+        }
+        else 
+            return ["No folder 'ADITO' for account '" + pMailBox + "' and user '" + pUser + "' found"];
+    }
+    return retMsg;
+}
+
+
+/*
+ * allocates passed headers/values to their object
+ * 
+ * @param pHeader {String} fieldname in exchange
+ * @param pData {String} value for Header
+ * @param pDataObj {{}} object for contactdata
+ * @param pAddrValueObjBusiness {{}} adressobject Organisations
+ * @param pAddrValueObjHome {{}} adressobject homeadress
+ * @param pAddrValueObjOther {{}} adressobject others
+ * 
+ */
+function addDataToValueObjects(pHeader, pData, pDataObj, pAddrValueObjBusiness, pAddrValueObjHome, pAddrValueObjOther)
+{
+    //with used appendChild method the pData values will be escaped automatically
+    
+    //differ contactdata and adressdata
+    //none of the abbreviation defined by the config
+    var headerNotNull = ["EmailAdress1", "EmailAddress2", "BusinessPhone", "BusinessHomepage", "HomePhone", "HomeFax", "OtherFax", "MobilePhone"];
+    
+    if (pData != "" || headerNotNull.indexOf(pHeader) == -1)
+    {
+        if (pHeader.indexOf("Business_") == -1 && pHeader.indexOf("Home_") == -1 && pHeader.indexOf("Other_") == -1 && pData != "")
+        {
+            pDataObj[pHeader] = {
+                "key" : pHeader,
+                "value" : pData
+            };
+        }
+        else 
+        {
+            //Organisation Adress
+            if (pHeader.indexOf("Business") != -1)
+            {
+                pHeader = pHeader.replace("Business_", "");
+                pAddrValueObjBusiness[pHeader] = {
+                    "key" : pHeader,
+                    "value" : pData
+                }
+            }
+            //Privatadress
+            else if (pHeader.indexOf("Home") != -1)
+            {
+                pHeader = pHeader.replace("Home_", "");
+                pAddrValueObjHome[pHeader] = {
+                    "key" : pHeader,
+                    "value" : pData
+                }
+            }
+            //other Adress
+            else if (pHeader.indexOf("Other") != -1)
+            {
+                pHeader = pHeader.replace("Other_", "");
+                pAddrValueObjOther[pHeader] = {
+                    "key" : pHeader,
+                    "value" : pData
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Build Address Object for the plugin call
+ * 
+ * @param pAddrObject {{}} addressobject for call
+ * @param pAddrValueObjHome {{}} adressobject with Privatadresse
+ * @param pAddrValueObjBusiness {{}} adressobject for Organisation
+ * @param pAddrValueObjOther {{}} adressobject for other adresses
+ */
+function buildAddrObject(pAddrObject, pAddrValueObjHome, pAddrValueObjBusiness, pAddrValueObjOther) 
+{
+    var homeOk = false;
+    var businessOk = false;
+    var otherOk = false;
+    
+    for each (var obj in pAddrValueObjHome)
+    {
+        if (obj["value"] != "")
+        {
+            homeOk = true;
+            break;
+        }
+    }
+    for each (obj in pAddrValueObjBusiness)
+    {
+        if (obj["value"] != "")
+        {
+            businessOk = true;
+            break;
+        }
+    }
+    for each (obj in pAddrValueObjOther)
+    {
+        if (obj["value"] != "")
+        {
+            otherOk = true;
+            break;
+        }
+    }
+    
+    if (homeOk)
+    {
+        pAddrObject["Home"] = {
+            "addressKey" : "Home",
+            "value" : pAddrValueObjHome
+        };
+    }
+    if (businessOk)
+    {
+        pAddrObject["Business"] = {
+            "addressKey" : "Business",
+            "value" : pAddrValueObjBusiness
+        };
+    }
+    if (otherOk)
+    {
+        pAddrObject["Other"] = {
+            "addressKey" : "Other",
+            "value" : pAddrValueObjOther
+        };
+    }
+}
+
+/*
+ * returns the exchangeID of the ADITO Folder of an exchange User
+ * if no folder is passed all folderIDs will be returned
+ * 
+ * @param {String} pAlias exchange-alias
+ * @param {String} pMailBox mail-adress of the user
+ * @param {String} pFolderName name of the folder for which the ID should returned none if all
+ */
+function getExchangeFolderID(pAlias, pMailBox, pFolderName)
+{
+    var folders = EwsSyncContactUtils.getContactFolders(pAlias, pMailBox);
+    
+    for ( var i = 0; i < folders.length; i++)
+    {    
+        if( folders[i].name.toUpperCase() == pFolderName.toUpperCase() )
+            return folders[i].id;
+    }
+    return "";
+}
+
+function escapeValuesForXML(pValue){
+    
+    var reps = {};
+    reps["&"]  = "&amp;";
+    reps["\""] = "&quot";
+    reps["'"]  = "&apos";
+    reps["<"]  = "&lt;";
+    reps[">"]  = "&gt;";
+    
+    pValue = text.replaceAll(pValue, reps).trim();
+    
+    return pValue
+}
+
+/*
+* Updates the Edit-Date and the exchangeID into the associated data set of AOSYS_SYNCCONTACT
+* If the ExchangeID isn't passed, then it will just update DATE_EDIT
+*
+* @param {Array<Array>} pUpdateValues 2d-array in the following form: [[CONTACTID, matching new EXCHANGEID]]
+* @param {String} pUserID ID of the corresponding user
+*/
+function updateADITOContactsAfterAction(pUpdateValues, pUserID)
+{
+    var cols = ["EXCHANGEID"];
+    var types = db.getColumnTypes("AB_SYNCCONTACT", cols);
+    var vals;
+    var cond = "";
+    var updArr = [];
+    for (let i = 0; i < pUpdateValues.length; i++)
+    {
+        vals = [];
+        // Get EXCHANGEID
+        if (pUpdateValues[i][1])
+            vals.push(pUpdateValues[i][1]);
+
+        cond = "CONTACT_ID = '" + pUpdateValues[i][0] + "' and USER_ID = '" + pUserID + "'";
+        updArr.push(["AB_SYNCCONTACT", cols, types, vals, cond]);
+    }
+    db.updates(updArr, "Data_alias", 300000);
+}