#include <sys/wait.h>
#include <string.h>
#include <limits.h>
+#include <time.h>
#include "citadel.h"
#include "server.h"
-#include <time.h>
#include "sysdep_decls.h"
#include "citserver.h"
#include "support.h"
struct citsmtp { /* Information about the current session */
int command_state;
+ char helo_node[256];
struct usersupp vrfy_buffer;
int vrfy_count;
char vrfy_match[256];
/*****************************************************************************/
+
+
/*
* Here's where our SMTP session begins its happy day.
*/
*/
void smtp_hello(char *argbuf, int is_esmtp) {
+ safestrncpy(SMTP->helo_node, argbuf, sizeof SMTP->helo_node);
+
if (!is_esmtp) {
cprintf("250 Greetings and joyous salutations.\r\n");
}
else {
cvt = convert_internet_address(user, node, SMTP->from);
lprintf(9, "cvt=%d, citaddr=<%s@%s>\n", cvt, user, node);
- if (!strcasecmp(node, config.c_nodename)) { /* FIX use fcn */
+ if (CtdlHostAlias(node) == hostalias_localhost) {
cprintf("550 You must log in to send mail from %s\r\n",
- config.c_fqdn);
+ node);
strcpy(SMTP->from, "");
return;
}
generate_rfc822_datestamp(nowstamp, time(NULL));
body = mallok(4096);
+
if (body != NULL) sprintf(body,
"Received: from %s\n"
" by %s;\n"
" %s\n",
- "FIX.FIX.com",
+ SMTP->helo_node,
config.c_fqdn,
nowstamp);
}
if (sock < 0) {
- *status = 3; /* dsn is already filled in */
+ *status = 4; /* dsn is already filled in */
return;
}
/* Process the SMTP greeting from the server */
if (sock_gets(sock, buf) < 0) {
- *status = 3;
+ *status = 4;
strcpy(dsn, "Connection broken during SMTP conversation");
sock_close(sock);
return;
lprintf(9, "%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
- *status = 3;
+ *status = 4;
strcpy(dsn, &buf[4]);
sock_close(sock);
return;
sprintf(buf, "HELO %s", config.c_fqdn);
sock_puts(sock, buf);
if (sock_gets(sock, buf) < 0) {
- *status = 3;
+ *status = 4;
strcpy(dsn, "Connection broken during SMTP conversation");
sock_close(sock);
return;
lprintf(9, "%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
- *status = 3;
+ *status = 4;
strcpy(dsn, &buf[4]);
sock_close(sock);
return;
/* HELO succeeded, now try the MAIL From: command */
- sprintf(buf, "MAIL From: ajc@uncnsrd.mt-kisco.ny.us"); /* FIX */
+ sprintf(buf, "MAIL From: FIX@uncnsrd.mt-kisco.ny.us"); /* FIX */
sock_puts(sock, buf);
if (sock_gets(sock, buf) < 0) {
- *status = 3;
+ *status = 4;
strcpy(dsn, "Connection broken during SMTP conversation");
sock_close(sock);
return;
lprintf(9, "%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
- *status = 3;
+ *status = 4;
strcpy(dsn, &buf[4]);
sock_close(sock);
return;
sprintf(buf, "RCPT To: %s", addr);
sock_puts(sock, buf);
if (sock_gets(sock, buf) < 0) {
- *status = 3;
+ *status = 4;
strcpy(dsn, "Connection broken during SMTP conversation");
sock_close(sock);
return;
lprintf(9, "%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
- *status = 3;
+ *status = 4;
strcpy(dsn, &buf[4]);
sock_close(sock);
return;
/* RCPT succeeded, now try the DATA command */
sock_puts(sock, "DATA");
if (sock_gets(sock, buf) < 0) {
- *status = 3;
+ *status = 4;
strcpy(dsn, "Connection broken during SMTP conversation");
sock_close(sock);
return;
}
/* If we reach this point, the server is expecting data */
- CtdlOutputMsg(msgnum, MT_RFC822, 0, 0, NULL, sock, 1);
+
+ CtdlRedirectOutput(NULL, sock);
+ CtdlOutputMsg(msgnum, MT_RFC822, 0, 0, 1);
+ CtdlRedirectOutput(NULL, -1);
+
sock_puts(sock, ".");
if (sock_gets(sock, buf) < 0) {
- *status = 3;
+ *status = 4;
strcpy(dsn, "Connection broken during SMTP conversation");
sock_close(sock);
return;
lprintf(9, "%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
- *status = 3;
+ *status = 4;
strcpy(dsn, &buf[4]);
sock_close(sock);
return;
+/*
+ * smtp_purge_completed_deliveries() is caled by smtp_do_procmsg() to remove
+ * all of the completed deliveries from a set of delivery instructions.
+ *
+ * It returns the number of incomplete deliveries remaining.
+ */
+int smtp_purge_completed_deliveries(char *instr) {
+ int i;
+ int lines;
+ int status;
+ char buf[1024];
+ char key[1024];
+ char addr[1024];
+ char dsn[1024];
+ int completed;
+ int incomplete = 0;
+
+ lines = num_tokens(instr, '\n');
+ for (i=0; i<lines; ++i) {
+ extract_token(buf, instr, i, '\n');
+ extract(key, buf, 0);
+ extract(addr, buf, 1);
+ status = extract_int(buf, 2);
+ extract(dsn, buf, 3);
+
+ completed = 0;
+
+ if (
+ (!strcasecmp(key, "local"))
+ || (!strcasecmp(key, "remote"))
+ || (!strcasecmp(key, "ignet"))
+ || (!strcasecmp(key, "room"))
+ ) {
+ if (status == 2) completed = 1;
+ else ++incomplete;
+ }
+
+ if (completed) {
+ remove_token(instr, i, '\n');
+ --i;
+ --lines;
+ }
+ }
+
+ return(incomplete);
+}
+
/*
* smtp_do_procmsg()
char addr[1024];
char dsn[1024];
long text_msgid = (-1);
+ int incomplete_deliveries_remaining;
msg = CtdlFetchMessage(msgnum);
if (msg == NULL) {
phree(results);
}
- /* Delete the instructions and replace with the updated ones */
- CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, NULL);
- msg = mallok(sizeof(struct CtdlMessage));
- memset(msg, 0, sizeof(struct CtdlMessage));
- msg->cm_magic = CTDLMESSAGE_MAGIC;
- msg->cm_anon_type = MES_NORMAL;
- msg->cm_format_type = FMT_RFC822;
- msg->cm_fields['M'] = malloc(strlen(instr)+256);
- sprintf(msg->cm_fields['M'],
- "Content-type: %s\n\n%s\n", SPOOLMIME, instr);
- phree(instr);
- CtdlSaveMsg(msg, "", SMTP_SPOOLOUT_ROOM, MES_LOCAL, 1);
- CtdlFreeMessage(msg);
+
+
+ /*
+ * Go through the delivery list, deleting completed deliveries
+ */
+ incomplete_deliveries_remaining =
+ smtp_purge_completed_deliveries(instr);
+
+
+ /*
+ * No delivery instructions remain, so delete both the instructions
+ * message and the message message.
+ */
+ if (incomplete_deliveries_remaining <= 0) {
+ CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, NULL);
+ CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, text_msgid, NULL);
+ }
+
+
+ /*
+ * Uncompleted delivery instructions remain, so delete the old
+ * instructions and replace with the updated ones.
+ */
+ if (incomplete_deliveries_remaining > 0) {
+ CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, NULL);
+ msg = mallok(sizeof(struct CtdlMessage));
+ memset(msg, 0, sizeof(struct CtdlMessage));
+ msg->cm_magic = CTDLMESSAGE_MAGIC;
+ msg->cm_anon_type = MES_NORMAL;
+ msg->cm_format_type = FMT_RFC822;
+ msg->cm_fields['M'] = malloc(strlen(instr)+256);
+ sprintf(msg->cm_fields['M'],
+ "Content-type: %s\n\n%s\n", SPOOLMIME, instr);
+ phree(instr);
+ CtdlSaveMsg(msg, "", SMTP_SPOOLOUT_ROOM, MES_LOCAL, 1);
+ CtdlFreeMessage(msg);
+ }
+
}
}
-/**** FIX temporary hack to run the queue *****/
-void cmd_qqqq(char *argbuf) {
- smtp_do_queue();
- cprintf("%d ok\n", OK);
-}
-
-
/*****************************************************************************/
/* MODULE INITIALIZATION STUFF */
CtdlRegisterServiceHook(SMTP_PORT,
smtp_greeting,
smtp_command_loop);
-
- /**** FIX ... temporary hack to run the queue ******/
- CtdlRegisterProtoHook(cmd_qqqq, "QQQQ", "run the queue");
-
create_room(SMTP_SPOOLOUT_ROOM, 3, "", 0);
+ CtdlRegisterSessionHook(smtp_do_queue, EVT_TIMER);
return "$Id$";
}