基於smtp協議的郵件係統(自己寫的)
最近幾天做好了應用【賤泰迪】,其中有個意見反饋,發送郵件,我知道可以調用係統發送郵件,但這種方法有個弊端,就是您的手機必須安裝Mail的客戶端,
因此我想不用係統發送郵件這種方式,能不能向任意郵箱發送郵件呢?給我自己丟下了一個命題。
於是我調查,發現SMTP發送email 無需係統支持,無需配置,
經過多次嚐試,多次失敗,終於完成了此項功能。
先來看應用【賤泰迪】的效果,

填寫您的郵箱、密碼等,我就能收到您的反饋意見,是不是很方便呢,
更多的效果,您可以下載賤泰迪(https://down.mumayi.com/464309)查看。
此貼,講這個功能給扣出來了,並附上其他的兩種方法發送郵件。
效果圖如下:


1、使用Mail客戶端發送郵件
這種方法前提您的手機必須安裝Mail客戶端,您可以測試的時候下載QQ郵箱客戶端,看看運行的效果。
- case R.id.button1:
- // 創建Intent
- Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
- // 設置內容類型
- emailIntent.setType("plain/text");
- // 設置額外信息
- emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
- new String[] { "收件人郵箱" });// 比如qq郵箱,測試的時候可以手機安裝qq郵箱客戶端
- emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "主題");
- emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "內容");
- // 啟動Activity
- startActivity(Intent.createChooser(emailIntent, "發送郵件..."));
- break;
2、使用SMTP發送郵件
這是此貼的重點所在,SMTP的全稱是“Simple Mail Transfer Protocol”,即簡單郵件傳輸協議。
它是一組用於從源地址到目的地址傳輸郵件的規範,通過它來控製郵件的中轉方式。
SMTP 協議屬於 TCP/IP 協議簇,它幫助每台計算機在發送或中轉信件時找到下一個目的地。
SMTP 服務器就是遵循 SMTP 協議的發送郵件服務器。
它需要三個jar包,下載地址:https://code.google.com/p/javamail-android/downloads/list
下載後複製libs,即可。
下麵介紹兩種方法實現使用SMTP發送郵件
(1)方法一
- case R.id.button2:
- new Thread() {
- @Override
- public void run() {
- EmailSender sender = new EmailSender();
- // 設置服務器地址和端口,網上搜的到
- sender.setProperties("smtp.qq.com", "465");
- // 分別設置發件人,郵件標題和文本內容
- try {
- sender.setMessage("發件人郵箱", "主題主題1", "內容內容1");
- sender.setReceiver(new String[] { "收件人郵箱" });
- sender.sendEmail("smtp.qq.com", "發件人郵箱", "發件人郵箱密碼");
- } catch (AddressException e) {
- e.printStackTrace();
- Log.e("wxl", "AddressException", e);
- } catch (MessagingException e) {
- e.printStackTrace();
- Log.e("wxl", "MessagingException", e);
- }
- }
- }.start();
- break;
這裏需要EmailSender.java
- package com.xiaomolong.example.smtpmail;
- import java.io.File;
- import java.util.Date;
- import java.util.Properties;
- import javax.activation.DataHandler;
- import javax.activation.FileDataSource;
- import javax.mail.Address;
- import javax.mail.Message;
- import javax.mail.MessagingException;
- import javax.mail.Session;
- import javax.mail.Transport;
- import javax.mail.internet.AddressException;
- import javax.mail.internet.InternetAddress;
- import javax.mail.internet.MimeBodyPart;
- import javax.mail.internet.MimeMessage;
- import javax.mail.internet.MimeMultipart;
- public class EmailSender {
- private Properties properties;
- private Session session;
- private Message message;
- private MimeMultipart multipart;
- public EmailSender() {
- super();
- this.properties = new Properties();
- }
- public void setProperties(String host, String post) {
- // 地址
- this.properties.put("mail.smtp.host", host);
- // 端口號
- this.properties.put("mail.smtp.post", post);
- // 是否驗證
- this.properties.put("mail.smtp.auth", true);
- this.session = Session.getInstance(properties);
- this.message = new MimeMessage(session);
- this.multipart = new MimeMultipart("mixed");
- }
- /**
- * 設置收件人
- *
- * @param receiver
- * @throws MessagingException
- */
- public void setReceiver(String[] receiver) throws MessagingException {
- Address[] address = new InternetAddress[receiver.length];
- for (int i = 0; i < receiver.length; i++) {
- address[i] = new InternetAddress(receiver[i]);
- }
- this.message.setRecipients(Message.RecipientType.TO, address);
- }
- /**
- * 設置郵件
- *
- * @param from
- * 來源
- * @param title
- * 標題
- * @param content
- * 內容
- * @throws AddressException
- * @throws MessagingException
- */
- public void setMessage(String from, String title, String content)
- throws AddressException,
- MessagingException {
- this.message.setFrom(new InternetAddress(from));
- this.message.setSubject(title);
- // 純文本的話用setText()就行,不過有附件就顯示不出來內容了
- MimeBodyPart textBody = new MimeBodyPart();
- textBody.setContent(content, "text/html;charset=gbk");
- this.multipart.addBodyPart(textBody);
- }
- /**
- * 添加附件
- *
- * @param filePath
- * 文件路徑
- * @throws MessagingException
- */
- public void addAttachment(String filePath) throws MessagingException {
- FileDataSource fileDataSource = new FileDataSource(new File(filePath));
- DataHandler dataHandler = new DataHandler(fileDataSource);
- MimeBodyPart mimeBodyPart = new MimeBodyPart();
- mimeBodyPart.setDataHandler(dataHandler);
- mimeBodyPart.setFileName(fileDataSource.getName());
- this.multipart.addBodyPart(mimeBodyPart);
- }
- /**
- * 發送郵件
- *
- * @param host
- * 地址
- * @param account
- * 賬戶名
- * @param pwd
- * 密碼
- * @throws MessagingException
- */
- public void sendEmail(String host, String account, String pwd)
- throws MessagingException {
- // 發送時間
- this.message.setSentDate(new Date());
- // 發送的內容,文本和附件
- this.message.setContent(this.multipart);
- this.message.saveChanges();
- // 創建郵件發送對象,並指定其使用SMTP協議發送郵件
- Transport transport = session.getTransport("smtp");
- // 登錄郵箱
- transport.connect(host, account, pwd);
- // 發送郵件
- transport.sendMessage(message, message.getAllRecipients());
- // 關閉連接
- transport.close();
- }
- }
(2)方法二
- case R.id.button3:
- new SendTask().execute();
- break;
- class SendTask extends AsyncTask<Integer, Integer, String> {
- // 後麵尖括號內分別是參數(例子裏是線程休息時間),進度(publishProgress用到),返回值 類型
- @Override
- protected void onPreExecute() {
- // 第一個執行方法
- super.onPreExecute();
- }
- @Override
- protected String doInBackground(Integer... params) {
- // contact, contactPsw, title, content;
- String isok = "";
- Mails m = new Mails("發件人郵箱", "發件人郵箱密碼");
- m.set_debuggable(false);
- String[] toArr = { "收件人郵箱" };
- m.set_to(toArr);
- m.set_from("發件人郵箱");
- m.set_subject("主題主題2");
- m.setBody("內容內容2");
- try {
- // m.addAttachment("/sdcard/filelocation");
- if (m.send()) {
- isok = "ok";
- } else {
- isok = "no";
- }
- } catch (Exception e) {
- Log.e("wxl", "Could not send email", e);
- }
- return isok;
- }
- @Override
- protected void onProgressUpdate(Integer... progress) {
- // 這個函數在doInBackground調用publishProgress時觸發,雖然調用時隻有一個參數
- // 但是這裏取到的是一個數組,所以要用progesss[0]來取值
- // 第n個參數就用progress[n]來取值
- super.onProgressUpdate(progress);
- }
- @Override
- protected void onPostExecute(String result) {
- // doInBackground返回時觸發,換句話說,就是doInBackground執行完後觸發
- // 這裏的result就是上麵doInBackground執行後的返回值,所以這裏是"執行完畢"
- // setTitle(result);
- if ("ok".equals(result)) {
- Toast.makeText(getApplicationContext(), "發送成功",
- Toast.LENGTH_SHORT).show();
- } else {
- Toast.makeText(getApplicationContext(), "發送失敗",
- Toast.LENGTH_SHORT).show();
- }
- super.onPostExecute(result);
- }
- }
這裏需要Mails.java
- package com.xiaomolong.example.smtpmail;
- import java.util.Date;
- import java.util.Properties;
- import javax.activation.CommandMap;
- import javax.activation.DataHandler;
- import javax.activation.DataSource;
- import javax.activation.FileDataSource;
- import javax.activation.MailcapCommandMap;
- import javax.mail.BodyPart;
- import javax.mail.Multipart;
- import javax.mail.PasswordAuthentication;
- import javax.mail.Session;
- import javax.mail.Transport;
- import javax.mail.internet.InternetAddress;
- import javax.mail.internet.MimeBodyPart;
- import javax.mail.internet.MimeMessage;
- import javax.mail.internet.MimeMultipart;
- public class Mails extends javax.mail.Authenticator {
- private String _user;
- private String _pass;
- private String[] _to;
- private String _from;
- private String _port;
- private String _sport;
- private String _host;
- private String _subject;
- private String _body;
- private boolean _auth;
- private boolean _debuggable;
- private Multipart _multipart;
- public Mails() {
- _host = "smtp.qq.com"; // default smtp server
- _port = "465"; // default smtp port
- _sport = "465"; // default socketfactory port
- _user = ""; // username _pass = ""; // password
- _from = ""; // email sent from
- _subject = ""; // email subject
- _body = ""; // email body
- _debuggable = false; // debug mode on or off - default off
- _auth = true; // smtp authentication - default on
- _multipart = new MimeMultipart(); // There is something wrong with
- // MailCap, javamail can not find a
- // handler for the multipart/mixed
- // part, so this bit needs to be
- // added.
- MailcapCommandMap mc = (MailcapCommandMap) CommandMap
- .getDefaultCommandMap();
- mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
- mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
- mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
- mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
- mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
- CommandMap.setDefaultCommandMap(mc);
- }
- public String get_user() {
- return _user;
- }
- public void set_user(String _user) {
- this._user = _user;
- }
- public String get_pass() {
- return _pass;
- }
- public void set_pass(String _pass) {
- this._pass = _pass;
- }
- public String[] get_to() {
- return _to;
- }
- public void set_to(String[] _to) {
- this._to = _to;
- }
- public String get_from() {
- return _from;
- }
- public void set_from(String _from) {
- this._from = _from;
- }
- public String get_port() {
- return _port;
- }
- public void set_port(String _port) {
- this._port = _port;
- }
- public String get_sport() {
- return _sport;
- }
- public void set_sport(String _sport) {
- this._sport = _sport;
- }
- public String get_host() {
- return _host;
- }
- public void set_host(String _host) {
- this._host = _host;
- }
- public String get_subject() {
- return _subject;
- }
- public void set_subject(String _subject) {
- this._subject = _subject;
- }
- public String get_body() {
- return _body;
- }
- public void set_body(String _body) {
- this._body = _body;
- }
- public boolean is_auth() {
- return _auth;
- }
- public void set_auth(boolean _auth) {
- this._auth = _auth;
- }
- public boolean is_debuggable() {
- return _debuggable;
- }
- public void set_debuggable(boolean _debuggable) {
- this._debuggable = _debuggable;
- }
- public Multipart get_multipart() {
- return _multipart;
- }
- public void set_multipart(Multipart _multipart) {
- this._multipart = _multipart;
- }
- public Mails(String user, String pass) {
- this();
- _user = user;
- _pass = pass;
- }
- public boolean send() throws Exception {
- Properties props = _setProperties();
- if (!_user.equals("") && !_pass.equals("") && _to.length > 0
- && !_from.equals("") && !_subject.equals("")
- && !_body.equals("")) {
- Session session = Session.getInstance(props, this);
- MimeMessage msg = new MimeMessage(session);
- msg.setFrom(new InternetAddress(_from));
- InternetAddress[] addressTo = new InternetAddress[_to.length];
- for (int i = 0; i < _to.length; i++) {
- addressTo[i] = new InternetAddress(_to[i]);
- }
- msg.setRecipients(MimeMessage.RecipientType.TO, addressTo);
- msg.setSubject(_subject);
- msg.setSentDate(new Date()); // setup message body
- BodyPart messageBodyPart = new MimeBodyPart();
- messageBodyPart.setText(_body);
- _multipart.addBodyPart(messageBodyPart); // Put parts in message
- msg.setContent(_multipart); // send email
- Transport.send(msg);
- return true;
- } else {
- return false;
- }
- }
- public void addAttachment(String filename) throws Exception {
- BodyPart messageBodyPart = new MimeBodyPart();
- DataSource source = new FileDataSource(filename);
- messageBodyPart.setDataHandler(new DataHandler(source));
- messageBodyPart.setFileName(filename);
- _multipart.addBodyPart(messageBodyPart);
- }
- @Override
- public PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(_user, _pass);
- }
- private Properties _setProperties() {
- Properties props = new Properties();
- props.put("mail.smtp.host", _host);
- if (_debuggable) {
- props.put("mail.debug", "true");
- }
- if (_auth) {
- props.put("mail.smtp.auth", "true");
- }
- props.put("mail.smtp.port", _port);
- props.put("mail.smtp.socketFactory.port", _sport);
- props.put("mail.smtp.socketFactory.class",
- "javax.net.ssl.SSLSocketFactory");
- props.put("mail.smtp.socketFactory.fallback", "false");
- return props;
- } // the getters and setters
- public String getBody() {
- return _body;
- }
- public void setBody(String _body) {
- this._body = _body;
- } // more of the getters and setters 錕斤拷.. }
- }
代碼粘完了,這裏采用了線程和異步,對於新手可以學學。【賤泰迪】采用的是第二種方法。
下麵開始說一下注意點:
首先加上聯網的權限,<uses-permission android:name="android.permission.INTERNET" />,這是小問題
以上代碼完成沒有問題,但是運行會拋這樣的異常:

這是為什麼,使用SMTP來發送E-mail,因此您的郵箱必須開啟此項服務,
【QQ郵箱】【設置】【賬戶】【POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務】如下圖:

最後附上下載地址:https://download.csdn.net/detail/xiangzhihong8/6661655
最後更新:2017-04-03 14:54:35