SMTP-клиент для мобильного телефона
|
|
Пакет java.io.* входящий в CLDC Connection Framework
предоставляет разработчикам мощный
инструмент для создания сетевых приложений.
Пакет содержит всего один класс Connector, 8
интерфейсов и один единственный Exception
(ConnectionNotFoundException), сигнализирующий о
невозможности установления сетевого
соединения. Используя данный пакет, разработчики могут устанавливать http, socket и другие соединения. Давайте вместе с вами создадим мини smtp клиент. Ниже представлен код нашего smtp клиента. Внимание!
public class SMTPClient { /*===========================================[ STATIC VARIABLES ]=============*/ public static final int DEFAULT_SMTP_PORT = 25; public static final String CRLF = "\r\n"; //если значение переменной 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); } } //============================================================================== |
|
Все права (c) SmartGSM |