Android自动发送邮件详解

前言

Android开发过程中,我们有时可能会利用到邮箱验证的功能。那么今天就让我们来学习下Android如何自动发送邮件的知识。

今天涉及到的内容有:

  1. 邮件发送原理
  2. 邮箱基本知识
    2.1 邮件协议
    2.2 邮箱类型
    2.3 邮箱服务器
  3. 邮箱授权码的获取
  4. 发邮件所需jar
  5. 用户权限
  6. 邮件发送封装类EmailSender的使用简介
  7. EmailSender在Activity中使用
  8. 效果图和项目结构图
  9. EmailSender 源码

先来波效果图


效果图.gif

一. 邮件发送原理

Android中的邮件发送原理是:根据发件箱的类型来确定邮箱服务器的基本参数设置,然后登录发件箱,获取发件箱授权码,然后设置发件箱地址昵称标题内容附件等信息,接着设置收件箱地址(为数组对象,意味着可以实现群发),最后执行发邮件逻辑。

二. 邮箱基本知识

2.1 邮件协议

收发邮件也是一种通讯模式,它拥有自己的邮件协议,常见的协议类型有:POP3SMTP,和IMAP

  • POP3: POP3Post Office Protocol 3的简称,即邮局协议的第3个版本,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。它是因特网电子邮件的第一个离线协议标准,POP3允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的。
  • SMTP: SMTP 的全称是“Simple Mail Transfer Protocol”,即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。SMTP 服务器就是遵循 SMTP 协议的发送邮件服务器。SMTP 认证,简单地说就是要求必须在提供了账户名和密码之后才可以登录 SMTP 服务器,这就使得那些垃圾邮件的散播者无可乘之机。增加 SMTP 认证的目的是为了使用户避免受到垃圾邮件的侵扰。
  • IMAP: IMAP全称是Internet Mail Access Protocol,即交互式邮件存取协议,它是跟POP3类似邮件访问标准协议之一。不同的是,开启了IMAP后,您在电子邮件客户端收取的邮件仍然保留 在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作。所以无论从浏览器登录邮箱或者客户端 软件登录邮箱,看到的邮件以及状态都是一致的。
2.2 邮箱类型

常见的邮箱类型有: qq邮箱,163邮箱,126邮箱,sohu邮箱,sina邮箱等。

2.3 邮箱服务器

根据不同的邮箱类型及协议,服务器的地址及端口有所不同。下面列出一些常见的邮箱服务器信息
126邮箱相关服务器服务器信息

服务器名称 服务器地址 SSL协议端口号 非SSL协议端口号
IMAP imap.126.com 993 143
SMTP smtp.126.com 465/994 25
POP3 pop.126.com 995 110

163邮箱相关服务器服务器信息

服务器名称 服务器地址 SSL协议端口号 非SSL协议端口号
IMAP imap.163.com 993 143
SMTP smtp.163.com 465/994 25
POP3 pop.163.com 995 110

qq邮箱相关服务器服务器信息

服务器名称 服务器地址 端口号
SMTP smtp.qq.com 465/587
POP3 pop.qq.com 995

由于不同邮箱及协议的不同,服务器地址和端口会发生很大变化,这里不一 一列举,大家自行百度即可。如我要搜 sina 邮箱的 smtp协议 服务器地址和端口,你可以直接百度sina smtp地址即可,一般相关信息都会给出服务器地址和端口。
本文讲解以163邮箱, SMTP协议服务器为例。

三. 邮箱授权码的获取

实现邮件发送功能,需要使用到发件人的邮箱地址邮箱授权码,那么如何才能开启并获取发件人的邮箱授权码呢?下面以我的163邮箱为例。
登录163邮箱 ----> 设置 ----> POP3/SMTP/IMAP ,然后回出现如下界面:

image.png

这里只要选择一个SMTP 服务即可,我选择开启的是POP3/SMTP服务,然后开启以后,界面会弹出二维码,提示你扫码发送短信验证,短信验证ok后,界面会出现一个16位长度字符串,这就是你当前邮箱的授权码了,注意保护好此授权码哦,不要泄露。其他邮箱的授权码获取方式与此类似,这里就不赘述了。然后将此授权码运用到你代码中去。

四. 发邮件所需jar

实现邮件发送需要以下三个jar的支持:

  • activation.jar
  • additionnal.jar
  • mail.jar

大家可以在这里下载jar包:邮件发送jar.zip
下载完毕以后,将jar拷贝到项目 app/libs/ 文件夹下,然后鼠标置于jar包上,右键选择 Add as Library...jar添加到依赖。

五. 用户权限

实现发邮件功能,需要授权网络权限,不然会报以下错误:

java.lang.SecurityException: Permission denied (missing INTERNET permission?)

所以,你需要在Androidmanifast.xml中添加网络权限:

 <uses-permission android:name="android.permission.INTERNET"/>

六. 邮件发送封装类EmailSender的使用简介

经过以上准备,接下来就可以愉快的编码了。这里我将邮件发送功能封装到了一个工具类EmailSender中,接下来简单介绍下EmailSender的使用。
EmailSender默认采用163邮箱, SMTP协议服务器发送短信功能。若你的发件箱也为163邮箱,那么你可以向下面这样进行发邮件:

        EmailSender.getInstance()
                .setFrom("xxxxx@163.com") //设置发件人邮箱地址
                .setFromNickName("奔跑的佩恩") //设置发件人昵称,不设置时默认昵称为邮箱地址名称
                .setAuthCode("16位邮箱授权码") //设置发件人邮箱授权码
                .setTitle("测试邮件") //设置发送邮件的标题
                .setContent("别打我,我是测试邮件") //设置发送邮件的内容
                .setFilePath(null) //添加附件,设置null时表示不发送附件
                .setTo(new String[]{"xxxxx@xxx.com"}) //设置收件邮箱地址数组
                //发送邮件,传null表示不监听发送邮件的结果
                .sendEmail(new EmailSender.OnSendEmailListener() {
                    @Override
                    public void success() {
                        LogUtil.i("====邮件发送成功======");
                        ToastUtil.shortShow("邮件发送成功");
                    }

                    @Override
                    public void failed(String message) {
                        LogUtil.i("====邮件发送失败=====message="+message);
                        ToastUtil.shortShow("邮件发送失败:"+message);
                    }
                });

因为邮箱服务器的设置包含了一系列key值,其他发送邮箱我为测试过,不知道如果换了邮箱类型后,服务器属性设置的key会不会发生变化。
目前我实现的163邮箱发送功能,邮箱服务器属性设置的key值如下:

        //地址
        this.mProperties.put("mail.smtp.host",mHost);
        //端口号
        this.mProperties.put("mail.smtp.post",mPost);
        //是否验证
        this.mProperties.put("mail.smtp.auth",isAuth);

若其他邮箱设置时,以上key值不发生变化,变的仅是地址,端口验证
那么,你可以像下面这样设置发送信息:

        EmailSender.getInstance()
                //默认服务器地址为"smtp.163.com",端口为"25"
                .setAddress("smtp.163.com", "25")
                //协议和验证,默认参数为 "smtp",true
                .setProperty("smtp",true)
                //默认字符集为utf-8
                .setCharsetName(EmailSender.UTF_8)
                .setFrom("xxxxx@163.com") //设置发件人邮箱地址
                .setFromNickName("奔跑的佩恩") //设置发件人昵称,不设置时默认昵称为邮箱地址名称
                .setAuthCode("16位邮箱授权码") //设置发件人邮箱授权码
                .setTitle("测试邮件") //设置发送邮件的标题
                .setContent("别打我,我是测试邮件") //设置发送邮件的内容
                .setFilePath(null) //添加附件,设置null时表示不发送附件
                .setTo(new String[]{"xxxxx@xxx.com"}) //设置收件邮箱地址数组
                //发送邮件,传null表示不监听发送邮件的结果
                .sendEmail(new EmailSender.OnSendEmailListener() {
                    @Override
                    public void success() {
                        LogUtil.i("====邮件发送成功======");
                        ToastUtil.shortShow("邮件发送成功");
                    }

                    @Override
                    public void failed(String message) {
                        LogUtil.i("====邮件发送失败=====message="+message);
                        ToastUtil.shortShow("邮件发送失败:"+message);
                    }
                });

ok,如果连服务器属性设置的key也发生了变化,那么你可以像下面这样设置邮件的发送:

        EmailSender.getInstance()
                .setHost("新地址key","服务器地址")
                .setPost("新端口key","服务器端口")
                .setAuthKey("新验证key")
                //协议和验证,默认参数为 "smtp",true
                .setProperty("新协议名",true)
                //默认字符集为utf-8
                .setCharsetName(EmailSender.UTF_8)
                .setFrom("xxxxx@xxx.com") //设置发件人邮箱地址
                .setFromNickName("奔跑的佩恩") //设置发件人昵称,不设置时默认昵称为邮箱地址名称
                .setAuthCode("16位邮箱授权码") //设置发件人邮箱授权码
                .setTitle("测试邮件") //设置发送邮件的标题
                .setContent("别打我,我是测试邮件") //设置发送邮件的内容
                .setFilePath(null) //添加附件,设置null时表示不发送附件
                .setTo(new String[]{"xxxxx@xxx.com"}) //设置收件邮箱地址数组
                //发送邮件,传null表示不监听发送邮件的结果
                .sendEmail(new EmailSender.OnSendEmailListener() {
                    @Override
                    public void success() {
                        LogUtil.i("====邮件发送成功======");
                        ToastUtil.shortShow("邮件发送成功");
                    }

                    @Override
                    public void failed(String message) {
                        LogUtil.i("====邮件发送失败=====message="+message);
                        ToastUtil.shortShow("邮件发送失败:"+message);
                    }
                });

七. EmailSender在Activity中使用

下面贴出EmailSenderActivity中使用代码:

public class TempActivity extends AppCompatActivity implements View.OnClickListener{

    private TextView mTvTest;
    private Button mBtnTest;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_temp);

        //初始化控件
        initView();
        //初始化数据
        initData();
        //控件监听
        setListener();
    }

    /**
     * 初始化控件
     **/
    private void initView() {
        mTvTest = findViewById(R.id.mTvTest);
        mBtnTest = findViewById(R.id.mBtnTest);
    }

    private void initData() {
        mTvTest.setText("我是测试啊");

    }

    /**
     * 控件监听
     **/
    private void setListener() {
        //点击事件
        mBtnTest.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
         switch (v.getId()) {
             case R.id.mBtnTest:
                 LogUtil.i("======我点击了======");

                 test();
                 break;
             default:
                 break;
         }
    }

    private void test(){

           EmailSender.getInstance()
//                //默认服务器地址为"smtp.163.com",端口为"25"
//                .setAddress("smtp.163.com", "25")
//                //协议和验证,默认参数为 "smtp",true
//                .setProperty("smtp",true)
//                //默认字符集为utf-8
//                .setCharsetName(EmailSender.UTF_8)
                .setFrom("xxxxx@163.com") //设置发件人邮箱地址
                .setFromNickName("奔跑的佩恩") //设置发件人昵称,不设置时默认昵称为邮箱地址名称
                .setAuthCode("16位邮箱授权码") //设置发件人邮箱授权码
                .setTitle("测试邮件") //设置发送邮件的标题
                .setContent("别打我,我是测试邮件") //设置发送邮件的内容
                .setFilePath(null) //添加附件,设置null时表示不发送附件
                .setTo(new String[]{"xxxxx@xxx.com"}) //设置收件邮箱地址数组
                //发送邮件,传null表示不监听发送邮件的结果
                .sendEmail(new EmailSender.OnSendEmailListener() {
                    @Override
                    public void success() {
                        LogUtil.i("====邮件发送成功======");
                        ToastUtil.shortShow("邮件发送成功");
                    }

                    @Override
                    public void failed(String message) {
                        LogUtil.i("====邮件发送失败=====message="+message);
                        ToastUtil.shortShow("邮件发送失败:"+message);
                    }
                });
    }

}

八. 效果图和项目结构图

效果图.gif
项目结构图.png

九. EmailSender 源码

EmailSender 源码如下:

还有 50% 的精彩内容
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
支付 ¥4.00 继续阅读
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容