Постановка задачи: Сделать отправку отчета об ошибках себе на почту.
Проблема: В 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());
}
}
Проблема: В 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);
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();
}
Зделать - Сделать
ОтветитьУдалить