00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "smtp.h"
00017
00018 static FILE *logfile;
00019 static int curday = 0;
00020
00021
00022
00023 #ifdef _WIN32
00024 int strcasecmp(const char *s1, const char *s2)
00025 {
00026 register int c;
00027
00028 while ((c = tolower(*s1)) == tolower(*s2)) {
00029 if (c == 0)
00030 return 0;
00031 s1++;
00032 s2++;
00033 }
00034 if (c < tolower(*s2))
00035 return -1;
00036 return 1;
00037 }
00038 #endif
00039
00040 static int get_logname(char *name, int count, struct tm *tm)
00041 {
00042
00043 char timestamp[32];
00044
00045 if (!tm) {
00046 time_t t;
00047
00048 time(&t);
00049 tm = localtime(&t);
00050 }
00051
00052 strftime(timestamp, count, "%Y%m%d", tm);
00053 snprintf(name, count, "logs/%s.%s", "anopesmtp", timestamp);
00054 curday = tm->tm_yday;
00055
00056 return 1;
00057 }
00058
00059
00060
00061
00062
00063 void close_log(void)
00064 {
00065 if (!logfile)
00066 return;
00067 fclose(logfile);
00068 logfile = NULL;
00069 }
00070
00071
00072
00073 static void remove_log(void)
00074 {
00075 time_t t;
00076 struct tm tm;
00077
00078 char name[PATH_MAX];
00079
00080 time(&t);
00081 t -= (60 * 60 * 24 * 30);
00082 tm = *localtime(&t);
00083
00084 if (!get_logname(name, sizeof(name), &tm))
00085 return;
00086 unlink(name);
00087 }
00088
00089
00090
00091
00092
00093
00094 int open_log(void)
00095 {
00096 char name[PATH_MAX];
00097
00098 if (logfile)
00099 return 0;
00100
00101 if (!get_logname(name, sizeof(name), NULL))
00102 return 0;
00103 logfile = fopen(name, "a");
00104
00105 if (logfile)
00106 setbuf(logfile, NULL);
00107 return logfile != NULL ? 0 : -1;
00108 }
00109
00110
00111
00112 static void checkday(void)
00113 {
00114 time_t t;
00115 struct tm tm;
00116
00117 time(&t);
00118 tm = *localtime(&t);
00119
00120 if (curday != tm.tm_yday) {
00121 close_log();
00122 remove_log();
00123 open_log();
00124 }
00125 }
00126
00127
00128
00129
00130
00131
00132
00133 void alog(const char *fmt, ...)
00134 {
00135 va_list args;
00136 time_t t;
00137 struct tm tm;
00138 char buf[256];
00139 int errno_save = errno;
00140
00141 if (!smtp_debug) {
00142 return;
00143 }
00144
00145 checkday();
00146
00147 if (!fmt) {
00148 return;
00149 }
00150
00151 va_start(args, fmt);
00152 time(&t);
00153 tm = *localtime(&t);
00154 strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", &tm);
00155 if (logfile && args) {
00156 fputs(buf, logfile);
00157 vfprintf(logfile, fmt, args);
00158 fputc('\n', logfile);
00159 }
00160 va_end(args);
00161 errno = errno_save;
00162 }
00163
00164
00165
00166
00167 char *strip(char *buf)
00168 {
00169 char *c;
00170 if ((c = strchr(buf, '\n')))
00171 *c = 0;
00172 if ((c = strchr(buf, '\r')))
00173 *c = 0;
00174 return buf;
00175 }
00176
00177
00178
00179
00180
00181
00182 char *lftocrlf(char *buf)
00183 {
00184 char *result = malloc(strlen(buf) + 2);
00185 strip(buf);
00186 strcpy(result, buf);
00187 strcat(result, "\r\n");
00188 return result;
00189 }
00190
00191
00192
00193
00194 void smtp_add_header(char *header)
00195 {
00196 struct smtp_header *head = malloc(sizeof(struct smtp_header));
00197
00198 head->header = lftocrlf(header);
00199 head->next = NULL;
00200
00201 if (!mail.smtp_headers) {
00202 mail.smtp_headers = head;
00203 }
00204 if (mail.smtp_headers_tail) {
00205 mail.smtp_headers_tail->next = head;
00206 }
00207 mail.smtp_headers_tail = head;
00208 }
00209
00210
00211
00212
00213 int smtp_is_header(char *buf)
00214 {
00215 char *tmp = strchr(buf, ' ');
00216
00217 if (!tmp)
00218 return 0;
00219
00220 if (*(tmp - 1) == ':')
00221 return 1;
00222 return 0;
00223 }
00224
00225
00226
00227
00228 void smtp_parse_header(char *buf, char **header, char **value)
00229 {
00230 strip(buf);
00231
00232 *header = strtok(buf, " ");
00233 *value = strtok(NULL, "");
00234 if (*header)
00235 (*header)[strlen(*header) - 1] = 0;
00236 }
00237
00238
00239
00240
00241 int smtp_is_end(char *buf)
00242 {
00243 if (*buf == '.')
00244 if (*(buf + 1) == '\r' || *(buf + 1) == '\n')
00245 return 1;
00246
00247 return 0;
00248 }
00249
00250
00251
00252
00253 void smtp_set_from(char *from)
00254 {
00255 mail.from = strdup(from);
00256 }
00257
00258
00259
00260
00261 void smtp_set_to(char *to)
00262 {
00263 char *c;
00264
00265 if ((c = strrchr(to, '<')) && *(c + 1)) {
00266 to = c + 1;
00267 to[strlen(to) - 1] = 0;
00268 }
00269 mail.to = strdup(to);
00270 }
00271
00272
00273
00274
00275 void smtp_add_body_line(char *line)
00276 {
00277 struct smtp_body_line *body;
00278
00279 body = malloc(sizeof(struct smtp_body_line));
00280
00281 body->line = lftocrlf(line);
00282 body->next = NULL;
00283
00284 if (!mail.smtp_body)
00285 mail.smtp_body = body;
00286 if (mail.smtp_body_tail)
00287 mail.smtp_body_tail->next = body;
00288 mail.smtp_body_tail = body;
00289
00290 }
00291
00292
00293
00294
00295 int smtp_connect(char *host, unsigned short port)
00296 {
00297 struct sockaddr_in addr;
00298
00299 if ((mail.sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
00300 return 0;
00301
00302 if ((addr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
00303 struct hostent *hent;
00304 if (!(hent = gethostbyname(host)))
00305 return 0;
00306 memcpy(&addr.sin_addr, hent->h_addr, hent->h_length);
00307 }
00308 addr.sin_family = AF_INET;
00309 addr.sin_port = htons(port ? port : 25);
00310 if (connect(mail.sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
00311 ano_sockclose(mail.sock);
00312 return 0;
00313 }
00314
00315 return 1;
00316 }
00317
00318
00319
00320
00321 int smtp_send(char *text)
00322 {
00323 int result = ano_sockwrite(mail.sock, text, strlen(text));
00324
00325 alog("SMTP: sent %s",text);
00326
00327 if (result == SOCKET_ERROR)
00328 ano_sockclose(mail.sock);
00329
00330 return result;
00331 }
00332
00333
00334
00335
00336 int smtp_read(char *buf, int len)
00337 {
00338 int result;
00339
00340 memset(buf, 0, len);
00341 result = ano_sockread(mail.sock, buf, len);
00342
00343 if (result == SOCKET_ERROR)
00344 ano_sockclose(mail.sock);
00345
00346 return result;
00347 }
00348
00349
00350
00351
00352 int smtp_get_code(char *text)
00353 {
00354 char *tmp = strtok(text, " ");
00355
00356 if (!tmp)
00357 return 0;
00358
00359 return atol(tmp);
00360 }
00361
00362
00363
00364
00365 int smtp_send_email()
00366 {
00367 char buf[1024];
00368 struct smtp_header *head;
00369 struct smtp_body_line *body;
00370 int code;
00371 int skip_done = 0;
00372
00373 if (!smtp_read(buf, 1024)) {
00374 alog("SMTP: error reading buffer");
00375 return 0;
00376 }
00377
00378 code = smtp_get_code(buf);
00379 if (code != 220) {
00380 alog("SMTP: error expected code 220 got %d",code);
00381 return 0;
00382 }
00383
00384 if (!smtp_send("HELO anope\r\n")) {
00385 alog("SMTP: error writting to socket");
00386 return 0;
00387 }
00388
00389 if (!smtp_read(buf, 1024)) {
00390 alog("SMTP: error reading buffer");
00391 return 0;
00392 }
00393
00394 code = smtp_get_code(buf);
00395 if (code != 250) {
00396 alog("SMTP: error expected code 250 got %d",code);
00397 return 0;
00398 }
00399
00400 strcpy(buf, "MAIL FROM: <");
00401 strcat(buf, mail.from);
00402 strcat(buf, ">\r\n");
00403
00404 if (!smtp_send(buf)) {
00405 alog("SMTP: error writting to socket");
00406 return 0;
00407 }
00408
00409 if (!smtp_read(buf, 1024)) {
00410 alog("SMTP: error reading buffer");
00411 return 0;
00412 }
00413
00414 code = smtp_get_code(buf);
00415 if (code != 250)
00416 return 0;
00417
00418 strcpy(buf, "RCPT TO: <");
00419 strcat(buf, mail.to);
00420 strcat(buf, ">\r\n");
00421
00422 if (!smtp_send(buf)) {
00423 alog("SMTP: error writting to socket");
00424 return 0;
00425 }
00426
00427 if (!smtp_read(buf, 1024)) {
00428 alog("SMTP: error reading buffer");
00429 return 0;
00430 }
00431
00432 code = smtp_get_code(buf);
00433 if (smtp_get_code(buf) != 250) {
00434 alog("SMTP: error expected code 250 got %d",code);
00435 return 0;
00436 }
00437
00438 if (!smtp_send("DATA\r\n")) {
00439 alog("SMTP: error writting to socket");
00440 return 0;
00441 }
00442
00443 if (!smtp_read(buf, 1024)) {
00444 alog("SMTP: error reading buffer");
00445 return 0;
00446 }
00447
00448 code = smtp_get_code(buf);
00449 if (code != 354) {
00450 alog("SMTP: error expected code 354 got %d",code);
00451 return 0;
00452 }
00453
00454 for (head = mail.smtp_headers; head; head = head->next) {
00455 if (!smtp_send(head->header)) {
00456 alog("SMTP: error writting to socket");
00457 return 0;
00458 }
00459 }
00460
00461 if (!smtp_send("\r\n")) {
00462 alog("SMTP: error writting to socket");
00463 return 0;
00464 }
00465
00466 for (body = mail.smtp_body; body; body = body->next) {
00467 if (skip_done) {
00468 if (!smtp_send(body->line)) {
00469 alog("SMTP: error writting to socket");
00470 return 0;
00471 }
00472 } else {
00473 skip_done = 1;
00474 }
00475 }
00476
00477 if (!smtp_send("\r\n.\r\n")) {
00478 alog("SMTP: error writting to socket");
00479 return 0;
00480 }
00481
00482 return 1;
00483 }
00484
00485
00486
00487 void smtp_disconnect()
00488 {
00489 smtp_send("QUIT\r\n");
00490 ano_sockclose(mail.sock);
00491 }
00492
00493
00494
00495 void mail_cleanup()
00496 {
00497 struct smtp_header *headers, *nexth;
00498 struct smtp_body_line *body, *nextb;
00499
00500 if (mail.from)
00501 free(mail.from);
00502 if (mail.to)
00503 free(mail.to);
00504
00505 headers = mail.smtp_headers;
00506 while (headers) {
00507 nexth = headers->next;
00508 free(headers->header);
00509 free(headers);
00510 headers = nexth;
00511 }
00512
00513 body = mail.smtp_body;
00514 while (body) {
00515 nextb = body->next;
00516 free(body->line);
00517 free(body);
00518 body = nextb;
00519 }
00520 }
00521
00522
00523
00524 int main(int argc, char *argv[])
00525 {
00526 char buf[8192];
00527
00528
00529
00530
00531
00532 int headers_done = 0;
00533
00534 #ifdef _WIN32
00535 WSADATA wsa;
00536 #endif
00537 char *server, *aport;
00538 short port;
00539
00540 if (argc == 1)
00541 return 0;
00542
00543 server = strtok(argv[1], ":");
00544 if ((aport = strtok(NULL, ""))) {
00545 port = atoi(aport);
00546 } else {
00547 port = 25;
00548 }
00549
00550 if (!server) {
00551 alog("No Server");
00552
00553 return 0;
00554 } else {
00555 alog("SMTP: server %s port %d",server,port);
00556 }
00557
00558 memset(&mail, 0, sizeof(mail));
00559
00560
00561
00562 #ifdef _WIN32
00563 if (WSAStartup(MAKEWORD(1, 1), &wsa) != 0)
00564 return 0;
00565 #endif
00566
00567
00568 while (fgets(buf, 8192, stdin)) {
00569 if (smtp_is_header(buf) && !headers_done) {
00570 char *header, *value;
00571 smtp_add_header(buf);
00572 smtp_parse_header(buf, &header, &value);
00573 if (!strcasecmp(header, "from")) {
00574 alog("SMTP: from: %s",value);
00575 smtp_set_from(value);
00576 } else if (!strcasecmp(header, "to")) {
00577 alog("SMTP: to: %s",value);
00578 smtp_set_to(value);
00579 } else if (smtp_is_end(buf)) {
00580 break;
00581 } else {
00582 headers_done = 1;
00583 smtp_add_body_line(buf);
00584 }
00585 } else {
00586 smtp_add_body_line(buf);
00587 }
00588 }
00589
00590 if (!smtp_connect(server, port)) {
00591 alog("SMTP: failed to connect to %s:%d",server, port);
00592 mail_cleanup();
00593 return 0;
00594 }
00595 if (!smtp_send_email()) {
00596 alog("SMTP: error during sending of mail");
00597 mail_cleanup();
00598 return 0;
00599 }
00600 smtp_disconnect();
00601 mail_cleanup();
00602
00603 return 1;
00604 }