/*
 * Intermud mail server, used by Huthar's mailer daemon
 * Original author: Huthar
 * Rewritten to conform to new socket efun specs,  Blackthorn (10/31/92)
 * Modified by Truilkan for use in Basis mudlib (11/01/92)
 * Modified by Pinkfish for use in the Discworld mudlib (5 jan 92)
 * (Stupid american date formats).
 */

#include <config.h>
#include "mailer.h"
#include "/adm/net/nameserver.h"
#include "socket.h"
#include "/adm/net/inet.h"

#define SAVE "/data/mail/"
 
#define log(x) log_file("MS", x)
#define MS_SAVE "mail-queue"
#define FLUSH_TIME 86400
#define AGE_TIME 604800
#define EOF "%EOF%"
#define EOT "%EOT%"
 
static mixed mqi;
static mixed outgoing;
 
mixed mail_queue;
int date_last_flushed;
 
void process_message(int fd);
void flush_mail_queue();
void age_queue();
 
void reset() {
  if ((time() - date_last_flushed) > FLUSH_TIME) {
    mqi = keys(mail_queue);
    flush_mail_queue();
    date_last_flushed = time();
  }
  age_queue();
} /* reset() */
 
void create() {
	seteuid(ROOT_UID);
  mail_queue = ([ ]);
  mqi = ({ });
  restore_object(SAVE + MS_SAVE);
  mqi = keys(mail_queue);
  flush_mail_queue();
} /* create() */

/*
 * Ahhh, so this send the intermud mail...
 */
void remote_mail(string from, string to, string subject, string cc,
                 string body, string *goto) {
  int i;
  string *tmp, name, mud;
 
  tmp = explode(body, "\n");
  while (tmp && (i = member_array(EOF, tmp)) != -1) {
    tmp[i] = EOF + ".";
  }
 
  if (!tmp) tmp = ({ });
  body = implode(tmp, "\n");

/* Ok, now make up a list of muds and who to send to at each one. */
  for (i=0;i<sizeof(goto);i++) {
    sscanf(goto[i], "%s@%s", name, mud);
    if (!mail_queue[mud]) {
      mail_queue[mud] = ({ });
    }
    mail_queue[mud] += ({
        ([ "recipient" : name, "to" : to, "cc" : cc,
         "from" : from, "subject" : subject, "date" : time(),
         "message" : body ]),
                     });
    mqi += ({ mud });
    if (member_array(mud, mqi) == -1)
      mqi += ({ mud });
  }
 
  save_object(SAVE + MS_SAVE);
} /* remote_mail() */
 
void dest_me() {
  destruct(this_object()); 
} /* dest_me() */
 
void set_mqi(mixed m) { mqi = m; }
string *query_mqi() { return mqi; }
 
mapping query_mail_queue() { return mail_queue; }
void set_mail_queue(mixed a) { mail_queue = a; }
 
void clear_mail_queue() {
  mail_queue = ([ ]);
  save_object(SAVE + "mail-queue");
} /* clear_mail_queue() */
 
void age_queue() {
  int i, j;
  string *key;
  mixed tmp;
 
  key = keys(mail_queue);
 
  for (i = 0; i < sizeof(key); i++) {
    tmp = mail_queue[key[i]];
    for (j = 0; j < sizeof(tmp); j++) {
      if (time() - tmp[j]["date"] > AGE_TIME) {
        log("Aging mail from: " +
            tmp[j]["from"] + ", dated: " + tmp[j]["date"] + "\n");
        tmp = exclude_array(tmp, j);
/* Thats probably what exclude_array does.
        exclude_array(tmp, j);
 */
      }
    }
  }
} /* age_queue() */
 
void flush_mail_queue() {
  string *muds, address, port;
  int id;
 
  if (!sizeof(mqi)) return;
 
  outgoing = mail_queue[mqi[0]];
/* ahhhh.  so this is what does the junk! */
  INET_D->open_to_service("mail", INETD_TYPE, mqi[0]);
} /* flush_mail_queue() */

/*
 * Send a bounce to all the messages in the outgoing queue...
 */
void bounce_message(string mess) {
  int i;

  for (i=0;i<sizeof(outgoing);i++) {
    MAILER->do_mail_message(outgoing[i]["from"], "Mail-Server",
                         "Delivery failed: "+mess, "",
                         "Message sent follows:\n>To: "+outgoing[i]["to"]+
                         "\n>Cc : "+ outgoing[i]["cc"]+"\n>Subject: "+
                         outgoing[i]["subject"]+"\n\n"+outgoing[i]["message"],
                         1);
  }
} /* bounce_message() */

void failed(string reason) {
  bounce_message(reason);
  map_delete(mail_queue, mqi[0]);
  mqi -= ({ mqi[0] });
  save_object(SAVE + MS_SAVE);
} /* failed() */

void connected(int id) {
  int i;
 
  previous_object()->write_fd(id, "tabor" + "\n");
  for (i = 0; i < sizeof(outgoing); i++) {
    previous_object()->write_fd(id, outgoing[i]["recipient"] + "\n");
    previous_object()->write_fd(id, replace_string(outgoing[i]["to"], ",", " ")+"\n");
    previous_object()->write_fd(id, replace_string(outgoing[i]["cc"], ",", " ")+"\n");
    previous_object()->write_fd(id, outgoing[i]["from"] + "\n");
    previous_object()->write_fd(id, outgoing[i]["subject"] + "\n");
    previous_object()->write_fd(id, outgoing[i]["date"] + "\n");
    previous_object()->write_fd(id, outgoing[i]["message"] + "\n");
    previous_object()->write_fd(id, EOF + "\n");
  }
  previous_object()->write_fd(id, EOT + "\n");
  previous_object()->close_fd(id);
  map_delete(mail_queue, mqi[0]);
  mqi -= ({ mqi[0] });
  save_object(SAVE + MS_SAVE);
  call_out("flush_mail_queue", 60);
} /* connected() */