帮酷LOGO
  • 显示原文与译文双语对照的内容
IMAP server built with Node.js and MongoDB

  • 源代码名称:wildduck
  • 源代码网址:http://www.github.com/nodemailer/wildduck
  • wildduck源代码文档
  • wildduck源代码下载
  • Git URL:
    git://www.github.com/nodemailer/wildduck.git
  • Git Clone代码到本地:
    git clone http://www.github.com/nodemailer/wildduck
  • Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/nodemailer/wildduck
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
  • WildDuck邮件服务器

    WildDuck是可以扩展的无 SPOF imap/pop3邮件服务器。 WildDuck使用分布式数据库( 分片+ 复制的MongoDB ) 作为后台存储所有数据,包括电子邮件。

    WildDuck尝试在产品设计中跟踪 Gmail 。 如果需要做出决定,那么通常的答案是做任何Gmail完成的操作。

    英镑目前正处于 beta 。 ! 将它的用于你自己的职责。

    要求

    • MongoDB 存储所有数据
    • 适用于pubsub和计数器的 Redis
    • Node.js 至少版本 6.0.0

    可选需求

    • Redis Sentinel用于自动Redis故障转移
    • 构建工具来安装需要编译的可选依赖项

    WildDuck可以以安装在任何 node.js 兼容平台上。

    没有SPOF体系结构

    可以复制WildDuck邮件服务器的每个组件,从而消除潜在的单点故障。

    存储

    附件复制和压缩可以降低存储大小的56% % 。

    用法

    脚本安装

    如果你有一个空白的和一个免费的域 NAME,你可以以指向那个可以以尝试的脚本所包含

    安装指令

    安装脚本安装并配置所有必需的依赖项和服务,包括让我们加密基于证书的证书,以将WildDuck作为邮件服务器运行。

    在 10 $ DigitalOcean 16.04实例上测试。

    手动安装

    假设你正在运行MongoDB和 Redis 。

    步骤 1从github获取代码

    $ git clone git://github.com/nodemailer/wildduck.git
    $ cd wildduck

    步骤 2安装依赖项

    安装来自npm的依赖项

    $ npm install --production

    步骤 3运行服务器

    要使用缺省配置文件,请运行以下命令:

    node server.js

    或者,如果要使用自己的配置替代默认配置选项,请运行以下( 自定义配置文件与默认值合并,因此只指定要更改的这些值):

    node server.js --config=/etc/wildduck.toml

    有关其他配置选项,请参见野生配置文档

    步骤 4创建用户帐户

    有关创建新用户帐户的详细信息,请参阅 API文档

    步骤 5使用 imap/pop3客户端登录

    任何IMAP或者POP3客户端都将。 使用步骤 4中的凭据。 登录。

    项目的目标

    • 使用集群数据库代替单个机器文件系统构建可以伸缩的分布式 imap/pop3服务器,并将它的作为邮件存储
    • 允许使用国际化的电子邮件地址
    • 将邮件自动发送到邮件文件夹或者通知邮件文件夹,以便标记为垃圾邮件
    • 通过HTTP提供已经解析的邮箱和消息数据。 这就使得创建网络邮件界面非常容易,无需解析RFC822消息来获取文本内容或者附件
    • HTTP API

    用户,邮箱和消息可以通过针对 WildDuck API的HTTP请求进行管理

    API文档

    常见问题解答

    work工作?

    是的可以运行服务器,并为邮件存储使用IMAP和POP3服务器,将邮件推送到邮件存储和 HTTP API服务器上,以创建新的用户。 全部由 node.js,MongoDB和Redis处理,不需要额外的依赖。 所提供的服务可以以被禁用并启用一个,例如,你可以以在一个主机和LMTP中处理 IMAP 。

    在WildDuck中如何实现安全性?

    从Wiki中阅读关于WildDuck安全实现的内容。

    什么是致命的特征?

    • 无状态Stateless启动尽可能多的实例。 可以以在不同的计算机中启动多个WildDuck实例,只要它们共享同一个MongoDB和jfs设置,用户就可以以连接。 这与传统的IMAP服务器非常不同,因为单一用户总是需要将( 或者被代理) 连接到相同的IMAP服务器。 WildDuck在MongoDB中保留所有必需的状态信息,所以不管使用哪个IMAP实例都不重要。
    • 扩展的为后端存储使用分片MongoDB集群。 如果空间不足,请添加新的碎片。
    • 你可以运行每个所需服务的多个实例。
    • 收费证书,允许用户在不使用密码的情况下自动配置Apple电子邮件客户端,从而自动配置身份验证令牌。应用程序特定密码。身份验证作用域。撤消身份验证令牌。审计日志甚至配置文件
    • 任何操作系统,包括 Windows,都能工作 至少在第一次运行MongoDB和Redis时。
    • 专注于国际化,IE 。 支持非ascii字符的电子邮件地址
    • 如果同一附件引用了相同的附件,则为 ,然后只存储一个附件的单个副本。
    • 使用 IMAP和 访问消息。 后者提供解析数据,因此无需获取RFC822消息和解析 html 。纯文本内容或者附件。 在这个页面上创建一个webmail界面是非常容易的。
    • 内置的地址标签: username+label@example.com delivered 。
    • 用户名和地址中的点仅是信息。 username@example.comuser.name@example.com 相同。
    • 为用户电子邮件帐户添加用户电子邮件帐户的收费,以将它的修改为超快速的电子邮件客户机
    • 超级容易调整。 整个代码库是纯 JavaScript,所以没有什么可以编译或者任何平台特定的。 如果你需要调整代码,改变代码,重启程序,你就可以开始了。 如果它在一台机器上工作,那么很可能它在其他机器上。
    • 更好的磁盘使用 。 附件重复数据删除和MongoDB压缩约 40%个小磁盘使用率作为所有存储的电子邮件大小的总和。
    • 为所有存储消息的自动GPG加密或者使用U2F进行身份验证,额外增加了额外的安全功能
    • 公开的日志用户可以访问有关它的帐户的日志。 这包括安全日志( 身份验证尝试,帐户更改) 和消息日志

    使用数据库作为邮件存储是不坏的?

    是的,过去它一直被认为是一个坏习惯在数据库中存储邮件。 为了一个好的理由。 像MySQL这样的关系数据库数据模型不能很好地与( 电子邮件mime树) 或者大型 blob ( 电子邮件来源) 之类的树。

    注意"关系关系"这个词实际上,像MongoDB这样的文档存储很好地。 文档存储非常适合存储树,而of不像"真实"对象存储那样好,它足以存储消息的原始部分。 另外,没有任何GridFS太具体,所以( 至少在理论上) 可以被任何对象存储替换。

    下面列出了另外一个使用数据库存储电子邮件的电子邮件服务器:

    :它是如何工作的

    每当收到消息时,WildDuck就将它解析为基于MIME树的树结构,并将这里树存储到 MongoDB 。 附件从树中移除并单独存储在GridStore中。 如果需要加载消息,那么WildDuck首先获取树结构,并根据需要从GridStore加载附件,然后将它编译回原始的RFC822消息。 结果应与原始消息相同,除非原始消息使用了unix换行符,否则可以能部分替换为 Windows 换行。

    WildDuck尝试保持会话( 基本上就是目前已知的uid和最新MODSEQ值的列表)的最小状态,以便能够在不同主机之间分发会话。 每当打开邮箱时,整个邮件列表都作为UID值的array 加载。 array 元素中的第一个UID指向消息 nr 。 1中的,第二个指向消息 nr 。 2等。

    实际更新数据( 。有关新消息和已经删除邮件的信息,标志更新和) 存储到日志日志中,只要发生任何情况,就通过 Redis pub/sub传播更新信标。 如果会话检测到当前邮箱中存在某些更改,并且可以向用户通知它( 例如。 进行了调用,日志日志被从数据库加载并应用于一次的UID array 一个操作。 一旦所有日志更新应用之后,结果应该是 MATCH的最新状态。 如果不可能通知用户( 取了一个接通电话),则日志日志未加载,用户继续看到旧状态。

    E-mail 协议支持

    WildDuck IMAP服务器支持以下IMAP标准:

    • 整个收费的套件与规格有一些细微的差别。 有关完整的列表,请参阅 below的 IMAP协议差异插件
    • 对新消息和已经删除邮件( 也关于标志更新)的 IDLE
    • 收费的CONDSTORE ( RFC4551 ) 和英镑支持( RFC5161 ) - 支持大多数规格,除了元数据被忽略的元数据
    • 磅 STARTTLS ( RFC2595 )
    • 命名空间 ( RFC2342 ) - 最小支持,仅列出具有层次结构分隔符的单个用户命名空间
    • 取消选择 ( RFC3691 )
    • UIDPLUS ( RFC4315 )
    • 专用使用 ( RFC6154 )
    • ID ( RFC2971 )
    • 移动 ( RFC6851 )
    • 对普通 ( RFC4959 ) 和收费 sasl ir进行收费的收费
    • APPENDLIMIT ( RFC7889 ) 最大全局允许消息大小在cap列表中公布
    • 这也意味着WildDuck本身支持unicode电子邮件用户名。 例如 是一个有效的电子邮件地址,它由WildDuck的一个测试实例承载
    • 配额 ( RFC2087 ) - 配额大小为一个帐户,使用单个配额 root 。 注意,配额大小并不表示磁盘中的实际字节存储,而是计算为 RFC822存储消息源的总数。
    • 在客户端和服务器之间花费的COMPRESS=DEFLATE ( RFC4978 ) 压缩流量

    WildDuck或多或少通过了 ImapTest的压力测试运行。 测试中出现的常见错误是未知标签( 。WildDuck不发送未经请求的FLAGS 更新,即使它发送未经请求的FETCH FLAGS 更新),有时是 STORE ( 在一个会话中删除的邮件不能在另一个会话中更新) 。

    相比之下,WildDuck处理单个用户的速度比Dovecot慢。 尤它的是当Dovecot直接从 文件系统 读取消息时,WildDuck正在重构不同部分的消息。

    单个用户的原始读/写速度通常不相关,因为获取整个邮箱内容不是经常发生的事情。 WildDuck通过MongoDB切分提供更好的并行化,因此更多用户不应该意味着。 在客户机之间提供快速同步速度也更重要( 例如。 通知新电子邮件和这样的电子邮件,它的中WildDuck因写前日志而优势,以及将这里日志推送到客户端的。

    POP3支持

    除了所需的POP3命令( RFC1939 ) WildDuck支持以下扩展:

    • UIDL
    • 用户
    • SASL
    • PIPELINING
    POP3命令行为

    deleting deleting删除消息或者标记消息等消息的所有更改都存储在UPDATE更新阶段 storage 。 在调用 QUIT ) 之后,只有在内存中更改才会保存在内存中。 如果消息被下载但没有发出,那么这条消息不会被标记为 。

    下拉列表

    POP3列表显示收件箱中最新的250邮件( 可以配置)

    定义

    WildDuck使用消息 _id 值( 24字节十六进制) 作为唯一标识。 如果邮件从一个邮箱移到另一个邮箱,那么它可能在列表中显示为。

    如果客户端下载邮件,这里消息将被标记为

    如果客户端删除邮件,这里邮件将被标记为已经看到并被移动到回收站文件夹

    消息过滤

    WildDuck在LMTP服务器中构建了消息过滤。 尽管过滤器不是脚本,这有点类似于筛选。

    筛选器可以通过 WildDuck API管理。

    IMAP协议差异

    这是与IMAP规范有关的已知差异列表。 列出的差异要么是有意的,要么是 Bug的特性。

    • Recent 标志未实现,很可能永远不会出现( RFC3501 2.3.2 ) 。
    • RENAME 不触摸与规范相对应的子文件夹( RFC3501 6.3.5. 但是,如果的层次名较低,则还必须重命名下层层次名。 ) WildDuck使用扁平层次结构存储所有文件夹,"/"分隔符是假的,仅用于列出邮箱
    • 未请求的FLAGS 响应( RFC3501 7.2.6.) 和 PERMANENTFLAGS 不发送( 。除了 SELECTEXAMINE 响应的一部分之外,) 。 WildDuck仅通知有关标记更新的标记更新。
    • 如果在其他会话中删除了匹配消息,WildDuck将使用 NOSTORE 进行响应
    • 忽略 SEARCH 命令的CHARSET 参数( RFC3501 6.4.4 ) 。
    • SEARCH MODSEQ的元数据参数忽略( RFC7162 3.1.5.) 。 你可以定义 <entry-name><entry-type-req> 值,但这些值不能用于任何
    • SEARCH TEXTSEARCH BODY 都使用 MongoDB $text 索引 against解码的明文版本。 RFC3501假定它应该是一个字符串 MATCH,要么是完全消息( TEXT ),要么是正文节( BODY ) 。
    • 如果在另一个会话中被删除的邮件被调用,会发生什么情况? 我不确定,需要去检查一下。
    • Autoexpunge,表示每当消息获得 Deleted 标志时,在 background 上调用 destroy 。 这与 IMAP rfc不存在冲突。

    其他的区别可能是真正的Bug 和无意。

    测试

    创建电子邮件帐户并使用你的IMAP客户端连接到它。 若要向这里帐户发送邮件,请运行示例脚本:

    node examples/push-message.js username@example.com

    这将使用内置的LMTP maildrop接口,向 username@example.com 收件箱中添加一个新消息。 如果你的电子邮件客户端已经连接,那么你应该立即看到新消息。

    电子邮件出站 SMTP

    使用 WildDuck ( 下面是 ZoneMTA,带有 ZoneMTA WildDuck插件插件) 。

    这将为你提供一个使用WildDuck帐户进行身份验证的出站SMTP服务器。 插件认证用户凭证,如果需要的话( 如果 header 来自: 地址不 MATCH 用户地址或者别名,则重写它) 。 此外,已经发送邮件的副本将上载到已经发送邮件文件夹。 本地传递直接发送到 WildDuck LMTP 。

    入站 SMTP

    使用 Haraka 队列/lmtp插件向WildDuck和 haraka-plugins-wildduck插件发送消息,以验证收件人地址和针对WildDuck用户数据库的配额使用。

    的未来考虑

    • 优化提取查询以只加载正文部分的部分数据

    • 将传入消息作为流解析到mime树中。 当前,整个消息在解析之前被缓冲在内存中。

    • 也许允许通过插件进行某种消息操作

    • WildDuck并不打算成为世界上最富特色的IMAP客户端。 因为没有太多的客户端能够从这些扩展中获益,所以大多数IMAP扩展是无用的。 虽然有几个扩展可以被添加到 WildDuck:

      • IMAP4非同步文字,LITERAL- ( RFC7888 ) 。 在附加检查邮箱配额时需要同步文本,小值可以与非同步版本一起使用。
      • 列表状态( RFC5819 )
      • 还有什么( 当然不通知也不叫 QRESYNC )?

    操作 WildDuck

    分片

    WildDuck支持MongoDB分片。仅当知道数据存储大于单独的副本时,才可以以考虑使用分片。 有些操作需要进行分散的查询,这可能是对大型集群性能的影响,但大多数查询在默认情况下包括碎片键。

    用以下键( 假设你将附件保留在单独的数据库中) 拆分以下集合:

    sh.enableSharding('wildduck');// consider using mailbox:hashed for messages only with large shard chunk sizesh.shardCollection('wildduck.messages', { mailbox:1, uid:1 });sh.shardCollection('wildduck.archived', { user:1, _id:1 });sh.shardCollection('wildduck.threads', { user:'hashed' });sh.shardCollection('wildduck.messagelog', { id:'hashed' });sh.shardCollection('wildduck.authlog', { user:'hashed' });sh.enableSharding('attachments');// attachment _id is a sha256 hash of attachment contentssh.shardCollection('attachments.attachments.files', { _id:'hashed' });sh.shardCollection('attachments.attachments.chunks', { files_id:'hashed' });

    磁盘使用情况

    测试表明,附件内容 vs的比例大约为 1: 10. 也就是说,你可以使用较小的SSD在多个磁盘之间分离数据库( 例如。 150 GB ) 用于消息数据和索引,以及更大更便宜的SATA ( 例如。 1 TB ) 用于附件内容。 这假设你在 storage.directoryPerDB:true 和中使用了 WiredTiger storage.wiredTiger.engineConfig.directoryForIndexes:true

    假设你使用名为 attachments的数据库作为附件内容:

    SSD mount :/var/lib/mongodb
    SATA mount:/var/lib/mongodb/attachments/collection

    MongoDB不抱怨现有的文件夹,因此在安装MongoDB之前你可以准备安装。

    Sentinel

    WildDuck可以使用 Redis Sentinel代替单一Redis主机进行自动故障转移。 当使用Sentinel和Redis主机失败时,可能需要花一点时间才能选择新主机。 在该窗口中缓存挂起的请求,因此大多数操作最终都应该成功。 但是,你可能希望在负载下测试故障转移,以查看它的行为。

    Redis Sentinel故障转移不保证一致性。 WildDuck不会在Redis中存储关键信息,因此即使发生某些数据丢失,也不应该引起注意。

    HAProxy

    使用HAProxy时,你可以启用代理协议在服务器日志中获取正确的远程地址。 你可以使用最基本的基于循环的平衡,因为不需要针对特定主机的持久。 不需要额外设置就可以使用TCP负载平衡和纯文本和TLS连接。

    如果TLS由HAProxy处理,则使用以下服务器配置指示WildDuck为TLS服务器,但TLS在上游处理。

    [imap]secure=true# this is a TLS serversecured=true# TLS is handled upstream[pop3]secure=true# this is a TLS serversecured=true# TLS is handled upstream

    自签名证书

    你可以通过将SIGHUP发送到主进程来重新加载更新的证书。 这将导致从磁盘读取应用程序配置。 重载仅影响某些设置,例如加载和更新所有的TLS证书。 在这种情况下,现有进程继续进行,而新的进程使用更新的证书。

    如果配置加载失败,请注意,它以异常结束。 确保WildDuck用户对TLS证书文件是可读的。

    许可证

    WildDuck邮件代理在欧盟 public 许可证 1.1或者更高版本下的许可证。




    Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语