基于smtp协议的邮件系统(自己写的)

最近几天做好了应用【贱泰迪】,其中有个意见反馈,发送邮件,

我知道可以调用系统发送邮件,但这种方法有个弊端,就是您的手机必须安装Mail的客户端,

因此我想不用系统发送邮件这种方式,能不能向任意邮箱发送邮件呢?给我自己丢下了一个命题。

于是我调查,发现SMTP发送email 无需系统支持,无需配置,

经过多次尝试,多次失败,终于完成了此项功能。

先来看应用【贱泰迪】的效果,

填写您的邮箱、密码等,我就能收到您的反馈意见,是不是很方便呢,

更多的效果,您可以下载贱泰迪(http://down.mumayi.com/464309)查看。

此贴,讲这个功能给扣出来了,并附上其他的两种方法发送邮件。

效果图如下:

1、使用Mail客户端发送邮件

这种方法前提您的手机必须安装Mail客户端,您可以测试的时候下载QQ邮箱客户端,看看运行的效果。

  1. case R.id.button1:
  2.                         // 创建Intent
  3.                         Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
  4.                         // 设置内容类型
  5.                         emailIntent.setType("plain/text");
  6.                         // 设置额外信息
  7.                         emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
  8.                                         new String[] { "收件人邮箱" });// 比如qq邮箱,测试的时候可以手机安装qq邮箱客户端
  9.                         emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "主题");
  10.                         emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "内容");
  11.                         // 启动Activity
  12.                         startActivity(Intent.createChooser(emailIntent, "发送邮件..."));
  13.                         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)方法一

  1. case R.id.button2:
  2.                         new Thread() {
  3.                                 @Override
  4.                                 public void run() {
  5.                                         EmailSender sender = new EmailSender();
  6.                                         // 设置服务器地址和端口,网上搜的到
  7.                                         sender.setProperties("smtp.qq.com", "465");
  8.                                         // 分别设置发件人,邮件标题和文本内容
  9.                                         try {
  10.                                                 sender.setMessage("发件人邮箱", "主题主题1", "内容内容1");
  11.                                                 sender.setReceiver(new String[] { "收件人邮箱" });
  12.                                                 sender.sendEmail("smtp.qq.com", "发件人邮箱", "发件人邮箱密码");
  13.                                         } catch (AddressException e) {
  14.                                                 e.printStackTrace();
  15.                                                 Log.e("wxl", "AddressException", e);
  16.                                         } catch (MessagingException e) {
  17.                                                 e.printStackTrace();
  18.                                                 Log.e("wxl", "MessagingException", e);
  19.                                         }
  20.                                 }
  21.                         }.start();
  22.                         break;

复制代码

这里需要EmailSender.java

  1. package com.xiaomolong.example.smtpmail;
  2. import java.io.File;
  3. import java.util.Date;
  4. import java.util.Properties;
  5. import javax.activation.DataHandler;
  6. import javax.activation.FileDataSource;
  7. import javax.mail.Address;
  8. import javax.mail.Message;
  9. import javax.mail.MessagingException;
  10. import javax.mail.Session;
  11. import javax.mail.Transport;
  12. import javax.mail.internet.AddressException;
  13. import javax.mail.internet.InternetAddress;
  14. import javax.mail.internet.MimeBodyPart;
  15. import javax.mail.internet.MimeMessage;
  16. import javax.mail.internet.MimeMultipart;
  17. public class EmailSender {
  18.         private Properties properties;
  19.         private Session session;
  20.         private Message message;
  21.         private MimeMultipart multipart;
  22.         public EmailSender() {
  23.                 super();
  24.                 this.properties = new Properties();
  25.         }
  26.         public void setProperties(String host, String post) {
  27.                 // 地址
  28.                 this.properties.put("mail.smtp.host", host);
  29.                 // 端口号
  30.                 this.properties.put("mail.smtp.post", post);
  31.                 // 是否验证
  32.                 this.properties.put("mail.smtp.auth", true);
  33.                 this.session = Session.getInstance(properties);
  34.                 this.message = new MimeMessage(session);
  35.                 this.multipart = new MimeMultipart("mixed");
  36.         }
  37.         /**
  38.          * 设置收件人
  39.          *
  40.          * @param receiver
  41.          * @throws MessagingException
  42.          */
  43.         public void setReceiver(String[] receiver) throws MessagingException {
  44.                 Address[] address = new InternetAddress[receiver.length];
  45.                 for (int i = 0; i < receiver.length; i++) {
  46.                         address[i] = new InternetAddress(receiver[i]);
  47.                 }
  48.                 this.message.setRecipients(Message.RecipientType.TO, address);
  49.         }
  50.         /**
  51.          * 设置邮件
  52.          *
  53.          * @param from
  54.          *            来源
  55.          * @param title
  56.          *            标题
  57.          * @param content
  58.          *            内容
  59.          * @throws AddressException
  60.          * @throws MessagingException
  61.          */
  62.         public void setMessage(String from, String title, String content)
  63.                         throws AddressException,
  64.                         MessagingException {
  65.                 this.message.setFrom(new InternetAddress(from));
  66.                 this.message.setSubject(title);
  67.                 // 纯文本的话用setText()就行,不过有附件就显示不出来内容了
  68.                 MimeBodyPart textBody = new MimeBodyPart();
  69.                 textBody.setContent(content, "text/html;charset=gbk");
  70.                 this.multipart.addBodyPart(textBody);
  71.         }
  72.         /**
  73.          * 添加附件
  74.          *
  75.          * @param filePath
  76.          *            文件路径
  77.          * @throws MessagingException
  78.          */
  79.         public void addAttachment(String filePath) throws MessagingException {
  80.                 FileDataSource fileDataSource = new FileDataSource(new File(filePath));
  81.                 DataHandler dataHandler = new DataHandler(fileDataSource);
  82.                 MimeBodyPart mimeBodyPart = new MimeBodyPart();
  83.                 mimeBodyPart.setDataHandler(dataHandler);
  84.                 mimeBodyPart.setFileName(fileDataSource.getName());
  85.                 this.multipart.addBodyPart(mimeBodyPart);
  86.         }
  87.         /**
  88.          * 发送邮件
  89.          *
  90.          * @param host
  91.          *            地址
  92.          * @param account
  93.          *            账户名
  94.          * @param pwd
  95.          *            密码
  96.          * @throws MessagingException
  97.          */
  98.         public void sendEmail(String host, String account, String pwd)
  99.                         throws MessagingException {
  100.                 // 发送时间
  101.                 this.message.setSentDate(new Date());
  102.                 // 发送的内容,文本和附件
  103.                 this.message.setContent(this.multipart);
  104.                 this.message.saveChanges();
  105.                 // 创建邮件发送对象,并指定其使用SMTP协议发送邮件
  106.                 Transport transport = session.getTransport("smtp");
  107.                 // 登录邮箱
  108.                 transport.connect(host, account, pwd);
  109.                 // 发送邮件
  110.                 transport.sendMessage(message, message.getAllRecipients());
  111.                 // 关闭连接
  112.                 transport.close();
  113.         }
  114. }

复制代码

(2)方法二

  1. case R.id.button3:
  2.                         new SendTask().execute();
  3.                         break;

复制代码

  1. class SendTask extends AsyncTask<Integer, Integer, String> {
  2.                 // 后面尖括号内分别是参数(例子里是线程休息时间),进度(publishProgress用到),返回值 类型
  3.                 @Override
  4.                 protected void onPreExecute() {
  5.                         // 第一个执行方法
  6.                         super.onPreExecute();
  7.                 }
  8.                 @Override
  9.                 protected String doInBackground(Integer... params) {
  10.                         // contact, contactPsw, title, content;
  11.                         String isok = "";
  12.                         Mails m = new Mails("发件人邮箱", "发件人邮箱密码");
  13.                         m.set_debuggable(false);
  14.                         String[] toArr = { "收件人邮箱" };
  15.                         m.set_to(toArr);
  16.                         m.set_from("发件人邮箱");
  17.                         m.set_subject("主题主题2");
  18.                         m.setBody("内容内容2");
  19.                         try {
  20.                                 // m.addAttachment("/sdcard/filelocation");
  21.                                 if (m.send()) {
  22.                                         isok = "ok";
  23.                                 } else {
  24.                                         isok = "no";
  25.                                 }
  26.                         } catch (Exception e) {
  27.                                 Log.e("wxl", "Could not send email", e);
  28.                         }
  29.                         return isok;
  30.                 }
  31.                 @Override
  32.                 protected void onProgressUpdate(Integer... progress) {
  33.                         // 这个函数在doInBackground调用publishProgress时触发,虽然调用时只有一个参数
  34.                         // 但是这里取到的是一个数组,所以要用progesss[0]来取值
  35.                         // 第n个参数就用progress[n]来取值
  36.                         super.onProgressUpdate(progress);
  37.                 }
  38.                 @Override
  39.                 protected void onPostExecute(String result) {
  40.                         // doInBackground返回时触发,换句话说,就是doInBackground执行完后触发
  41.                         // 这里的result就是上面doInBackground执行后的返回值,所以这里是"执行完毕"
  42.                         // setTitle(result);
  43.                         if ("ok".equals(result)) {
  44.                                 Toast.makeText(getApplicationContext(), "发送成功",
  45.                                                 Toast.LENGTH_SHORT).show();
  46.                         } else {
  47.                                 Toast.makeText(getApplicationContext(), "发送失败",
  48.                                                 Toast.LENGTH_SHORT).show();
  49.                         }
  50.                         super.onPostExecute(result);
  51.                 }
  52.         }

复制代码

这里需要Mails.java

  1. package com.xiaomolong.example.smtpmail;
  2. import java.util.Date;
  3. import java.util.Properties;
  4. import javax.activation.CommandMap;
  5. import javax.activation.DataHandler;
  6. import javax.activation.DataSource;
  7. import javax.activation.FileDataSource;
  8. import javax.activation.MailcapCommandMap;
  9. import javax.mail.BodyPart;
  10. import javax.mail.Multipart;
  11. import javax.mail.PasswordAuthentication;
  12. import javax.mail.Session;
  13. import javax.mail.Transport;
  14. import javax.mail.internet.InternetAddress;
  15. import javax.mail.internet.MimeBodyPart;
  16. import javax.mail.internet.MimeMessage;
  17. import javax.mail.internet.MimeMultipart;
  18. public class Mails extends javax.mail.Authenticator {
  19.         private String _user;
  20.         private String _pass;
  21.         private String[] _to;
  22.         private String _from;
  23.         private String _port;
  24.         private String _sport;
  25.         private String _host;
  26.         private String _subject;
  27.         private String _body;
  28.         private boolean _auth;
  29.         private boolean _debuggable;
  30.         private Multipart _multipart;
  31.         public Mails() {
  32.                 _host = "smtp.qq.com"; // default smtp server
  33.                 _port = "465"; // default smtp port
  34.                 _sport = "465"; // default socketfactory port
  35.                 _user = ""; // username _pass = ""; // password
  36.                 _from = ""; // email sent from
  37.                 _subject = ""; // email subject
  38.                 _body = ""; // email body
  39.                 _debuggable = false; // debug mode on or off - default off
  40.                 _auth = true; // smtp authentication - default on
  41.                 _multipart = new MimeMultipart(); // There is something wrong with
  42.                                                                                         // MailCap, javamail can not find a
  43.                                                                                         // handler for the multipart/mixed
  44.                                                                                         // part, so this bit needs to be
  45.                                                                                         // added.
  46.                 MailcapCommandMap mc = (MailcapCommandMap) CommandMap
  47.                                 .getDefaultCommandMap();
  48.                 mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
  49.                 mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
  50.                 mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
  51.                 mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
  52.                 mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
  53.                 CommandMap.setDefaultCommandMap(mc);
  54.         }
  55.         public String get_user() {
  56.                 return _user;
  57.         }
  58.         public void set_user(String _user) {
  59.                 this._user = _user;
  60.         }
  61.         public String get_pass() {
  62.                 return _pass;
  63.         }
  64.         public void set_pass(String _pass) {
  65.                 this._pass = _pass;
  66.         }
  67.         public String[] get_to() {
  68.                 return _to;
  69.         }
  70.         public void set_to(String[] _to) {
  71.                 this._to = _to;
  72.         }
  73.         public String get_from() {
  74.                 return _from;
  75.         }
  76.         public void set_from(String _from) {
  77.                 this._from = _from;
  78.         }
  79.         public String get_port() {
  80.                 return _port;
  81.         }
  82.         public void set_port(String _port) {
  83.                 this._port = _port;
  84.         }
  85.         public String get_sport() {
  86.                 return _sport;
  87.         }
  88.         public void set_sport(String _sport) {
  89.                 this._sport = _sport;
  90.         }
  91.         public String get_host() {
  92.                 return _host;
  93.         }
  94.         public void set_host(String _host) {
  95.                 this._host = _host;
  96.         }
  97.         public String get_subject() {
  98.                 return _subject;
  99.         }
  100.         public void set_subject(String _subject) {
  101.                 this._subject = _subject;
  102.         }
  103.         public String get_body() {
  104.                 return _body;
  105.         }
  106.         public void set_body(String _body) {
  107.                 this._body = _body;
  108.         }
  109.         public boolean is_auth() {
  110.                 return _auth;
  111.         }
  112.         public void set_auth(boolean _auth) {
  113.                 this._auth = _auth;
  114.         }
  115.         public boolean is_debuggable() {
  116.                 return _debuggable;
  117.         }
  118.         public void set_debuggable(boolean _debuggable) {
  119.                 this._debuggable = _debuggable;
  120.         }
  121.         public Multipart get_multipart() {
  122.                 return _multipart;
  123.         }
  124.         public void set_multipart(Multipart _multipart) {
  125.                 this._multipart = _multipart;
  126.         }
  127.         public Mails(String user, String pass) {
  128.                 this();
  129.                 _user = user;
  130.                 _pass = pass;
  131.         }
  132.         public boolean send() throws Exception {
  133.                 Properties props = _setProperties();
  134.                 if (!_user.equals("") && !_pass.equals("") && _to.length > 0
  135.                                 && !_from.equals("") && !_subject.equals("")
  136.                                 && !_body.equals("")) {
  137.                         Session session = Session.getInstance(props, this);
  138.                         MimeMessage msg = new MimeMessage(session);
  139.                         msg.setFrom(new InternetAddress(_from));
  140.                         InternetAddress[] addressTo = new InternetAddress[_to.length];
  141.                         for (int i = 0; i < _to.length; i++) {
  142.                                 addressTo[i] = new InternetAddress(_to[i]);
  143.                         }
  144.                         msg.setRecipients(MimeMessage.RecipientType.TO, addressTo);
  145.                         msg.setSubject(_subject);
  146.                         msg.setSentDate(new Date()); // setup message body
  147.                         BodyPart messageBodyPart = new MimeBodyPart();
  148.                         messageBodyPart.setText(_body);
  149.                         _multipart.addBodyPart(messageBodyPart); // Put parts in message
  150.                         msg.setContent(_multipart); // send email
  151.                         Transport.send(msg);
  152.                         return true;
  153.                 } else {
  154.                         return false;
  155.                 }
  156.         }
  157.         public void addAttachment(String filename) throws Exception {
  158.                 BodyPart messageBodyPart = new MimeBodyPart();
  159.                 DataSource source = new FileDataSource(filename);
  160.                 messageBodyPart.setDataHandler(new DataHandler(source));
  161.                 messageBodyPart.setFileName(filename);
  162.                 _multipart.addBodyPart(messageBodyPart);
  163.         }
  164.         @Override
  165.         public PasswordAuthentication getPasswordAuthentication() {
  166.                 return new PasswordAuthentication(_user, _pass);
  167.         }
  168.         private Properties _setProperties() {
  169.                 Properties props = new Properties();
  170.                 props.put("mail.smtp.host", _host);
  171.                 if (_debuggable) {
  172.                         props.put("mail.debug", "true");
  173.                 }
  174.                 if (_auth) {
  175.                         props.put("mail.smtp.auth", "true");
  176.                 }
  177.                 props.put("mail.smtp.port", _port);
  178.                 props.put("mail.smtp.socketFactory.port", _sport);
  179.                 props.put("mail.smtp.socketFactory.class",
  180.                                 "javax.net.ssl.SSLSocketFactory");
  181.                 props.put("mail.smtp.socketFactory.fallback", "false");
  182.                 return props;
  183.         } // the getters and setters
  184.         public String getBody() {
  185.                 return _body;
  186.         }
  187.         public void setBody(String _body) {
  188.                 this._body = _body;
  189.         } // more of the getters and setters 锟斤拷.. }
  190. }

复制代码

代码粘完了,这里采用了线程和异步,对于新手可以学学。【贱泰迪】采用的是第二种方法。

下面开始说一下注意点:

首先加上联网的权限,<uses-permission android:name="android.permission.INTERNET" />,这是小问题

以上代码完成没有问题,但是运行会抛这样的异常:

这是为什么,使用SMTP来发送E-mail,因此您的邮箱必须开启此项服务,

【QQ邮箱】【设置】【账户】【POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务】如下图:

最后附上下载地址:http://download.csdn.net/detail/xiangzhihong8/6661655

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Seebug漏洞平台

CVE-2017-16943 Exim UAF漏洞分析

感恩节那天,meh在Bugzilla上提交了一个exim的uaf漏洞:https://bugs.exim.org/show_bug.cgi?id=2199,这周...

4185
来自专栏刘望舒

Android PMS处理APK的复制

在上一篇文章Android包管理机制之PackageInstaller安装APK中,我们学习了PackageInstaller是如何安装APK的,最后会将APK...

2065
来自专栏各种机器学习基础算法

laravel5.4上传EXCEL并解析

首先,通过composer引入Laravel Excel v2.1库 composer require maatwebsite/excel ~2.1.0 将Se...

35212
来自专栏纯洁的微笑

springboot(十一):Spring boot中mongodb的使用

mongodb是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多。由于很多公司使用了云服务,服务器默认都开放了外网地址,...

3486
来自专栏Linux驱动

34.QT-制作串口助手(并动态检测在线串口,附带源码)

将qextserialport-1.2rc.zip解压,将解压后的src目录拷贝到项目里的子目录SerialSrc下,在项目pro文件中增加下面这行

1413
来自专栏Kubernetes

从源码解析kube-scheduler默认的配置

本文作为Kubernetes Scheduler源码分析的番外篇,补充一个方面的分析:从源码层面解析kube-scheduler的默认配置是怎么做的。 从头来看...

3286
来自专栏影子

开始食用grpc(之二)

转载请注明出处:https://www.cnblogs.com/funnyzpc/p/9570992.html

5324
来自专栏Coding01

深入浅出 Laravel Echo (3)

看完 public channel 的流程,我们该来说说怎么跑通 private channel 了。

2463
来自专栏蜉蝣禅修之道

如何为豆瓣FM写一个chrome的歌词插件

1743
来自专栏Java与Android技术栈

Android App安全防范措施的小结

关闭打印的日志,防止日志中的调试信息被看到。如果在网络框架中使用了日志,那就更加需要关闭了。

1082

扫码关注云+社区

领取腾讯云代金券