/
ColdCore-3.0a8/
ColdCore-3.0a8/src/
new object $smtp_interface: $connection_interface, $has_name;

var $has_commands local = #[];
var $has_commands remote = #[];
var $has_commands shortcuts = #[];
var $has_name name = ['prop, "smtp_interface", "smtp_interface"];
var $root created_on = 849172060;
var $root flags = ['variables, 'methods, 'code, 'core];
var $root inited = 1;
var $root managed = [$smtp_interface];
var $root manager = $smtp_interface;
var $root quota_exempt = 1;
var $smtp_interface cmd_help = #[["HELP", ["HELP [<topic>]", "    For more help on any command type 'help <cmd>'"]], ["QUIT", ["QUIT", "    Ends your mail session"]], ["EXPN", ["EXPN <recipient>", "   Expand an address."]], ["VRFY", ["VRFY <recipient>", "   Verify an address."]], ["HELO", ["HELO <hostname>", "   Introduce yourself."]], ["MAIL", ["MAIL FROM: <sender>", "   Specify sender/return path."]], ["NOOP", ["NOOP", "   Do nothing"]], ["RCPT", ["RCPT TO:<recipient>", "   Specifies the recipient.  Can be used any number of times."]], ["DATA", ["DATA", "   Following data is collected as the message", "   End with a single dot"]]];
var $smtp_interface cmds = #[["HELP", 'help_cmd], ["QUIT", 'quit_cmd], ["VRFY", 'verify_cmd], ["EXPN", 'verify_cmd], ["HELO", 'hello_cmd], ["MAIL", 'mail_from_cmd], ["NOOP", 'noop_cmd], ["RCPT", 'recipient_cmd], ["DATA", 'data_cmd]];
var $smtp_interface given_hostname = "";
var $smtp_interface header = 0;
var $smtp_interface mail_body = 0;
var $smtp_interface mail_from = 0;
var $smtp_interface mail_status = 0;
var $smtp_interface mail_to = 0;
var $smtp_interface read_header = 0;

public method .connection_starting() {
    arg addr, port;
    
    (.connection()).write((("220 " + ($sys.server_info('server_hostname))) + " SMTP ColdMail 1.0/1.0; ") + ($time.format("%a, %d %b %Y %T %Z")));
};

public method .data_cmd() {
    arg rest;
    var conn;
    
    conn = .connection();
    if (mail_from == "") {
        conn.write("503 Need MAIL command");
    } else if (mail_to == []) {
        conn.write("503 Need RCPT command");
    } else {
        conn.write("354 Enter mail, end with \".\" on a line by itself");
        mail_status = 'read_body;
    }
};

public method .get_cmd() {
    arg cmd;
    
    return (> cmds[cmd] <);
};

public method .get_cmd_help() {
    arg help;
    
    return (> cmd_help[help] <);
};

public method .get_cmds() {
    return cmds.keys();
};

public method .hello_cmd() {
    arg rest;
    var conn;
    
    conn = .connection();
    if ((rest.length()) == 0) {
        conn.write("501 HELO requires domain address");
    } else if (given_hostname == 0) {
        conn.write(((("250 " + ($sys.server_info('server_hostname))) + " Hello ") + (conn.address())) + ", pleased to meet you");
        given_hostname = rest;
    } else {
        conn.write("503 portland.puremagic.com Duplicate HELO");
    }
};

public method .help_cmd() {
    arg rest;
    var i, conn;
    
    conn = .connection();
    if ((rest.length()) == 0) {
        conn.write(["214-This is ColdMail 0.01.", "214-Valid Commands:"]);
        for i in (definer().get_cmds())
            conn.write("214-  " + i);
        conn.write("214 End of Help");
    } else {
        catch ~keynf {
            rest = definer().get_cmd_help(rest);
            for i in (rest)
                conn.write("214-" + i);
            conn.write("214 End of Help");
        } with {
            conn.write(("504 HELP topic '" + rest) + "' not found.");
        }
    }
};

public method .init_smtp_interface() {
    .reset_interface();
    mail_status = 'idle;
};

public method .mail_from_cmd() {
    arg rest;
    var conn, i;
    
    conn = .connection();
    if (((rest.length()) <= 5) || (((i = ":" in rest) != 5) || ((| rest.subrange(1, 5) |) != "from:"))) {
        conn.write(("501 Syntax error in \"" + (rest.subrange(1, (i == 0) ? (rest.length()) : (i - 1)))) + "\"");
    } else if (mail_from != "") {
        conn.write("503 Sender already specified");
    } else {
        .reset_interface();
        mail_from = (rest.subrange(6)).trim();
        conn.write(("250 " + mail_from) + "... sender ok");
    }
};

public method .noop_cmd() {
    arg rest;
    
    (.connection()).write("250 Ok");
};

public method .parse_line() {
    arg line;
    var method, cmd, args, name, rest, m, last;
    
    if (mail_status == 'read_body) {
        if (line == ".") {
            return .send_mail();
        } else {
            if (read_header) {
                mail_body += [line];
            } else if (!line) {
                read_header = 1;
            } else if ((m = regexp(line, "^([^ ][^:]+) *: *(.*)$"))) {
                header += [m];
            } else if (header) {
                last = header[listlen(header)];
                header = sublist(header, 1, listlen(header));
                last = replace(last, 2, (last[2]) + line);
                header += [last];
            }
            return;
        }
    }
    cmd = line.word(1);
    if ((line.length()) >= ((cmd.length()) + 2))
        args = line.subrange((cmd.length()) + 2);
    else
        args = "";
    catch ~keynf {
        method = definer().get_cmd(cmd);
    } with {
        (.connection()).write("500 unrecognized command");
        return 'disconenct;
    }
    return .(method)(args);
};

public method .quit_cmd() {
    arg rest;
    
    (.connection()).write(("221 " + ($sys.server_info('server_hostname))) + " closing connection");
    return 'disconnect;
};

public method .recipient_cmd() {
    arg rest;
    var conn, i, user;
    
    conn = .connection();
    if (mail_from == "") {
        conn.write("503 Need MAIL before RCPT");
    } else if (((rest.length()) <= 3) || (((i = ":" in rest) != 3) || ((| rest.subrange(1, 3) |) != "to:"))) {
        conn.write(("501 Syntax error in \"" + (rest.subrange(1, (i == 0) ? (rest.length()) : (i - 1)))) + "\"");
    } else {
        catch any {
            user = $smtp.parse_recipient(rest.subrange(4));
            mail_to += [user];
            conn.write(("250 " + user) + "... recipient ok");
        } with {
            if (error() == ~ambig)
                conn.write("553 Ambiguous Recipient");
            else
                conn.write(((((traceback()[1])[3]) || 550) + " ") + ((traceback()[1])[2]));
        }
    }
};

public method .reset_interface() {
    header = [];
    read_header = 0;
    mail_from = "";
    mail_to = [];
    mail_body = [];
};

public method .send_mail() {
    var mail, l, subj;
    
    .set_name(mail_from, 'prop);
    mail = $mail_message.new_mail();
    subj = "<NO SUBJECT>";
    for l in (header) {
        if ((l[1]) == "Subject")
            subj = l[2];
    }
    mail.set_subject(subj);
    mail.set_text(mail_body);
    catch any {
        mail.set_meta(header);
        mail.send(@mail_to);
        mail.set_from(mail_from);
        (.connection()).write(("250 " + ($smtp_daemon.get_msg_id())) + " Message accepted for delivery");
    } with {
        (.connection()).write("550 Requested action not taken: Error delivering mail");
    }
    .reset_interface();
};

public method .uninit_smtp_interface() {
    header = 0;
    read_header = 0;
    mail_from = 0;
    mail_to = 0;
    mail_body = 0;
    mail_status = 0;
};

public method .verify_cmd() {
    arg rest;
    var conn, user, i, out;
    
    conn = .connection();
    if ((rest.length()) == 0) {
        conn.write("501 Argument required");
    } else {
        if (!($smtp.allowed('VRFY))) {
            conn.write("252 VRFY not allowed");
            return;
        }
        out = [];
        for i in (rest.explode()) {
            catch any {
                out = setadd(out, $smtp.parse_recipient(i));
            } with {
                switch (error()) {
                    case ~ambig:
                        conn.write("553 Ambiguous Recipient");
                    default:
                        conn.write(((((traceback()[1])[3]) || 550) + " ") + ((traceback()[1])[2]));
                        return;
                }
            }
        }
        for i in [1 .. (out.length()) - 1]
            conn.write("250-" + ($smtp.format_email_address(out[i])));
        if (out)
            conn.write("250 " + ($smtp.format_email_address(out.last())));
    }
};