电子邮件服务原理与搭建

作者: 阿堃堃堃堃 | 来源:发表于2017-10-30 20:52 被阅读66次

    引言

    最近在为一个海事项目内网环境搭建邮件服务器,对邮件服务的原理和流程有了更深的认识与梳理。
    说起电子邮件,最容易想到的就是使用B/S架构的gmail、163、QQ邮箱收发邮件了。但对于一个企业内部而言,往往不会采用这些第三方公司开放的邮箱应用和服务,这主要是出于对信息保密、灵活定制、维护方便、存储空间等方面的考虑,因此越来越多的企业都开始自己搭建电子邮件服务,使得内部员工可以在同一个内网下使用。
    本文首先简单介绍下邮件服务器的工作原理与相关协议,再实际记录下采用开源项目Apache James(Java Apache Mail Enterprise Server)搭建邮件服务器的过程与关键点。

    工作原理

    邮件服务器其实是若干构件的一个统称,具体细化后其实是由用户代理、发送服务器、接收服务器、邮件发送协议(SMTP)、邮件接收协议(POP3)组成的,如下图所示。


    发件流程
    1. 发件人借助用户代理(客户端软件,如outlook、网页版QQ邮箱)起草邮件,点击发送邮件
    2. 用户代理与发送服务器建立TCP可靠连接
    3. 用户代理(充当STMP客户)以STMP协议承载传输至发送服务器(充当STMP服务器)
    4. 发送服务器收到邮件后将他们暂存到一个邮件缓冲队列中,保证后续传输到达顺序的正确性
    5. 发送服务器与目的接收服务器建立TCP可靠连接
      6.发送服务器(这次充当STMP客户)依次摘取邮件缓冲队列队首邮件,再同样以STMP协议经网络传输至接收方IP下的接收服务器(充当STMP服务器)
    收件流程
    1. 收件人打开用户代理(客户端软件)并建立与接收服务器的TCP可靠连接
    2. 用户代理使用POP3(IMAP)协议从接收服务器中读取邮件数据
    3. 将读取到的邮件数据呈现到客户端界面上
    4. 当然如果要求更完备一些的话,比如若要允许收发外域邮件,那么还要涉及5.DNS服务器进行域名解析,若要保证在客户端对邮件的操作结果都时刻同步至服务器,那么还要涉及IMAP交互式邮件存取协议等等。

    搭建流程

    由上已经知道,邮件服务器的核心是用户代理、发送/接收服务器及它们之间通信的协议,因此在搭建时我采用了一个开源的B/S架构的Web客户端工程作为用户代理,还有一个开源的Apache James基于Spring3.x而写的邮件服务工程作为邮件服务器,他们都是基于Java语言编写的。本文的搭建都是在CentOS 6.3系统上进行的,搭建过程涉及JDK安装、Tomcat安装、MySQL安装、Web服务部署、James服务部署。下面依次记录这几个过程及遇到的问题。

    1.JDK安装

    Web端的Java环境采用的是jdk1.8.0_131版本,通过从官网下载该版本的tar.gz包,解压到lib目录并配置环境变量,具体命令如下:

    #解压jdk
    cd /usr/lib/java
    tar -zvxf jdk1.8.0_131.tar.gz #事先将压缩包放于此目录
    #配置环境变量
    vi /etc/profile
    export JAVA_HOME=/usr/share/jdk1.8.0_131 
    export PATH=$JAVA_HOME/bin:$PATH 
    export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    
    2.Tomcat安装

    Tomcat作为Web服务的容器应该已经是约定俗成的传统了,虽然有更轻量级的Jetty,但其启动命令很长让我觉得很不优雅所以不怎么爱用。搭建很简单,也是从官网下载Tomcat8(与jdk版本保持一致)的tar.gz包,然后解压到/usr/local目录,具体命令如下:

    #解压tomcat
    cd /usr/local
    tar -zvxf apache-tomcat-8.5.16.tar.gz #事先将压缩包放于此目录
    #重命名
    mv apache-tomcat-8.5.16 tomcat
    #修改tomcat的java环境
    cd /usr/local/tomcat/bin
    vi catalina.sh
    export JAVA_HOME=/usr/lib/java/jdk1.8.0_131
    vi setclasspath.sh
    export JAVA_HOME=/usr/lib/java/jdk1.8.0_131
    #启动
    cd /usr/local/tomcat/bin 
    ./startup.sh
    #停止
    ./shutdown.sh
    
    3.MySQL安装

    数据库采用MySQL,安装过程采用yum,先下载安装包源并安装源,然后安装MySQL,命令如下:

    # 下载mysql源安装包
    shell> wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
    # 安装mysql源
    shell> yum localinstall mysql57-community-release-el7-8.noarch.rpm
    #检查mysql源是否安装成功
    yum repolist enabled | grep "mysql.*-community.*"
    #安装MySQL
    yum install mysql-community-server
    #启动
    service mysqld start
    #停止
    service mysqld stop
    

    root用户的初始密码自动生成再了/var/log/mysqld.log下,我们对该密码进行更改方便后续使用,命令如下:

    #抓取root初始密码
    grep 'temporary password' /var/log/mysqld.log
    #修改密码
    mysql -uroot -p
    set password for 'root'@'localhost'=password('Grenade2017~');
    

    但是之后搭建好Web服务和James服务后,我们发现了两个问题。第一个是插入汉字的时候在数据库中会变成???,这个问题比较明确,解决办法是在/etc/my.cnf文件中的[mysqld]与[client]下加上配置,命令如下:

    vi /etc/my.cnf
    #[mysqld]下加入
    character-set-server=utf8
    #[client]下加入
    default-character-set=utf8
    

    若是采用jdbc连接的数据库,也可以在jdbc的配置文件对应数据库的那行加上编码配置:

    jdbc:mysql://localhost:3306/email?useUnicode=true&characterEncoding=UTF-8
    

    另一个问题比较隐秘但也跟踪出来了,就是Web端在访问表名的时候随意采用大小写,一会儿大写,一会儿小写,一会儿驼峰,部署在Windows系统上时没有问题,但一旦拿到linux下就出表名相关的问题。这是因为Windows平台上的MySQL数据库对表名大小写不敏感,而Linux系统对数据库表名大小写敏感。解决办法很简单,同样是在/etc/my.cnf文件的[mysqld]下加入配置,命令如下:

    #[mysqld]下加入
    lower_case_table_names = 1 # 0/默认:敏感 1:不敏感
    
    4.Web服务部署

    Web工程是采用SSH(Spring-Struts-Hibernate)编写的,需要的jar包都已经引入了,所以在部署的时候我们只需要打好war包放在tomcat的webapps目录下即可。但在打war包之前记得将数据库配置文件jdbc.properties中的连接信息替换成自己的:

    jdbc.url=jdbc\:mysql\://localhost\:3306/email
    jdbc.username=root
    jdbc.password=123456
    
    5 James服务部署

    Apache James(Java Apache Mail Enterprise Server)是Apache组织的子项目之一,完全采用纯Java技术开发,实现了SMTP、POP3与NNTP等多种邮件相关协议。James也是一个邮件应用平台,可以通过Mailet扩充其功能,如Mail2SMS、Mail2Fax等。James提供了比较完善的配置方案,尤其是关于邮件内容存储和用户信息存储部分,可以选择在文件、数据库或其他介质中保存。更多详情可参见Apache James Project。本文仅给出James服务工程的配置与部署过程,包括如下几个步骤。

    1) 数据库修改

    James工程的conf目录下有一个database.properties配置文件,可对其中的数据库信息进行配置以适应部署时的生产环境,如下所示:

    database.driverClassName=com.mysql.jdbc.Driver
    database.url=jdbc:mysql://localhost:3306/email
    database.username=root
    database.password=123456
    vendorAdapter.database=MYSQL
    openjpa.streaming=false
    
    2) 不依赖外网

    如果不做任何修改,在默认情况下启动James服务,会报无法访问外网的错误(在spring-beans.xml文件中)。这个问题是因为James基于Spring3.x,会采用XML文件进行一些beans的配置,而XML文件格式、语法、结构等方面正确性的验证又依赖于XSD文件(XML Schemas Definition)。而spring-beans.xml中配置的XSD文件是通过HTTP协议访问外网服务器上的资源得到的,我们需要把访问路径改为本地XSD文件所在的路径(刚好包含于对应的jar包中)。修改如下所示:

    <beans xmlns="http://www.springframework.org/schema/beans" 
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:camel="http://camel.apache.org/schema/spring"
           xmlns:amq="http://activemq.apache.org/schema/core" 
           xsi:schemaLocation="
              http://www.springframework.org/schema/beans classpath:/org/springframework/beans/factory/xml/spring-beans-3.0.xsd
              http://camel.apache.org/schema/spring classpath:/camel-spring.xsd
              http://activemq.apache.org/schema/core classpath:/activemq.xsd">
    
    3) 后台启动

    James服务的启动很简单,进入bin目录,输入下面命令:

    cd /usr/local/james/bin
    ./run.sh
    

    但这样做存在一个问题:因为通常我们采用ssh远程访问服务器,当启动服务后只要关闭终端,James服务对应的进程也会退出。因此我们需要在命令末尾加上&保证是后台启动,不占用终端界面进程:

    ./run.sh &
    

    但这样做以后会发现退出终端后进程还是断了,网上查了一番后才发现,原来真正的后台启动需要采用nohup命令,它可以忽略挂起、退出等信号,如下所示:

    nohup ./run.sh &
    

    结语

    本文仅是对电子邮件服务的基本原理和搭建给出了一个大概的整理,但仍然缺少对邮件服务器更底层原理性东西的阐述,如SMTP协议、POP3协议、服务器推技术等,若感兴趣可以查阅相关资料进行阅读。
    关于本文用到的两个工程的代码可以在我的GitHub中的email仓库下载,其中文件夹james-server-container-spring-3.0-M2就是James工程,剩余部分都是Web端工程的内容,可导入到idea/eclipse打成war包部署。

    相关文章

      网友评论

        本文标题:电子邮件服务原理与搭建

        本文链接:https://www.haomeiwen.com/subject/vgvmpxtx.html