changeset 112:eb5ec53ecbc7

Make mlmmj-send capable of handling a bounce from the relayhost and invoke mlmmj-bounce to handle it like any other bounce. This is (hopefully) the last SMTP functionality we have to implement.
author mmj
date Thu, 27 May 2004 09:31:31 +1000
parents f8e554e122a1
children c25dfbff557e
files src/mlmmj-send.c
diffstat 1 files changed, 133 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/mlmmj-send.c	Thu May 27 09:29:48 2004 +1000
+++ b/src/mlmmj-send.c	Thu May 27 09:31:31 2004 +1000
@@ -19,6 +19,8 @@
 #include <sys/wait.h>
 #include <signal.h>
 #include <libgen.h>
+#include <syslog.h>
+#include <stdarg.h>
 
 #include "mlmmj-send.h"
 #include "mlmmj.h"
@@ -97,56 +99,134 @@
 	return bounceaddr;
 }
 
+int bouncemail(const char *listdir, const char *mlmmjbounce, const char *from)
+{
+	char *myfrom = strdup(from);
+	char *addr, *num, *c;
+	size_t len;
+	pid_t pid = 0;
+
+	if((c = strchr(myfrom, '@')) == NULL) {
+		log_error(LOG_ARGS, "strchr(%s, '@') = [%s]", myfrom, c);
+		free(myfrom);
+		return 0; /* Success when mailformed 'from' */
+	}
+	*c = '\0';
+	num = strrchr(myfrom, '-');
+	num++;
+	c = strchr(myfrom, RECIPDELIM);
+	myfrom = strchr(c, '-');
+	myfrom++;
+	len = num - myfrom - 1;
+	addr = malloc(len + 1);
+	addr[len] = '\0';
+	memcpy(addr, myfrom, len);
+	errno = 0;
+
+	pid = fork();
+	
+	if(pid < 0) {
+		log_error(LOG_ARGS, "fork() failed!");
+		return 1;
+	}
+	
+	if(pid > 0)
+		return 0;
+	
+	execlp(mlmmjbounce, mlmmjbounce,
+			"-L", listdir,
+			"-a", addr,
+			"-n", num, 0);
+
+	log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjbounce);
+
+	return 1;
+}
+
 int send_mail(int sockfd, const char *from, const char *to,
-	      const char *replyto, FILE *mailfile)
+	      const char *replyto, FILE *mailfile,
+	      const char *listdir, const char *mlmmjbounce)
 {
 	int retval = 0;
+	char *reply;
 
-	if((retval = write_mail_from(sockfd, from)) != 0) {
+	retval = write_mail_from(sockfd, from);
+	if(retval) {
 		log_error(LOG_ARGS, "Could not write MAIL FROM\n");
 		return retval;
 	}
-	if((retval = checkwait_smtpreply(sockfd, MLMMJ_FROM)) != 0) {
-		log_error(LOG_ARGS, "Wrong MAIL FROM:\n");
-		return retval;
+	reply = checkwait_smtpreply(sockfd, MLMMJ_FROM);
+	if(reply) {
+		log_error(LOG_ARGS, "Error in MAIL FROM. Reply = [%s]",
+				reply);
+		free(reply);
+		write_rset(sockfd);
+		checkwait_smtpreply(sockfd, MLMMJ_RSET);
+		return MLMMJ_FROM;
 	}
-
-	if((retval = write_rcpt_to(sockfd, to)) != 0) {
+	retval = write_rcpt_to(sockfd, to);
+	if(retval) {
 		log_error(LOG_ARGS, "Could not write RCPT TO:\n");
 		return retval;
 	}
-	if((retval = checkwait_smtpreply(sockfd, MLMMJ_RCPTTO)) != 0) {
-		log_error(LOG_ARGS, "Wrong RCPT TO:\n");
-		return retval;
+
+	reply = checkwait_smtpreply(sockfd, MLMMJ_RCPTTO);
+	if(reply) {
+		write_rset(sockfd);
+		checkwait_smtpreply(sockfd, MLMMJ_RSET);
+		if(mlmmjbounce && (reply[1] == '5') && ((reply[0] == '4') ||
+					(reply[0] == '5'))) {
+			return bouncemail(listdir, mlmmjbounce, from);
+		} else {
+			log_error(LOG_ARGS, "Error in RCPT TO. Reply = [%s]",
+					reply);
+			free(reply);
+			return MLMMJ_RCPTTO;
 	}
-	if((retval = write_data(sockfd)) != 0) {
+	}
+
+	retval = write_data(sockfd);
+	if(retval) {
 		log_error(LOG_ARGS, "Could not write DATA\b");
 		return retval;
 	}
-	if((retval = checkwait_smtpreply(sockfd, MLMMJ_DATA)) != 0) {
-		log_error(LOG_ARGS, "Mailserver not ready for DATA\n");
-		return retval;
+
+	reply = checkwait_smtpreply(sockfd, MLMMJ_DATA);
+	if(reply) {
+		log_error(LOG_ARGS, "Error with DATA. Reply = [%s]", reply);
+		write_rset(sockfd);
+		checkwait_smtpreply(sockfd, MLMMJ_RSET);
+		return MLMMJ_DATA;
 	}
-	if(replyto)
-		if((retval = write_replyto(sockfd, replyto)) != 0) {
+
+	if(replyto) {
+		retval = write_replyto(sockfd, replyto);
+		if(retval) {
 			log_error(LOG_ARGS, "Could not write reply-to addr.\n");
 			return retval;
 		}
-	if((retval = write_mailbody_from_file(sockfd, mailfile)) != 0) {
+	}
+
+	retval = write_mailbody_from_file(sockfd, mailfile);
+	if(retval) {
 		log_error(LOG_ARGS, "Could not write mailbody\n");
 		return retval;
 	}
 
-	if((retval = write_dot(sockfd)) != 0) {
+	retval = write_dot(sockfd);
+	if(retval) {
 		log_error(LOG_ARGS, "Could not write <CR><LF>.<CR><LF>\n");
 		return retval;
 	}
 
-	if((retval = checkwait_smtpreply(sockfd, MLMMJ_DOT)) != 0) {
+	reply = checkwait_smtpreply(sockfd, MLMMJ_DOT);
+	if(reply) {
 		log_error(LOG_ARGS, "Mailserver did not ack end of mail.\n"
 				"<CR><LF>.<CR><LF> was written, to no"
-				"avail\n");
-		return retval;
+				"avail. Reply = [%s]", reply);
+		write_rset(sockfd);
+		checkwait_smtpreply(sockfd, MLMMJ_RSET);
+		return MLMMJ_DOT;
 	}
 
 	return 0;
@@ -155,21 +235,25 @@
 int initsmtp(int *sockfd, const char *relayhost)
 {
 	int retval = 0;
+	char *reply = NULL;
 	char *myhostname = hostnamestr();
 	
 	init_sockfd(sockfd, relayhost);
 	
-	if((retval = checkwait_smtpreply(*sockfd, MLMMJ_CONNECT)) != 0) {
-		log_error(LOG_ARGS, "No proper greeting to our connect\n"
-			  "We continue and hope for the best\n");
+	if((reply = checkwait_smtpreply(*sockfd, MLMMJ_CONNECT)) != NULL) {
+		log_error(LOG_ARGS, "No proper greeting to our connect"
+			  "Reply: [%s]", reply);
+		free(reply);
+		retval = MLMMJ_CONNECT;
 		/* FIXME: Queue etc. */
 	}	
 	write_helo(*sockfd, myhostname);
 	free(myhostname);
-	if((checkwait_smtpreply(*sockfd, MLMMJ_HELO)) != 0) {
-		log_error(LOG_ARGS, "Error with HELO\n"
-			  "We continue and hope for the best\n");
+	if((reply = checkwait_smtpreply(*sockfd, MLMMJ_HELO)) != NULL) {
+		log_error(LOG_ARGS, "Error with HELO. Reply: [%s]", reply);
 		/* FIXME: quit and tell admin to configure correctly */
+		free(reply);
+		retval = MLMMJ_HELO;
 	}
 
 	return retval;
@@ -178,12 +262,15 @@
 int endsmtp(int *sockfd)
 {
 	int retval = 0;
+	char *reply;
 	
 	write_quit(*sockfd);
 
-	if((retval = checkwait_smtpreply(*sockfd, MLMMJ_QUIT)) != 0) {
-		log_error(LOG_ARGS, "Mailserver would not let us QUIT\n"
-			  "We close the socket anyway though\n");
+	if((reply = checkwait_smtpreply(*sockfd, MLMMJ_QUIT)) != 0) {
+		log_error(LOG_ARGS, "Mailserver would not let us QUIT. "
+			  "We close the socket anyway though.");
+		free(reply);
+		retval = MLMMJ_QUIT;
 	}
 
 	close(*sockfd);
@@ -193,7 +280,8 @@
 
 int send_mail_many(int sockfd, const char *from, const char *replyto,
 		   FILE *mailfile, FILE *subfile, const char *listaddr,
-		   const char *archivefilename, const char *listdir)
+		   const char *archivefilename, const char *listdir,
+		   const char *mlmmjbounce)
 {
 	int sendres = 0;
 	char *bounceaddr, *addr, *index, *dirname, *addrfilename;
@@ -204,12 +292,12 @@
 		chomp(addr);
 		if(from)
 			sendres = send_mail(sockfd, from, addr, replyto,
-					    mailfile);
+					    mailfile, listdir, NULL);
 		else {
 			bounceaddr = bounce_from_adr(addr, listaddr,
 						     archivefilename);
 			sendres = send_mail(sockfd, bounceaddr, addr, replyto,
-				  mailfile);
+				  mailfile, listdir, mlmmjbounce);
 			free(bounceaddr);
 		}
 		if(sendres && listaddr && archivefilename) {
@@ -226,8 +314,8 @@
 				free(addr);
 				return 1;
 			}
+			addrfilename = concatstr(2, dirname, "/subscribers");
 			free(dirname);
-			addrfilename = concatstr(2, dirname, "/subscribers");
 			addrfile = fopen(addrfilename, "w");
 			if(addrfile == NULL) {
 				log_error(LOG_ARGS, "Could not create %s",
@@ -291,19 +379,23 @@
 {
 	size_t len = 0;
 	int sockfd = 0, opt, mindex;
-	FILE *subfile = NULL, *mailfile = NULL, *tmpfile;
+	int deletewhensent = 1, *newsockfd, sendres;
 	char *listaddr, *mailfilename = NULL, *subfilename = NULL;
 	char *replyto = NULL, *bounceaddr = NULL, *to_addr = NULL;
 	char *relayhost = NULL, *archivefilename = NULL, *tmpstr;
 	char *listctrl = NULL, *subddirname = NULL, *listdir = NULL;
-	int deletewhensent = 1, *newsockfd, sendres;
+	char *mlmmjbounce = NULL, *argv0 = strdup(argv[0]);
 	DIR *subddir;
+	FILE *subfile = NULL, *mailfile = NULL, *tmpfile;
 	struct dirent *dp;
 	pid_t childpid;
 	struct sigaction sigact;
 	
 	log_set_name(argv[0]);
 
+	mlmmjbounce = concatstr(2, dirname(argv0), "/mlmmj-bounce");
+	free(argv0);
+	
 	while ((opt = getopt(argc, argv, "VDhm:l:L:R:F:T:r:")) != -1){
 		switch(opt) {
 		case 'D':
@@ -408,7 +500,7 @@
 	case '1': /* A single mail is to be sent */
 		initsmtp(&sockfd, relayhost);
 		sendres = send_mail(sockfd, bounceaddr, to_addr,
-				replyto, mailfile);
+				replyto, mailfile, listdir, NULL);
 		endsmtp(&sockfd);
 		if(sendres) {
 			/* error, so keep it in the queue */
@@ -437,7 +529,7 @@
 	case '2': /* Moderators */
 		initsmtp(&sockfd, relayhost);
 		send_mail_many(sockfd, bounceaddr, NULL, mailfile, subfile,
-			       NULL, NULL, listdir);
+			       NULL, NULL, listdir, NULL);
 		endsmtp(&sockfd);
 		break;
 	default: /* normal list mail */
@@ -486,12 +578,13 @@
 				initsmtp(newsockfd, relayhost);
 				send_mail_many(*newsockfd, NULL, NULL,
 					       mailfile, subfile, listaddr,
-					       archivefilename, listdir);
+					       archivefilename, listdir,
+					       mlmmjbounce);
 				endsmtp(newsockfd);
 				free(newsockfd);
 				exit(EXIT_SUCCESS);
 			} else {
-				log_error(LOG_ARGS, "%d/%d connections open",
+				syslog(LOG_INFO, "%d/%d connections open",
 						conncount, MAX_CONNECTIONS);
 			}
 		}