4 * Reject incoming SMTP messages containing strings that tell us that the
5 * message is probably spam.
18 #include <sys/types.h>
20 #if TIME_WITH_SYS_TIME
21 # include <sys/time.h>
25 # include <sys/time.h>
34 #include <sys/socket.h>
37 #include "sysdep_decls.h"
38 #include "citserver.h"
42 #include "dynloader.h"
49 #include "internet_addressing.h"
50 #include "clientsocket.h"
54 #ifdef ___NOT_CURRENTLY_IN_USE___
55 /* Scan a message for spam */
56 int spam_filter(struct CtdlMessage *msg) {
57 int spam_strings_found = 0;
58 struct spamstrings_t *sptr;
61 /* Bail out if there's no message text */
62 if (msg->cm_fields['M'] == NULL) return(0);
66 ptr = msg->cm_fields['M'];
67 while (ptr++[0] != 0) {
68 for (sptr = spamstrings; sptr != NULL; sptr = sptr->next) {
69 if (!strncasecmp(ptr, sptr->string,
70 strlen(sptr->string))) {
76 if (spam_strings_found) {
77 if (msg->cm_fields['0'] != NULL) {
78 phree(msg->cm_fields['0']);
80 msg->cm_fields['0'] = strdoop("Unsolicited spam rejected");
81 return(spam_strings_found);
91 * Connect to the SpamAssassin server and scan a message.
93 int spam_assassin(struct CtdlMessage *msg) {
101 #define SPAMASSASSIN_HOST "127.0.0.1"
102 #define SPAMASSASSIN_PORT "783"
105 if (msg_fp == NULL) return(0);
107 /* Connect to the SpamAssassin server */
108 lprintf(9, "Connecting to SpamAssassin\n");
109 sock = sock_connect(SPAMASSASSIN_HOST, SPAMASSASSIN_PORT, "tcp");
111 /* If the service isn't running, just pass the mail
112 * through. Potentially throwing away mails isn't good.
117 /* Measure the message (I don't like doing this with a tempfile
118 but right now it's the only way)
120 lprintf(9, "Measuring message\n");
121 CtdlRedirectOutput(msg_fp, -1);
122 CtdlOutputPreLoadedMsg(msg, 0L, MT_RFC822, 0, 0, 1);
123 CtdlRedirectOutput(NULL, -1);
124 fseek(msg_fp, 0L, SEEK_END);
125 content_length = ftell(msg_fp);
127 lprintf(9, "Content-length is %ld\n", content_length);
130 lprintf(9, "Transmitting command\n");
131 sprintf(buf, "CHECK SPAMC/1.2\r\nContent-length: %ld\r\n\r\n",
134 lprintf(9, "sock_write() returned %d\n",
135 sock_write(sock, buf, strlen(buf))
137 while (content_length > 0) {
138 block_length = sizeof(buf);
139 if (block_length > content_length) {
140 block_length = content_length;
142 fread(buf, block_length, 1, msg_fp);
143 sock_write(sock, buf, block_length);
144 content_length -= block_length;
145 lprintf(9, "Wrote %ld bytes (%ld remaining)\n",
146 block_length, content_length);
148 fclose(msg_fp); /* this also deletes the file */
150 /* Close one end of the socket connection; this tells SpamAssassin
153 lprintf(9, "sock_shutdown() returned %d\n",
154 sock_shutdown(sock, SHUT_WR)
158 lprintf(9, "Awaiting response\n");
159 if (sock_gets(sock, buf) < 0) {
162 lprintf(9, "<%s\n", buf);
163 if (strncasecmp(buf, "SPAMD", 5)) {
166 if (sock_gets(sock, buf) < 0) {
169 lprintf(9, "<%s\n", buf);
170 if (!strncasecmp(buf, "Spam: True", 10)) {
175 if (msg->cm_fields['0'] != NULL) {
176 phree(msg->cm_fields['0']);
178 msg->cm_fields['0'] = strdoop(
179 "Message rejected by SpamAssassin");
188 char *Dynamic_Module_Init(void)
191 /* ** This one isn't in use. It's a spam filter I wrote, but we're going to
192 try the SpamAssassin stuff instead.
193 CtdlRegisterMessageHook(spam_filter, EVT_SMTPSCAN);
197 CtdlRegisterMessageHook(spam_assassin, EVT_SMTPSCAN);