/* $Id$ */
-#define SMTP_PORT 2525
-
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include "msgbase.h"
#include "tools.h"
#include "internet_addressing.h"
+#include "genstamp.h"
struct citsmtp { /* Information about the current session */
int vrfy_count;
char vrfy_match[256];
char from[256];
- char recipient[256];
int number_of_recipients;
+ int delivery_mode;
};
+
enum { /* Command states for login authentication */
smtp_command,
smtp_user,
smtp_password
};
-#define SMTP ((struct citsmtp *)CtdlGetUserData(SYM_SMTP))
+enum { /* Delivery modes */
+ smtp_deliver_local,
+ smtp_deliver_remote
+};
-long SYM_SMTP;
+#define SMTP ((struct citsmtp *)CtdlGetUserData(SYM_SMTP))
+#define SMTP_RECP ((char *)CtdlGetUserData(SYM_SMTP_RECP))
+long SYM_SMTP;
+long SYM_SMTP_RECP;
/*
* Here's where our SMTP session begins its happy day.
CC->internal_pgm = 1;
CC->cs_flags |= CS_STEALTH;
CtdlAllocUserData(SYM_SMTP, sizeof(struct citsmtp));
+ CtdlAllocUserData(SYM_SMTP_RECP, 256);
+ sprintf(SMTP_RECP, "%s", "");
cprintf("220 Welcome to the Citadel/UX ESMTP server at %s\n",
config.c_fqdn);
int cvt;
char user[256];
char node[256];
+ char recp[256];
+ int is_spam = 0; /* FIX implement anti-spamming */
if (strlen(SMTP->from) == 0) {
cprintf("503 MAIL first, then RCPT. Duh.\n");
return;
}
- if (strlen(SMTP->recipient) > 0) {
- cprintf("550 Only one recipient allowed (FIX)\n");
- return;
- }
-
if (strncasecmp(argbuf, "To:", 3)) {
cprintf("501 Syntax error\n");
return;
}
- strcpy(SMTP->recipient, &argbuf[3]);
- striplt(SMTP->recipient);
+ strcpy(recp, &argbuf[3]);
+ striplt(recp);
+ alias(recp);
+
+ cvt = convert_internet_address(user, node, recp);
+ sprintf(recp, "%s@%s", user, node);
+
- cvt = convert_internet_address(user, node, SMTP->recipient);
switch(cvt) {
case rfc822_address_locally_validated:
cprintf("250 %s is a valid recipient.\n", user);
+ ++SMTP->number_of_recipients;
+ CtdlReallocUserData(SYM_SMTP_RECP,
+ strlen(SMTP_RECP) + 1024 );
+ strcat(SMTP_RECP, "local|");
+ strcat(SMTP_RECP, user);
+ strcat(SMTP_RECP, "|0\n");
return;
+
case rfc822_no_such_user:
- cprintf("550 %s: no such user\n", SMTP->recipient);
- strcpy(SMTP->recipient, "");
+ cprintf("550 %s: no such user\n", recp);
+ return;
+
+ case rfc822_address_invalid:
+ if (is_spam) {
+ cprintf("551 Away with thee, spammer!\n");
+ }
+ else {
+ cprintf("250 Remote recipient %s ok\n", recp);
+ ++SMTP->number_of_recipients;
+ CtdlReallocUserData(SYM_SMTP_RECP,
+ strlen(SMTP_RECP) + 1024 );
+ strcat(SMTP_RECP, "remote|");
+ strcat(SMTP_RECP, recp);
+ strcat(SMTP_RECP, "|0\n");
+ return;
+ }
return;
}
- strcpy(SMTP->recipient, "");
- cprintf("599 Unknown error (FIX)\n");
+ cprintf("599 Unknown error\n");
}
+
+/*
+ * Back end for smtp_data() ... this does the actual delivery of the message
+ * Returns 0 on success, nonzero on failure
+ */
+int smtp_message_delivery(struct CtdlMessage *msg) {
+ char user[256];
+ char node[256];
+ char name[256];
+ int successful_saves = 0;
+ int failed_saves = 0;
+ long msgid = (-1L);
+
+ lprintf(9, "smtp_message_delivery() called\n");
+
+ /* Fill in 'from' fields with envelope information if missing */
+ process_rfc822_addr(SMTP->from, user, node, name);
+ if (msg->cm_fields['A']==NULL) msg->cm_fields['A'] = strdoop(user);
+ if (msg->cm_fields['N']==NULL) msg->cm_fields['N'] = strdoop(node);
+ if (msg->cm_fields['H']==NULL) msg->cm_fields['H'] = strdoop(name);
+
+ /* Save the message in the queue */
+ msgid = CtdlSaveMsg(msg,
+ "",
+ SMTP_SPOOLOUT_ROOM,
+ MES_LOCAL,
+ 1);
+ ++successful_saves;
+
+ /* FIX go thru each local user and save to boxes
+ then stuff remote users in queue list
+ then delete from queue if num remote users is 0
+ */
+
+ return(failed_saves);
+}
+
+
+
/*
* Implements the DATA command
*/
void smtp_data(void) {
char *body;
struct CtdlMessage *msg;
+ int retval;
+ char nowstamp[256];
-/*
if (strlen(SMTP->from) == 0) {
cprintf("503 Need MAIL command first.\n");
return;
return;
}
-*/
-
cprintf("354 Transmit message now; terminate with '.' by itself\n");
- body = CtdlReadMessageBody(".", config.c_maxmsglen);
+
+ 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",
+ config.c_fqdn,
+ nowstamp);
+
+ body = CtdlReadMessageBody(".", config.c_maxmsglen, body);
if (body == NULL) {
cprintf("550 Unable to save message text: internal error.\n");
return;
}
- fprintf(stderr, "Converting message...\n");
+ lprintf(9, "Converting message...\n");
msg = convert_internet_message(body);
- /* FIX do something with it! */
- CtdlSaveMsg(msg, "", BASEROOM, MES_LOCAL, 1);
+ /* If the user is locally authenticated, FORCE the From: header to
+ * show up as the real sender
+ */
+ if (CC->logged_in) {
+ if (msg->cm_fields['A'] != NULL) phree(msg->cm_fields['A']);
+ if (msg->cm_fields['N'] != NULL) phree(msg->cm_fields['N']);
+ if (msg->cm_fields['H'] != NULL) phree(msg->cm_fields['H']);
+ msg->cm_fields['A'] = strdoop(CC->usersupp.fullname);
+ msg->cm_fields['N'] = strdoop(config.c_nodename);
+ msg->cm_fields['H'] = strdoop(config.c_humannode);
+ }
+ retval = smtp_message_delivery(msg);
CtdlFreeMessage(msg);
- cprintf("599 command unfinished but message saved\n");
+ if (!retval) {
+ cprintf("250 Message accepted for delivery.\n");
+ }
+ else {
+ cprintf("550 Internal error.\n");
+ }
}
}
else {
- cprintf("500 I'm afraid I can't do that, Dave.\n");
+ cprintf("502 I'm afraid I can't do that, Dave.\n");
}
}
-
char *Dynamic_Module_Init(void)
{
SYM_SMTP = CtdlGetDynamicSymbol();
+ SYM_SMTP_RECP = CtdlGetDynamicSymbol();
CtdlRegisterServiceHook(SMTP_PORT,
smtp_greeting,
smtp_command_loop);
+ create_room(SMTP_SPOOLOUT_ROOM, 3, "", 0);
return "$Id$";
}
+