java 发表于 2018-1-10 09:40:18

wildduck---imap分析

任何状态:
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前缀。


java 发表于 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

java 发表于 2018-1-12 10:16:02


命令行连接mongo 192.168.10.68:27017/wildduck -u wildduck -p wildduck
认证方式:MONGODB-CRRoundcube 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 authenticatedFETCH 序列号集 邮件数据
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 Flags permitted
S: * OK UIDs valid
S: * 2 EXISTS
S: * 0 RECENT
S: * OK Highest
S: * OK Predicted next UID
S: C2 OK SELECT completedC: 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)
S: * 2 FETCH (UID 28 RFC822.SIZE 686 FLAGS (\Seen) BODY {418}
S: Received: from authenticated-user (PRIMARY_HOSTNAME )
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)
S: * 1 FETCH (BODY {9}
S: content
S:UID 28)
S: C7 OK UID FETCH completed以 C7 UID FETCH 28 (BODY.PEEK) 命令示例分析邮件正文获取逻辑。
./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;
getQueryResponselet 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.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.js127
messageData.modseq = mailboxData.modifyIndex + 1;


页: [1]
查看完整版本: wildduck---imap分析