/* * mail2nntp.c * * The mail2nntp program reads mail from stdin and posts it * to one or more newsgroups using NNTP. It delivers the mes- * sage immediately or fails. If queuing is desired it can * operate as a LMTP server. * * The OSSP Project, Cable & Wireless Deutschland GmbH * Thomas Lotterer, * */ #include #include #include #include #include /* third party */ #include "str.h" /* own headers */ #include "lmtp.h" #define ERR_EXECUTION -1 #define ERR_DELIVERY -2 #define MESSAGE_MAXLEN 8*1024*1024 static ssize_t trace_read(int d, void *buf, size_t nbytes); static ssize_t trace_write(int d, const void *buf, size_t nbytes); static lmtp_rc_t lmtp_cb_lhlo (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx); static lmtp_rc_t lmtp_cb_mail (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx); static lmtp_rc_t lmtp_cb_rcpt (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx); static lmtp_rc_t lmtp_cb_data (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx); static lmtp_rc_t lmtp_cb_quit (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx); static void usage(char *command); static void test(void); int main(int argc, char **argv) { int i; // general purpose scratch int, index ... // read in the arguments while ((i = getopt(argc, argv, "p:l:h:m:tv")) != -1) switch (i) { case 'p': // -p protocol break; case 'l': // -l logtarget break; case 'h': // -h host[:port] break; case 'm': // -m mode break; case 'd': // -t (tracing) break; case 'v': // -v (verbose) break; case '?': default: //FIXME usage(argv[0]); //FIXME exit(ERR_EXECUTION); } argc -= optind; argv += optind; // remaining args is/are newsgroup/s //FIXME printf("Hello, World!\n"); test(); //FIXME printf("Hello, Again!\n"); return 0; } /* * print usage information * */ static void usage(char *command) { fprintf(stderr, "USAGE: %s [-p protocol] [-l logtarget] "\ "[-h host[:port]] [-m mode] [-t] [-v] newsgroup [newsgroup ...]\n", command); return; } /* * tracing * */ ssize_t trace_read(int d, void *buf, size_t nbytes) { ssize_t rc; int tracefile; rc = read(d, buf, nbytes); if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) { write(tracefile, buf, rc); close(tracefile); } return rc; } ssize_t trace_write(int d, const void *buf, size_t nbytes) { ssize_t rc; int tracefile; rc = write(d, buf, nbytes); if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) { write(tracefile, buf, rc); close(tracefile); } return rc; } /* * test a function * */ extern void lmtp_debug_dumplmtp(lmtp_t *lmtp); static void test(void) { lmtp_t *lmtp; lmtp_rc_t rc; lmtp_req_t req; lmtp_res_t res; lmtp_io_t io; #define BUFLEN 100 char buf[BUFLEN]; io.read=trace_read; io.write=trace_write; io.select=select; lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO, &io); // lmtp_debug_dumplmtp(lmtp); lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, NULL, NULL, NULL); lmtp_register(lmtp, "MAIL", lmtp_cb_mail, NULL, NULL, NULL); lmtp_register(lmtp, "RCPT", lmtp_cb_rcpt, NULL, NULL, NULL); lmtp_register(lmtp, "DATA", lmtp_cb_data, NULL, NULL, NULL); lmtp_register(lmtp, "QUIT", lmtp_cb_quit, NULL, NULL, NULL); // lmtp_debug_dumplmtp(lmtp); /* printf("DEBUG: 05 lmtp_response\n"); res.statuscode="123"; res.dsncode="1.2.3"; res.statusmsg="Hello,\nthis is a\nmultiline\nmessage"; lmtp_response(lmtp, &res); */ /* do { rc = lmtp_readline(lmtp, buf, BUFLEN); printf("DEBUG: 06 lmtp_readline=%d ***%s***\n", rc, buf); } while(rc == LMTP_OK); */ /* do { rc = lmtp_request(lmtp, &req); printf("DEBUG: 07 lmtp_request=%d ***%s***%s***\n", rc, req.verb, req.msg); } while(rc == LMTP_OK || rc == LMTP_ERR_VERB); */ /* printf("DEBUG: 08 lmtp_loop=%d\n", */ lmtp_loop(lmtp) /*)*/; /* printf("DEBUG: 99.\n"); */ return; } static lmtp_rc_t lmtp_cb_lhlo(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx) { lmtp_res_t res; lmtp_rc_t rc = LMTP_OK; res.statuscode = "250"; res.dsncode = NULL; /* DSN not used for greeting */ res.statusmsg = "ENHANCEDSTATUSCODES\nDSN"; /* RFC2034, RFC1894 */ lmtp_response(lmtp, &res); return rc; } static lmtp_rc_t lmtp_cb_mail(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx) { lmtp_res_t res; lmtp_rc_t rc = LMTP_OK; res.statuscode = "553"; res.dsncode = "5.1.8"; res.statusmsg = "bad sender FIXME"; res.statuscode = "250"; res.dsncode = "2.1.0"; res.statusmsg = "sender ok FIXME"; lmtp_response(lmtp, &res); return rc; } static lmtp_rc_t lmtp_cb_rcpt(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx) { lmtp_res_t res; lmtp_rc_t rc = LMTP_OK; res.statuscode = "250"; res.dsncode = "2.1.5"; res.statusmsg = "Recipient ok FIXME"; lmtp_response(lmtp, &res); return rc; } static lmtp_rc_t lmtp_cb_data(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx) { lmtp_res_t res; lmtp_rc_t rc = LMTP_OK; char *buf; char errorstring[128]; res.statuscode = "354"; res.dsncode = NULL; /* DSN not used for data */ res.statusmsg = "Enter mail, end with \".\" on a line by itself"; lmtp_response(lmtp, &res); rc = lmtp_readmsg(lmtp, &buf, MESSAGE_MAXLEN); if(rc == LMTP_OK) { // printf("DEBUG: message=***%s***\n", buf); res.statuscode = "250"; res.dsncode = "2.0.0"; res.statusmsg = "Message accepted for delivery"; } else if (rc == LMTP_ERR_OVERFLOW) { res.statuscode = "500"; res.dsncode = "5.0.0"; res.statusmsg = "Message accepted for delivery"; } else if (rc == LMTP_ERR_SYSTEM) { res.statuscode = "500"; res.dsncode = "5.0.0"; str_format(errorstring, sizeof(errorstring), "Message accepted for delivery %s", strerror(errno)); res.statusmsg = errorstring; } lmtp_response(lmtp, &res); return rc; } static lmtp_rc_t lmtp_cb_quit(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx) { lmtp_res_t res; lmtp_rc_t rc = LMTP_EOF; res.statuscode = "221"; res.dsncode = "2.0.0"; res.statusmsg = "Closing connection."; lmtp_response(lmtp, &res); return rc; }