--- lmtp2nntp.c 2001/08/14 14:42:41 1.17
+++ lmtp2nntp.c 2001/08/16 15:00:50 1.18
@@ -74,6 +74,9 @@
int option_verbose;
int option_tracing;
int option_groupmode;
+ int option_deliverymode;
+ char *option_deliverymodefakestatus;
+ char *option_deliverymodefakedsn;
int nsc;
struct ns ns[MAXNEWSSERVICES];
char *azGroupargs;
@@ -88,6 +91,12 @@
GROUPMODE_HEADER
};
+enum {
+ DELIVERYMODE_FAKE,
+ DELIVERYMODE_POST,
+ DELIVERYMODE_FEED
+};
+
/*
* print usage information
*/
@@ -130,6 +139,9 @@
ctx->option_verbose = FALSE;
ctx->option_tracing = FALSE;
ctx->option_groupmode = GROUPMODE_ARG;
+ ctx->option_deliverymode = DELIVERYMODE_FAKE;
+ ctx->option_deliverymodefakestatus = "553"; /* Requested action not taken: mailbox name not allowed */
+ ctx->option_deliverymodefakedsn = "5.7.1"; /* Delivery not authorized, message refused */
ctx->nsc = 0;
for (i=0; i < MAXNEWSSERVICES; i++) {
ctx->ns[i].h = "";
@@ -157,8 +169,48 @@
#endif
/* read in the arguments */
- while ((i = getopt(argc, argv, "g:h:t:v")) != -1) {
+ while ((i = getopt(argc, argv, "d:g:h:t:v")) != -1) {
switch (i) {
+ case 'd': /* -d deliverymode */
+ if (strcasecmp(optarg, "post") == 0)
+ ctx->option_deliverymode = DELIVERYMODE_POST;
+ else if (strcasecmp(optarg, "feed") == 0)
+ ctx->option_deliverymode = DELIVERYMODE_FEED;
+ else {
+ if (strlen(optarg) != 9) {
+ fprintf(stderr, "%s:Error: Invalid format or length \"%s\" to option -d\n", progname, optarg);
+ exit(ERR_EXECUTION);
+ }
+
+ if (optarg[3] != '/') {
+ fprintf(stderr, "%s:Error: Invalid format or missing slash \"%s\" to option -d\n", progname, optarg);
+ exit(ERR_EXECUTION);
+ }
+
+ optarg[3] = '\0';
+ ctx->option_deliverymodefakestatus = &optarg[0];
+ ctx->option_deliverymodefakedsn = &optarg[4];
+
+ if ( strlen(ctx->option_deliverymodefakestatus) != 3
+ || !isdigit(ctx->option_deliverymodefakestatus[0])
+ || !isdigit(ctx->option_deliverymodefakestatus[1])
+ || !isdigit(ctx->option_deliverymodefakestatus[2])) {
+ fprintf(stderr, "%s:Error: Invalid status in format \"%s\" to option -d\n", progname, optarg);
+ exit(ERR_EXECUTION);
+ }
+
+ if ( (strlen(ctx->option_deliverymodefakedsn) != 5)
+ || !isdigit(ctx->option_deliverymodefakedsn[0])
+ || (ctx->option_deliverymodefakedsn[1] != '.')
+ || !isdigit(ctx->option_deliverymodefakedsn[2])
+ || (ctx->option_deliverymodefakedsn[3] != '.')
+ || !isdigit(ctx->option_deliverymodefakedsn[4])
+ || (ctx->option_deliverymodefakedsn[0] != ctx->option_deliverymodefakestatus[0])) {
+ fprintf(stderr, "%s:Error: Invalid dsn in format \"%s\" to option -d\n", progname, optarg);
+ exit(ERR_EXECUTION);
+ }
+ }
+ break;
case 'g': /* -g groupmode */
if (strcasecmp(optarg, "arg") == 0)
ctx->option_groupmode = GROUPMODE_ARG;
@@ -355,9 +407,17 @@
}
} while (i < ctx->nsc);
+ /* RFC0821 4.2.1. REPLY CODES BY FUNCTION GROUPS
+ * "421 <domain> Service not available, closing transmission channel [This
+ * may be a reply to any command if the service knows it must shut down]"
+ *
+ * RFC1893 2. Status Codes, 3.5 Network and Routing Status
+ * 4.X.X Persistent Transient Failure
+ * X.4.1 No answer from host
+ */
if (ctx->nsc == 0) {
- res.statuscode = "501";
- res.dsncode = "5.0.0";
+ res.statuscode = "421";
+ res.dsncode = "4.4.1";
res.statusmsg = "No connection to any NNTP Service."; //FIXME add error strings from above DEBUGs
lmtp_response(lmtp, &res);
return LMTP_OK;
@@ -715,26 +775,72 @@
}
//fprintf(stderr, "DEBUG: after msg_join\n");
- bSuccess = FALSE;
+ bSuccess = NNTP_EOF; /* assume a hard error for the worst case */
for (i = 0; i < ctx->nsc; i++) {
//fprintf(stderr, "DEBUG: trying service %s\n", ctx->ns[i].h);
- if ((rc = nntp_post(ctx->ns[i].nntp, ctx->msg)) == NNTP_OK)
- bSuccess = TRUE;
+ switch (ctx->option_deliverymode) {
+ case DELIVERYMODE_FAKE:
+ break;
+ case DELIVERYMODE_POST:
+ rc = nntp_post(ctx->ns[i].nntp, ctx->msg);
+ break;
+ case DELIVERYMODE_FEED:
+ rc = nntp_feed(ctx->ns[i].nntp, ctx->msg);
+ break;
+ }
+ if (rc == NNTP_OK)
+ bSuccess = NNTP_OK;
+ if ( bSuccess != NNTP_OK
+ && (
+ (rc == NNTP_TIMEOUT)
+ || (rc == NNTP_ERR_SYSTEM)
+ || (rc == NNTP_DEFER)
+ )
+ )
+ bSuccess = NNTP_DEFER;
}
//FIXME rc has only last error
+ /* RFC0821 4.2.1. REPLY CODES BY FUNCTION GROUPS
+ * "250 Requested mail action okay, completed"
+ * "451 Requested action aborted: local error in processing"
+ * "554 Transaction failed"
+ *
+ * RFC1893 2. Status Codes
+ * 2.X.X Success
+ * 4.X.X Persistent Transient Failure
+ * 5.X.X Permanent Failure
+ *
+ * RFC1893 3.5 Network and Routing Status
+ * X.0.0 Other undefined Status
+ * X.4.2 Bad connection
+ */
rcpt = NULL;
while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
- if (bSuccess == TRUE) {
- str_format(errorstring, sizeof(errorstring), "Message accepted for delivery to %s", rcpt);
- res.statuscode = "250";
- res.dsncode = "2.0.0";
- res.statusmsg = errorstring;
+ if (ctx->option_deliverymode == DELIVERYMODE_FAKE) {
+ res.statuscode = ctx->option_deliverymodefakestatus;
+ res.dsncode = ctx->option_deliverymodefakedsn;
+ res.statusmsg = "NNTP noop fake return";
} else {
- str_format(errorstring, sizeof(errorstring), "Last error posting message: %s", nntp_error(rc));
- res.statuscode = "500";
- res.dsncode = "5.0.0";
- res.statusmsg = errorstring;
+ switch (bSuccess) {
+ case NNTP_OK:
+ str_format(errorstring, sizeof(errorstring), "Message accepted for delivery to %s", rcpt);
+ res.statuscode = "250";
+ res.dsncode = "2.0.0";
+ res.statusmsg = errorstring;
+ break;
+ case NNTP_DEFER:
+ res.statuscode = "451";
+ res.dsncode = "4.4.2";
+ res.statusmsg = "Requested action aborted, local error in processing.";
+ lmtp_response(lmtp, &res);
+ break;
+ default:
+ str_format(errorstring, sizeof(errorstring), "Last error posting message: %s", nntp_error(rc));
+ res.statuscode = "554";
+ res.dsncode = "5.4.2";
+ res.statusmsg = errorstring;
+ }
}
lmtp_response(lmtp, &res);
}
|