        (void)fclose(mbox_file);
        (void)close(spamd_sock);
        return DEFER;
-@@ -228,22 +261,67 @@ int spam(uschar **listptr) {
+@@ -230,22 +263,67 @@ spam(uschar **listptr)
      return DEFER;
    }
  

 
   /* now send the file */
   /* spamd sometimes accepts conections but doesn't read data off
@@ -255,41 +333,53 @@ int spam(uschar **listptr) {
    * Note: poll() is not supported in OSX 10.2 and is reported to be
    *       broken in more recent versions (up to 10.4).
    */
-#ifndef NO_POLL_H
-  pollfd.fd = spamd_sock;
-  pollfd.events = POLLOUT;
-#endif
-  (void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK);
+#ifdef HAVE_LINUX_SENDFILE
+  ssize_t copied = 0;
+  int mbox_fd;
+  off_t off = 0, size;
+  struct stat st;
+
+  mbox_fd = fileno(mbox_file);
+  if( fstat(mbox_fd, &st) == -1 ) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+      "spam acl condition: %s on scan file", strerror(errno));
+    (void)close(spamd_sock);
+    (void)fclose(mbox_file);
+    return DEFER;
+  }
+  size = st.st_size;
+  for (;;) {
+    if (spam_poll_socket(spamd_sock, start) == -1) {
+      (void)close(spamd_sock);
+      (void)fclose(mbox_file);
+      return DEFER;
+    }
+    copied = sendfile(spamd_sock, mbox_fd, &offset, (size - offset));
+    if (copied < 0) {
+      if (errno == EINTR)
+        continue;
+
+      log_write(0, LOG_MAIN|LOG_PANIC,
+        "spam acl condition: %s on spamd socket", strerror(errno));
+      (void)close(spamd_sock);
+      (void)fclose(mbox_file);
+      return DEFER;
+    }
+    else {
+      size -= copied;
+      if (size == 0) {
+        /* the whole file has been sent */
+        break;
+      }
+    }
+  }
+#else
   do {
     read = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file);
     if (read > 0) {
       offset = 0;
 again:
-#ifndef NO_POLL_H
-      result = poll(&pollfd, 1, 1000);
-
-/* Patch posted by Erik ? for OS X and applied by PH */
-#else
-      select_tv.tv_sec = 1;
-      select_tv.tv_usec = 0;
-      FD_ZERO(&select_fd);
-      FD_SET(spamd_sock, &select_fd);
-      result = select(spamd_sock+1, NULL, &select_fd, NULL, &select_tv);
-#endif
-/* End Erik's patch */
-
-      if (result == -1 && errno == EINTR)
-        goto again;
-      else if (result < 1) {
-        if (result == -1)
-          log_write(0, LOG_MAIN|LOG_PANIC,
-            "spam acl condition: %s on spamd socket", strerror(errno));
-        else {
-          if (time(NULL) - start < SPAMD_TIMEOUT)
-          goto again;
-          log_write(0, LOG_MAIN|LOG_PANIC,
-            "spam acl condition: timed out writing spamd socket");
-        }
+      if (spam_poll_socket(spamd_sock, start) == -1) {
         (void)close(spamd_sock);
         (void)fclose(mbox_file);
         return DEFER;
@@ -318,6 +408,7 @@ again:
     (void)fclose(mbox_file);
     return DEFER;
   }
+#endif /* HAVE_LINUX_SENDFILE */
 
   (void)fclose(mbox_file);
 
@@ -346,60 +437,103 @@ again:
   /* reading done */
   (void)close(spamd_sock);
 

diff --git a/src/expand.c b/src/expand.c
index 8e94c3e..45f446d 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -644,6 +644,7 @@ static var_entry var_table[] = {
   { "sn8",                 vtype_filter_int,  &filter_sn[8] },
   { "sn9",                 vtype_filter_int,  &filter_sn[9] },
 #ifdef WITH_CONTENT_SCAN
