diff -ru zarafa-7.1.4/provider/libserver/ZarafaCmd.cpp zarafa-7.1.4.spamhook/provider/libserver/ZarafaCmd.cpp
--- zarafa-7.1.4/provider/libserver/ZarafaCmd.cpp	2013-02-28 17:13:17.000000000 +0100
+++ zarafa-7.1.4.spamhook/provider/libserver/ZarafaCmd.cpp	2013-04-15 11:34:45.018632455 +0200
@@ -84,6 +84,7 @@
 #include "StreamUtil.h"
 #include "CommonUtil.h"
 #include "StorageUtil.h"
+#include "UnixUtil.h"
 
 #include "ZarafaICS.h"
 
@@ -7655,6 +7656,179 @@
 	bool		 bMoved;
 }COPYITEM;
 
+//SPAM HOOK
+//This function parses an e-mail to the /etc/zarafa/userscripts/junklearn script. With 2 arguments:
+//ham or spam
+//message id
+//and pipes the mail header to the script.
+//This script wil be inhaled by MoveObjects();
+/////////////////////////////////////////////////////////////////////////////////////////////////
+int SpamHook(ECDatabase *lpDatabase,int ulId, unsigned int ulDestFolderId)
+{
+
+		ALLOC_DBRESULT();
+		ECRESULT er = erSuccess;
+		std::string shScriptPath = g_lpSessionManager->GetConfig()->GetSetting("junklearn_script");
+		string shMailStatus;
+		entryId* junkFolderEntryId;
+		entryId* wasteBucketEntryId;
+		int shNumRows;
+
+		//dont do anything if the junklearn script doesnt exist:
+		int fCheck=open(shScriptPath.c_str(), O_RDONLY);
+		if (fCheck==0) {
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_INFO,"SpamHook: skipping, script "+shScriptPath+" not found");
+			er=erSuccess;
+			goto exit;
+		}
+		close(fCheck);
+
+		//Get store object ID via message object id
+		unsigned int storeId;
+		er = g_lpSessionManager->GetCacheManager()->GetStore(ulId,&storeId,NULL);
+		if(er != erSuccess) 
+		{
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve source folder.");
+			goto exit;
+		}
+
+		//get deleted items folder entry id
+		strQuery="SELECT val_binary FROM properties WHERE hierarchyid="+stringify(storeId)+" AND tag="+stringify(PROP_ID(PR_IPM_WASTEBASKET_ENTRYID));
+		er = lpDatabase->DoSelect(strQuery, &lpDBResult);
+		if(er != erSuccess) {
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve wastebasket entryid from DB.");
+			goto exit;
+		}
+		lpDBRow = lpDatabase->FetchRow(lpDBResult);
+		lpDBLen = lpDatabase->FetchRowLengths(lpDBResult);
+		shNumRows=lpDatabase->GetNumRows(lpDBResult);
+		if(shNumRows<1)
+		{
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve wastebasket entryid, empty DB result.");
+			goto exit;
+		}
+
+		//Convert 'deleted items' entryid to objectid.
+		wasteBucketEntryId = new entryId[0];
+		wasteBucketEntryId->__ptr=(unsigned char*)lpDBRow[0];
+		wasteBucketEntryId->__size=lpDBLen[0];
+		unsigned int wasteBucketFolderId;
+		er=g_lpSessionManager->GetCacheManager()->GetObjectFromEntryId(wasteBucketEntryId,&wasteBucketFolderId);
+		delete wasteBucketEntryId;
+		if(er!=erSuccess)
+		{
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve wastebasket entryid, converting to objectID.");
+			goto exit;
+		}
+
+		//Get 'junk folder' entryId.
+		FREE_DBRESULT();
+		strQuery="SELECT val_binary  FROM receivefolder LEFT JOIN mvproperties ON receivefolder.objid=mvproperties.hierarchyid WHERE receivefolder.storeid="+stringify(storeId)+" AND receivefolder.messageclass='IPC' AND mvproperties.tag="+stringify(PROP_ID(PR_ADDITIONAL_REN_ENTRYIDS))+" AND mvproperties.orderid=4";
+		er = lpDatabase->DoSelect(strQuery, &lpDBResult);
+		if(er != erSuccess) {
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve junkfolder entryids from DB.");
+			goto exit;
+		}
+		lpDBRow = lpDatabase->FetchRow(lpDBResult);
+		lpDBLen = lpDatabase->FetchRowLengths(lpDBResult);
+		shNumRows=lpDatabase->GetNumRows(lpDBResult);
+		if(shNumRows<1)
+		{
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve junkfolder entryid, empty DB result.");
+			goto exit;
+		}
+
+		//Convert 'junk folder' entryid to objectid.
+		junkFolderEntryId = new entryId[0];
+		junkFolderEntryId->__ptr=(unsigned char*)lpDBRow[0];
+		junkFolderEntryId->__size=lpDBLen[0];
+		unsigned int junkFolderId;
+		er=g_lpSessionManager->GetCacheManager()->GetObjectFromEntryId(junkFolderEntryId,&junkFolderId);
+		delete junkFolderEntryId;
+		if(er!=erSuccess)
+		{
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve junkfolder entryid, converting to objectID.");
+			goto exit;
+		}
+			
+		//Get source folder object ID. (Actually we should check if mail came from subfolders in the 'deleted items folder', which I think never happens.)
+		unsigned int srcFolderId;
+		er=g_lpSessionManager->GetCacheManager()->GetParent(ulId,&srcFolderId);
+		if(er!=erSuccess)
+		{
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error while retrieve src folder id.");
+			goto exit;
+		}
+
+		//now we can determine if object being moved from or to the junkfolder
+		//if destination folder is junk, mark as spam
+		if(ulDestFolderId==junkFolderId)
+  			shMailStatus="spam";
+		else
+		{
+			//if destination folder is not TRASH and de source folder is JUNK, mark as ham
+			if(ulDestFolderId!=wasteBucketFolderId  &&  srcFolderId==junkFolderId)
+				shMailStatus="ham";
+			else
+				//its just a normal movement, so do nothing.
+				goto exit;
+		}
+
+		//Get the mail from the DB.
+		FREE_DBRESULT();
+		strQuery="SELECT val_string FROM properties WHERE tag="+stringify(PROP_ID(PR_TRANSPORT_MESSAGE_HEADERS))+" AND hierarchyid= "+stringify(ulId);
+		er = lpDatabase->DoSelect(strQuery, &lpDBResult);
+		if(er != erSuccess) {
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: db error while retrieve mail header.");
+			goto exit;
+		}
+
+		lpDBRow = lpDatabase->FetchRow(lpDBResult);
+		shNumRows=lpDatabase->GetNumRows(lpDBResult);
+
+		if(shNumRows<=0) {
+			g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: warning mail header empty or this object is no e-mail");
+			goto exit;
+		}
+
+		{
+			//now its time to open the spamhook script and pass the mail to it:
+			shScriptPath=shScriptPath+" "+shMailStatus+" "+stringify(ulId);
+			int ulFpWrite = -1;
+			int ulFpRead = -1;
+			int ulCommandRetval;
+
+			//we asume failure, unless we make it all the way though the script
+			er=ZARAFA_E_UNKNOWN;
+
+			pid_t ulCommandPid = unix_popen_rw(g_lpSessionManager->GetLogger(), shScriptPath.c_str(), &ulFpWrite, &ulFpRead, NULL, NULL, true, false);
+			if (ulCommandPid <= 0) {
+				g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error opening subprocess.");
+				goto exit;
+			}
+
+			//pass the data to the subprocess:
+			write(ulFpWrite, lpDBRow[0], strlen(lpDBRow[0]));
+			ulCommandRetval=unix_pclose(ulFpRead, ulFpWrite, ulCommandPid);
+
+			//subprocess is done, check results
+			if (ulCommandRetval<0) {
+				g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_WARNING,"SpamHook: error "+shScriptPath+" exits with: "+stringify(WEXITSTATUS(ulCommandRetval)));
+				goto exit;
+			}
+		}
+
+		g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_INFO,"SpamHook:  "+shScriptPath+" successfully executed.");
+		er=erSuccess;
+
+	exit:
+		// Free database results
+		FREE_DBRESULT();
+
+		return er;
+}
+
+
 // Move one or more messages and/or moved a softdeleted message to a normal message
 ECRESULT MoveObjects(ECSession *lpSession, ECDatabase *lpDatabase, ECListInt* lplObjectIds, unsigned int ulDestFolderId, unsigned int ulSyncId)
 {
@@ -8641,6 +8815,16 @@
 
 	// @note The object type checking wille be done in MoveObjects or CopyObject
 
+//SPAMHOOK
+/////////////////////////////////////
+        //Iterate over all mail ids and initiate spamhook.
+	for(iObjectId = lObjectIds.begin(); iObjectId != lObjectIds.end(); iObjectId++)
+	{
+		SpamHook(lpDatabase,*iObjectId,ulDestFolderId);
+	}
+//SPAMHOOK END
+////////////////////////////////////
+	
 	//check copy or a move
 	if(ulFlags & FOLDER_MOVE ) { // A move
 		er = MoveObjects(lpecSession, lpDatabase, &lObjectIds, ulDestFolderId, ulSyncId);
diff -ru zarafa-7.1.4/provider/server/ECServer.cpp zarafa-7.1.4.spamhook/provider/server/ECServer.cpp
--- zarafa-7.1.4/provider/server/ECServer.cpp	2013-02-28 17:13:17.000000000 +0100
+++ zarafa-7.1.4.spamhook/provider/server/ECServer.cpp	2013-04-15 11:14:40.000000000 +0200
@@ -963,6 +963,7 @@
 		{ "deletegroup_script",			"/etc/zarafa/userscripts/deletegroup", CONFIGSETTING_RELOADABLE},
 		{ "createcompany_script",		"/etc/zarafa/userscripts/createcompany", CONFIGSETTING_RELOADABLE },
 		{ "deletecompany_script",		"/etc/zarafa/userscripts/deletecompany", CONFIGSETTING_RELOADABLE },
+		{ "junklearn_script",                   "/etc/zarafa/userscripts/junklearn", CONFIGSETTING_RELOADABLE },
 		{ "user_safe_mode",				"no", CONFIGSETTING_RELOADABLE },
 
 		// Storename format
