Пакет
java.io.* входящий в CLDC Connection Framework предоставляет разработчикам
мощный инструмент для создания сетевых приложений. Пакет содержит всего один
класс Connector, 8 интерфейсов и один единственный Exception (ConnectionNotFoundException),
сигнализирующий о невозможности установления сетевого соединения.
Используя данный пакет, разработчики могут устанавливать http, socket и другие
соединения. Давайте вместе с вами создадим мини smtp клиент. Ниже представлен
код нашего smtp клиента.
Внимание!
Данный код является иллюстративным материалом возможностей J2ME.
Он не является пособием по написанию smtp клиента.
Если вам необходимо информация о SIMPLE MAIL TRANSFER PROTOCOL, смотрите RFC
821.
Если вам необходимо информация о том как написать smtp клиент, читайте
соответсвующую литературу и обращайтесь к специалистам в данной области.
public class SMTPClient { /*===========================================[ STATIC VARIABLES ]=============*/ public static final int DEFAULT_SMTP_PORT = 25; public static final String CRLF = "rn"; //если значение переменной true //тестовая информация будет выводиться public static final boolean DEBUG = true; /*===========================================[ PRIVATE INSTANCE VARIABLES ]=====*/ //адрес smtp сервера private String smtpServer = null; //порт smtp сервера private int port; //отображаемое имя получателя private String displayFromName; //адрес получателя private String fromName; private StreamConnection connection = null; private DataInputStream in = null; private DataOutputStream out = null; /*===========================================[ PUBLIC CONSTRUCTORS ]===========*/ public SMTPClient (String smtp, int port, String displayFromName, String fromName) { this.smtpServer = smtp; this.port = port; this.displayFromName = displayFromName; this.fromName = fromName; } /*===========================================[ PUBLIC CLASS METHODS ]=========*/ public void send (String displayToName, String mailTo, String subject, String date, byte [] body) throws IOException { try { //открываем соединение с smtp сервером //в соответсвие с CLDC String, параметр должен соответсвовать //следующей схеме: "protocol:address;parameters" connection = (StreamConnection)Connector.open ("socket://" + smtpServer + ":"+port); //получаем поток из которого будем читать данные in = connection.openDataInputStream(); //получаем поток в который будем писать данные out = connection.openDataOutputStream(); //После установления соединение, сервер сообщает о себе //и как бы приглашает нас к себе. //Например: '220 BBN-UNIX.ARPA Simple Mail Transfer Service Ready' String str = readLine(); if (DEBUG) clientPrint (str); //Смотрим код который вернул сервер, //если код сообщает об ошибке выкидываем IOException isOk (str, "220", "server is not ready:"); //Теперь мы здороваемся с сервером. //(По хорошему, мы должны послать ему информацию о себе, //а не его же адрес, как делается ниже) String sent = "HELO "+ smtpServer.toString() + CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //Читаем ответ. //Например: '250 BBN-UNIX.ARPA' str = readLine(); if (DEBUG) clientPrint (str); //Смотрим код который вернул сервер, //если код сообщает об ошибке выкидываем IOException isOk (str, "250", "server is not ready:"); //==============================MAIL========================================== //Теперь, после соблюдения всех формальностей, начинаем отсылать письмо. //Для этого необходимо открыть smtp транзакцию. //Транзакция состоит из 3 шагов. //1 шаг транзакции это комманда MAIL, //которая предоставляет информацию об отправителе. if (fromName != null && fromName.trim().length() != 0) sent = "MAIL FROM: <" + fromName + ">" + CRLF; else sent = "MAIL FROM: < > " + CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //Читаем ответ сервера. //Например: '250 OK' str = readLine(); if (DEBUG) clientPrint (str); //Смотрим код который вернул сервер, //если код сообщает об ошибке выкидываем IOException isOk (str, "250", "MAIL error"); //==============================RCPT========================================== //2 шаг это состоит из одной или болле комманд RCPT, //которая предоставляет информацию серверу, кому мы посылаем письмо. sent = "RCPT TO: <" + mailTo + ">" + CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //Читаем ответ сервера. //Например: '250 OK' str = readLine(); if (DEBUG) clientPrint (str); //Смотрим код который вернул сервер, //если код сообщает об ошибке выкидываем IOException isOk (str, "250", "RCPT error"); //==============================DATA========================================== //3 шаг транзакции это комманда DATA. //После успешного выполнения этой комманды мы //мы сможем посылать наше письмо. sent = "DATA" + CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //Читаем ответ сервера. //Например: '250 OK' str = readLine(); if (DEBUG) clientPrint (str); //Смотрим код который вернул сервер, //если код сообщает об ошибке выкидываем IOException isOk (str, "354", "DATA error"); //==============================FROM========================================== //Посылаем mail адрес отправителя письма. //Почему снова отсылается //адрес отправителя письма, читайте RFC 821 if (displayFromName != null && displayFromName.trim().length() != 0) sent = "From: " + displayFromName + "<" + fromName + ">" + CRLF; else sent = "From: <" + fromName + ">"+CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //================================TO======================================== //Посылаем mail адрес получателя письма. //Почему снова отсылается //адрес получателя письма, читайте RFC 821 if (displayToName != null && displayToName.trim().length() != 0) sent = "To: " + displayToName + "<" + mailTo + ">"+ CRLF; else sent = "To: <" + mailTo + ">"+CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //=============================TITLE============================================ //Посылаем тему письма. sent = "Subject:" + (subject != null? subject: "") + CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //=============================BODY============================================ //Посылаем тело письма. if (body != null && body.length == 0) { out.write (body, 0, body.length); writeLine (CRLF); if (DEBUG) serverPrint ("write body: " + new String (body, 0, body.length) + CRLF); } //===================================QUIT======================================= //Теперь сигнализируем серверу о том, что тело письма закончилось. sent = CRLF + "." + CRLF; writeLine (sent); if (DEBUG) serverPrint (sent); //Читаем ответ сервера. //Например: 250 OK str = readLine(); if (DEBUG) clientPrint (str); //Смотрим код который вернул сервер, //если код сообщает об ошибке выкидываем IOException isOk (str, "354", "End letter error"); //Прощаемся с сервером. writeLine ("QUIT" + CRLF); if (DEBUG) serverPrint ("QUIT" + CRLF); //Читаем ответ сервера. //Например: '221 BBN-UNIX.ARPA Service closing transmission channel' str = readLine(); if (DEBUG) clientPrint (str); //Смотрим код который вернул сервер, //если код сообщает об ошибке выкидываем IOException isOk (str, "221", "QUIT error"); } catch (IOException io) { //Выкидаваем exception. throw io; } finally { //Закрываем потоки и сокет. if (in != null) try {in.close();} catch (IOException ex){} if (out != null) try {out.close();} catch (IOException ex){} if (connection != null) try {connection.close();} catch (IOException ex){} in = null; out = null; connection = null; } } private String readLine() throws IOException { //Читаем строчку с сервера. //(Приведенный ниже код не является оптимальным, //а служит для иллюстративных целей) StringBuffer buffer = new StringBuffer(); byte [] ch = new byte[1]; in.read (ch); while (ch[0] != 13) { buffer.append (new String (ch)); in.read(ch); } in.read (ch); return buffer.toString(); } private void writeLine (String str) throws IOException { //Пишем серверу. byte [] b = str.getBytes(); out.write (b, 0, b.length); } private void isOk (String serverMessage, String ok, String message) throws IOException { //Проверяем код который вернул сервер. //Если он не соответсвует необходимому выкидываем IOException. if (serverMessage == null || !serverMessage.trim().startsWith (ok)) throw new IOException (message + ":" + serverMessage); } public void serverPrint (String str) { //Выводим сообщения от сервера в System.err System.err.println ("S:" + str); } public void clientPrint (String str) { //Выводим сообщения которые мы посылаем серверу в System.err System.err.println ("C:" + str); } } //==============================================================================
|