/********************************************************************************** * nWordPress is an automated migration of WordPress 2.5.1 performed by Numiton. * * copyright : (C) 2008 Numiton - www.numiton.com * email : numiton@users.sourceforge.net * * $Id: SMTP.java,v 1.3 2008/10/03 18:45:29 numiton Exp $ * **********************************************************************************/ /********************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * **********************************************************************************/ /*************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * ***************************************************************************/ package org.numiton.nwp.wp_includes; import static com.numiton.VarHandling.*; import java.io.Serializable; import org.apache.log4j.Logger; import org.numiton.nwp.GlobalConsts; import org.numiton.nwp.GlobalVars; import com.numiton.URL; import com.numiton.array.Array; import com.numiton.array.ArrayEntry; import com.numiton.file.FileSystemOrSocket; import com.numiton.generic.*; import com.numiton.string.Strings; //////////////////////////////////////////////////// //SMTP - PHP SMTP class // //Version 1.02 // //Define an SMTP class that can be used to connect //and communicate with any SMTP server. It implements //all the SMTP functions defined in RFC821 except TURN. // //Author: Chris Ryan // //License: LGPL, see LICENSE //////////////////////////////////////////////////// /** * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP * commands except TURN which will always return a not implemented * error. SMTP also provides some utility methods for sending mail * to an SMTP server. * @package PHPMailer * @author Chris Ryan */ public class SMTP implements ContextCarrierInterface, Serializable, Cloneable { protected static final Logger LOG = Logger.getLogger(SMTP.class.getName()); public GlobalConsts gConsts; public GlobalVars gVars; /** * SMTP server port * @var int */ public int SMTP_PORT = 25; /** * SMTP reply line ending * @var string */ public String CRLF = "\r\n"; /** * Sets whether debugging is turned on * @var bool */ public int do_debug; // the level of debug to perform /** *#@+ * @access private */ public Integer smtp_conn; //the socket to the server public Array<Object> error = new Array<Object>(); //error if any on the last call public String helo_rply; //the reply the server sent to us for HELO /** * Generated in place of local variable 'line' from method 'Data' because it * is used inside an inner class. */ String Data_line = null; /** * Generated in place of local variable 'line_out' from method 'Data' * because it is used inside an inner class. */ String Data_line_out = null; /** * Generated in place of local variable 'l' from method 'Expand' because it * is used inside an inner class. */ String Expand_l = null; /** * #@-* Initialize the class so that the data is in a known state. * @access public * @return void */ public SMTP(GlobalVars javaGlobalVariables, GlobalConsts javaGlobalConstants) { setContext(javaGlobalVariables, javaGlobalConstants); this.smtp_conn = 0; this.error = null; this.helo_rply = null; this.do_debug = 0; } /************************************************************* * CONNECTION FUNCTIONS * ***********************************************************/ /** * Connect to the server specified on the port specified. * If the port is not specified use the default SMTP_PORT. * If tval is specified then a connection will try and be * established with the server for that number of seconds. * If tval is not specified the default is 30 seconds to * try on the connection. * * SMTP CODE SUCCESS: 220 * SMTP CODE FAILURE: 421 * @access public * @return bool */ public boolean Connect(String host, int port, double tval) { Ref<Integer> errno = new Ref<Integer>(); Ref<String> errstr = new Ref<String>(); String announce = null; // set the error val to null so there is no confusion this.error = null; // make sure we are __not__ connected if (this.Connected()) { // ok we are connected! what should we do? // for now we will just give an error saying we // are already connected this.error = new Array<Object>(new ArrayEntry<Object>("error", "Already connected to a server")); return false; } if (empty(port)) { port = this.SMTP_PORT; } // connect to the smtp server this.smtp_conn = FileSystemOrSocket.fsockopen(gVars.webEnv, host, // the host of the server port, // the port to use errno, // error number if any errstr, // error message if any tval); // give up after ? secs // verify we connected properly if (empty(this.smtp_conn)) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Failed to connect to server"), new ArrayEntry<Object>("errno", errno), new ArrayEntry<Object>("errstr", errstr)); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + strval(errstr) + " (" + strval(errno) + ")" + this.CRLF); } return false; } // sometimes the SMTP server takes a little longer to respond // so we will give it a longer timeout for the first read // Windows still does not have support for this timeout function if (!equal(Strings.substr("PHP_OS", 0, 3), "WIN")) { FileSystemOrSocket.socket_set_timeout(gVars.webEnv, this.smtp_conn, intval(tval), 0); } // get any announcement stuff announce = this.get_lines(); // set the timeout of any socket functions at 1/10 of a second //if(function_exists("socket_set_timeout")) // socket_set_timeout($this->smtp_conn, 0, 100000); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + announce); } return true; } /** * Performs SMTP authentication. Must be run after running the Hello() * method. Returns true if successfully authenticated. * @access public * @return bool */ public boolean Authenticate(String username, String password) { String rply = null; String code = null; // Start authentication FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "AUTH LOGIN" + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (!equal(code, 334)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "AUTH not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } // Send encoded username FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, URL.base64_encode(username) + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (!equal(code, 334)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "Username not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } // Send encoded password FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, URL.base64_encode(password) + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (!equal(code, 235)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "Password not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * Returns true if connected to a server otherwise false * @access private * @return bool */ public boolean Connected() { Array<Object> sock_status = new Array<Object>(); if (!empty(this.smtp_conn)) { sock_status = FileSystemOrSocket.socket_get_status(gVars.webEnv, this.smtp_conn); if (booleanval(sock_status.getValue("eof"))) { // hmm this is an odd situation... the socket is // valid but we aren't connected anymore if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> NOTICE:" + this.CRLF + "EOF caught while checking if connected"); } this.Close(); return false; } return true; // everything looks good } return false; } /** * Closes the socket and cleans up the state of the class. It is not * considered good to use this function without first trying to use QUIT. * @access public * @return void */ public void Close() { this.error = null; // so there is no confusion this.helo_rply = null; if (!empty(this.smtp_conn)) { // close the connection and cleanup FileSystemOrSocket.fclose(gVars.webEnv, this.smtp_conn); this.smtp_conn = 0; } } /*************************************************************** * SMTP COMMANDS * *************************************************************/ /** * Issues a data command and sends the msg_data to the server * finializing the mail transaction. $msg_data is the message * that is to be send with the headers. Each header needs to be * on a single line followed by a <CRLF> with the message headers * and the message body being seperated by and additional <CRLF>. * * Implements rfc 821: DATA <CRLF> * * SMTP CODE INTERMEDIATE: 354 * [data] * <CRLF>.<CRLF> * SMTP CODE SUCCESS: 250 * SMTP CODE FAILURE: 552,554,451,452 * SMTP CODE FAILURE: 451,554 * SMTP CODE ERROR : 500,501,503,421 * @access public * @return bool */ public boolean Data(String msg_data) { String rply = null; String code = null; Array<String> lines = new Array<String>(); String field = null; boolean in_headers = false; int max_line_length = 0; Array<Object> lines_out = new Array<Object>(); int pos = 0; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Data() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "DATA" + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 354)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "DATA command not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } // the server is ready to accept data! // according to rfc 821 we should not send more than 1000 // including the CRLF // characters on a single line so we will break the data up // into lines by \r and/or \n then if needed we will break // each of those into smaller lines to fit within the limit. // in addition we will be looking for lines that start with // a period '.' and append and additional period '.' to that // line. NOTE: this does not count towards are limit. // normalize the line breaks so we know the explode works msg_data = Strings.str_replace("\r\n", "\n", msg_data); msg_data = Strings.str_replace("\r", "\n", msg_data); lines = Strings.explode("\n", msg_data); // we need to find a good way to determine is headers are // in the msg_data or if it is a straight msg body // currently I'm assuming rfc 822 definitions of msg headers // and if the first field of the first line (':' sperated) // does not contain a space then it _should_ be a header // and we can process all lines before a blank "" line as // headers. field = Strings.substr(lines.getValue(0), 0, Strings.strpos(lines.getValue(0), ":")); in_headers = false; if (!empty(field) && !booleanval(Strings.strstr(field, " "))) { in_headers = true; } max_line_length = 998; // used below; set here for ease in change while (booleanval( new ListAssigner<Object>() { public Array<Object> doAssign(Array<Object> srcArray) { if (strictEqual(srcArray, null)) { return null; } Data_line = strval(srcArray.getValue(1)); return srcArray; } }.doAssign(Array.each(lines)))) { lines_out = new Array<Object>(); if (equal(Data_line, "") && in_headers) { in_headers = false; } // ok we need to break this line up into several // smaller lines while (Strings.strlen(Data_line) > max_line_length) { pos = Strings.strrpos(Strings.substr(Data_line, 0, max_line_length), " "); // Patch to fix DOS attack if (!booleanval(pos)) { pos = max_line_length - 1; } lines_out.putValue(Strings.substr(Data_line, 0, pos)); Data_line = Strings.substr(Data_line, pos + 1); // if we are processing headers we need to // add a LWSP-char to the front of the new line // rfc 822 on long msg headers if (in_headers) { Data_line = "\t" + Data_line; } } lines_out.putValue(Data_line); // now send the lines to the server while (booleanval( new ListAssigner<Object>() { public Array<Object> doAssign(Array<Object> srcArray) { if (strictEqual(srcArray, null)) { return null; } Data_line_out = strval(srcArray.getValue(1)); return srcArray; } }.doAssign(Array.each(lines_out)))) { if (Strings.strlen(Data_line_out) > 0) { if (equal(Strings.substr(Data_line_out, 0, 1), ".")) { Data_line_out = "." + Data_line_out; } } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, Data_line_out + this.CRLF); } } // ok all the message data has been sent so lets get this // over with aleady FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, this.CRLF + "." + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "DATA not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * Expand takes the name and asks the server to list all the * people who are members of the _list_. Expand will return * back and array of the result or false if an error occurs. * Each value in the array returned has the format of: * [ <full-name> <sp> ] <path> * The definition of <path> is defined in rfc 821 * * Implements rfc 821: EXPN <SP> <string> <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE FAILURE: 550 * SMTP CODE ERROR : 500,501,502,504,421 * @access public * @return string array */ public Array<Object> Expand(Object name) { String rply = null; String code = null; Array<String> entries = new Array<String>(); Array<Object> list = new Array<Object>(); this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Expand() without being connected")); return new Array<Object>(); } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "EXPN " + strval(name) + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "EXPN not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return new Array<Object>(); } // parse the reply and place in our array to return to user entries = Strings.explode(this.CRLF, rply); while (booleanval( new ListAssigner<Object>() { public Array<Object> doAssign(Array<Object> srcArray) { if (strictEqual(srcArray, null)) { return null; } Expand_l = strval(srcArray.getValue(1)); return srcArray; } }.doAssign(Array.each(entries)))) { list.putValue(Strings.substr(Expand_l, 4)); } return list; } /** * Sends the HELO command to the smtp server. * This makes sure that we and the server are in * the same known state. * * Implements from rfc 821: HELO <SP> <domain> <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE ERROR : 500, 501, 504, 421 * @access public * @return bool */ public boolean Hello(String host) { this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Hello() without being connected")); return false; } // if a hostname for the HELO wasn't specified determine // a suitable one to send if (empty(host)) { // we need to determine some sort of appopiate default // to send to the server host = "localhost"; } // Send extended hello first (RFC 2821) if (!this.SendHello("EHLO", host)) { if (!this.SendHello("HELO", host)) { return false; } } return true; } /** * Sends a HELO/EHLO command. * @access private * @return bool */ public boolean SendHello(String hello, String host) { String rply = null; String code = null; FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, hello + " " + host + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER: " + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", hello + " not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } this.helo_rply = rply; return true; } /** * Gets help information on the keyword specified. If the keyword * is not specified then returns generic help, ussually contianing * A list of keywords that help is available on. This function * returns the results back to the user. It is up to the user to * handle the returned data. If an error occurs then false is * returned with $this->error set appropiately. * * Implements rfc 821: HELP [ <SP> <string> ] <CRLF> * * SMTP CODE SUCCESS: 211,214 * SMTP CODE ERROR : 500,501,502,504,421 * @access public * @return string */ public String Help(Object keyword) { String extra = null; String rply = null; String code = null; this.error = null; // to avoid confusion if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Help() without being connected")); return strval(false); } extra = ""; if (!empty(keyword)) { extra = " " + strval(keyword); } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "HELP" + extra + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 211) && !equal(code, 214)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "HELP not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return strval(false); } return rply; } /** * Starts a mail transaction from the email address specified in * $from. Returns true if successful or false otherwise. If True * the mail transaction is started and then one or more Recipient * commands may be called followed by a Data command. * * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE SUCCESS: 552,451,452 * SMTP CODE SUCCESS: 500,501,421 * @access public * @return bool */ public boolean Mail(Object from) { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Mail() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "MAIL FROM:<" + strval(from) + ">" + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "MAIL not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * Sends the command NOOP to the SMTP server. * * Implements from rfc 821: NOOP <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE ERROR : 500, 421 * @access public * @return bool */ public boolean Noop() { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Noop() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "NOOP" + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "NOOP not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } public boolean Quit() { return Quit(true); } /** * Sends the quit command to the server and then closes the socket * if there is no error or the $close_on_error argument is true. * * Implements from rfc 821: QUIT <CRLF> * * SMTP CODE SUCCESS: 221 * SMTP CODE ERROR : 500 * @access public * @return bool */ public boolean Quit(boolean close_on_error) { String byemsg = null; boolean rval = false; Array<Object> e = new Array<Object>(); String code = null; this.error = null; // so there is no confusion if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Quit() without being connected")); return false; } // send the quit command to the server FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "quit" + this.CRLF); // get any good-bye messages byemsg = this.get_lines(); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + byemsg); } rval = true; e = null; code = Strings.substr(byemsg, 0, 3); if (!equal(code, 221)) { // use e as a tmp var cause Close will overwrite $this->error e = new Array<Object>( new ArrayEntry<Object>("error", "SMTP server rejected quit command"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_rply", Strings.substr(byemsg, 4))); rval = false; if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(e.getValue("error")) + ": " + byemsg + this.CRLF); } } if (empty(e) || close_on_error) { this.Close(); } return rval; } /** * Sends the command RCPT to the SMTP server with the TO: argument of $to. * Returns true if the recipient was accepted false if it was rejected. * * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> * * SMTP CODE SUCCESS: 250,251 * SMTP CODE FAILURE: 550,551,552,553,450,451,452 * SMTP CODE ERROR : 500,501,503,421 * @access public * @return bool */ public boolean Recipient(Object to) { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Recipient() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "RCPT TO:<" + strval(to) + ">" + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250) && !equal(code, 251)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "RCPT not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * Sends the RSET command to abort and transaction that is * currently in progress. Returns true if successful false * otherwise. * * Implements rfc 821: RSET <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE ERROR : 500,501,504,421 * @access public * @return bool */ public boolean Reset() { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Reset() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "RSET" + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "RSET failed"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * Starts a mail transaction from the email address specified in * $from. Returns true if successful or false otherwise. If True * the mail transaction is started and then one or more Recipient * commands may be called followed by a Data command. This command * will send the message to the users terminal if they are logged * in. * * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE SUCCESS: 552,451,452 * SMTP CODE SUCCESS: 500,501,502,421 * @access public * @return bool */ public boolean Send(Object from) { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Send() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "SEND FROM:" + strval(from) + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "SEND not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * Starts a mail transaction from the email address specified in * $from. Returns true if successful or false otherwise. If True * the mail transaction is started and then one or more Recipient * commands may be called followed by a Data command. This command * will send the message to the users terminal if they are logged * in and send them an email. * * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE SUCCESS: 552,451,452 * SMTP CODE SUCCESS: 500,501,502,421 * @access public * @return bool */ public boolean SendAndMail(Object from) { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called SendAndMail() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "SAML FROM:" + strval(from) + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "SAML not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * Starts a mail transaction from the email address specified in * $from. Returns true if successful or false otherwise. If True * the mail transaction is started and then one or more Recipient * commands may be called followed by a Data command. This command * will send the message to the users terminal if they are logged * in or mail it to them if they are not. * * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE SUCCESS: 552,451,452 * SMTP CODE SUCCESS: 500,501,502,421 * @access public * @return bool */ public boolean SendOrMail(Object from) { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called SendOrMail() without being connected")); return false; } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "SOML FROM:" + strval(from) + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "SOML not accepted from server"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return false; } return true; } /** * This is an optional command for SMTP that this class does not * support. This method is here to make the RFC821 Definition * complete for this class and __may__ be implimented in the future * * Implements from rfc 821: TURN <CRLF> * * SMTP CODE SUCCESS: 250 * SMTP CODE FAILURE: 502 * SMTP CODE ERROR : 500, 503 * @access public * @return bool */ public boolean Turn() { this.error = new Array<Object>(new ArrayEntry<Object>("error", "This method, TURN, of the SMTP " + "is not implemented")); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> NOTICE: " + strval(this.error.getValue("error")) + this.CRLF); } return false; } /** * Verifies that the name is recognized by the server. * Returns false if the name could not be verified otherwise * the response from the server is returned. * * Implements rfc 821: VRFY <SP> <string> <CRLF> * * SMTP CODE SUCCESS: 250,251 * SMTP CODE FAILURE: 550,551,553 * SMTP CODE ERROR : 500,501,502,421 * @access public * @return int */ public String Verify(Object name) { String rply = null; String code = null; this.error = null; // so no confusion is caused if (!this.Connected()) { this.error = new Array<Object>(new ArrayEntry<Object>("error", "Called Verify() without being connected")); return strval(false); } FileSystemOrSocket.fputs(gVars.webEnv, this.smtp_conn, "VRFY " + strval(name) + this.CRLF); rply = this.get_lines(); code = Strings.substr(rply, 0, 3); if (this.do_debug >= 2) { echo(gVars.webEnv, "SMTP -> FROM SERVER:" + this.CRLF + rply); } if (!equal(code, 250) && !equal(code, 251)) { this.error = new Array<Object>( new ArrayEntry<Object>("error", "VRFY failed on name \'" + strval(name) + "\'"), new ArrayEntry<Object>("smtp_code", code), new ArrayEntry<Object>("smtp_msg", Strings.substr(rply, 4))); if (this.do_debug >= 1) { echo(gVars.webEnv, "SMTP -> ERROR: " + strval(this.error.getValue("error")) + ": " + rply + this.CRLF); } return strval(false); } return rply; } /******************************************************************* * INTERNAL FUNCTIONS * ******************************************************************/ /** * Read in as many lines as possible * either before eof or socket timeout occurs on the operation. * With SMTP we can tell if we have more lines to read if the * 4th character is '-' symbol. If it is a space then we don't * need to read anything else. * @access private * @return string */ public String get_lines() { String data = null; String str = null; data = ""; while (booleanval(str = FileSystemOrSocket.fgets(gVars.webEnv, this.smtp_conn, 515))) { if (this.do_debug >= 4) { echo(gVars.webEnv, "SMTP -> get_lines(): $data was \"" + data + "\"" + this.CRLF); echo(gVars.webEnv, "SMTP -> get_lines(): $str is \"" + str + "\"" + this.CRLF); } data = data + str; if (this.do_debug >= 4) { echo(gVars.webEnv, "SMTP -> get_lines(): $data is \"" + data + "\"" + this.CRLF); } // if the 4th character is a space then we are done reading // so just break the loop if (equal(Strings.substr(str, 3, 1), " ")) { break; } } return data; } public void setContext(GlobalVariablesContainer javaGlobalVariables, GlobalConstantsInterface javaGlobalConstants) { gConsts = (GlobalConsts) javaGlobalConstants; gVars = (GlobalVars) javaGlobalVariables; gVars.gConsts = gConsts; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public GlobalVariablesContainer getGlobalVars() { return gVars; } }