Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1517|回复: 2
打印 上一主题 下一主题

wildduck---imap分析

[复制链接]

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
跳转到指定楼层
楼主
发表于 2018-1-10 09:40:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
任何状态:
CAPABILITY 、 NOOP、 LOGOUT

Not Authenticated State: 非认证状态
STARTTLS、AUTHENTICATE、LOGOUT

Authenticated State: 认证状态
SELECT、EXAMINE、CREATE、DELETE、RENAME、SUBSCRIBE、UNSUBSCRIBE、LIST、LSUB、STATUS、APPEND

Selected State: 选择状态
CHECK、CLOSE、EXPUNGE、SEARCH、FETCH、STORE、COPY、UID

实验/扩展指令:
带X前缀指令,即如果不是标准协议所规定必须使用X前缀,任何此指令的响应也必须冠以X前缀。


回复

使用道具 举报

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
沙发
 楼主| 发表于 2018-1-10 09:49:25 | 只看该作者
安全连接openssl s_client -connect 127.0.0.1:993
C: c1 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN ENABLE ID IDLE SASL-IR
c1 OK CAPABILITY completed


非安全连接
telnet 127.0.0.1 143

C: c1 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN ENABLE ID IDLE SASL-IR STARTTLS
S: c1 OK CAPABILITY completed



1.CAPABILITY
回复 支持 反对

使用道具 举报

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
板凳
 楼主| 发表于 2018-1-12 10:16:02 | 只看该作者

命令行连接  mongo 192.168.10.68:27017/wildduck -u wildduck -p wildduck
认证方式:MONGODB-CR
Roundcube Webmail 基于浏览器IMAP客户端

命令代码跟踪
./mail_server/imap-core/lib/imap-server.js
./mail_server/imap-core/lib/imap-connection.js
./mail_server/imap-core/lib/imap-command.js
-------------['CREATE', require('./commands/create')],
./mail_server/imap-core/lib/commands/create.js
./mail_server/lib/handlers/on-create.js
./mail_server_new/mail_server/lib/mailbox-handler.js
新建 ttttt 邮件夹
db.getCollection('mailboxes').find({path:"ttttt",user:ObjectId("5a4df9907104a52b2b3750e5")});
根据返回的mailboxData,判断如果有此邮件夹返回,没有继续进行下面查询
db.getCollection('users').find({_id:ObjectId("5a4df9907104a52b2b3750e5")},{retention:true});
{retention:true}的意思是只返回 _id和retention字段
查到后,则直接插入到mailboxes集合
db.getCollection('users').insertOne({
"_id": "5a5588f030f3756efb0145a1",
"user": "5a4df9907104a52b2b3750e5",
"path": "ttttt",
"uidValidity": 1515555056,
"uidNext": 1,
"modifyIndex": 0,
"subscribed": true,
"flags": [],
"retention": 0
})
如果是子邮件夹如下:
{
"_id": "5a558dd030f3756efb0145a4",
"user": "5a4df9907104a52b2b3750e5",
"path": "test/tt",
"uidValidity": 1515556304,
"uidNext": 1,
"modifyIndex": 0,
"subscribed": true,
"flags": [],
"retention": 0
}
IMAP对应命令:
C: A0004 CREATE test
S: A0004 OK CREATE completed
-------------['RENAME', require('./commands/rename')],
./mail_server/imap-core/lib/commands/rename.js
./mail_server/lib/handlers/on-rename.js
./mail_server_new/mail_server/lib/mailbox-handler.js
重新命名邮件夹 mytest 为 mytest2
db.getCollection('mailboxes').findOne({path:"mytest",user:ObjectId("5a4df9907104a52b2b3750e5")});
存在的话调用 mailboxHandler执行下面操作
再判断一下
db.getCollection('mailboxes').findOne({_id:ObjectId("5a5585bc6115886efe086625"),user:ObjectId("5a4df9907104a52b2b3750e5")});
判断新名称不存在
db.getCollection('mailboxes').findOne({path:"mytest2",user:ObjectId("5a4df9907104a52b2b3750e5")});
查到后,则直接插入到mailboxes集合
db.getCollection('mailboxes').findOneAndUpdate(
{_id:ObjectId("5a5585bc6115886efe086625") },
{ $set: { path : 'mytest2' } },
{}
)
IMAP对应命令:
C: A0007 RENAME mytest mytest2
S: A0007 OK RENAME completed
可能的问题:含有子邮件夹的邮件夹的重命名
-------------['DELETE', require('./commands/delete')],
./mail_server/imap-core/lib/commands/delete.js
./mail_server/lib/handlers/on-delete.js
./mail_server_new/mail_server/lib/mailbox-handler.js
删除 mytest2 邮件夹
db.getCollection('mailboxes').findOne({path:"mytest2",user:ObjectId("5a4df9907104a52b2b3750e5")});
存在的话调用 mailboxHandler执行下面操作
再判断一下
db.getCollection('mailboxes').findOne({_id:ObjectId("5a5585bc6115886efe086625"),user:ObjectId("5a4df9907104a52b2b3750e5")});
存在进行删除
db.getCollection('mailboxes').deleteOne({_id:ObjectId("5a5585bc6115886efe086625")});
IMAP对应命令:
C: A0005 DELETE mytest2
S: A0005 OK DELETE completed
可能存在的问题:删除存在子邮件夹或邮件夹中含有邮件的情况
-------------['SUBSCRIBE', require('./commands/subscribe')],
-------------['UNSUBSCRIBE', require('./commands/unsubscribe')],
-------------['LSUB', require('./commands/lsub')],
LSUB <folder><mailbox>
LSUB命令修正了LIST命令,LIST返回用户$HOME目录下所有的文件,但LSUB命令只显示那些使用SUBSCRIBE命令设置为活动邮箱的文件。两个参数:邮箱路径和邮箱名。
C: A116 LSUB “” *
S:* LSUB () “/” stuff/junk
S:* LSUB () “/” neebox
S:* LSUB () “/” new/anotherbox
S: A116 OK LSUB completed

-------------['FETCH', require('./commands/fetch')],   ['UID FETCH', require('./commands/fetch')],
./mail_server/imap-core/lib/commands/fetch.js
./mail_server/lib/handlers/on-fetch.js
./mail_server/imap-core/lib/handler/imap-compiler.js
./mail_server/imap-core/lib/imap-connection.js
./mail_server/imap-core/lib/handler/imap-compile-stream.js
./imap-core/lib/handler/imap-handler.js

IMAP对应命令:
C: C1 login "hcj@hcjserver.com" "test123"
S: C1 OK hcj@hcjserver.com authenticated
FETCH 序列号集 邮件数据
FETCH 命令用于读取邮件的文本信息,且仅用于显示的目的。包含两个参数,messageset:表示希望读取的邮件号列表,IAMP服务器邮箱中的每个邮件都有 一个唯一的ID标识,
(邮件号列表参数可以是一个邮件号,也可以是由逗号分隔的多个邮件号,或者由冒号间隔的一个范围),IMAP服务器返回邮件号列表中 全部邮件的指定数据项内容。
数据名参数确定能够被独立返回的邮件的一部分 https://www.cnblogs.com/qiubole/archive/2007/11/23/970180.html
---------------------
MIME,英文全称为“Multipurpose Internet Mail Extensions”,即多用途互联网邮件扩展,在MIME出现之前,互联网电子邮件主要遵循由RFC 822所制定的标准,
MIME在 RFC 822的基础上对电子邮件规范做了大量的扩展,引入了新的格式规范和编码方式,在MIME的支持下,图像、声音、动画等二进制文件都可方便的通过电子邮件来进行传递。
目前互联网上使用的基本都是遵循MIME规范的电子邮件。
   MIME技术规范的完整内容由RFC 2045-2049定义
行1 From: ”suntao” <suntao@fimmu.com>
行2 To: <yxj@fimmu.com>
行3 Subject: hello world
行4 Date: Mon, 9 Oct 2006 16:51:34 +0800
行5 MIME-Version: 1.0
行6 Content-Type: text/plain;
行7            charset="us-ascii"
行8 Date: Mon, 9 Oct 2006 16:48:25 +0800
行9
行10 Hello world
行11
在一个邮件体里面,区段数1代表的邮件的正文,区段数二代表的是第一个附件,区段数三代表的是第二个附件,以此类推。
在这些区段里,如果有哪个区段又是多区段的,比如2区段的内容格式是mulipart或者是MESSAGE/RFC822类型的,那么这个区段又嵌套了多个子区段,
嵌套的各子区段是用2.1,2.2……等等表示,类似,如果2.1又有嵌套,那么还会有2.1.1,2.1.2等区段。
---------------------
C: C2 SELECT "INBOX"
S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
S: * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] Flags permitted
S: * OK [UIDVALIDITY 1515059600] UIDs valid
S: * 2 EXISTS
S: * 0 RECENT
S: * OK [HIGHESTMODSEQ 85] Highest
S: * OK [UIDNEXT 30] Predicted next UID
S: C2 OK [READ-WRITE] SELECT completed
C: C3 UID FETCH 1:* (FLAGS)
S: * 2 FETCH (FLAGS (\Seen) UID 28)
S: * 1 FETCH (FLAGS (\Seen) UID 29)
S: C3 OK UID FETCH completed

C: C6 UID FETCH 28 (UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (From To Cc Bcc Subject Date Message-ID Received X-Priority References In-Reply-To Content-Type)])
S: * 2 FETCH (UID 28 RFC822.SIZE 686 FLAGS (\Seen) BODY[HEADER.FIELDS (From To Cc Bcc Subject Date Message-ID Received X-Priority References In-Reply-To Content-Type)] {418}
S: Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP])
S:     by mail.marty.ltd (Postfix) with ESMTPA id 44709822925
S:     for <hcj@hcjserver.com>; Tue,  9 Jan 2018 01:37:51 +0000 (UTC)
S: Content-Type: text/plain; charset=US-ASCII;
S:  format=flowed
S: Date: Tue, 09 Jan 2018 09:37:50 +0800
S: From: hcj@hcjserver.com
S: To: hcj@hcjserver.com
S: Subject: uuuu111
S: Message-ID: <484742613e86dbcb83d45f752dcc10bd@hcjserver.com>
S:
S: )
S: C6 OK UID FETCH completed

C: C7 UID FETCH 28 (BODY.PEEK[1])
S: * 1 FETCH (BODY[1] {9}
S: content
S:  UID 28)
S: C7 OK UID FETCH completed
以 C7 UID FETCH 28 (BODY.PEEK[1]) 命令示例分析邮件正文获取逻辑。
./mail_server/imap-core/lib/imap-tools.js
value = indexer.getContents(mimeTree, item);  664
./mail_server/imap-core/lib/indexer/indexer.js
return this.rebuild(node, true, skipExternal);
let remainder = false;
remainder = node.body.buffer;
let res = new PassThrough();
res.write(remainder);
return {
            type: 'stream',
            value: res,
            expectedLength: this.getSize(mimeTree, textOnly)
        };
value = indexer.getContents(mimeTree, item);
values.push(value);
return values;
getQueryResponse
let stream = imapHandler.compileStream(
                                session.formatResponse('FETCH', message.uid, {
                                    query: options.query,
                                    values: session.getQueryResponse(options.query, message, {
                                        logger: server.logger,
                                        fetchOptions: {},
                                        database: db.database,
                                        attachmentStorage: messageHandler.attachmentStorage,
                                        acceptUTF8Enabled: session.isUTF8Enabled()
                                    })
                                })
                            );
formatResponse{
response.attributes[1].push({
                            type: 'ATOM',
                            value: data.values.toString()
                        });
return response;
}
compileStream{
...
let output = new PassThrough();
output.write(value);
return output;
}
let limiter = new LimitedFetch({
                                key: 'idw:' + session.user.id,
                                ttlcounter: messageHandler.counters.ttlcounter,
                                maxBytes: limit
                            });
stream.pipe(limiter);
// send formatted response to socket
session.writeStream.write(limiter, () => {
    server.logger.debug(
        {
            tnx: 'flags',
            cid: session.id
        },
        '[%s] UPDATE FLAGS for "%s"',
        session.id,
        message.uid
    );
  }
session.writeStream = new IMAPComposer({
            connection: this
        });

./mail_server/lib/handlers/on-copy.js  127
messageData.modseq = mailboxData.modifyIndex + 1;


回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-5-3 03:09 , Processed in 0.058633 second(s), 18 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表