Skip to content

源码运行

电子邮件基于开源项目 Apache James Project 进行开发,James 是一个企业级的邮件服务器,支持 IMAP, SMTP, POP3 等多种协议。 James 支持使用 Mailet 和 Matcher 的概念来处理电子邮件。Mailet 是一个可以对邮件执行操作的处理程序,而 Matcher 则用于定义哪些邮件应该被特定的 Mailet 处理。 更多关于 James 的详细信息可以访问 James 官网

我们的电子邮件项目是 webmail,即网页端实现邮件的收发,对于 James 邮件服务器来说相当于中间层,对 James 进行调用实现邮件的收发,通过跟数字底座的结合实现了人员的同步,即数字底座的人员都会在 James 中有唯一的邮箱账号。

由于 James 是一个企业级的邮件服务器,所以在邮箱账号创建后我们也可使用独立的电子邮件客户端软件(如 Thunderbird、Foxmail 等)进行邮件的收发

James 安装运行

James 安装运行参考官方文档 https://james.apache.org/server/install.html

当前安装运行文档基于 James 版本 3.8.0, 以域名 example.com 为例说明安装过程

软件需求

  • Java 虚拟机。James-3.8.0 需要 Java 11 来运行
  • 管理员用户权限。Linux/Unix 平台需要 root 用户权限, Windows 平台需要管理员用户权限
  • Libc6。对于 Linux 平台还需要 Libc6 库来执行 james 的相应命令(以 Ubuntu 安装为例:sudo apt-get install libc6-i386 libc6-dev-i386
  • 系统资源。系统需要足够的 CPU、内存、硬盘、网络带宽等系统资源,James 配置了使用 512 MB 内存,这些配置都需要根据自己的使用量来评估和调整

二进制包下载

对于没有服务器个性化需求的用户,可以直接从 James 下载页 下载二进制包进行部署,我们下载了 james-server-app-3.8.0-app.zip。 其他的包则是在支持的特性上有所不同,具体可参考 James 的多种打包

生成密钥对

此步骤为后面某些协议启用 SSL/TLS 而做的准备,如不需要启用加密端口可跳过此步骤,但是更推荐启用并优先使用加密端口

shell
$ keytool -genkey -alias james -keyalg RSA -storetype PKCS12 -keystore /Users/tobin/Documents/james/conf/keystore
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
  [Unknown]:  test
您的组织单位名称是什么?
  [Unknown]:  test
您的组织名称是什么?
  [Unknown]:  test
您所在的城市或区域名称是什么?
  [Unknown]:  test
您所在的省/市/自治区名称是什么?
  [Unknown]:  test
该单位的双字母国家/地区代码是什么?
  [Unknown]:  test
CN=test, OU=test, O=test, L=test, ST=test, C=test是否正确?
  [否]:  y

命令执行完成后会生成密钥对并存储在密钥库文件 /Users/tobin/Documents/james/conf/keystore

配置文件修改

二进制包下载后解压,配置文件放在 conf 目录下

这里根据我们的需求修改相应的配置文件,由于某些配置文件内容较多,只列出需要修改的某块配置

以我们需要用 MySQL 来存储邮件和用户信息,并开启 SMTPIMAPPOP3 协议为例,我们需要调整以下配置文件:

  • domainlist.xml
xml
<domainlist class="org.apache.james.domainlist.jpa.JPADomainList">
   <autodetect>false</autodetect>
   <autodetectIP>false</autodetectIP>
   <defaultDomain>example.com</defaultDomain> <!-- 使用的邮箱域名,本地调试可保持 localhost 不调整 -->
</domainlist>
  • mailetcontainer.xml
xml
<mailetcontainer enableJmx="true">
    <processors>
        <processor state="transport" enableJmx="true">
            <!-- 注释此 mailet,否则不能外发邮件 -->
            <!-- <mailet match="RemoteAddrNotInNetwork=127.0.0.1" class="ToProcessor">
                <processor>relay-denied</processor>
                <notice>550 - Requested action not taken: relaying denied</notice>
            </mailet> -->
        </processor>
    </processors>
</mailetcontainer>
  • james-database.properties

调整使用 MySQL 作为邮件及用户信息的存储库,在 MySQL 中建 james

调整配置后需 将 MySQL 对应的驱动包放入 lib 文件夹 中,否则启动会报驱动找不到的错

properties
database.driverClassName=com.mysql.cj.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/james?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useCompression=true&useSSL=false&allowPublicKeyRetrieval=true
database.username=root
database.password=111111

vendorAdapter.database=MYSQL
  • log4j2.xml

可以根据自己的需求调整日志存放的位置及相应代码的日志输出

  • usersrepository.xml
xml
<usersrepository name="LocalUsers" class="org.apache.james.user.jpa.JPAUsersRepository">
    <algorithm>MD5</algorithm> <!-- 修改加密算法为 MD5,这里主要是用于数字底座的用户与 James 同步 -->
</usersrepository>
  • smtpserver.xml
xml
<smtpservers>
    <smtpserver enabled="true">
        <jmxName>smtpserver</jmxName>
        <bind>0.0.0.0:25</bind>
        <connectionBacklog>200</connectionBacklog>
        <connectiontimeout>360</connectiontimeout>
        <connectionLimit>0</connectionLimit>
        <connectionLimitPerIP>0</connectionLimitPerIP>

        <auth>
            <announce>forUnauthorizedAddresses</announce> <!-- 对于未授权的地址开启认证 -->
            <!-- <requireSSL>false</requireSSL> -->
            <plainAuthEnabled>true</plainAuthEnabled> <!-- 启用明文认证,建议结合 SSL/TLS 使用 -->
        </auth>

        <authorizedAddresses>0.0.0.0</authorizedAddresses> 
        <maxmessagesize>0</maxmessagesize>
        <addressBracketsEnforcement>true</addressBracketsEnforcement>

        <handlerchain>
            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
        </handlerchain>
    </smtpserver>
    <smtpserver enabled="true">

        <jmxName>smtpserver-ssl</jmxName>
        <bind>0.0.0.0:465</bind>
        <connectionBacklog>200</connectionBacklog>

        <tls socketTLS="true" startTLS="false"> <!-- 使用socketTLS,所有通信都是加密的 -->
            <keystore>file://conf/keystore</keystore> <!-- keystore 位于 James 的 conf 目录中 -->
            <keystoreType>PKCS12</keystoreType> <!-- 生成密钥对步骤中指定的密钥库的存储类型 -->
            <secret>111111</secret> <!-- 生成密钥对步骤中指定的密钥库口令 -->
            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
            <algorithm>RSA</algorithm> 
        </tls>

        <connectiontimeout>360</connectiontimeout>
        <connectionLimit>0</connectionLimit>
        <connectionLimitPerIP>0</connectionLimitPerIP>

        <auth>
            <announce>forUnauthorizedAddresses</announce> <!-- 对于未授权的地址开启认证 -->
            <!-- <requireSSL>false</requireSSL> -->
            <plainAuthEnabled>true</plainAuthEnabled>
        </auth>

        <authorizedAddresses>0.0.0.0</authorizedAddresses>
        <maxmessagesize>0</maxmessagesize>
        <addressBracketsEnforcement>true</addressBracketsEnforcement>

        <handlerchain>
            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
        </handlerchain>
    </smtpserver>
</smtpservers>
  • imapserver.xml
xml
<imapservers>
    <imapserver enabled="true">
        <jmxName>imapserver</jmxName>
        <bind>0.0.0.0:143</bind>
        <connectionBacklog>200</connectionBacklog>

        <connectionLimit>0</connectionLimit>
        <connectionLimitPerIP>0</connectionLimitPerIP>
        <plainAuthDisallowed>false</plainAuthDisallowed>
        <auth>
            <plainAuthEnabled>true</plainAuthEnabled> <!-- 启用明文认证,建议结合 SSL/TLS 使用 -->
        </auth>
    </imapserver>
    <imapserver enabled="true"> <!-- 本地测试可根据自己需求移除这一块,减少配置 -->
        <jmxName>imapserver-ssl</jmxName>
        <bind>0.0.0.0:993</bind>
        <connectionBacklog>200</connectionBacklog>
    
        <tls socketTLS="true" startTLS="false"> <!-- 使用socketTLS,所有通信都是加密的 -->
            <keystore>file://conf/keystore</keystore> <!-- keystore 位于 James 的 conf 目录中 -->
            <keystoreType>PKCS12</keystoreType> <!-- 生成密钥对步骤中指定的密钥库的存储类型 -->
            <secret>111111</secret> <!-- 生成密钥对步骤中指定的密钥库口令 -->
            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
        </tls>
    
        <connectionLimit>0</connectionLimit>
        <connectionLimitPerIP>0</connectionLimitPerIP>
        <plainAuthDisallowed>false</plainAuthDisallowed>
        <auth>
            <plainAuthEnabled>true</plainAuthEnabled> <!-- 启用明文认证 -->
        </auth>
    </imapserver>
</imapservers>
  • pop3server.xml
xml
<pop3servers>
    <pop3server enabled="true">
       <jmxName>pop3server</jmxName>
       <bind>0.0.0.0:110</bind>
       <connectionBacklog>200</connectionBacklog>
       <connectiontimeout>1200</connectiontimeout>
       <connectionLimit>0</connectionLimit>
       <connectionLimitPerIP>0</connectionLimitPerIP>
         
       <handlerchain>
           <handler class="org.apache.james.pop3server.core.CoreCmdHandlerLoader"/>
       </handlerchain>
    </pop3server>
    <pop3server enabled="true">
        <jmxName>pop3server-ssl</jmxName>
        <bind>0.0.0.0:995</bind>
        <connectionBacklog>200</connectionBacklog>

        <tls socketTLS="true" startTLS="false">
            <keystore>file://conf/keystore</keystore>
            <keystoreType>PKCS12</keystoreType>
            <secret>111111</secret>
            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
        </tls>

        <connectiontimeout>1200</connectiontimeout>
        <connectionLimit>0</connectionLimit>
        <connectionLimitPerIP>0</connectionLimitPerIP>

        <handlerchain>
            <handler class="org.apache.james.pop3server.core.CoreCmdHandlerLoader"/>
        </handlerchain>
    </pop3server>
</pop3servers>

DNS 设置

对于互联网收发,需要设置相应的域名解析,如果域名设置处仍旧使用 localhost (仅用于本地的测试)则这步可跳过

记录类型主机记录(域名前缀)记录值
MX@mail.example.com
Amail邮件服务器公网 IP
Apop邮件服务器公网 IP
Aimap邮件服务器公网 IP
Asmtp邮件服务器公网 IP

运行

进入 bin 目录下执行命令 ./james start 即可启动 James

接下来就可以创建用户来收发邮件,可以通过命令 ./james-cli.sh adduser user@example.com 111111 创建用户, 其中 user@example.com 为用户邮箱(用户邮箱中的域名部分需跟配置文件 domainlist.xml 中设置的一致),111111 为对应的邮箱密码

服务器端口设置

一些服务器默认禁用了端口的互联网访问,所以需要对相应的端口放行才能正常的使用邮件服务

协议非加密端口加密端口
SMTP25465
POP3110995
IMAP143993

至此,我们已经在 James 邮件服务器上新建了 user@example.com 邮箱,并且可以用这个邮箱在各个邮件服务器之间收发邮件了

webmail 安装运行

由于本项目依赖数字底座,数字底座在电子邮件中提供了单点登录认证、组织身份的服务,所以需要先将对应的数字底座服务启动,可参考数字底座源码运行文档

下载源码

前往 gitee 下载代码,地址: https://gitee.com/risesoft-y9/y9-email

后端项目

引入项目

打开 IDEA,点击左上角的 File ,在下拉选项中选择 Open,找到源码目录选择最外层的根目录 y9-email 打开 open-y9-email.png

修改配置文件

修改服务的配置文件 application.yml,将 MySQL、Redis、Kafka 等服务端口和密码改为自己的服务地址和密码。

对于未使用的中间件,对应的设置可以不用修改,不同的数据库适配详细配置,请点击参考数据库适配,以下为 MySQL 数据库的数据源连接配置

risenet-y9boot-webapp-webmail 工程配置:

yaml
spring:
    datasource:
        druid:
            y9-public:
                driver-class-name: com.mysql.cj.jdbc.Driver
                url: jdbc:mysql://localhost:3306/y9_public?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useCompression=true&useSSL=false&allowPublicKeyRetrieval=true
                username: root
                password: 111111
            webmail:
                # 连接 james 的库,用于邮箱的管理
                driver-class-name: com.mysql.cj.jdbc.Driver
                url: jdbc:mysql://localhost:3306/james?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useCompression=true&useSSL=false&allowPublicKeyRetrieval=true
                username: root
                password: 111111
y9:
    app:
        webmail:
            # 需要修改为自己的邮件服务器域名
            imapHost: imap.example.com 
            imapPort: 143
            smtpHost: smtp.example.com
            smtpPort: 25
            host: example.com

运行

将服务的上下文修改为对应服务名,将 Tomcat 的端口调整为 7056 以便前端、或其他服务能正常调用

工程名字服务名称
risenet-y9boot-webapp-webmailwebmail

添加完成之后选择相应的 Tomcat 点击 Debug 即可启动服务

前端项目

运行前提

node.js 版本 v14.20.0 或者更高版本

这个项目里的配置文件是对应这套开源代码的后端代码,需要先在本地环境中,将后端的代码运行起来,才能运行起来看到页面效果。

本地运行

打开 cmd

$ cd vue\y9vue-webmail # 进入前端工程文件夹
$ npm i # 安装依赖
$ npm run serve # 依赖安装完成后,运行程序

前端工程默认使用 7070 端口。

如果需要部署到其他环境,可以执行 npm run build 或者 npm run build-test 打包部署至正式或者测试环境,需要修改 .env.production 或者 .env.test 中的配置

访问服务

运行成功后,复制事项链接,打开浏览器访问:http://localhost:7070/webmail/

默认账号:

测试账号 登录名:user 密码:Risesoft@2022

Released under the GPL-3.0 License.