четверг, 18 августа 2011 г.

Отправка почты без использования сторонних библиотек

Постановка задачи: Сделать отправку отчета об ошибках себе на почту.
Проблема: В Android-е версии 1.6 есть стандартный Intent для этих целей, но используя его, пользователь будет видить почту и пароль отправителя, а также почту получателя, что не желательно в моем случае. Есть подключаемое API, но оно 1) занимает много место 2) при обфускации с библиотеками этого API возникли проблемы. Что меня и подтолкнуло написать свою реализацию отправки почты.
Версия Android-а: 1.6
Пример использования класса EmailSender:


 private void send(String message) {
    try {
      EMailSender sender = new EMailSender("login@mail.ru""password""94.100.177.1", 2525);
      sender.sendMail(
"login@mail.ru""заголовок", message);
    } catch (Exception e) {
      Log.e("test""send error" + e.toString());
    }
  }



Исходный код этого класса:                                                          


import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

import android.os.SystemClock;

import com.evos.model.impl.common.Base64;

public class EMailSender {

  private OutputStream _out;
  private Socket _socket;
  private String _sender;
  private String _password;
  private String _smtpAddress;
  private int _port;

  public EMailSender(String sender, String password, String smtpAddress, int port) {
    _sender = sender;
    _password = password;
    _smtpAddress = smtpAddress;
    _port = port;
  }

  public synchronized void sendMail(String recipients, String title, String body) throws IOException {
    connect();
    String plain = "\0" + _sender + "\0" + _password;
    String plain64 = Base64.encodeBytes(plain.getBytes());
    write("EHLO " + "nerivne" + "\r\n");
    write("AUTH PLAIN " + plain64 + "\r\n");
    SystemClock.sleep(500);
    write("MAIL FROM:<" + _sender + "> SIZE=" + body.length() + "\r\n");
    write("RCPT TO:<" + recipients + ">\r\n");
    SystemClock.sleep(500);
    write("DATA\r\n");
    write("From: <"+ _sender +">\r\n" +
       "To: <" + recipients + ">\r\n" +
       "Subject: " + title + "\r\n" +
       "Content-Type: text/plain" + ";\r\n" +
       "\tcharset=\"utf-8\"\r\n");
    write("\r\n" + body + "\r\n.\r\n");
    write("RSET\r\n");
    write("QUIT\r\n");
    SystemClock.sleep(1500);
    disconnect();
  }


  private void connect() throws IOException {
    _socket = new Socket();
    InetSocketAddress sockaddr = new InetSocketAddress(_smtpAddress, _port);
    _socket.connect(sockaddr, 4000);
    _out = _socket.getOutputStream();
  }

  private void disconnect() throws IOException {
    _out.close();
    _socket.close();
  }

  private void write(String str) throws IOException {
    _out.write(str.getBytes());
  }

}





SystemClock.sleep Проставлен там где от сервера нужно было дождаться некоторого ответа, прежде чем зделать следующий шаг.
Я использую у себя сторонний класс Base64, Если вы разрабатывате на платформе Android выше версии 2.1, то там есть втроенный класс, и Вам желательно использовать его.
String encoded = Base64.encodeToString(data.getBytes(), Base64.DEFAULT);
Вместо класса Base64 Вы можете воспользоваться функией: 
public String encode(String input_string)
 {
  StringBuffer output = new StringBuffer();
  byte[] enc = new byte[64];
  int i = 0; int j = 0;

  int length = input_string.length();

  for (; i < 26; i++) enc[i] = (byte)(65 + j++); j = 0;
  for (; i < 52; i++) enc[i] = (byte)(97 + j++); j = 0;
  for (; i < 62; i++) enc[i] = (byte)(48 + j++);
  enc[(i++)] = 43;
  enc[(i++)] = 47;

  i = 0;
  while (i < length - 2) {
   int s0 = input_string.charAt(i++);
   int s1 = input_string.charAt(i++);
   int s2 = input_string.charAt(i++);

   output.append((char)enc[(s0 >> 2 & 0x3F)]);
   output.append((char)enc[((s0 << 4 | s1 >> 4) & 0x3F)]);
   output.append((char)enc[((s1 << 2 | s2 >> 6) & 0x3F)]);
   output.append((char)enc[(s2 & 0x3F)]);
  }
  if (length - i == 1) {
   int s0 = input_string.charAt(i++);
   output.append((char)enc[(s0 >> 2 & 0x3F)]);
   output.append((char)enc[(s0 << 4 & 0x3F)]);
   output.append('=');
   output.append('=');
  } else if (length - i == 2) {
   int s0 = input_string.charAt(i++);
   int s1 = input_string.charAt(i++);
   output.append((char)enc[(s0 >> 2 & 0x3F)]);
   output.append((char)enc[((s0 << 4 | s1 >> 4) & 0x3F)]);
   output.append((char)enc[(s1 << 2 & 0x3F)]);
   output.append('=');
  }
  return output.toString();
 }
 

1 комментарий: