diff -Naur mlmmj-1.2.13-split/include/do_all_the_voodo_here.h mlmmj-1.2.13/include/do_all_the_voodo_here.h
--- mlmmj-1.2.13-split/include/do_all_the_voodo_here.h	2007-02-26 11:01:19.000000000 +0100
+++ mlmmj-1.2.13/include/do_all_the_voodo_here.h	2007-02-26 11:08:01.000000000 +0100
@@ -30,6 +30,6 @@
 void getinfo(const char *line, struct mailhdr *readhdrs);
 int do_all_the_voodo_here(int infd, int outfd, int hdrfd, int footfd,
 	      const char **delhdrs, struct mailhdr *readhdrs,
-	      struct strlist *allhdrs, const char *subjectprefix);
+	      struct strlist *allhdrs, const char *subjectprefix, const char** delmime, struct strlist *allmime);
 
 #endif /* DO_ALL_THE_VOODO_HERE_H */
diff -Naur mlmmj-1.2.13-split/README mlmmj-1.2.13/README
--- mlmmj-1.2.13-split/README	2007-02-26 11:01:19.000000000 +0100
+++ mlmmj-1.2.13/README	2007-02-26 11:54:53.000000000 +0100
@@ -126,6 +126,13 @@
 
 10) Have a look at the file TUNABLES for runtime configurable things.
 
+11) If you want to strip parts with certain mimetypes from multipart/mime messages
+    add a file called 'mimestrip' containing these mimetypes to the control/ directory.
+
+12) If you want to deny multipart/mime messages with certain mimetypes add a file
+    called 'mimedeny' continaing these mimetypes to the control/directory
+
+
 Tunables in include/mlmmj.h:
  · There's some time intervals for how mlmmj-maintd operates. I've choosen
    non-strict defaults, so depending on your BOFH rate you might want to tweak.
diff -Naur mlmmj-1.2.13-split/src/do_all_the_voodo_here.c mlmmj-1.2.13/src/do_all_the_voodo_here.c
--- mlmmj-1.2.13-split/src/do_all_the_voodo_here.c	2007-02-26 11:01:19.000000000 +0100
+++ mlmmj-1.2.13/src/do_all_the_voodo_here.c	2007-02-26 11:45:09.000000000 +0100
@@ -107,11 +107,156 @@
 	return 0;
 }
 
+/* check if the supplied headers contain a Content-Type header with boundary  */
+static int find_boundary(struct strlist *allhdrs, char** mime_type, char** boundary)
+{
+	int x;
+	*boundary = NULL;
+	*mime_type = NULL;
+	for( x = 0 ; x < allhdrs->count ; x++ ){
+		char* hdr = allhdrs->strs[x];
+		if(hdr && !strncasecmp(hdr,"Content-Type:",13)){
+			char* pos = hdr + 13;
+			size_t len = 0;
+
+			/* find the start of the mimetype */
+			while(*pos && (*pos == ' ' || *pos == '\t'))
+				++pos;
+
+			if(*pos == '"'){                   /* handle quoted mime types */
+				++pos;
+				while(pos[len] && pos[len] != '"')
+					++len;
+			}else{
+				while(pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';')
+					++len;
+			}
+
+			/* extract mime type */
+			if(len){
+				*mime_type = mymalloc(len+1);
+				strncpy(*mime_type,pos,len);
+				(*mime_type)[len] = '\0';
+			}
+
+			pos += len;
+			len = 0;
+			/* find start of the boundary info */
+			while(*pos && strncasecmp(pos,"boundary=",9))
+				++pos;
+			if(*pos == '\0')         /* no boundary */
+				return 0;
+			pos += 9;
+			if(*pos == '"'){         /* quoted boundary */
+				++pos;
+				while(pos[len] && pos[len] != '"')
+					++len;
+			}else{                  /* unquoted boundary */
+				while(pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';')
+					++len;
+			}
+
+			/* extract boundary */
+			*boundary = mymalloc(len + 3);
+			strcpy(*boundary,"--");
+			strncat(*boundary,pos,len);
+
+			return 0;
+		}
+	}
+	return 0;
+}
+
+/* dump multipart messages skipping parts specified in delmime*/
+static int dump_multipart(int infd, int outfd, char* boundary, const char **delmime, struct strlist *allmime)
+{
+	char* line;
+	int strip_part = 0;
+	int end_of_part = 0;
+
+	/* parse mail line by line */
+        while((line = mygetline(infd)) != NULL) {
+		int i;
+		struct strlist hdrs;
+		char* new_boundary = NULL;
+		hdrs.count = 0;
+		hdrs.strs = NULL;
+
+		/* found a boundary that has been mentioned in the header */
+		if(!strncmp(line,boundary,strlen(boundary))){
+			strip_part = 0;
+			/* check if the boundary is the beginning of a new part */
+			if(strncmp(line + strlen(boundary),"--",2)){
+				char* mime_type = NULL;
+
+				/* read headers */
+				if( gethdrs(infd, &hdrs) < 0) {
+					log_error(LOG_ARGS, "could not read headers");
+					return -1;
+				}
+				/* get mimetype and boundary from the headers */
+				if(find_boundary(&hdrs,&mime_type,&new_boundary) < 0) {
+					log_error(LOG_ARGS, "Error searching for mime_type and boundary");
+					return -1;
+				}
+
+				/* append mime type to mimelist and check if the part should be stripped */
+				if(mime_type) {
+					append_strtolist(allmime,mime_type);
+					if(delmime && findit(mime_type, delmime))
+						strip_part = 1;
+					myfree(mime_type);
+				}
+			}else{
+				end_of_part=1;
+			}
+		}
+		if(!strip_part) {
+			if(writen(outfd, line, strlen(line)) < 0){
+				log_error(LOG_ARGS, "Error when dumping rest of mail");
+				return -1;
+			}
+			/* write headers if any */
+			if(hdrs.count) {
+				for(i = 0; i < hdrs.count ; i++) {
+					if(writen(outfd, hdrs.strs[i], strlen(hdrs.strs[i])) < 0){
+						log_error(LOG_ARGS, "Error when dumping headers for rest of mail");
+						return -1;
+					}
+				}
+				if(writen(outfd, "\n", 1) < 0) {
+					log_error(LOG_ARGS,"Error writting end of hdrs.");
+					return -1;
+				}
+			}
+			/* dump embedded (multipart) part */
+			if(new_boundary) {
+				if( dump_multipart(infd,outfd, new_boundary, delmime, allmime) < 0){
+					log_error(LOG_ARGS, "Error when dumping nested part");
+					return -1;
+				}
+				myfree(new_boundary);
+			}
+		}
+		/* free headers if any */
+		if(hdrs.strs) {
+			for(i = 0; i < hdrs.count ; i++) 
+				myfree(hdrs.strs[i]);
+			myfree(hdrs.strs);
+		}
 
+		myfree(line);
+
+		if(end_of_part)
+			break;
+	}
+	return 0;
+}
 
 int do_all_the_voodo_here(int infd, int outfd, int hdrfd, int footfd,
 		 const char **delhdrs, struct mailhdr *readhdrs,
-		 struct strlist *allhdrs, const char *prefix)
+		 struct strlist *allhdrs, const char *prefix,
+		 const char **delmime, struct strlist *allmime)
 {
 	char *subject, *unqp;
 	int hdrsadded = 0;
@@ -120,6 +265,10 @@
 
 	allhdrs->count = 0;
 	allhdrs->strs = NULL;
+	if(allmime) {
+		allmime->count = 0;
+		allmime->strs = NULL;
+	}
 
 	/* copy headers */
 	gethdrs(infd,allhdrs);
@@ -203,6 +352,28 @@
 			return -1;
 	}
 
+	if(allmime){
+		char* mime_type = NULL,*boundary=NULL;
+		if(find_boundary(allhdrs,&mime_type,&boundary) < 0) {
+			log_error(LOG_ARGS, "Error searching for mime_type and boundary");
+			return -1;
+		}
+
+		if(mime_type) {
+			append_strtolist(allmime,mime_type);
+			myfree(mime_type);
+		}
+
+		if(boundary) {
+			/* dump multipart message */
+			if(dump_multipart(infd, outfd, boundary, delmime, allmime) < 0) {
+				log_error(LOG_ARGS, "Error when dumping multipart");
+				return -1;
+			}
+			myfree(boundary);
+		}
+	}
+
 	/* Just print the rest of the mail */
 	if(dumpfd2fd(infd, outfd) < 0) {
 		log_error(LOG_ARGS, "Error when dumping rest of mail");
diff -Naur mlmmj-1.2.13-split/src/mlmmj-process.c mlmmj-1.2.13/src/mlmmj-process.c
--- mlmmj-1.2.13-split/src/mlmmj-process.c	2007-02-26 11:01:19.000000000 +0100
+++ mlmmj-1.2.13/src/mlmmj-process.c	2007-02-26 11:52:26.000000000 +0100
@@ -166,6 +166,21 @@
 	}
 }
 
+static enum action check_mime(struct strlist *denymime, struct strlist * allmime)
+{
+	int i;
+	for(i=0;i<allmime->count;i++){
+		int x;
+		for(x=0; x < denymime->count ; x++){
+			if(!strcasecmp(allmime->strs[i],denymime->strs[x])){
+				log_error(LOG_ARGS, "A mail with mime %s was denied",
+						    allmime->strs[i]);
+				return DENY; 
+			}
+		}
+	}
+	return ALLOW;
+}
 
 static enum action do_access(struct strlist *rule_strs, struct strlist *hdrs)
 {
@@ -366,8 +381,11 @@
 	struct email_container rpemails = { 0, NULL };
 	struct email_container dtemails = { 0, NULL };
 	struct strlist *access_rules = NULL;
+	struct strlist *mime_deny = NULL;
 	struct strlist *delheaders = NULL;
 	struct strlist allheaders;
+	struct strlist *delmime = NULL;
+	struct strlist allmime;
 	struct strlist *alternates = NULL;
 	struct mailhdr readhdrs[] = {
 		{ "From:", 0, NULL },
@@ -483,12 +501,21 @@
 	delheaders->strs[delheaders->count++] = mystrdup("From ");
 	delheaders->strs[delheaders->count++] = mystrdup("Return-Path:");
 	delheaders->strs[delheaders->count] = NULL;
-	
+
+	/* get a list of mime parts that should be stripped */
+	delmime = ctrlvalues(listdir, "mimestrip");
+	if(delmime == NULL) {
+		delmime = mymalloc(sizeof(struct strlist));
+		delmime->count = 0;
+		delmime->strs = NULL;
+	}
+
+
 	subjectprefix = ctrlvalue(listdir, "prefix");	
 	
 	if(do_all_the_voodo_here(rawmailfd, donemailfd, hdrfd, footfd,
 				(const char**)delheaders->strs, readhdrs,
-				&allheaders, subjectprefix) < 0) {
+				&allheaders, subjectprefix,(const char**)delmime->strs, &allmime) < 0) {
 		log_error(LOG_ARGS, "Error in do_all_the_voodo_here");
 		exit(EXIT_FAILURE);
 	}
@@ -599,7 +626,7 @@
 			}
 			if(do_all_the_voodo_here(rawmailfd, donemailfd, -1,
 					-1, (const char**)delheaders->strs,
-					NULL, &allheaders, NULL) < 0) {
+					NULL, &allheaders, NULL, (const char**)delmime->strs, &allmime) < 0) {
 				log_error(LOG_ARGS, "do_all_the_voodo_here");
 				exit(EXIT_FAILURE);
 			}
@@ -654,6 +681,12 @@
 
 	myfree(delheaders);
 
+	for(i = 0; i < delmime->count; i++)
+		myfree(delmime->strs[i]);
+	myfree(delmime->strs);
+	myfree(delmime);
+
+
 	if(strcmp(efrom, "") == 0) { /* don't send mails with <> in From
 					     to the list */
 		discardname = concatstr(3, listdir,
@@ -808,11 +841,34 @@
 	noaccessdenymails = statctrl(listdir, "noaccessdenymails");
 
 	access_rules = ctrlvalues(listdir, "access");
-	if (access_rules) {
-		enum action accret;
+	mime_deny = ctrlvalues(listdir,"mimedeny");
+	if (access_rules || mime_deny) {
+		enum action accret = ALLOW;
 		/* Don't send a mail about denial to the list, but silently
 		 * discard and exit. Also do this in case it's turned off */
-		accret = do_access(access_rules, &allheaders);
+
+		/* check rules */
+		if(access_rules)
+			accret = do_access(access_rules, &allheaders);
+
+		/* check allowed mime types */
+		if(accret == ALLOW && mime_deny)
+			accret = check_mime(mime_deny, &allmime);
+
+		/* free rules */
+		if(access_rules) {
+			for(i = 0; i < access_rules->count; i++)
+				myfree(access_rules->strs[i]);
+			myfree(access_rules->strs);
+			myfree(access_rules);
+		}
+		if(mime_deny) {
+			for(i = 0; i < mime_deny->count; i++)
+				myfree(mime_deny->strs[i]);
+			myfree(mime_deny->strs);
+			myfree(mime_deny);
+		}
+
 		if (accret == DENY) {
 			if ((strcasecmp(listaddr, fromemails.emaillist[0]) ==
 						0) || noaccessdenymails) {


