1 /* -*- C -*- 2 * Spamtest connection library 3 * File: spamtest.h 4 * (C) Alex Tutubalin <lexa@lexa.ru> 5 * and 6 * Mike Patutin <patutin@vist-v.ru> 7 * Apr-May 2003 8 * 9 * Created: Wed Apr 23 22:08:08 2003 10 */ 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <sys/time.h> 15 16 #include "msgstore.h" 17 18 #ifndef SPAM_FILTER_LIBRARY 19 #define SPAM_FILTER_LIBRARY 20 21 #ifdef __cplusplus 22 extern "C" 23 { 24 #endif 25 26 /* filter actions modes - change message/bounce message */ 27 typedef enum 28 { 29 STS_ACTION_CHANGE= 1, 30 STS_ACTION_BOUNCE= 2 31 } spamtest_reply_t; 32 33 /* change action types */ 34 typedef enum 35 { 36 STS_HEADER_NONE= 0, 37 STS_HEADER_DEL= 1, 38 STS_HEADER_CHG= 2, 39 STS_HEADER_ADD= 3, 40 STS_HEADER_NEW= 4, 41 STS_HEADER_PREPEND= 5 42 } spamtest_action_t; 43 44 #define STS_ABUF_S 4096 45 /* timeouts in milliseconds */ 46 #define STS_DEFAULT_CONNECT_TIMEOUT 1000 47 #define STS_DEFAULT_SND_RCV_TIMEOUT 50000 48 49 /* error codes */ 50 /* if you add new code - don't forget to change sts_strerror function */ 51 #define STS_ERR_NO_ERR 0 52 #define STS_ERR_OUT_OF_MEMORY -1 53 #define STS_ERR_ILLEGAL_ADDRESS -2 54 #define STS_ERR_UNABLE_TO_CONNECT -3 55 #define STS_ERR_CONNECT_TIMEOUT -4 56 #define STS_ERR_SND_RCV_TIMEOUT -5 57 #define STS_ERR_INCORRECT_PROTOCOL -6 58 #define STS_ERR_LIBRARY_ERR -7 59 #define STS_ERR_UNABLE_TO_RESOLVE -8 60 #define STS_ERR_SELECT_FD_ERR -9 61 #define STS_ERR_READ_ERR -10 62 #define STS_ERR_ILLEGAL_CONFIG -11 63 #define STS_ERR_BUFFER_NOT_PRESENT -12 64 #define STS_ERR_BUFFER_IS_FULL -14 65 #define STS_ERR_WRITE_ERR -15 66 #define STS_ERR_GET_RECORD_SIZE -16 67 #define STS_ERR_RECORD_TOO_LARGE -17 68 #define STS_ERR_INVALID_PARAMS -18 69 #define STS_ERR_NOT_INITED -19 70 71 /* sts_prepare_envelope status codes */ 72 #define STS_PREPARE_OK 0 73 #define STS_ERR_ILLEGAL_RELAY 1 74 #define STS_ERR_ILLEGAL_RCPT 2 75 #define STS_ERR_ILLEGAL_MAIL_FROM 4 76 77 78 /* flags for sts_send_body/sts_send_envelope */ 79 #define STS_REINIT_TIMEOUT 16 80 #define STS_FLUSH_DATA 32 81 #define STS_FINAL_CHUNK 64 82 83 /* flags for spamtest_session_t->flags */ 84 #define STS_USE_POLL 1 85 86 87 /* session status types */ 88 typedef enum 89 { 90 STS_SENDERROR = -2, /* I/O or other error */ 91 STS_CONTINUE = -1, /* should continue sending message */ 92 STS_ACCEPT=0, /* message accepted, result should be analyzed 93 and actions on message performed */ 94 STS_FILTER_ERROR=1, /* filter returns an error, message should be 95 rejected with 45x code */ 96 STS_REJECT=8, /* filter rejects message, 55x code should be 97 returned to sender */ 98 STS_BLACKHOLE=16, /* message blackholed - 220 code to sender, no 99 actions on message itself */ 100 STS_SMTP_ACCEPT=128 /* filter accepts message and have sent it by 101 SMTP - 220 OK to sender, no actions on message */ 102 } 103 session_status_t; 104 105 typedef enum 106 { 107 STS_SMTP_MODE= 254, 108 STS_ACTIONS_MODE= 253 109 } 110 filter_mode_t; 111 112 /* logger procedure definition */ 113 struct __spamtest_session_t; 114 struct __msg_heap_t; 115 typedef int (* logger_proc)(struct __spamtest_session_t *s,int loglevel,const char * fmt,...); 116 117 118 /* this data structure describes header actions to be performed */ 119 120 typedef struct hdraction_t 121 { 122 spamtest_action_t type; /* STS_HEADER_ADD/DEL/NEW/CHG */ 123 char *header; /* header name */ 124 char *value; /* header value (not useful 125 with STS_HEADER_DEL */ 126 } 127 hdraction_t; 128 129 130 /* describes message status returned by filter */ 131 132 typedef struct message_status_t 133 { 134 spamtest_reply_t action; /* STS_ACTION_CHANGE/BOUNCE */ 135 char *mailfrom; /* Envelope mail from for 136 generated message */ 137 recipient_list_t *rcpts; /* RCPT TO list for message */ 138 int action_count; /* count for header actions */ 139 hdraction_t *act_array; /* array of header actions */ 140 message_text_t *bouncemsg; /* message body for 141 STS_ACTION_BOUNCE */ 142 /* for internal use */ 143 int action_alloc; 144 } message_status_t; 145 146 147 /* this data structure describes spamtest session status */ 148 149 typedef struct 150 { 151 session_status_t status; /* CONTINUE/ACCEPT/... */ 152 153 char *reason; /* for REJECT/ERROR - message 154 to be sent to sender in 155 SMTP chat */ 156 157 int errorcode; /* filter error code (use 158 sts_strerror() for 159 explanation */ 160 161 int count; /* for ACCEPT status - count 162 of generated messages */ 163 164 message_status_t *ms_array; /* array of generated message 165 statuses */ 166 /* for internal use */ 167 int alloc; 168 struct __msg_heap_t *storeptr; 169 }spamtest_status_t; 170 171 172 struct __bufio_t; 173 174 /* spam session definition */ 175 typedef struct __spamtest_session_t { 176 177 /* == THESE PARAMETERS ARE SET BY USER === */ 178 179 char *access_address; /* "unix:/path/to/socket" or 180 "tcp:host:port" */ 181 char *mail_domain; /* default mail domain for address 182 * canonification */ 183 184 size_t bufsize; /* size of read/write buffers, default 185 * is 64k */ 186 187 logger_proc logp; /* logger procedure */ 188 189 long rw_timeout; /* read/write timeout in milliseconds */ 190 long connect_timeout; /* connect timeout in milliseconds */ 191 192 unsigned int flags; /* STS_USE_POLL and so on */ 193 194 195 /* == THESE PARAMETERS SHOULD BE USED BY USER === */ 196 197 spamtest_status_t status; /* session state (see spamtest_status_t 198 * definition for filed description */ 199 200 201 int recomended_size; /* recommended data size to send in 202 sts_send_body at once */ 203 204 int should_store_message; /* should user store local copy of 205 * message or filter will send mail by 206 * itself */ 207 208 char *message_id; /* Message-ID generated by filter 209 * module */ 210 211 /* internal filter data, do not touch */ 212 int filter_fd; 213 // char *relay_IP; 214 char *mail_from; 215 long timeout_curr; 216 int timeout_nq; 217 filter_mode_t filter_mode; /* SMTP or ACTIONS */ 218 recipient_list_t *rcpts; 219 recipient_list_t *attrs; 220 char *record_buf; 221 222 /* flags */ 223 int envelope_sent; /* 1=envelope already sent to filter*/ 224 int header_sent; /* 1=header already sent to filter*/ 225 int body_sent; /* 1=message body sent to 226 * filter (no more 227 * transmissions) */ 228 int chunk_sent; 229 int rb_ptr; 230 int line_complete; 231 struct timeval tvs; /* time when current operation 232 * start (do not modify!) */ 233 /* buffers */ 234 struct __bufio_t *bufio; 235 struct __msg_heap_t *store; 236 unsigned char attr_buf[STS_ABUF_S]; 237 238 unsigned int magic; /* sentinel */ 239 } spamtest_session_t; 240 241 242 /* ==== LIBRARY CALLS ==== */ 243 244 /* converts numeric STS_* error code into string */ 245 const char *sts_strerror(int ercode); 246 247 /* initialinig and start connection */ 248 int sts_init(spamtest_session_t *session); 249 int sts_reuse(spamtest_session_t *session); 250 251 // use poll instead of select() 252 253 /* 254 sts_prepare_envelope and others: 255 Initializes part (or full) of message envelope 256 DOES NOT SEND anything to filter, prepare data only 257 sts_prepare_envelope returns additional status in *status field 258 */ 259 int sts_set_sender(spamtest_session_t *s, const char *mail_from); 260 int sts_add_recipient(spamtest_session_t *s, const char *rcpt); 261 int sts_set_relay(spamtest_session_t *s, const char *relay_IP); 262 /* all of the above */ 263 int sts_prepare_envelope(spamtest_session_t *s, 264 const char* mail_from, 265 const char * rcpt, 266 const char *relay_IP, 267 int *stat); 268 269 int sts_add_attribute(spamtest_session_t *s, const char *attrname, const char *attrval); 270 271 /* 272 sts_send_body: 273 sends part of mail message to filtering engine. 274 275 Returns: 276 NULL if invalid or uninitialized session data specified 277 spamtest_status_t* structure overwise 278 279 msgbody points to part of message data (headers and body), 280 msglen sets data length 281 flags parameter is a bit mask with fields: 282 STS_REINIT_TIMEOUT - reinit timeout, discard old 283 execution statistics 284 STS_FLUSH_DATA - force flushing of data to filter and 285 reanalysing 286 STS_FINAL_CHUNK - this call of sts_send_body is final 287 (calls sts_body_end internally) 288 289 */ 290 spamtest_status_t* sts_send_body(spamtest_session_t *session, 291 const char *msgbody, 292 size_t msglen, 293 int flags); 294 295 /* 296 sts_body_end: 297 flushes I/O buffers and forces filter to return message status 298 299 Returns: 300 NULL if invalid or uninitialized session data specified 301 spamtest_status_t* structure overwise 302 flags parameter is a bit mask with fields: 303 STS_REINIT_TIMEOUT - reinit timeout, discard old 304 execution statistics 305 STS_FLUSH_DATA - force flushing of data to filter and 306 reanalysing 307 308 */ 309 spamtest_status_t* sts_body_end(spamtest_session_t *session, 310 int flags); 311 312 /* 313 sts_close: 314 closes all sockets, deallocates all memory. 315 Returns: 316 STS_ERR_ code (use sts_strerror for explanation) 317 */ 318 319 int sts_close(spamtest_session_t *session); 320 void sts_library_init(void); 321 322 323 /* === Utility and diagnostic functions === */ 324 325 /* actions/status manip */ 326 327 void dump_message_status(spamtest_status_t *smsg); 328 headers_list_t* make_changed_headers(message_status_t * sts, message_t *message); 329 spamtest_status_t* glue_actions(spamtest_status_t *s); 330 331 332 extern int sts_default_logger_log_level; 333 334 int rfc822_unquote_one(char *dest,unsigned int size, char *from, char *defdomain); 335 int rfc822_quote_one(char *dest,unsigned int size, char *from, char *defdomain); 336 recipient_list_t *rfc822_unquote_list(recipient_list_t *from,char *defdomain); 337 recipient_list_t *rfc822_quote_list(recipient_list_t *from,char *defdomain); 338 339 340 #ifdef __cplusplus 341 } 342 #endif 343 344 #endif /* SPAM_FILTER_LIBRARY */ 345