Android 邮件接收协议IMAP介绍

在之前的一篇博客中介绍了邮件接收POP3,今天就来学习下另外一种协议IMAP,android里面还有一中邮件接收协议Exchange,这个还没有具体的学习,以后学习了再记录下来。
IMAP协议(Internet Mail Access Protocol,Internet邮件访问协议),也是一种获取邮件的协议,它也POP3协议的主要是用户可以不用把所有的邮件全部都下载,可以直接通过客户端对邮件服务器去访问。IMAP协议是运行在TCP/IP协议之上,端口号是143,POP3协议的端口号是110。
同样也可以在电脑的通过cmd 用imap协议登录邮箱
输入cmd之后在命令行端输入telnet imap.qq.com 143 ,如果是其他邮箱,不如163,sina 对应的应该输入 imap.163.com ,imap.sina.com,输入连接成功后会出现下面的界面
这里说一下哦,如果输入telnet imap.qq.com 143时出现telnet不是内部命令这是因为你的电脑上的telnet客户端的设置没有打开,可以在控制面板—程序和功能—-打开和关闭window的功能,这里面把telnet客户端勾选上就可以了。
连接成功之后可以输入你的账户名和密码啦
登录的命令就是A01 login 账户名称 密码 (注意账户名和密码中间有空格)
可以通过A02 LIST “” *命令列出信箱列表,注意哦 imap协议获取的邮件信箱列表,相比pop3会多出垃圾箱。
A03 Select INBOX 是选择收件箱
A06 Fetch 1 full 这是获取第一封邮件的邮件头
A07 Fetch 1 rfc822 获取第一封邮件的完整内容
imap的命令相比pop3的命令要多,这里就不一一列举了拉

在这里呢学习下在android源码Email模块对imap协议接收邮件的实现

在PopImapSyncAdapterService.java 这个类是imap和pop3 sync邮件的关键类
 private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
        public SyncAdapterImpl(Context context) {
            super(context, true /* autoInitialize */);
        }
        //在onPerformSync方法里面去同步邮件
        @Override
        public void onPerformSync(android.accounts.Account account, Bundle extras,
                String authority, ContentProviderClient provider, SyncResult syncResult) {
            PopImapSyncAdapterService.performSync(getContext(), account, extras, provider,
                    syncResult);
        }
    }

AbstractThreadedSyncAdapter 是android提供的一个同步账户的类,它是一个抽象类,里面的onPerformSync()是需要重写的,当AbstractThreadedSyncAdapter 收到开始同步startSync()的请求后会去调用onPerformSync()
所以把我们的请求操作都封装到onPerformSync()中,同时为了让系统可以找到我们要同步的账户,需要在这个Service 里面配置action android:name=”android.content.SyncAdapter” 和metadata

private static void performSync(){
.....
在这里有调用到sync()
 for (long mailboxId: mailboxesToUpdate) {
                        sync(context, mailboxId, extras, syncResult, false, 0);
.....
                    }
                    }
private static void sync(){
    .....
    在这里通过判断用户选择的接收协议是imap和pop3 分别进行同步邮件的操作
    if (protocol.equals(legacyImapProtocol)) {
                        status = ImapService.synchronizeMailboxSynchronous(context, account,
                                mailbox, deltaMessageCount != 0, uiRefresh);
                    } else {
                        status = Pop3Service.synchronizeMailboxSynchronous(context, account,
                                mailbox, deltaMessageCount);
                    }
                    EmailServiceStatus.syncMailboxStatus(resolver, extras, mailboxId, status, 0,
                            lastSyncResult);
 .......
}

现在看下使用imap协议同步邮件,pop3邮件同步邮件协议在之前的一篇里面已经简单介绍啦

public static synchronized int synchronizeMailboxSynchronous(Context context,
            final Account account, final Mailbox folder, final boolean loadMore,
            final boolean uiRefresh) throws MessagingException {

Store remoteStore = null;
remoteStore = Store.getInstance(account, context);
            processPendingActionsSynchronous(context, account, remoteStore, uiRefresh);
            这里就是用imap协议sync邮件
            synchronizeMailboxGeneric(context, account, remoteStore, folder, loadMore, uiRefresh);
            nc.cancelLoginFailedNotification(account.mId);

     }

private synchronized static void synchronizeMailboxGeneric(){
    localOldestCursor = resolver.query(EmailContent.Message.CONTENT_URI,)..
    final Folder remoteFolder = remoteStore.getFolder(mailbox.mServerId);
    final int remoteMessageCount = remoteFolder.getMessageCount();
    Message[] remoteMessages;
    remoteMessages = remoteFolder.getMessages(0, endDate, null);
    //进行本地uid索引
 Cursor localUidCursor = null;
        HashMap<String, LocalMessageInfo> localMessageMap = new HashMap<String, LocalMessageInfo>();
        try {

            final long queryEndDate = 0;
            localUidCursor = resolver.query(
                    EmailContent.Message.CONTENT_URI,
                    LocalMessageInfo.PROJECTION,
                    EmailContent.MessageColumns.ACCOUNT_KEY + "=?"
                            + " AND " + MessageColumns.MAILBOX_KEY + "=?"
                            + " AND " + MessageColumns.TIMESTAMP + ">=?",
                    new String[] {
                            String.valueOf(account.mId),
                            String.valueOf(mailbox.mId),
                            String.valueOf(queryEndDate) },
                    null);
            while (localUidCursor.moveToNext()) {
                LocalMessageInfo info = new LocalMessageInfo(localUidCursor);

                if (!TextUtils.isEmpty(info.mServerId)) {
                    localMessageMap.put(info.mServerId, info);
                }
            }
        } finally {
            if (localUidCursor != null) {
                localUidCursor.close();
            }
        }
}

final ArrayList<Message> unsyncedMessages = new ArrayList<Message>();
        final HashMap<String, Message> remoteUidMap = new HashMap<String, Message>();
//这里是与服务器上面的邮件对比,如果本地没有,加入到unsyncedMessages中,最后将unsyncedMessages 去download下来
for (int i = remoteMessages.length - 1; i >= 0; i--) {
            Message message = remoteMessages[i];

            remoteUidMap.put(message.getUid(), message);

            LocalMessageInfo localMessage = localMessageMap.get(message.getUid());
            if (localMessage == null ||
                    (localMessage.mFlagLoaded == EmailContent.Message.FLAG_LOADED_UNLOADED) ||
                    (localMessage.mFlagLoaded == EmailContent.Message.FLAG_LOADED_PARTIAL)) {
                unsyncedMessages.add(message);
            }
if (unsyncedMessages.size() > 0) {
    //download邮件
            downloadFlagAndEnvelope(context, account, mailbox, remoteFolder, unsyncedMessages,
                    localMessageMap, unseenMessages);
        }

对imap协议同步邮件的流程只是知道个大概的流程,没有POP3的流程来的印象深刻,还是因为之前的一个POP3 协议同步邮件bug让我一个从来的没有看过邮件代码的小菜鸟慢慢的通过log分析才接触邮件代码。
记得当时连邮件的接收和发送协议都不知道是啥,硬着头皮去通过log看代码,虽然到最后用个很搓的办法给规避了。不过这个问题也是让我一直记忆深刻。对邮件的学习还只是懂一点皮毛,或者说是一点皮毛都算不上。不过还是希望通过今后的学习,让自己学到的东西更过啦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值