命令行连接 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;
|