--- src/spam.c.orig 2011-01-20 19:29:51.179597017 +0300 +++ src/spam.c 2011-02-21 21:17:15.051230555 +0300 @@ -21,6 +21,9 @@ int spam_ok = 0; int spam_rc = 0; +/* push formatted line into vector */ +static int push_line(struct iovec *iov, int i, const char *fmt, ...); + int spam(uschar **listptr) { int sep = 0; uschar *list = *listptr; @@ -211,14 +214,26 @@ } /* now we are connected to spamd on spamd_sock */ - (void)string_format(spamd_buffer, - sizeof(spamd_buffer), - "REPORT SPAMC/1.2\r\nUser: %s\r\nContent-length: %ld\r\n\r\n", - user_name, - mbox_size); + int r, request_p = 0; + const char *helo; + struct iovec request_v[64]; + + r = 0; + r += push_line(request_v, request_p++, "REPORT SPAMC/1.2\r\n"); + r += push_line(request_v, request_p++, "Content-length: %lu\r\n", mbox_size); + r += push_line(request_v, request_p++, "Queue-Id: %s\r\n", message_id); + r += push_line(request_v, request_p++, "From: <%s>\r\n", sender_address); + r += push_line(request_v, request_p++, "Recipient-Number: %d\r\n", recipients_count); + for (i = 0; i < recipients_count; i ++) + r += push_line(request_v, request_p++, "Rcpt: <%s>\r\n", recipients_list[i].address); + if ((helo = expand_string(US"$sender_helo_name")) != NULL && *helo != '\0') + r += push_line(request_v, request_p++, "Helo: %s\r\n", helo); + if (sender_host_address != NULL) + r += push_line(request_v, request_p++, "IP: %s\r\n", sender_host_address); + r += push_line(request_v, request_p++, "\r\n"); /* send our request */ - if (send(spamd_sock, spamd_buffer, Ustrlen(spamd_buffer), 0) < 0) { + if (writev(spamd_sock, request_v, request_p) < 0) { (void)close(spamd_sock); log_write(0, LOG_MAIN|LOG_PANIC, "spam acl condition: spamd send failed: %s", strerror(errno)); @@ -329,7 +344,7 @@ (void)close(spamd_sock); /* dig in the spamd output and put the report in a multiline header, if requested */ - if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nContent-length: %*u\r\n\r\n%lf/%lf\r\n%n", + if( sscanf(CS spamd_buffer,"SPAMD/%7s 0 EX_OK\r\nSpam: %*s ; %lf / %lf\r\nContent-length: %*u\r\n\r\n%n", spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) { /* try to fall back to pre-2.50 spamd output */ @@ -420,4 +435,31 @@ }; } +static int +push_line(struct iovec *iov, const int i, const char *fmt, ...) +{ + va_list ap; + size_t len; + char buf[512]; + + if (i >= 64) { + log_write(0, LOG_MAIN, "rspam: %s: index out of bounds", __FUNCTION__); + return (-1); + } + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + iov[i].iov_base = string_copy(US buf); + iov[i].iov_len = len; + + if (len >= sizeof(buf)) { + log_write(0, LOG_MAIN, "rspam: %s: error, string was longer than %d", __FUNCTION__, sizeof(buf)); + return (-1); + } + + return 0; +} + #endif