Giter VIP home page Giter VIP logo

android-mail's Introduction

Android-Mail

Android-Mail 是基于 JavaMail 库设计与开发的邮箱 App 。2022年12月完成本项目的代码重构后,不再独立提供封装 JavaMail 的库,而是以整个 App 项目的形式来开源代码。 本项目工程包含两部分,分别是app模块和mailkit模块。app 模块含有邮箱客户端的界面和操作逻辑等代码;mailkit 模块主要封装了 JavaMail ,以 API 的形式 提供给 app 模块调用。Android-Mail 客户端目前支持的功能有:配置邮件服务器、发送简单邮件、获取文件夹列表、同步邮件、加载邮件、读取邮件。 README 会列出 mailkit API 供大家查阅和参考,带有“ * ”的标题表示该 API 未被 app 模块使用。 因 JavaMail 内容博大精深,作者的水平和时间有限,所以计划本项目不长期维护,请大家见谅。

2023年4月,Android-Mail 原先使用的 SQLite 数据库(LitePal ORM)被替换为 QuickIO 数据库。QuickIO 是作者自研的高性能嵌入式 NoSQL 数据库,现以作为试验,引入到 Android-Mail 项目中使用。

效果图

服务器设置 邮箱文件夹列表 菜单弹窗
写邮件 收件箱列表 查看邮件内容

MailKit API

配置邮件服务器

MailKit.Config config = new MailKit.Config(c -> {
    c.account = "[email protected]";
    c.password = "password";
    c.nickname = "Li Hua";
    c.SMTPHost = "smtp.qq.com";
    c.SMTPPort = 465;
    c.SMTPSSLEnable = true;
    c.IMAPHost = "imap.qq.com";
    c.IMAPPort = 993;
    c.IMAPSSLEnable = true;
});

验证邮件服务器配置

MailKit.auth(config, () -> {
    //验证成功,执行后续操作
}, e -> {
    //验证失败
    Log.d(TAG, e.getMessage());
});

发送邮件

MailKit.Draft draft = new MailKit.Draft(d -> {
    d.to = new String[]{"[email protected]"};
    d.subject = "Android-Mail Test";
    d.text = "Hello world";
    //d.cc = new String[]{"..."};   抄送人地址
    //d.bcc = new String[]{"..."};  密送人地址
    //d.html = "..."                发送富文本邮件内容
});

MailKit.SMTP smtp = new MailKit.SMTP(config);
smtp.send(draft, () -> {
    //发送成功,执行后续操作
}, e -> {
    //发送失败
    Log.d(TAG, e.getMessage());
});

获取文件夹列表

MailKit.IMAP imap = new MailKit.IMAP(config);
imap.getDefaultFolders(strings -> {
    //获取成功,打印列表的文件夹名称
    strings.forEach(s -> Log.d(TAG, s));
}, e -> {
    //获取失败
    Log.d(TAG, e.getMessage());
});

获取指定的文件夹

MailKit.IMAP imap = new MailKit.IMAP(config);
//获取指定名称的文件夹
MailKit.IMAP.Folder folder = imap.getFolder("INBOX");
//获取收件箱文件夹
MailKit.IMAP.Inbox inbox = imap.getInbox();
//获取草稿箱文件夹
MailKit.IMAP.DraftBox draftBox = imap.getDraftBox();

加载文件夹中的邮件头列表

邮箱中文件夹中存在多封邮件,用load方法加载缓存到App本地,使用说明:

  • 若本地还没缓存过邮件消息时,minUID值传入一个小于0的值,例如-1,它将加载最新的20封邮件。
  • 若本地客已缓存过邮件消息时,则给minUID传入本地缓存的全部邮件中UID最小的那个值,它将加载比minUID值更小的20封邮件。
  • 每次加载的邮件的数量在[0, 20]之间。
MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Folder folder = imap.getFolder("INBOX");
folder.load(-1, msgList -> {
    //加载成功,执行后续操作
    msgList.forEach(msg -> {
        Log.d(TAG, String.valueOf(msg.uid));
        Log.d(TAG, String.valueOf(msg.sentDate));
        Log.d(TAG, String.valueOf(msg.flags.isSeen));
        Log.d(TAG, String.valueOf(msg.flags.isStar));
        Log.d(TAG, msg.subject);
        Log.d(TAG, msg.from.address);
        Log.d(TAG, msg.from.nickname);
        msg.toList.forEach(to -> {
            Log.d(TAG, to.address);
            Log.d(TAG, to.nickname);
        });
        msg.ccList.forEach(cc -> {
            Log.d(TAG, cc.address);
            Log.d(TAG, cc.nickname);
        });
        //Log.d(TAG, String.valueOf(msg.mainBody == null)); load方法不加载邮件正文内容
    });  
}, e -> {
    //加载失败
    Log.d(TAG, e.getMessage());
});

同步文件夹中的邮件头

本地每隔一段时间就应该与邮件服务器进行一次邮件同步,同步主要是查询邮件服务器是否有新邮件和本地已缓存过的邮件在服务器中是否有被删除,使用说明:

  • 参数localUIDArray为本地客户端已缓存的全部邮件UID。
  • 若发现服务端有邮件的UID比数组localUIDArray中的最大UID还要大,则拉取该邮件消息(新邮件)。
  • 若发现数组localUIDArray中的某一个UID值在服务端中不存在,则返回该UID。
  • 假设服务端[6, 5, 4, 2, 1],客户端[4, 3, 2],同步该服务端结果:新消息[6, 5],已删除[3]。
//本地已缓存邮件消息的uid
long[] localUIDArray = new long[]{1, 2, 3, 4, 5, 6};
//如果本地还没有缓存过邮件,传入一个空数组既不同步邮件,也不拉取邮件
//long[] longs = new long[0];

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Folder folder = imap.getFolder("INBOX");
folder.sync(localUIDArray, (msgList, longs) -> {
    //同步成功,执行后续操作
    //获取新邮件
    msgList.forEach(msg -> {
        Log.d(TAG, String.valueOf(msg.uid));
        Log.d(TAG, String.valueOf(msg.sentDate));
        Log.d(TAG, String.valueOf(msg.flags.isSeen));
        Log.d(TAG, String.valueOf(msg.flags.isStar));
        Log.d(TAG, msg.subject);
        Log.d(TAG, msg.from.address);
        Log.d(TAG, msg.from.nickname);
        msg.toList.forEach(to -> {
            Log.d(TAG, to.address);
            Log.d(TAG, to.nickname);
        });
        msg.ccList.forEach(cc -> {
            Log.d(TAG, cc.address);
            Log.d(TAG, cc.nickname);
        });
        //Log.d(TAG, String.valueOf(msg.mainBody == null)); sync方法不加载邮件正文内容
    });
    //本地需要删除的邮件UID
    longs.forEach(uid -> Log.i(TAG, String.valueOf(uid)));
}, e -> {
    //同步失败
    Log.d(TAG, e.getMessage());
});

通过网络读取邮件详情

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Folder folder = imap.getFolder("INBOX");

//假设UID = 1967;不支持获取文件内容的附件
folder.getMsg(1967, msg -> {
    //读取成功,执行后续操作
    Log.d(TAG, String.valueOf(msg.uid));
    Log.d(TAG, String.valueOf(msg.sentDate));
    Log.d(TAG, String.valueOf(msg.flags.isSeen));
    Log.d(TAG, String.valueOf(msg.flags.isStar));
    Log.d(TAG, msg.subject);
    Log.d(TAG, msg.from.address);
    Log.d(TAG, msg.from.nickname);
    msg.toList.forEach(to -> {
        Log.d(TAG, to.address);
        Log.d(TAG, to.nickname);
    });
    msg.ccList.forEach(cc -> {
        Log.d(TAG, cc.address);
        Log.d(TAG, cc.nickname);
    });
    Log.d(TAG, msg.mainBody.type);
    Log.d(TAG, msg.mainBody.content); 
}, e -> {
    //读取失败
    Log.d(TAG, e.getMessage());
});

* 标记或移除邮件的star

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

//传入需要标记或移除star的邮件UID数组,需要star则为true,否则为false
inbox.star(new long[]{1967}, true, () -> {
    //操作完成,执行后续操作
}, e -> {
    //操作失败
    Log.d(TAG, e.getMessage());
});

* 标记邮件状态是否已读

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

//传入需要标记邮件UID数组,标记已读则为true,否则为false
inbox.readStatus(new long[]{1967}, false, () -> {
    //操作完成,执行后续操作
}, e -> {
    //操作失败
    Log.d(TAG, e.getMessage());
});

* 移动邮件到另一文件夹

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

//设置需要把邮件移动到的文件夹名称,传入邮件UID数组
inbox.move("Deleted Messages", new long[]{1876}, () -> {
    //操作完成,执行后续操作
}, e -> {
    //操作失败
    Log.d(TAG, e.getMessage());
});

* 彻底删除文件夹中的邮件

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

//传入需要彻底删除的邮件UID数组
inbox.delete(new long[]{1966}, () -> {
    //操作完成,执行后续操作
}, e -> {
    //操作失败
    Log.d(TAG, e.getMessage());
});

* 统计文件夹中的全部邮件数量和未读邮件的数量

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

//统计文件夹中的全部邮件数量和未读邮件的数量
inbox.count((total, unread) -> {
    //操作完成,执行后续操作
}, e -> {
    //操作失败
    Log.d(TAG, e.getMessage());
});

* 把草稿保存到草稿箱

MailKit.Draft draft = new MailKit.Draft(d -> {
    d.to = new String[]{"[email protected]"};
    d.subject = "MailKit test";
    d.text = "Hello world";
});

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.DraftBox draftBox = imap.getDraftBox();
draftBox.save(draft, () -> {
    //保存成功,执行后续操作
}, e -> {
    //保存失败
    Log.d(TAG, e.getMessage());
});

* 按邮件主题搜索邮件内容(部分邮件服务器供应商不支持)

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

String subject = "需要搜索的邮件主题";
inbox.searchBySubject(subject, msgList -> {
    //搜索成功,执行后续操作
    msgList.forEach(msg -> {
        Log.d(TAG, String.valueOf(msg.uid));
        Log.d(TAG, String.valueOf(msg.sentDate));
        Log.d(TAG, String.valueOf(msg.flags.isSeen));
        Log.d(TAG, String.valueOf(msg.flags.isStar));
        Log.d(TAG, msg.subject);
        Log.d(TAG, msg.from.address);
        Log.d(TAG, msg.from.nickname);
        msg.toList.forEach(to -> {
            Log.d(TAG, to.address);
            Log.d(TAG, to.nickname);
        });
        msg.ccList.forEach(cc -> {
            Log.d(TAG, cc.address);
            Log.d(TAG, cc.nickname);
        });
        //Log.d(TAG, String.valueOf(msg.mainBody == null)); 不支持获取邮件正文内容
    });
}, e -> {
    //搜索失败
    Log.d(TAG, e.getMessage());
});

* 按发件人昵称搜索邮件内容(部分邮件服务器供应商不支持)

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

String nickname = "Lisa";
inbox.searchByFrom(nickname, msgList -> {
    //搜索成功,执行后续操作
}, e -> {
    //搜索失败
    Log.d(TAG, e.getMessage());
});

* 按收件人昵称搜索邮件内容(部分邮件服务器供应商不支持)

MailKit.IMAP imap = new MailKit.IMAP(config);
MailKit.IMAP.Inbox inbox = imap.getInbox();

String nickname = "Li Hua";
inbox.searchByTo(nickname, msgList -> {
    //搜索成功,执行后续操作
}, e -> {
    //搜索失败
    Log.d(TAG, e.getMessage());
});

App中用到的开源项目

License

Copyright 2018 Zhang Guanhu

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

android-mail's People

Contributors

artbits avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

android-mail's Issues

在android平台part.getContent()为空,初始化时可加上如下配置

// 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);

不能加载最新的邮件

使用
EmailKit.useIMAPService(config) .getInbox() .load(-1, new EmailKit.GetLoadCallback)
加载邮件,拿到的邮件却不包含最新的邮件。
因为要从邮件中拿验证码,这就导致拿到的验证码都是之前收到的。

关于重构后的问题

新年快乐,新版本重构后和之前旧版本差别有点大,我想了解一下新版本有优化什么功能吗?之前使用的时候发现第一次拉取邮件比较慢,尤其是邮箱里有未读邮件。

Android 12 beta2 报错,更改build.gradle解决

Android 12 beta2 中运行报错,更改build.gradle解决

implementation 'com.sun.mail:android-mail:1.6.2'
implementation 'com.sun.mail:android-activation:1.6.2'

更改为

implementation 'com.sun.mail:android-mail:1.6.6'
implementation 'com.sun.mail:android-activation:1.6.6'

syncMessage方法,腾讯企业邮箱测试 同步无效

用此框架登录腾讯企业邮箱(A),先通过拉取邮件方法,共有5条邮件
然后我用测试邮箱给(A)发送测试邮件,通过网页发现(A)收到了邮件变成了6条!可是在Java里首次调用此框架同步方法syncMessage返回的(List messageList, long[] deleteUidList)都是空!

支持附件吗?

作者您好,非常欣赏您的做法,我想问邮箱框架支持附件上传下载功能吗

附件下载问题

问题: 请问在使用 javaMail 下载附件的时候,有没有遇到过附件下载很慢的问题.
我在使用 javaMail 进行下载附件的时候,速度总是超不过 50kb/s

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.