电子邮件服务原理与搭建

引言

最近在为一个海事项目内网环境搭建邮件服务器,对邮件服务的原理和流程有了更深的认识与梳理。
说起电子邮件,最容易想到的就是使用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包部署。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容