Hello, I am using CentOS 4 and DSPAM Anti-Spam Suite 3.6.8 (agent/library) Configuration parameters: --enable-daemon --enable-clamav --enable- syslog --with-logdir=/var/log/dspam --with-storage-driver=mysql_drv --enable-virtual-users --enable-preferences-extension --with-mysql- libraries=/usr/lib/mysql --with-mysql-includes=/usr/include/mysql --enable-large-scale --enable-long-usernames --with-dspam-home- owner=dspam --with-dspam-home-group=dspam --with-dspam-owner=dspam --with-dspam-group=dspam --enable-debug
Description of problem ---------------------- With notifications turned on, if dspam processes a first-time message to a test user, with or without --client option: dspam --user testuser --deliver=innocent --stdout < v1 I expect to see the message on stdout, preceded by the firstrun.txt notice, but all I see is the message. Syslog reports, 'Error getting exit status of delivery agent: : Broken pipe' and debug log reports, 'Opening pipe to LDA:'. I do see a firstrun timestamp file created in testuser's home directory, so only the delivery of the notice seems in error. A similar problem has been reported twice in dspam-user: In 2006-02-23, http://article.gmane.org/gmane.mail.spam.dspam.user/9833, 'When dspam tries to send firstrun.txt or firstspam.txt, the user doesn't receive the message, and I see the error message in my mail.info: mail1 dspam[4390]: Error getting exit status of delivery agent: : Broken pipe.' In 2006-09-27, http://article.gmane.org/gmane.mail.spam.dspam.user/11481, 'My debug output seems to indicate the DSPAM is calling a NULL local delivery agent and thinks the message went out ok, when in fact, nothing went out nor was received.' Analysis -------- If dspam can deliver a message to stdout, then why can't it similarly deliver a notification? Rather, dspam tries a local delivery with null delivery arguments. Inspecting the source code, we see that an innocent message is delivered by the following function call: deliver_message(ATX, parse_message->data, (ATX->flags & DAF_STDOUT) ? NULL : ATX->mailer_args, node_nt->ptr, ATX->sockfd ? ATX->sockfd : stdout, DSR_ISINNOCENT); However, a notification is delivered by send_notice() calling the same function with slightly different arguments: deliver_message(ATX, b->data, ATX->mailer_args, username, stdout, DSR_ISINNOCENT); When the same arguments are used, we get the expected result: a notification is sent along with the innocent message. Using --client also works. Testing now with --deliver=spam, we expect to see only the notification on stdout, because the test message is innocent and won't be delivered to stdout. This proves true without --client, but in client mode, although the notification is sent, the LMTP session hangs with the line, '250 2.6.0 <testuser> Message accepted for delivery: INNOCENT', and one needs to send a TERM signal to break the session. Analysis (client mode) ---------------------- If dspam can successfully terminate an LMTP session after sending a notification followed by an innocent message, why can't it terminate after sending only a notification? Inspecting the code again, we see that send_notice() is not setting a flag, relying on it being set elsewhere after calling deliver_message(). However, in this particular case, no other parts of the code will set it because no other output will be delivered. if (ATX->sockfd && ATX->flags & DAF_STDOUT) ATX->sockfd_output = 1; The flag is used by daemon.c, as follows: /* Send a terminating '.' if --stdout in 'dspam' mode */ if (ATX->sockfd_output) { if (!(ATX->flags & DAF_SUMMARY)) if (send_socket(TTX, ".")<=0) goto CLOSE; When the flag is set, we get the expected results for executing the following command: dspam --client --user testuser --deliver=spam --stdout < v1 One more problem ---------------- In 2006-08-06, http://article.gmane.org/gmane.mail.spam.dspam.devel/2526, the poster writes, '...quarantine, web frontend, log and web stats are all disabled. I noticed that with this configuration, I cannot use the notifications out-of-the-box as the folders under $DSPAM_HOME/data/ are not created automatically (resulting in the notifications being sent ever and ever).' He recommends, '_ds_prepare_path_for must be called...' The function mentioned is responsible for creating the path for the user's home directory if needed. The do_notifications() function, which calls send_notice() once for each possible notification, presumes other parts of the code will have created the user's home directory. But in the configuration explored by the poster, no other features requiring a user directory is enabled. We can modify do_notifications() to call _ds_prepare_path_for() before creating a timestamp file: _ds_prepare_path_for(filename); /* add this */ file = fopen(filename, "w"); Two annoyances -------------- 1. Notification messages lack a 'From ' header, necessary for mail systems using the mbox format and probably harmless for other formats. The send_notice() function can add it to the outgoing notice with the following lines of code: snprintf(buf, sizeof(buf), "From DSPAM %s", ctime(&now)); buffer_cat(b, buf); (Also suggested in http://article.gmane.org/gmane.mail.spam.dspam.user/10121.) 2. If I omit any of the files containing a notice, dspam doesn't send the notice, but it creates a corresponding timestamp file anyway. It would be useful if a timestamp was created only if a notice was sent, for example, if I decide to add a notification file later, its message would get sent without my having to manually remove the timestamp file. Inspecting send_notice() again, we see that it returns two possible errors: LOG(LOG_ERR, ERR_IO_FILE_OPEN, filename, strerror(errno)); return EFILE; ... LOG(LOG_CRIT, ERR_MEM_ALLOC); return EUNKNOWN; The first error is failure to open the file containing the notice to send. In do_notifications(), we can test for success from send_notice() before creating a timestamp file, rather than creating it unconditionally: if (!send_notice(ATX, "firstrun.txt", ATX->mailer_args, CTX->username)) { /* create timestamp file here */ } Patch ----- A patch against version 3.6.8 is attached. It makes changes to file dspam.c, in functions do_notifications() and send_notice(). The author or authors of this submission hereby release any and all copyright interest in this code, documentation, or other materials included to the DSPAM project and its primary governors. We intend this relinquishment of copyright interest in perpetuity of all present and future rights to said submission under copyright law. -- Steven Chan Vancouver Community Network