node-imap-sync-client
说明
网址: https://gitee.com/linuxmail/node-imap-sync-client
同步操纵 imap 客户端, 见例子 examples
本客户端将来的版本也不考虑支持 fetch bodystructure / envelope,
请慎重选择
本imap客户端, 特点:
- 全部命令都是 promise 风格
- 重要用于和 IMAPD 服务器同步邮箱数据和邮件数据
- 不支持bodystructure,envelope等, 只完整下载信件, 信件解析由其他库负责
- 支持文件夹的创建/删除/移动(改名)
- 支持邮件的复制/移动/删除/标志/上传
- 支持获取文件夹下邮件UID列表
- 各种方法返回的邮箱文件夹名字都是 Buffer
接口 interface
对象初始化 选项
- interface ImapSyncClientOptions extends socketSyncBuffer.options {
- user: string // 用户
- pass: string // 密码
- tryStartTLS?: boolean // 如果服务器支持就启动 STARTTLS
- startTLS?: boolean // 是否启动 STARTTLS
- cmdIdInfo?: string // imap 命令 ID 的具体内容, 一般用于向服务器表明身份
- }
复制代码 回调函数类型, 记录通讯协议内容
- interface ReadWriteRecordHandler {
- (type: string, data: Buffer): void // type: read/write
- }
复制代码 读取一行, 解析为一组 token
- export interface ReadOneLineResult {
- tokens: Buffer[]
- extraDataLength: number // 最后一个token 形如: {123}
- }
复制代码 命令 status 结果解析
- interface MboxStatus {
- messages: number
- recent: number
- uidnext: number
- uidvalidity: number
- unseen: number
- }
复制代码 命令 list/lsub 返回的结果按行解析
- interface MboxAttrs {
- noinferiors: boolean
- noselect: boolean
- junk: boolean
- trash: boolean
- sent: boolean
- drafts: boolean
- }
复制代码 命令 select 返回的结果解析
- interface MboxSelect {
- exists: number
- recent: number
- uidvalidity: number
- uidnext: number
- highestmodseq: number
- }
复制代码 文件夹信息
- interface MboxInfo {
- pathname: Buffer, // 文件夹名(Buffer), 返回的文件夹名字可能不是 imap-utf-7 编码
- mboxNameUtf8: string, // 文件夹名), 一定是 ""
- attrs: mboxAttrs
- status?: mboxStatus
- subscribed?: boolean
- }
复制代码 邮件标志
- interface MailFlags {
- answered?: boolean // 是否已回复
- seen?: boolean // 是否已读
- draft?: boolean // 是否草稿
- flagged?: boolean // 是否标记(星标)
- deleted?: boolean // 是否删除
- }
复制代码 邮件标志 + 邮件 UID, 用于邮件列表
- interface MailUidWithFlags extends mailFlags {
- uid: number
- }
复制代码 uidplus 扩展, 移动/复制/上传的结果
- interface UidplusResult {
- uidvalidity: number,
- uid: number
- }
复制代码 使用方法
见例子: examples/imap.js
创建对象
- const imapSyncClient = require("imap-sync-sclient")
- let ic = new imapSyncClient.imapSyncClient({
- host: "127.0.0.1",
- port: 143,
- user: "test@linuxmail.cn",
- pass: "password",
- tryStartTLS: true,
- })
复制代码 打开毗连并初始化
打开imap毗连,并认证等, 使用者可以自己实现类似的方法- // 返回 null 表示网络错误, 否则返回 boolean 值, true 表示成功
- async open()
复制代码 发起 STARTTLS 握手
发起命令 STARTTLS, 然后开始 ssl 握手- // 返回 null 表示网络错误, 否则返回 boolean 值, true 表示成功
- async cmdStartTLS();
复制代码 读取welcome
- // 返回 null 表示网络错误, 否则返回 Buffer
- // open() 方法内会调用这个方法
- async readWelcome()
复制代码 命令 capability
- // 执行执行命令 capability 并返回结果, 同时保存到缓存
- async forceGetCapability()
- // 首先从缓存中取值
- async getCapability()
复制代码 登录
现在只支持 login- // 返回 null 表示网络失败, 否则返回 boolean, true表示认证成功
- // open() 方法会调用这个方法
- async login()
复制代码 命令 ID
open() 方法会调用这个方法- // 返回 null 表示网络失败, 否则返回 boolean, true表示认证成功
- // idInfo 为空则使用对象初始化参数 cmdIdInfo
- async cmdId(idInfo?: string)
复制代码 命令 LIST/LSUB
- // 返回 null 表示网络失败, 否则返回 mboxInfo[]
- async getMboxList()
- async getSubscribedMboxList()
- // 获取文件夹全部信息(LIST + LSUB + STATUS)
- async getAllMboxInfos()
复制代码 命令 create, 创建文件夹
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async createMbox(pathname: string | Buffer)
- // 创建文件夹, 并订阅
- async createAndSubscribeMbox(pathname: string | Buffer)
复制代码 命令 delete, 删除文件夹
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async deleteMbox(pathname: string | Buffer)
复制代码 命令 subscribe, 订阅文件夹
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async subscribeMbox(pathname: string | Buffer)
复制代码 命令 unSubscribe, 取消订阅文件夹
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async unSubscribeMbox(pathname: string | Buffer)
复制代码 命令 rename, 文件夹改名
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async renameMbox(fromPathname: string | Buffer, toPathname: string | Buffer)
复制代码 命令 select, 选择(打开)文件夹
- // 返回 null 表示网络失败, 返回 false 表示不存在, 否则返回 mboxSelect
- // 命令 select, 选择(打开) 文件夹
- async forceSelectMbox(pathname: string | Buffer) {
- // 如过select的文件夹不变,则直接返回成功
- async selectMbox(pathname: string | Buffer) {
复制代码 命令 UID MOVE, 移动邮件
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- // 一封
- async moveOneMailByUid(uid: number | string, toPathname: string | Buffer, options?: {
- callbackForUidplus?: { (r: { uidvalidity: number, uid: number }): void }
- })
- // 多封
- async moveMailByUid(uids: string, toPathname: string | Buffer, options?: {})
复制代码 命令 MOVE, 移动邮件
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- // 一封
- async moveOneMailBySn(sn: number | string, toPathname: string | Buffer, options?: {
- callbackForUidplus?: { (r: { uidvalidity: number, uid: number }): void }
- })
- // 多封
- async moveMailBySn(sns: string, toPathname: string | Buffer, options?: {})
复制代码 命令 UID COPY, 复制邮件
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- // 一封
- async copyOneMailByUid(uid: number | string, toPathname: string | Buffer, options?: {
- callbackForUidplus?: { (r: { uidvalidity: number, uid: number }): void }
- })
- // 多封
- async copyMailByUid(uids: string, toPathname: string | Buffer, options?: {})
复制代码 命令 COPY, 复制邮件
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- // 一封
- async copyOneMailBySn(sn: number | string, toPathname: string | Buffer, options?: {
- callbackForUidplus?: { (r: { uidvalidity: number, uid: number }): void }
- })
- // 多封
- async copyMailBySn(sns: string, toPathname: string | Buffer, options?: {})
复制代码 命令 UID STORE, 设置标志
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async setMailFlagByUid(uidOrUids: number | string, flags: mailFlags, set_or_unset?: boolean)
- async unsetMailFlagByUid(uidOrUids: number | string, flags: mailFlags)
复制代码 命令 STORE, 设置标志
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async setMailFlagBySn(snOrSns: number | string, flags: mailFlags, set_or_unset?: boolean)
- async unsetMailFlagBySn(snOrSns: number | string, flags: mailFlags)
复制代码 删除信件, UID
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async deleteMailByUid(uidOrUids: number | string)
复制代码 删除信件
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async deleteMailBySn(snOrSns: number | string)
复制代码 获取邮件列表 UID + 标志
- // 返回 null 表示网络失败, 否则返回 mailUidWithFlags[]
- async fetchUidListWithFlags()
复制代码 通过搜索命令, 获取邮件 UID 列表
- // 返回 null 表示网络失败, 否则返回 number[]
- // 全部邮件
- async searchAllUids()
- // 全部未读邮件
- async searchUnseenUids()
- // 全部已回复邮件
- async searchAnsweredUids()
- // 全部设置了已删除标记的邮件
- async searchDeletedUids()
- // 全部草稿邮件
- async searchDraftUids()
- // 全部flagged(星标)邮件
- async searchFlaggedUids()
复制代码 命令 append, 上传信件
- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- // callbackForMailPieceData, 多次调用, 返回上传的信件的部分数据,读够mailSize就不在执行
- // options.callbackForUidplus, 如果支持 uidplus 协议, 则执行
- async appendMail(mboxname: Buffer | string, mailSize: number,
- callbackForMailPieceData: { (): Promise<Buffer | null> },
- options?: {
- flags?: mailFlags
- date?: any /* string, unix-time, Date */
- callbackForUidplus?: { (r: uidplusResult): void }
- })
复制代码 imap 返回结果 OK/NO/BAD
- // 返回 boolean
- resultIsOk()
- resultIsNo()
- resultIsBad()
复制代码 也许服务器有新的信件, 回调
- setMaybeHaveNewMailHandler(handler: (pathname: Buffer) => any)
复制代码 编译字符串
- escape(str: string | Buffer): string | Buffer
- // 例如:
- escape("a\nb"c") => "a\\nb"c"
- // 或
- escape("a\nb"c") => {5}
- a
- b"c
复制代码 其他
- // 设置调试模式
- setDebugMode(tf = true)
- // 设置回调函数,记录通讯协议
- setReadWriteRecordHandler(handler: readWriteRecordHandler)
- // 返回协议的最后一行
- getLastReadedBuffer(): Buffer
- // 是否网络错误
- isNetError()
- // 是否逻辑错误
- isLogicError()
- // 是否密码错误
- isPasswordError()
复制代码 扩展(基础) API
通用 IMAP 命令 封装
大部分IMAP命令可以靠这个基础封装实现- // 返回 null 表示网络失败, 否则返回 boolean, true表示成功
- async generalCmd(cmdArgv: (Buffer | string)[], options?: {
- callbackForUntag?: { (data: Buffer[]): Promise<void> }
- callbackForTag?: { (data: Buffer[]): Promise<void> }
- [keys: string]: any
- })
复制代码 比方:- async _searchUidsByFlag(flag: string) {
- let uids: number[] = []
- let res = await this.generalCmd(["UID SEARCH ", flag], {
- callbackForUntag: async (tokens: Buffer[]) => {
- let i;
- for (i = 2; i < tokens.length; i++) {
- uids.push(parseInt(tokens[i].toString()))
- }
- },
- })
- if (!res) {
- return null
- }
- return uids
- }
复制代码 读取行数据,并解析为 tokens
- // 读一行返回,并解析为 tokens
- async readOneLineTokens()
- // 读取一个完整的返回, 并解析为 tokens
- async readTokens()
- // 解析返回结果是不是 OK/NO/BAD
- parseResult(tokens: Buffer[]): boolean
复制代码 读写原始socket数据
见 this.socket, 见模块 socket-sync-buffer
字符集转码
见过太多不规范的文件夹名字, 以 "研发部" 为例子- 合法的(imap-utf-7): &eBRT0ZDo-
- 不规范的(imap-utf-7): &eBRT0D-
- 非法的(utf-7): 研发部
- 非法的(GBK): 研发部
复制代码 本库作者以为, 库不可能自动正确处置惩罚这些文件夹名字的解码, 而只是返回Buffer.
不做进一步的转码工作, 以保证通过 Buffer 能正确的操纵这些文件夹
而文件夹的名字要最终转为UTF-8用于显示,使用者必要自己承担乱码的风险, 发起通过库 jschardet 来自动辨认字符集
下面是规范的字符集转码方法:- //
- const imapSyncClient = require("imap-sync-sclient")
- // 字符集转码: imap-utf-7 => utf-8
- function imapSyncClient.imapUtf7ToUtf8(str: string | Buffer): string
- // 字符集转码: utf-8 => imap-utf-7
- function imapSyncClient.utf8ToImapUtf7(str: string | Buffer): string
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |