Index: src/main/java/org/jvnet/mimepull/MemoryData.java
===================================================================
--- src/main/java/org/jvnet/mimepull/MemoryData.java	(revision 213)
+++ src/main/java/org/jvnet/mimepull/MemoryData.java	(working copy)
@@ -94,8 +94,7 @@
                 String prefix = config.getTempFilePrefix();
                 String suffix = config.getTempFileSuffix();
                 File tempFile = TempFiles.createTempFile(prefix, suffix, config.getTempDir());
-                // delete the temp file when VM exits as a last resort for file clean up
-                tempFile.deleteOnExit();
+                TempFileCleaner.register(tempFile);
                 if (LOGGER.isLoggable(Level.FINE)) {
                     LOGGER.log(Level.FINE, "Created temp file = {0}", tempFile);
                 }
Index: src/main/java/org/jvnet/mimepull/TempFileCleaner.java
===================================================================
--- src/main/java/org/jvnet/mimepull/TempFileCleaner.java	(revision 0)
+++ src/main/java/org/jvnet/mimepull/TempFileCleaner.java	(revision 0)
@@ -0,0 +1,201 @@
+package org.jvnet.mimepull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+class TempFileCleaner {
+
+    private static final Logger LOGGER = Logger.getLogger(TempFileCleaner.class.getName());
+    private static final String CLEANER_TIMER_NAME = "mimepull-cleaner-timer";
+    private static final int DEFAULT_INTERVAL = 10; // minutes
+    private static final int MAX_COUNT = 5;
+
+    private static final TempFileCleaner instance = new TempFileCleaner();
+    private static final ScheduledExecutorService scheduler;
+    private ConcurrentHashMap<File, Integer> fileMap;
+
+    static {
+        int interval = DEFAULT_INTERVAL;
+        try {
+            interval = Integer.getInteger("org.jvnet.mimepull.interval", DEFAULT_INTERVAL);
+        } catch (SecurityException se) {
+            if (LOGGER.isLoggable(Level.CONFIG)) {
+                LOGGER.log(Level.CONFIG,
+                        "Cannot read ''{0}'' property, using defaults.",
+                        new Object[] {"org.jvnet.mimepull.interval"});
+            } 
+        }
+
+        ThreadFactory factory = new ThreadFactory() {
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread t = new Thread(r);
+                t.setName(CLEANER_TIMER_NAME);
+                t.setDaemon(true);
+                return t;
+            }
+        };
+        scheduler = Executors.newScheduledThreadPool(1, factory);
+        scheduler.scheduleWithFixedDelay(new Cleaner(), interval, interval, TimeUnit.MINUTES);
+        LOGGER.log(Level.FINE, "Created temporary file cleaner for MIMEPULL");
+    }
+
+    /* Private constructor. */
+    private TempFileCleaner() {
+        this.fileMap = new ConcurrentHashMap<File, Integer>();
+
+        Thread hook = new Thread(new ShutdownHook());
+        Runtime.getRuntime().addShutdownHook(hook);
+    }
+
+    private synchronized int countup(File f) {
+        Integer count = instance.fileMap.get(f);
+        if (count == null) {
+            count = Integer.MIN_VALUE;
+        }else {
+            ++count;
+            instance.fileMap.put(f, count);
+        }
+        return count.intValue();
+    }
+
+    public static void register(File f) {
+        instance.fileMap.put(f, -1);
+    }
+
+    public static boolean delete(File f) {
+        if (LOGGER.isLoggable(Level.FINER)) {
+            LOGGER.log(Level.FINER, "Deleting file = {0}", f.getName());
+        }
+
+        boolean deleted = false;;
+        try {
+            deleted = f.delete();
+        } catch (SecurityException se) {
+            LOGGER.log(Level.WARNING, null, se);
+        }
+
+        if (deleted) {
+            // remove fileMap entry
+            instance.fileMap.remove(f);
+        } else {
+            // count up
+            Integer count = instance.fileMap.get(f);
+            if (count != null) {
+                ++count;
+                instance.fileMap.put(f, count);
+            }
+        }
+
+        return deleted;
+    }
+
+    static class Cleaner implements Runnable {
+        @Override
+        public void run() {
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Cleaning start.");
+            }
+
+            int removedCount = 0;
+            if (!instance.fileMap.isEmpty()) {
+                ArrayList<File> list = new ArrayList<File>();
+
+                Set<Entry<File, Integer>> entries = instance.fileMap.entrySet();
+                for (Entry<File, Integer> entry : entries) {
+                    int count = entry.getValue().intValue();
+                    if (count < 0) {
+                        continue;
+                    }
+
+                    File file = entry.getKey();
+                    if (!file.exists()) {
+                        list.add(file);
+                        continue;
+                    }
+
+                    // try to delete file
+                    try {
+                        if (file.delete()) {
+                            if (LOGGER.isLoggable(Level.FINE)) {
+                                LOGGER.log(Level.FINE, "Deleting file = {0}", file.getName());
+                            }
+                            ++removedCount;
+                            list.add(file);
+                            continue;
+                        }
+                    } catch (Exception ex) {
+                        LOGGER.log(Level.WARNING, null, ex);
+                    }
+
+                    // give up deletion by this Cleaner
+                    count = instance.countup(file);
+                    if (MAX_COUNT < count) {
+                        file.deleteOnExit();
+                        list.add(file);
+                    }
+                }
+                entries.clear();
+
+                // remove deleted file entries
+                for (File deletedFile : list) {
+                    instance.fileMap.remove(deletedFile);
+                }
+            }
+
+            if (LOGGER.isLoggable(Level.FINE)) {
+                StringBuilder msg = new StringBuilder();
+                msg.append("Cleaning finished");
+                if (removedCount >= 0) {
+                    msg.append(" ");
+                    msg.append(removedCount);
+                    msg.append(" files removed.");
+                } else {
+                    msg.append(".");
+                }
+                LOGGER.log(Level.FINE, msg.toString());
+            }
+        }
+    }
+
+    static class ShutdownHook implements Runnable {
+        @Override
+        public void run() {
+            int size = instance.fileMap.size();
+            if (size > 0) {
+                if (LOGGER.isLoggable(Level.FINE)) {
+                    LOGGER.log(Level.FINE, "files = " + size);
+                }
+
+                Set<File> files = instance.fileMap.keySet();
+                for (File file : files) {
+                    if (file.exists()) {
+                        boolean deleted = false;
+                        try {
+                            deleted = file.delete();
+                        } catch (Exception ex) {
+                            LOGGER.log(Level.WARNING, null, ex);
+                        }
+
+                        // give up deletion by this Cleaner
+                        if (!deleted) {
+                            file.deleteOnExit();
+                        }
+                    }
+                }
+                instance.fileMap.clear();
+            }
+            scheduler.shutdown();
+        }
+    }
+
+}
Index: src/main/java/org/jvnet/mimepull/WeakDataFile.java
===================================================================
--- src/main/java/org/jvnet/mimepull/WeakDataFile.java	(revision 213)
+++ src/main/java/org/jvnet/mimepull/WeakDataFile.java	(working copy)
@@ -130,7 +130,7 @@
         refList.remove(this);
         try {
             raf.close();
-            boolean deleted = file.delete();
+            boolean deleted = TempFileCleaner.delete(file);
             if (!deleted) {
                 if (LOGGER.isLoggable(Level.INFO)) {
                     LOGGER.log(Level.INFO, "File {0} was not deleted", file.getAbsolutePath());