搜吥到正常wwW98XFW的联通4gapn接入点设置了,检查过网络98XFWCom挺正常的啊

联想p700在家的时候正常,到了外地为什么打开数据连接后通知栏e符号却没有出现,也还上不了网_百度知道
联想p700在家的时候正常,到了外地为什么打开数据连接后通知栏e符号却没有出现,也还上不了网
我有更好的答案
http,主要部件保修2年,系统及软件保修1年,国外行货需要注册IWS全球联保,服务站的选择可以查询.cn/forum.php?intcmp=FM_LBBS_baidureply" target="_blank">http://lenovobbs.lenovo?intcmp=I_F_FWWD其他问题也可以在这两个论坛比较全.cn/lenovo/wsi/station/servicestation/default.aspx://support1.lenovo!为了方便起见,建议您到联想的服务站查询诊断问题.php
人类失去联想,世界将会怎样!
主营:IT网络服务
8.aspx 查询就近站点,建议备份机身资料进行恢复出厂设置尝试(主菜单-系统设置-备份和重置-恢复出厂设置-重置手机);如上述操作后问题依旧无法得到有效解决、请核对数据开关服务是否开启:00—18.lenovomobile.com)进行咨询了解,建议更换网络环境尝试;4、如您有条件更换其他sim卡,建议您更换sim卡进行对比使用,若个别sim卡无法正常联网,不排除是兼容性问题,建议联系运营商具体检测处理;5、建议对接入点进行切换尝试.cn/ServiceStation,即支持移动&#47:“系统设置——SIM管理——数据连接——选择您要上网的SIM卡”;3、建议您更换其他手机或对比周边其他同运营商用户使用情况,为了您日后的正常使用,建议您抽空到附近联想授权维修站具体检测处理。您可以访问 联通的2G网络和联通3G网络,请确认所使用sim卡在此范围,给您的使用带来了不便。根据您的描述:“菜单-系统设置-更多-移动网络-接入点名称(APN)”,将选项切换到不同接入点重启尝试;6、建议您核对接入点参数有效性,您可以与运营商客服进一步联系确认您好;7、如上述操作无法改善。维修站点营业时间通常为周一至周日9,请您参考。 欢迎您随时与我们联系或访问联想乐问吧(
为您推荐:
其他类似问题
您可能关注的内容
数据连接的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)chmod 777 /home/ftpd/incoming
chown ftp /home/ftpd/incoming
chgrp ftp /home/ftpd/incoming
改etc下的ftpaccess,我的是这样:
loginfails 2
class&& local&& real,guest,anonymous *.domain 0.0.0.0
class&& remote& real,guest,anonymous *
limit&& local&& 20& Any&&&&&&&&&&&&&&&& /etc/msgs/msg.toomany
limit&& remote& 100 SaSu|Any&& /etc/msgs/msg.toomany
limit&& remote& 60& Any&&&&&&&&&&&&&&&& /etc/msgs/msg.toomany
readme& README*&&& login
readme& README*&&& cwd=*
message /welcome.msg&&&&&&&&&&& login
message .message&&&&&&&&&&&&&&& cwd=*
compress&&&&&&& yes&&&&&&&&&&&& local remote
tar&&&&&&&&&&&& yes&&&&&&&&&&&& local remote
# allow use of private file for SITE GROUP and SITE GPASS?
private&&&&&&&& yes
# passwd-check& &none|trivial|rfc822&& [&enforce|warn&]
passwd-check&&& rfc822& warn
log commands real
log transfers anonymous,real inbound,outbound
shutdown /etc/shutmsg
# all the following default to &yes& for everybody
& delete&&&&&&&&& no&&&&& guest,anonymous&&&&&&&& # delete permission?
& overwrite&&&&&& no&&&&& guest,anonymous&&&&&&&& # overwrite permission?
& rename&&&&&&&&& no&&&&& guest,anonymous&&&&&&&& # rename permission?
& chmod&&&&&&&&&& no&&&&& anonymous&&&&&&&&&&&&&& # chmod permission?
& umask&&&&&&&&&& no&&&&& anonymous&&&&&&&&&&&&&& # umask permission?
# specify the upload directory information
& upload& /home/ftp& /pub&&&&&&&&&&&& no
& upload& /home/ftp& /pub1&&&&&&&&&&& no
& upload& /home/ftp& /incoming&&&&&&& yes
& upload& /home/ftp& /pub1/incoming&&&&&&& yes
& upload& /home/ftp& /bin&&&&&&&&& no
& upload& /home/ftp& /etc&&&&&&&&& no
& # directory aliases...& [note, the &:& is not required]
alias&& inc:&&& /incoming
cdpath& /incoming
cdpath& /pub
# path-filter...
path-filter& anonymous& /etc/pathmsg& ^[-A-Za-z0-9_\.]*$& ^\.& ^-
path-filter& guest&&&&& /etc/pathmsg& ^[-A-Za-z0-9_\.]*$& ^\.& ^-
# specify which group of users will be treated as &guests&.
guestgroup ftponly
email user@hostname
更改/etc/smb.conf,主要要确定下面的内容:
workgroup=MYWKGP
smb passwd file=/etc/smbpasswd
security=user (使用unix用户安全)
encrypt passwords= yes
然后就可以添加目录了,首先添加宿主目录:
(其实就是把对应的行的注释去掉)
comment = home directory
browseable = no
writeable= yes
还可以再加一个共享目录:
comment = public directory
path=/public
public=yes
writeable=no
read only=yes
printable=no
最后当然是加入用户,比如想把fake用户当成windows 系统中的winfake,执行
smbadduser fake:winfake
输入访问口令,以后在windows 98中只要提供winfake和对应口令
就可以访问/home/fake和/public目录
有时windows 95/98会出现一些兼容问题,研究encrypt passwords=那一行吧
==================================================================
最好用swat来设置吧,把/etc/inet.conf最后swat前的注释去掉
然后重启inetd,就可以通过任意一个机器用浏览器来配置了
输入地址http://samba_server:901/即可
95/98/nt都可以的说,还好这里什么机器都有,嘿嘿,都可以互相
访问的,包括打印,95/98网络登录时要用samba里的用户名哦
&&&&&&& workgroup = IPC
&&&&&&& netbios name = DATASERVER
&&&&&&& server string = Data Server - Linux
&&&&&&& encrypt passwords = Yes
&&&&&&& log file = /var/log/samba/log.%m
&&&&&&& max log size = 50
#这三行设置超时,还没搞清楚,不过这样马马虎虎能工作,一定要设
#否则mount上的设备umount不掉,一直busy的说,:PP
&&&&&&& change notify timeout = 30
&&&&&&& deadtime = 1
&&&&&&& keepalive = 0
&&&&&&& socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
&&&&&&& dns proxy = No
#这三行是umask的设置,看情况设置吧
&&&&&&& create mask = 0755
&&&&&&& force create mode = 0755
&&&&&&& force directory mode = 0755
#用户的home目录,根据用户不同而变化,本来就有的,不是我加的说
&&&&&&& comment = Home Directories
&&&&&&& read only = No
&&&&&&& browseable = No
[printers]
&&&&&&& comment = All Printers
&&&&&&& path = /var/spool/samba
&&&&&&& print ok = Yes
&&&&&&& browseable = No
#我自己加的一个共享目录
&&&&&&& comment = Public Software
&&&&&&& path = /home/ftp/pub
&&&&&&& guest ok = Yes
apache虚拟服务器
多域名单IP的:
1. 首先要解决域名的问题,你可以用nslookup &你的域名&看看该域名是不是指向了你IP, *.yeah.net本来就是做的虚拟主机, 所以解析出来都是指向www.yeah.net (202.96.152.198), 通常情况下, apache启动时会检查你用作虚拟主机的域名。
2. 改httpd.conf, 加&virtualhost& 例如:
&&&&&&& &VirtualHost I007.com&& (写IP也可以)
&&&&&&& ServerAdmin
&&&&&&& DocumentRoot /home/I007/public_html
&&&&&&& ServerName I007.com& (这里只能写域名)
&&&&&&& &/VirtualHost&
1. 最好每个IP还是能对应一个域名
2. 加载ip_alias模块 (/sbin/insmod ip_alias)
3. 加IP& (/sbin/ifconfig eth?:? ???.???.???.???)
4. 改httpd.conf, 和上面差不多
可以看出, 两者可以共存,以上均做过实验, 没有问题..
apache+php3+mysql
*安装apache-devel rpm包.
*安装MySQL相关的包.
&& rpm -ivh MySQL-3.22.25-1.i386.rpm
&& rpm -ivh MySQL-client-3.22.25-1.i386.rpm
&& rpm -ivh MySQL-devel-3.22.25-1.i386.rpm
*下载php3源文件php-3.0.tar.gz
*解开源文件
&& tar xzvf& php-3.0.tar.gz
*进入php-3.0源文件目录
&& ./configure --with-mysql=/usr --with-apxs=/usr/sbin/apxs --with-config-file
-path=/etc/httpd (还有其他选项,可以运行 ./configure --help 看看)
*建一个modules目录
& mkdir modules
*进入regex目录
& 运行 make r (这一步可能不必要)
& 运行 make lib
*退回上一级目录
& 运行 make install
* cp modules/libphp3.so /etc/httpd/modules/
* cp php3.ini-dist /etc/httpd/php3.ini
* 修改/etc/httpd/conf/httpd.conf 加入
&&&&&&& LoadModule php3_module&&&&&&& modules/libphp3.so
&&&&&&& AddModule mod_php3.c
& 修改/etc/httpd/conf/srm.conf 加入
&&&&&&& AddType application/x-http-php3 .php3
*重起apache
&&& /etc/rc.d/init.d/httpd restart
&&& 查看mysqld是否已经运行.如果没有,先运行mysqld
&&& 将php3源文件下tests目录下的mysql文件拷贝到 /home/httpd/html目录下
&&& lynx localhost/mysql.php3
&&& 如果有问题,可以将mysql.php3中的127.0.0.1改为localhost
apache+apacheJserv
=============================================================================
首先使用BJLC光盘上的jdk1.2pre2
具体装过程略
rpm: apache-1.3.9 apache-devel jsdk-2.0
tgz: Apache-Jserv1.1 gnujsp-1.0.0
解开Jserv的src
./configure --enable-EAPI --with-JSDK=/usr/lib/classes/jsdk.jar \
--with-apxs=/usr/sbin/apxs
应该没有问题,很顺利编译通过
再/etc/httpd/conf/httpd.conf
在最后(一定要在最后否则有很多小麻烦)
Include ./jserv/jserv.conf
重新启动apache
http://localhost/servlet/Hello
如果能看到应该就差不多了
试http://localhost/jserv/
一般是403 forbidden
如果是forbidden
jserv.conf
搜索Location
里面有一段allow
改成allow localhost.localdomain
好像就可以了
用localhost或者是127.0.0.1都不行
反正这是我碰到的倒霉事希望大家能一次成功
到这apache-jserv就算是完成了,也就是有了
一个servlet容器并且有了在apache里面的模块
能够同这个容器进行通信,通信协议最好用
apjv12,反正所由地方都设成apjv12就没有问题
否则很可能出现不匹配的情况,最后导致
500错误,在log中显示malformed fata
前面提到servlet容器建好了
Jserv调通了,还有两个很有用的log文件
在我的mdk7里面是
/usr/logs/里面的mod_jserv.log和jserv.log
这两个文件在调试中极有用
它们的权限要求nobody可以写
所以我的做法是
chmod 664 *
chgrp nobody *
大牛是不是这样做,我不知道
可能这样会有安全性问题
前面如果你看到了jserv的状态页点击apjv12://localhost:8007
应该能够看到各个zone的配置
如果看不到应该收到所谓selfservlet一个选项
没有打开的提示,打开就好了好像是在jserv.properties里面
接下来是搞gnujsp
解开了会发现jsp是完全用java写成的例程
主要是两个gnujsp-...jar和servlet-...jar
反正我用的是gnujsp10和servlet-2.0-plus
拷到/usr/servlet/jsp(这是随便给的)
编写gjsp.properties文件
servlet.gnujsp.class=org.gjt.jsp.JspServlet
servlet.gnijsp.initArgs=checkclass=true,\ //这样编译好的jspservlet可以利用
pagebase=/home/httpd/html,\
scratchdir=/usr/servlets/jsp/scratch,\ //这里要有文章
debug=true,\ //先打开,调好了再关掉
compiler=builtin-javac -classpath \ //这里builtin-javac需要jdk1.2的tools.jar
%classpath%:%scratchdir%:/usr/servlets/jsp/gnujsp.jar:\
/usr/servlets/jsp/servlet.jar:/usr/servlets/jsp/beans \ //指定编译用的classpath
-d %scratchdir% -deprication %source% //就是编译一个普通的java文件一样
首先要注意你选择的scratchdir一定要nobody可写,其次使用builtin的javac
需要在jserv.properties加上
wrapper.class...=/usr/jdk1.2/lib/tools.jar (这是我安装的路径)
到这里jsp的zone就差不多了
现在开始在jserv.properties里面指明zones
很简单不废话了
最后是在jserv.conf里面作mount,照着例子写
也不难,前面有人贴过了
最后就可以试试自己的jsp了
首先先从http://localhost/jserv/
里面看一看jsp的zone配制出来没有
验证一下参数都正确
====================================================================================================
1.先确认apachejserv已能正常工作
2.把gnujsp10.jar,servlet-2.0-plus.jar拷到/home/httpd/sevlets目录下
3.修改jserv.conf,加入
ApJServAction .jsp /servlets/org.gjt.jsp.JspServlet
ApjServMount /java /root(这个目录主要是用来存放jsp生成的java
和class文件,可视具体情况而定)
4.修改jserv.properties,加入
wrapper.classpath=/usr/jdk/lib/tools.jar
wrapper.classpath=/home/httpd/servlets/gnujsp10.jar
wrapper.classpath=/home/httpd/servlets/servlet-2.0-plus.jar
5.修改zone.properties,加入
repositories=/home/httpd/java/
servlet.gnujsp.code=org.gjt.jsp.JspServlet
servlet.org.gjt.jsp.JspServlet.initArgs=checkclass=true
servlet.org.gjt.jsp.JspServlet.initArgs=scratchdir=/home/httpd/java
servlet.org.gjt.jsp.JspServlet.initArgs=compiler=builtin-javac -encoding %enco
ding% -classpath %classpath% -d %scratchdir% -deprecation %source%
apache+tomcat
&&& 编译得到mod_jserv.so和ApacheJServ.jar
&&& 在tomcat3.0的etc子目录里面有tomcat.conf,在httpd.conf里面Include一下
启动tomcat(./tomcat.sh start)然后启动httpd,看看成功了没有。
&&& 如果不行,我碰到的一个问题是log file有问题,直接指定成下面的样子
&&&&&&& ApJServLogFile /var/log/httpd/mod_jserv.log
&&& 最后实验http://localhost:8080/一下确信tomcat跑了。然后实验http://localhost:8080/examples/jsp和http://localhost/examples/jsp
java环境(中文)
&&& 好象有许多人都碰到了这个问题, 我以前也碰到过, 在网上找了一些解决方法看了看, 在自己的机器上试了试, 都没有解决问题, 趁着这几天把 Debian的中文问题搞好了, 顺便把这个也弄一弄, 终于搞明白了一些东西. 错误之处还请大家指教. 这里主要指的是 Swing 中显示的中文, 关于其他中文操作问题,暂不作讨论.
&&& 其实说起来 Java 的中文问题非常简单, 有两个重要因素, 一个是编译时的编码(encoding), 另一个是字体. 这两个缺一不可.
一, 编译时的编码:
&&& 指的是编译 Java 的源程序时指定的编码格式, 即使用
&&&&&&&&&&& javac -encoding MyEncoding MyJavaFile.java
&&& 编译 MyJavaFile 时 -encoding 所指定的 MyEncoding. 通常中文的编码有大陆和新加坡使用的 GB2312 以及 台湾和香港使用的 Big5, 普通英文用的是ISO_8859_1. 这里只关注 GB2312. 如果在编译的命令行中指定了编码, 那么就使用指定的编码格式, 如果没有指定, 将使用系统缺省的编码格式, 在 windows的中文简体版下都是 GB2312, 而 Linux 下不同的终端可以有不同的编码, 可以直接设置环境变量 LC_ALL LANG 等指定相应的不同类型信息的编码, 比如数字,日期, 货币, 姓名等等. 可以用 locale 命令来看当前终端所有的编码. 在Java 程序中可以使用 System.getProperty(&file.encoding&); (注 1) 来获取当前的编码格式. 好了, 当编译的时候, 源码中的中文字符串都会按照指定的或者缺省的编码格式映射为相应的 UNICODE , 而不是看做简单的 ASCII 字符.所以编码格式就是处理源码中的各种各样的字符, 与运行时无关, 所以如果你的源文件中没有直接需要使用中文的地方, 比如菜单, 按钮, 标签什么的, 就不需要指定编码了.
二, 字体的选择:
&&& 必须使用能够显示中文的字体, 好象有些废话. 但还是有必要说一说. AWT 可以在中文系统中直接显示中文, 但是在不是中文系统但是有中文字体的系统中不能, 需要修改一下 $JAVA_HOME/jre/lib/font.properties,加入中文字体, 至于怎么加入, 就不谈了. 而 Swing 不需要这样, 只要你的系统中有中文字体就可以使用这样的字体来显示中文. 怎么知道一种字体能不能显示中文呢? 看下面的程序片段: (注 2)
&&&&&&& Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFFonts();
&&&&&&& System.out.println(&Chinese Fonts: \n&);
&&&&&&& for (int i = 0; i & fonts. i ++)
&&&&&&&&&&& if (fonts[i].canDisplayUpTo(&\u4e00&) & 0)&& // 注 3
&&&&&&&&&&& {
&&&&&&&&&&&&&&& System.out.println(fonts[i].getFontName());
&&&&&&&&&&& }
&&& 好了, 知道了系统中有没有中文字体, 然后选择一个就是了. 如果选择了不能显示中文的字体, 通常的情况是显示方框.
&&& 好了, Swing 的中文显示介绍完了, 输入和编辑中文就和显示差不多, 选一个字体就可以了, 具体得看你而 Linux 的具体设置了, 这里就不多说了.
&&& 从以上两点来看, 其实最重要的还是字体的选择. 我的网站上有 ScreenShot和测试程序, 欢迎来访问. http://SuperMMX.dhs.org
注 1: 据 jdk1.2.2 的文档, 并没有这个属性, 很奇怪, 但是确实可用.
注 2: jdk 1.2 以上自带的字体支持 Unicode, 但是不支持 Unicode 汉字. 所以打出来的结果包含了 jdk 自带的字体.
注 3: UNICODE 中, UNICODE 汉字从 \u3400 到 \u9FFF 中间, \uF900 到 \uFAFF也有一些, 但是 GB2312 和 Big5 的汉字和字符都是在 \u4E00 到 \u9FFF中间.
jdk tools doc
一篇没有作者名字, 也没有出处的英文文章.
&&& 主要的问题是如何配置sendmail.cf.
&&& 如果你用的是redhat,执行:
cd /usr/lib/sendmail-cf/cf
m4 redhat.mc & sendmail.cf
cp sendmail.cf /etc/sendmail.cf
sendmail -bd(或者reboot)
&&& 上面的方法配置之后服务器发信没问题,而远端机器却不能发信,是因为缺省redhat.mc生成的sendmail.cf禁止了客户服务,
这样:找到下面一行(sendmail.cf):
R$*&&&&&&&&& $#error $@ 5.7.1 $: &550 relay denied&
R$-&&&&&&&&& $@ ok
&&& 就行了,不过当心有人用你的系统发垃圾邮件
sendmail扮演的角色
1. sendmail扮演的角色
  sendmail程序扮演着多种不同的角色,最主要的角色就是传递电子邮件。它监听来自网络的电子邮件,传送电子邮件到另一台机器,通过本地传送,将本地信件传给本地程序。它能够在邮件中附加上文件,也能够使用管道将邮件发给其它程序。它能够维护一个邮件队列,有序地将邮件发送出去,还可以理解接收者的邮件别名,将其发送到真正的目标用户当中去。
1.1在文件系统中的角色
  sendmail程序的角色(位置)在本地文件系统中,就象一个倒置的树,如图3-1。当sendmail运行时,首先读取/etc/sendmail.cf配置文件。在这个配置文件中,能够指出sendmail所需要的其它文件与目录的位置。
  图3-1 sendmail.cf的层次结构
  安全起见,在配置文件/etc/sendmail.cf中指定的文件、目录名一般都使用绝对路径,例如:使用/var/spool/mqueue,而不使用mqueue。在我们讲解这些文件之前,首先运行如下命令以收集一个文件列表:
% grep = /& /etc/sendmail.cf
  注:如果你使用的是V8.7以上版本的sendmail,则你需要查找的应该改为”/[^0-9].*/”.
  这个命令将会出现类似如下的结果:
O AliasFile=/etc/aliases
#O ErrorHeader=/etc/sendmail.oE
O HelpFile=/usr/lib/sendmail.hf
O QueueDirectory=/var/spool/mqueue
O StatusFile=/etc/sendmail.st
#O UserDatabaseSpec=/etc/userdb
#O ServiceSwitchFile=/etc/service.switch
#O HostsFile=/etc/hosts
#O SafeFileEnvironment=/arch
Mlocal,P=/bin/mail, F=lsDFMAw5:/|@rmn, S=10/30, R=20/40,
Mprog,& P=/bin/sh, F=lsDFMoeu, S=10/30, R=20/40, D=$z:/,
  请注意,有些行是以字母O开始,有些行是以字母M开始,有些行是以#开始的。以字母O开始的行是配置选项。字母O后面紧跟着选项的名字。选项的值指出了sendmail使用的文件。例如,AliasFile定义了本地的aliases数据库文件。以M开始的行则定义了分发代理。以#开始的行就是注释。
  首先我们考察以O开始的选项行。然后再分析以M开始的分发代理选项。
1.1.1 aliases文件
  aliasing就是将接收者的名字转换另一个名字。一种情况下是将一些通用名字(如root、webmaster)转换成真正的用户名。另一种情况下是将一个名字转换成多个名字的列表(如使用邮件列表)。
  Aliases文件在sendmail.cf文件中的AliasFile选项中指定,例如:
O AliasFile=/etc/aliases
  以下是一个aliases文件的简要实例:
# Mandatory aliases.
postmaster: root
MAILER-DAEMON: postmaster
# The five forms of aliases
& John_Adams:& adamj
& xpres: ford,carter,bush
& oldlist: :include: /usr/local/oldguys
& nobody: /dev/null
ftphelp:& |/usr/local/bin/sendhelp
  你的aliases文件可能更长、更复杂的,不过,以上这个示例也显示了aliases所有可能的构成。
  以#开始的行,是注释行。空行被忽略不计。第一行就是一个注释行,它指出了2、3两行是每一个aliases文件被必须强制拥有的。所有的别名格式都是一样的,一个名字(别名)和一个要改为成的名字(原名)。别名在“:”号的左边,原名在“:”号的右边。名字是不区分大小写。例如:POSTMASTER,Postmaster以及postmaster都是相同的。
  如果信封上列出的接收者名字是本地用户的话,sendmail程序就会查找aliases文件。如果sendmail发现接收者名字如果与aliases文件中的“:”号左边的名字相匹配,就将接收者名字替换为“:”号右边的名字。例如:发给本地的postmaster的信,会被转变成为发给root的信。
  在一个名字被替换后,会使用这个被替换后的名字继续查找,直到没有匹配的名字为止。如MAILER-DAEMON首先被转变为postmatser,然后postmaster又被改被为root。由于没有一个以root开始的别名项,所以转换过程到此结束,信件最后被传送到root的信箱中去。
  任何一个aliases文件必须有一个将postmaster转变成实际用户的别名项。因为当邮件出现问题时,总是会生成一个错误报告的信,发给postmaster。所以最好将这样的信发给邮件的系统管理员。
  当电子邮件被退回时,将会发给MAILER-DAEMON。所以这个别名是必须的。没有这个设置的话,退回的信将会在发件人与收件人之间不断来回传送。
  Aliases文件中有五种类型:
John_Adams:& adamj
xpres: ford,carter,reagan,bush
oldlist: :include: /usr/local/oldguys
nobody: /dev/null
ftphelp: |/usr/local/bin/sendhelp
  首先我们看一下第一行,这一行的格式与我们前面的例子相似,这一句让sendmail程序将发给John_Adams的信都给真实用户adamj。
  xpres那一行则象大家演示了如何将一个名字扩展到一组名字,发给xpres的信件将扩展为ford、carter、reagan、bush,并使用这些名字进行aliases处理,直到无匹配为止。然后将信件的副本分发给每一个。
  而oldlist这行,则象大家演示了如何从一个文件中读取一组名字,本例中就是让sendmail将发给oldlist的信息扩展为在/usr/local/oldguys文件里的用户列表。请记住它的格式,在文件绝对路径名前需加上“:include:”。
  nobody这一行,象大家演示了如何用文件名代替别名。发到这个邮件中的内容将添加到所指定的文件后面去。这里指定的是/dev/null。这样就是指发到nobody的信件将会被简单地丢弃。
  最后一行,ftphelp那一行象大家演示了如何用程序名代替别名。字符“|”使sendmail将这个邮件信息通过管道发给所指定的程序。
  aliases文件可能变得非常复杂。它能够用于解决许多特殊的问题。aliases文件的更多的内容将在第24章:别名中详述。
1.1.2 邮件队列目录
  在很多情况下,都可能使一个电子邮件临时无法发送,例如:远程主机已经down了,或临时出现了磁盘错误。为了确保邮件最终能够发送成功,sendmail将会把它们存到邮件队列目录中,直到发送成功为止。
  配置文件中的选项QueueDirectory用于指定sendmail的邮件队列目录:
O& QueueDirectory=/var/spool/mqueue
  这里指出的目录名必须是全路径名。
  如果你用足够的权限,看一看队列目录。如果没有邮件等待发送的话,它们可能是空的。如果它们不是空的,那么可能包括形如以下的文件:
dfQAA07038&& dfMAA08000&& qfQAA07038&& qfMAA08000
  当一个邮件信息进入了邮件队列,将分成两个部分,每一个部分都保存在一个文件中。头信息存在一个文件名是以qf开头的文件中。邮件内容部分则存在一个文件名是以df开头的文件中。
  上例中,有两个邮件在邮件队列中。其中一个被标识为QAA07038,而另一个被标识为MAA08000。
  队列文件的格式与处理方法,我们将在第23章:邮件队列中详细说明。
1.2本地分发的角色
  sendmail的另外一个角色则是分发电子邮件信息给本地用户。一个本地用户在本地系统上有一个邮箱。分发本地邮件,就是将其附加到这个用户的邮箱中。
  通常,sendmail不是直接将邮件信息直接放到文件中去。在上一节中,我们看到,只有指定sendmail程序将邮件附加到一个文件中时,才这样做的。但这是一个例外,不是规则,sendmail调用其他程序执行分发。被调用的程序叫做分发代理。
  在你的sendmail.cf文件中,有两行用来定义本地分发代理,其中一个用于在本地系统中分发邮件:
Mlocal,P=/bin/mail, F=lsDFMAw5:/|@rm, s=10, R=20/40,
Mprog,P=/bin/sh, F=lsDFMeu, S=10, R=20/40, D=$z:/,
  程序/bin/mail用来将邮件附加到用户的邮箱中。程序/bin/sh用来运行其它程序来处理分发。
1.2.1 分发到邮箱
  配置文件中,以Mlocal开始的行定义了邮件如何附加到用户的邮箱文件中去。通常是使用/bin/mail程序,也可以使用deliver或mail.local程序。
  在UNIX系统中,用户的邮箱是一个单独文件,其中个邮件信息。通常UNIX系统约定(但不是唯一的可能)每一个在邮箱文件中邮件信息以一个五字节长的“From ”(4个字母、一个空格)开始,并以一个空行结束。
  Sendmail程序并不知道也不关心用户的邮箱文件是什么样的。而只关心将邮件添加到邮箱文件中的程序名称。例如:/bin/mail。以M开头的配置行定义了分发代理,详细的介绍可以参看第6章:Mail中枢和分发代理,以及第30章:分发代理。
1.2.2 借助程序分发
  在1.1小节中的aliases文件示例中的ftphelp行,是以字符“|”开始的程序名作为Mail的目的地:
ftphelp:& |/usr/local/bin/sendhelp
  在此情况下,发送到ftphelp中的mail,经过别名转换到|/usr/local/bin/sendhelp中。以字符“|”开始的目的地地址告诉sendmail启动这个程序,而非添加到一个文件中去。这主要是实现使用一个邮件程序对接收的邮件作一些有用的处理。
  Sendmail程序不直接运行邮件的分发程序。而是运行一个shell,并告诉shell运行这个程序。这个shell的名字在配置文件中以Mprog开始的行中定义:
Mprog,P=/bin/sh, F=lsDFMeu, S=10, R=20/40, D=$z:/,
  在这个例子是,指定的shell是/bin/sh。也可以使用/bin/ksh或smrsb。
1.3网络传输角色
  sendmail还有一个角色就是负责将邮件传送到另一台机器。当sendmail确定接收者不在本地系统中时,邮件将传送出去。下列是典型的配置文件中定义负责将邮件传送到其它机器的分发代理:
MsmtpP=[IPC], F=mDFMuX, S=11/31, R=21, E=
MuucpP=/usr/bin/uux, F=DFMhuUd, S=12, R=22/42, M=,
  而在实际的配置文件中可能会有一些不同。上面例子中,smtp可以写为ether或ddn或其它的一些东西。而uucp可以写为suucp或uucp-dom。一个重要的知识点就是有一些分发代理处理本地分发,另外一些处理跨越网络的分发。
1.1.1 TCP/IP
  sendmail程序内在拥有在同一种网络中传输邮件的能力,那就是使用TCP/IP;下列的行就是用来指示sendmail去处理:
MsmtpP=[IPC], F=mDFMux, S=11/31, R=21, E=
  其中[IPC]可以写作[TCP],它们是完全等价的。
  当sendmail程序在TCP/IP网络中传输mail时,首先发送“信封”上的发信人主机名到另一个站点。如果这个站点认可这个发信人的主机名是合法的,本地的sendmail程序将发送“信封”上的收信人列表。这个站点针对每一个收件人确定接受或拒绝。如果一些收件人被接受,则本地的sendmail程序发送出邮件信息(信头和信体)。
1.1.2 UUCP
  在配置文件中设置sendmail如何通过UUCP传输邮件的行如下所示:
MuucpP=/usr/bin/uux, F=DFMhuUd, S=12, R=22/42, M=,
  这行告诉sendmail程序使用/bin/uux来通过UUCP网络传输邮件。
1.1.3 其它协议
  sendmail程序还可通过其它网络协议传输mail。你可以从我们前面做过grep操作的输出结果中发现它们,它们看上去象:
Mfax,& P=/usr/local/lib/fax/mailfax, F=DFMhu, S=14, R=24, M=100000,
Mmail11, P=/usr/etc/maill11, F=nsFx, S=15, R=25, A=mail11 $g $x $h $u
Mmac,P=/usr/bin/macmail, F=CDFMmpsu, R=16, S=16, A=macmail Ct $u
  Mfax行定义了使用sendmail发送FAX的途径。FAX通过电话线传输文件的图形影象。在这个配置中,程序/usr/lib/fax/mailfax,将一个邮件文件的图形影象FAX出去。
  Mmail11行定义了使用mail11程序在DEC网络上传输邮件,一般应用于DEC系统。
  Mmac行定义了在Macintosh电脑系统的AppleTalk网络上传输邮件。
  在所有的这些例子中,sendmail通过专用的服务程序在网络上发送电子邮件。记住,sendmail本身只能直接在基于TCP/IP的网络上工作。
1.4 Daemon角色
  就象sendmail能够在基于TCP/IP的网络上传输电子邮件一样,它也能够接收来自于网络的电子邮件。为了实现这个,就必须运行在daemon(守候进程)模式。Daemon是一个运行在后台,不受终端约束的程序。
  作为一个daemon,sendmail通常在系统启动时就运行。当一个电子邮件发送到你的机器时,远程机器将与运行在你机器上的sendmail daemon“商谈”。
  想观察你的系统如何将sendmail运行在daemon模式下,你可执行以下任何一条命令:
% grep sendmail& /etc/rc* (BSD系统)
% grep sendmail& /etc/init.d/*& (SysV系统)
% grep sendmail& /etc/*rc (HP-UX系统)
  一个典型的输出是:
/etc/rc.local:if& [-f /usr/lib/sendmail Ca Cf /etc/sendmail.cf]; then
/etc/rc.local: /usr/lib/sendmail Cbd Cq1h; echo Cn& ‘ sendmail’
  上面的第二行是sendmail在系统启动时运行的命令。
/usr/lib/sendmail Cbd Cq1h
  命令选项-bd是使sendmail运行在daemon模式下。命令选项-q1h是让sendmail每小时唤醒一次,处理队列。
如何运行sendmail
2.如何运行sendmail
  一种运行sendmail的方法是,直接在命令行上附加接收者参数。例如:下面命令就是发一个邮件消息给george。
% /usr/lib/sendmail george
  你也可以同时给出多个接收者。例如,发一个邮件给george,truman和teddy:
% /usr/lib/sendmail george,truman,teddy
  sendmail程序可以接受两种不同的命令行参数。不以“-”字符开始的参数是接收者,如上面的george。而以“-”字符开始的参数则是影响sendmail运行的开发选项。所有的命令行开关选项的解释,
  标记&& 说明
&&& -b&& 设置运行模式
&&& -v&& 运行于冗长模式
&&& -d&& 运行于调试模式
2.1适宜的模式(-b)
  sendmail程序的“-b”参数可以衍生出许多功能。例如:使sendmail显示队列的内容,使sendmail重建别名数据库。本章将介绍一些比较常用到的子参数。
  格式&& 说明
&&& -ba&& 使用ARPAnet(灰皮书书)协议
&&& -bD&& 以守候进程模式运行,但不fork
&&& -bd&& 以守候进程模式运行
&&& -bH&& 清除固有的主机状态
&&& -bh&& 打印固有的主机状态
&&& -bi&& 重建别名数据库
&&& -bm&& 成为一个邮件发送者
&&& -bp&& 打印邮件队列内容
&&& -bs&& 在标准输入处运行SMTP
&&& -bt&& 测试模式:仅解析地址
&&& -bv&& 检验:不收集、分发
&&& -bz&& 冻结配置文件
  选项可以使sendmail执行时象其它名字。每个名字可以是一个硬连接,一个符号连接,或sendmail的一份拷贝。
hoststat -bh 打印固有主机状态
mailq -bp 显示邮件队列内容
newaliases -bi 重建别名数据库
purgestat -bH 清除固有主机状态
smtpd -bd 以守侯进程运行
2.1.1 守候进程模式 (-bd)
  sendmail程序能够在后台以守侯进程模式运行,监听来自其它机器的邮件。Sendmail当第一次以守侯进程模式运行时,程序只读取配置文件一次,然后就一直运行,不再读取配置文件了。也就是说,执行后将不会发现配置文件的变化。
  当你对配置文件sendmail.cf做了任何修改,都需要kill掉sendmail进程,然后重新启动它。但当你kill掉这个守候进程前,必须知道如何正确地重新启动它。这些信息是/etc/sendmail/pid或一个系统rc文件。
  在BSD系列的UNIX系统,守候进程通常使用以下命令启动:
/usr/lib/sendmail Cbd Cq1h
  命令行开关选项“-bd”指定sendmail以守候进程方式运行。“-q”选项告诉sendmail多久去查看一次待处理邮件队列。“-q1h”就是将其设置为1小时。
  在你的机器上启动sendmail的命令,可能与我们这儿给出的是不同的。如果你管理许多不同的UNIX系统,你无须知道每一种是如何运行的。
2.1.1.1 kill并重启sendmail v8.7
  在sendmail 8.7以后的版本中,kill并重启sendmail变得比较简单。一个单一的命令将会完成这一工作:
% kill CHUP `head C1 /etc/sendmail.pid`
  这个单一的命令与下一个小节中的两个命令的效果完全相同。
2.1.1.2 kill并重启sendmail v8.6
  当你要以守候进程方式启动sendmail,你须确认没有一个已运行的sendmail守候进程。在8.6版sendmail中,可以在/etc/sendmail.pid文件的第一行中找到进程ID号pid。你可以执行以下命令来kill掉sendmail:
% kill `head C1 /etc/sendmail.pid`
  当你kill掉当前运行的守候进程,你可以使用以下命令来重新运行sendmail:
% `tail C1 /etc/sendmail.pid`
2.1.1.3 kill并重启老版本sendmail
  在老版本的sendmail中,你必须使用ps来获得sendmail的进程ID号pid。在BSD UNIX和System V UNIX使用ps的方法不尽相同。
  针对BSD UNIX来说,ps命令的将得到类似以下的输出:
% ps ax | grep sendmail | grep Cv grep
&& 99& ?& IN& 0:07& /usr/lib/sendmail -bd Cq1h
% kill 99
  这个输出的最左边的就是进程ID号。
  针对System V UNIX系统来说,ps命令的参数及命令输出都不尽相同:
% ps ae | grep sendmail
&& 99& ?0:01 sendmail
% kill 99
  在老版本的sendmail中,你必须通过查看rc文件来获知如何重启sendmail。
2.1.1.4 如果你忘记了kill守候进程
  如果你在重启sendmail时,忘了kill掉原来的进程的话,你就会看到类似以下列出的错误消息,每5秒显示一次。
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Getrequests: cannot bind: Addredd already in use
Opendaemonsocket: Server SMTP socket wedged:exiting
2.1.2 显示邮件队列模式 (-bp)
  sendmail程序能够显示邮件队列的内容。可以通过两种方法实现:一种是运行mailq,另一种是运行带开关选项“-bp”的sendmail。无论你使用哪种方法,邮件队列将会显示出来。如果这个队列是空的,sendmail将打印出:
Mail queue is empty
  如果有一个邮件正在等待队列中,那么将输出更多的消息,其中包含类似于下列的信息:
)&& Mail Queue (1 requests)
--Q-ID---&& --Size--&& ----Q-Time
-------------------Sender/Recipient-------------------
GAA29775*&& 702&& Thu Mar 12 16:51&you@here.us.edu&
&& Deferred:Host fbi.dc.gov is down
& &george@fbi.dc.gov&
  在此,带开关选项“-bp”的sendmail显示了仅有一个邮件信息在队列中。如果有多个,那么每一个邮件都会像这样列出来。每一个至少有两行输出。
  第一行显示邮件和发送者的细节信息。GAA29775是这个邮件在队列中的标记。“*”号则代表由于这个邮件正在被处理,所以已被锁定。“702”是邮件体的字节数。这里的时间则是邮件被放入队列的时间。地址则显示了发送者的名字。
  第二行则可能显示出错的原因,这个邮件就是因为暂时无法分发,所以才暂存在队列中的。
  第三行则可能显示接收者地址。
  如果你想更完整、清楚地了解这里的输出,参见第23章:队列。
2.1.3 重建别名库模式 (-bi)
  由于sendmail有可能需要在存放上千条别名记录的aliases文件中寻找别名,为了提高效率,可以使用dbm或db格式来存储。使用这种数据库格式来存储将大大提高检索速度。
  尽管sendmail可以在aliases文件改变时自动更新数据库,但它并不总能及时完成。你可以通过运行newaliases命令或带“-bi”开关选项的sendmail来完成,以下这两个命令是相同的:
% newaliases
% /usr/lib/sendmail -bi
  稍过一会儿,将显示出统计信息:
/etc/aliases: 859 aliases, longest 615 bytes, 28096 bytes total
  这一行表示数据库已成功重建。从8.6版以后,就可以存在多个别名文件,所以每一行都是以别名文件名开始的。然后是显示处理了的别名,最大的一项的长度,总长度, 同时有多少个出错也会显示出来。
  关于aliases文件更详细的信息,参见第24章:别名。
2.1.4 校验模式 (-bv)
  带开关选项“-bv”的sendmail是一个简单方便的检查别名的工具。它能够在别名中递归地查找,并显示出最终的用户名称。
  假设aliases文件中有如下别名设置:
animals:& farmanimals, wildanimals
bill-eats:& redmeat
birds:& farmbirds, wildbirds
bob-eats:& seafood,whitemeat
farmanimals:& pig, cow
farmbirds:& chicken, turkey
fish:& cod, tuna
redmeat:& animals
seafood:& fish,shellfish
shellfish:& crab, lobster
ted-eats:& bob-eats, bill-eats
whitemeat:& birds
wildanimals:& deer, boar
wildbirds:& quail
  虽然你也可以通过演算得知ted-eats最终的用户名称,但远不如使用sendmail来帮你完成那样方便。使用sendmail也将更加准确,而且对于很大很复杂的aliases文件来说,更加显得重要。
  另外,sendmail Cbv还有一个附加的功能,那就是可以检验别名是否真的可分发。假设在aliases文件中包含以下一行:
root:& fred, larry
  假定fred是一个拥有本地机器帐户的系统管理员,但用户larry已经离开,帐号已经被删除。你可以运行sendmail Cbv检查所有的用户是否有效:
% /usr/lib/sendmail Cbv root
  这个命令将在aliases文件检查root用户,由于larry不存在,输出将会如下所示:
larry … User unknow
fred … deliverable: mailer local, user fred
2.2冗长模式(-v)
  命令行开关选项“-v”,将使sendmail运行在冗长(verbose)模式下。在这个模式下,sendmail将会打印出转发邮件的每一步的详细说明。为了观察运行在冗长模式下sendmail的运行情况,可以执行:
% /usr/lib/sendmail Cv you & sendstuff
  邮件传送在本地进行,输出如下所示:
you …& Connecting to loca…
you …& Sent
  当sendmail通过TCP/IP网络传送邮件到其它机器,它将使用一个叫SMTP(简单邮件传输协议)。为了观察使用SMTP的情况,我们再次运行sendmail程序,但这次,我们使用一个不在本地的E-mail地址代替“you”:
% /usr/lib/sendmail Cv you@remote.domain & sendstuff
  这个命令的输出看起来类似:
you@remote.domain … Connecting to remote.domain via smtp …
220-remote.Domain Sendmail 8.6.12/8.5 ready at
Fri, 13 Dec :12 C0800
220 ESMTP spoken here
&&& EHLO here.us.edu
250-remote.domain Hello here.us.edu,pleased to meet you
&&& MAIL From:&you@here.us.edu&
250 &you@here.us.edu& … Sender ok
&&& RCPT To:&you@remote.domain&
250 &you@remote.domain& … Recipient ok
354 Enter mail, end with “.” on a line by itself
250 GAA20115 Message accepted for delivery
you@remote.domain … Sent (GAA20115 Message accepted for delivery)
Closing connection to remote.domain
221 remote.domain closing connection
  以数字开头的行和以字符串“&&&”开头的行组成了SMTP的会话过程。我们马上说谈论一下它们。其它行显示本地sendmail尝试做的操作和成功完成的操作:
you@remote.domain … Connecting to remote.domain via smtp …
you@remote.domain … Sent (GAA20115 Message accepted for delivery)
Closing connection to remote.domain
  第一行显示使用网络发送信件到远程主机remote.domain上。最后两行显示邮件已经发送成功。
  在SMTP会话中,以“&&&”开始的行显示本地机器对远程机器的交谈。而来自远程机器的应答行则以数字开始的行。现在我们来看一下会话过程。
220-remote.Domain Sendmail 8.6.12/8.5 ready at
Fri, 13 Dec :12 C0800
220 ESMTP spoken here
  一旦sendmail与远程机器连接上后,sendmail就等待远程机器初始化会话。远程机器说它准备好发送,详细的主机名。如果远程主机也运行了sendmail,也将说sendmail的名字与版本。还有就是日期与时间。
  第二行也以220开始,“ESMTP spoken here”的含义是远程站点能够使用扩展的SMTP协议。如果远程机器跑的sendmail是8.7或以上版本,ESMTP将可能会出现在第一行。
  如果sendmail等待接收这个初始化信息太久,就会打印“Connection timed out”信息,并将这个邮件放入邮件队列中。
  接着,本地sendmail发送EHLO(以&&&开始),传送扩展的HELLO信息,和本地主机名:
&&& EHLO here.us.edu
250-remote.domain Hello here.us.edu,pleased to meet you
  在EHLO中的E说明本地sendmail也是使用ESMTP的。远程主机以250开始的回执ESMTP支持的服务列表。
  如果本地机器发送EHLO消息时,传送的是短主机名(如here)就可能会遇到一个问题。远程主机无法得知这个短主机名的位置,因为它不在远程主机的域remote.domain中。这也就是为什么sendmail一直使用完整的主机名来表示。一个完整的主机名是由主机名加上一个点,然后再加上DNS域名项。
  如果到现在为止,一切正常的话,本地机器将说明邮件的发件人:
&&& MAIL From:&you@here.us.edu&
250 &you@here.us.edu& … Sender ok
  在此,发件人的地址是远程机器认可的。
  下一步,本地机器将说明收件人的名字:
&&& RCPT To:&you@remote.domain&
250 &you@remote.domain& … Recipient ok
  如果远程主机上并无用户you的话,远程主机将返回“User unknown”错误,在此,收件人OK。注意这里的OK不一定能确保地址是完好的。只是确认了这个地址是可接受的。
  当信封信息发送完成后,sendmail程序将试图发送信件信息(包括信头和信体)。
354 Enter mail, end with “.” on a line by itself
  DATA告诉远程主机准备好了。当远程主机指示发送信息时,本地主机照做。最后的一个点用来标记一个邮件结束。这是SMTP的规定。因为邮件消息可能包含多行,而用一个小点开始也是合法,所以sendmail将会把这些小点转换成两个再发送出去。例如,假定当我们要发送以下文件时:
My results matched yours at first:
But then the numbers suddenly jumped high, looking like
Noise saturated the line.
为了防止以小点开始的行照成疑义,sendmail将会在以小点开始的行,插入一个附加的小点,所以实际传输的内容如下所示:
My results matched yours at first:
But then the numbers suddenly jumped high, looking like
Noise saturated the line.
  而另一方收到邮件后,再将这个附加的小点去掉,还原成原来的邮件内容。
  远程主机上的sendmail将显示队列管理附于的标识:
250 GAA20115 Message accepted for delivery
221 remote.domain closing connection
  本地主机上的sendmail发送QUIT,说明全部工作完成。远程主机返回应答信息确认。
  注意,-v参数在发送信息到远程主机上时十分有用。它能够显示出SMTP会话过程,以帮助我们了解邮件转发的过程,也有利于我们排错。
2.3调试模式(-d)
  sendmail程序也能产生并输出调试信息。要使用调试模式运行sendmail的话,就需要使用-d参数。这个参数将产生比-v参数更多、更详细的信息。输入以下命令行,用自己的帐户名代替you:
% /usr/lib/sendmail Cd& you& & /dev/null
  这个命令行产生很冗长的处理信息。我们在此不打算说明这些输出信息,在此,只需记住在sendmail程序在调试模式下运行会产生大量的信息。
  同时,也会产生大量的调试信息,你可以修改、显示这些调试信息。你可以在-d参数后加上一个数字,输出将会限制在只输出指定类的调试信息。
  输入以下命令用自己的帐户名代替you:
% /usr/lib/sendmail Cd40& you& & /dev/null
  在此,-d40是调试第40类的信息。这类的信息是关于邮件队列的。以下是一个输出实例:
&&&&& queueing GAA14008 (new id) queueall=1 &&&&&
queueing 95688=you:
mailer 4 (local), host ‘’
user ‘you’, ruser ‘&null&’
next=0, alias 95460, uid 0, gid 0
flags=6008&QPRIMARY,QPINGONFAILURE,QPINGONDELAY&
owner=(none), home=”/home/you”, fullname=”Your FullName”
orcpt=”(none)”, statmta=(none), rstatus=(none)
&&&&& done queueing GAA14008 &&&&&
  对于一个类,还可以指定一个级别,这个级别是用来调整输出的量。一个低级别将产生较少的输出,一个高级别将产生更多、更复杂的输出。它们的格式是在-d参数之后加上:
category.level
  例如:
% /usr/lib/sendmail Cd0.1 -bp
  参数-d0指示sendmail产生通用的调试信息。而级别1则让sendmail的输出减少到最小限度。这个值可以省略,因为.1是缺省值。参数-bp让sendmail打印出邮件队列内容。输出看起来如下所示:
Version 8.8.4
Compiled with:LOG& NAMED_BIND& NDBM& NETINET& NETUNIX& NIS& SCANF
= = = = = = = = = = = SYSTEM IDENTITY (after readcf) = = = = = = = = = = =
(short domain name) $w = here
(canonical domain name) $j =here.us.edu
(subdomain name) $m =us.edu
(node name) $k = here
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Mail queue is empty
  在此,开关选项“-d0.1”让sendmail打印出版本号、一些关于编译的信息,以及你的主机名。现在你提高级别看一下:
% /usr/lib/sendmail Cd0.11 -bp
  这时将显示如下信息:
Version 8.8.4
Compiled with:LOG& NAMED_BIND& NDBM& NETINET& NETUNIX& NIS& SCANF
OS Defines: HASFLOCK& HASGETUSERSHELL& HASINITGROUPS& HASLSTAT
HASSETREUID& HASSETSID& HASSETVBUF& HASUNAME& IDENTPROTO
& IP_SRCROUTE
Config file: /etc/sendmail.cf
Pid file: /etc/sendmail.pid
Canonical name: here.us.edu
UUCP nodename: here
a.k.a.: [123.45.67.89]
= = = = = = = = = = = SYSTEM IDENTITY (after readcf) = = = = = = = = = = =
(short domain name) $w = here
(canonical domain name) $j =here.us.edu
(subdomain name) $m =us.edu
(node name) $k = here
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Mail queue is empty
sendmail.cf
3. sendmail.cf文件
  在sendmail的配置文件sendmail.cf中的文本,有的形如MODEM的噪声,有的形如Dithers的咒语一样:
R$+@$=w&&&&&& ?& sendmail.cf文件
{$/{{.+&&&&&&&&& ?& modem的噪声
!@#!@@!&& ?& Dithers的咒语
对于生手而言,要构建象下面的配置文件,一定是一件恐怖的事情:
R$+@$=W&& $@$1@$H user@thishost -& user@hub
R$=W!$+$@$2@$H&& thishost!user -& user@hub
R@$=W:$+& $@@$H:$2&& @thishost:something
R$+%$=W&& $@$&#$1@$2&& user%thishost
  不过,如果回想起以前学习C语言时,你是否会对这个表达式感到恐惧呢?
# define getc(p)(--(p) -&_cnt&=0? ((int)*(p)-&ptr++):_filbuf(p))
  就象任何一个新语言一样,学习sendmail.cf文件中所使用的语言需要时间和实践。在本章中,我们将介绍这个语言,不会在此只是对其作一个入门性的概述。
  sendmail.cf文件是sendmail每次启动时要读取的配置文件。它包含了sendmail启动时必须的信息。它列出了所有重要文件的位置,指定了这些文件的缺省权限。包含了一些影响sendmail行为的选项。更重要的是,它还包含了地址重写(rewriting addresses)规则。
  Sendmail.cf文件是按行组织的。一个配置命令行,均是由字符开头的,而且每行只有一个命令:
V7 ? 正确的
V7 ? 不正确,前面多了个空格
V7 Fw/etc/mxhosts ? 不正确,一行中有两个命令
Fw/etc/mxhosts ? 正确
  每一个配置命令行,是由命令加上特定参数构成的。例如,命令V的参数是一个数字,而F命令的参数则是字母w,再加上绝对路径。
命令&& 说明
V&&&& 定义配置文件的版本(从8.6版开始才要求)
M&&&& 定义一个邮件传送代理
D&&&& 定义一个宏
R&&&& 定义一个地址重写规则
S&&&& 声明一个规则集
C&&&& 定义一宏集
F&&&& 从一个文件与管道中定义一宏集
O&&&& 定义一个选项
H&&&& 定义一个信头
P&&&& 定义传送优先级
T&&&& 声明受托用户(在8.1版忽略,8.7版重用)
K&&&& 声明一个key字数据库(从8.1版开始使用)
E&&&& 定义一个环境变量(从8.7版开始使用)
L&&&& 包括扩展的负载均衡支持
  有一些配置命令,象V只会在sendmail.cf文件中出现一次,而有些象R命令就会多次在配置文件sendmail.cf中出现。
  空行、以“#”开始的行将被处理为注释行而被忽略。一个以tab开始的行,则说明是上一行的继续,如:
# a commnet ? 注释行
/Brekeley ? V7命令的继续
  除了一个命令,一个空行,一个空格,一个tab,或一个#字符以外,其它情况都是错误的。如果sendmail程序发现这种情况,将打印出如下警告,并忽略此行,然后接着读取后面的配置:
sendmail.cf : line 15:unknown control line “v6”
  在这,sendmail找到了一行以v开始的行。由于小写的v不是一个有效的命令,sendmail将发出警告。而行号则指出了这个错误所在行。
  下面几个小节将对每一种命令进行简单的实例说明。而这些命令的作用将会在本教程中阐述。所以如果在本节中无法完全理解的话,也不必担心。因为这里所有神秘的东西,在本书结束时都将变得十分清晰明白。
3.2最小配置
  最小的配置的文件可以是空文件。你可以使用以下命令来创建这个文件:
% cp /dev/null& client.cf
  我们会慢慢地往这个文件中添加配置。将其命名为client.cf是为了避免覆盖了系统中的sendmail.cf文件。
  现在,我们再运行sendmail,测试这个新配置文件的有效性:
% ./sendmail CCclient.cf Cbt &/dev/null
  命令行开关选项-C用于指定sendmail使用一个指定的配置文件。而开关选项-bt则告诉sendmail运行在rule-testing模式下。注意,sendmail读取你的空配置文件,运行,没有任何提示。同时注意当在第2章编译完后无法运行sendmail,但现在你可以了。那是因为当时你没有配置文件,而现在有一个了(尽管这个文件是空的)。
3.2.1 版本
  为了防止旧版本的sendmail因读取新版本的配置文件而破坏,在sendmail 8.1开始引入了一个V命令,这个命令的格式如下:
  编辑文件client.cf,然后加上这一行。“V”必须位于行首。后面跟的版本号必须是7,才能够使所有8.8版的sendmail.cf中的新功能生效。数字7是sendmail.cf的语法,表示有7个主要的变化。
3.2.2 注释
  注释语句能够帮助其他人理解你的配置文件。同时,他们也能通过注释记起你几个月前的修改。注释语句对sendmail的执行速度影响极小,所以你无需担心这一问题。前面我们说过,以#开始的行,被sendmail认为是注释行,整行将被忽略。例如:
# This is a comment
  另外,注释语句也可以在命令之后,如:
V7#This is another comment
  增加一些注释语句到你的sendmail.cf文件中,使其成为:
# This is a comment
V7# This is another comment
Sendmail程序读取这个配置文件也将没有任何提示。
% ./sendmail CCclient.cf Cbt &/dev/null
3.3快速导览
  你将发现,在配置文件中的其它命令远比V命令来得复杂。这儿,我们现在对每个命令作一个快速的导览,仅够你能够对它们有一个初步的了解。
3.3.1 邮件传送代理
  通常情况下,sendmail程序不自己传送邮件,而是调用一个程序来完成。M命令就是定义一个邮件传送代理。例如,就象以前我们看到过的:
Mlocal,& P=/bin/mail, F=lsDFMAw5:/|@rmn, S=10, R=20/40,
  这将告诉sendmail,本地的邮件使用/bin/mail传送。这一行中的参数将在第6章:邮件中枢与传送代理,第30章:传送代理中详细说明。
  义一个值,然后可以在多次使用,提高sendmail.cf的可维护性。D命令用于定义宏。一个宏名可以是一个单字母或用大括号包起来的多个字符。定义一次后,就可以在其它地方使用。
DRmail.us.edu& ? 一个单字符
D{REMOTE}mail.us.edu&& ? 用大括号包含起来的多个字符(从8.7版开始)
  在这,R和{REMOTE}都是宏名,值是mail.us.edu。这个值可以在任何地方用$R和${REMOTE}访问。宏将在第7章:宏中介绍,更详细的在第31章:定义宏中。
3.3.3 规则
  sendmail.cf文件的核心是一系列的地址重写规则。这是非常重要的,因为地址必须符合多种标准。R命令用来定义这些规则:
R$-&& $@ $1 @ $R&& user -& user @ remote
  邮件地址将与最左边的规则($-)进行比较。如果与这个规则匹配,它们将根据右边的规则($@ $1 @ $R)进行重写。而在最右边的文本则是注释(注意,这里不需要使用#号)。
  如果使用多字符的宏名,并用#号标出注释的话,将使语句减少一些神秘:
R$- # If a plain user name
$@ $1 @ ${REMOTE}& # append “@” remote host
3.3.4 规则集(Rule Sets)
  由于地址重写可能需要好几步,规则可以组织成为规则集,用S命令开始规则集:
  S3该命令定义规则集3,从sendmail 8.7版开始,规则集也可以使用字符来命令,如:
  该命令定义Hubset规则集,这种方式的命名,sendmail将会自己对其编号。
  所有的跟在S命令后的R命令(规则)组成规则集。一个规则集结束于定义另一个规则集的S命令。
3.3.5宏集(Class Macros)
  用D命令定义的宏只能有一个值,但这通常是不够的。我们经常需要定义一个拥有多个值的宏,然后就像数组一样来组织这些值。C命令定义一个宏集。一个宏集就像一个数组一样,能够有多个项。宏集的名字是一个单字母,从8.7版开始,也可以用大括号包含多个字符作为名字,例如:
CW& localhost& fontserver ? 一个单字符作为名字―W
C{MY_NAMES}& localhost& fontserver& ? 多个字符作名字---{MY_NAMES}
  在这里,每一个宏集都包含两个值:localhost和fontserver。我们可以通过表达式$=W和$={MY_NAMES}来访问这些宏集。有关于宏集的更多信息,可以参考第12章和第32章。
3.3.6 文件宏集(File Class Macros)
  为了管理更加容易,我们常将比较长的信息或经常变化的信息存放到一个文件中去。命令F可以定义一个文件宏集。这个宏集的值是这个文件的内容,如:
FW/etc/mynames
F{MY_NAMES}/etc/mynames
  在此,文件宏集W和{MY_NAMES}将从文件/etcmynames中获得它们的值。
  文件宏集也可以从一个程序的输出中得值。它定义为:
FM|/bin/shownames
F{MY_NAMES}|/bin/shownames
  在此,sendmail将运行程序/bin/shownames,这个程序的输出将成为文件宏集的值。
3.3.7 选项
  选项将告诉sendmail程序许多有用的和必要的事情。它们指定key文件的位置,设置超时时间,以及定义sendmail在出错时如何处理。它可以调整sendmail,以使它符合你特定的需要。
  命令O用来设置这些选项。以下就是一个例子:
OQ/var/spool/mqueue
O QueueDirectory=/var/spool/mqueue
  在此,Q选项定义邮件队列文件为/var/spool/mqueue。
3.3.8 信头
  邮件消息由两个部分组成:一个是信头部分,另一个是在空行后的主体部分。主体部分可以包括任何内容。而信头部分,则需要严格按照标准。H命令用来指定信头的格式:
Hreceived:$?sfrom $s $.by Sj ($v/$Z) $?r with $r$. Id $I$?u for $u$.; $b
  这个特定的H命令告诉sendmail收到后,必须在每一封信的信头加上这一行。
3.3.9 优先级
  并不是所有的邮件具有相同的优先级。邮件列表的信应该在只有一个收件人的信的后面发送。P命令用于设定邮件的优先级。这个优先级用于邮件队列处理时决定邮件的顺序。
Pjuck=-100
  这个P命令告诉sendmail,信头中用juck的信最后处理。关于这个命令的更详细内容,参见第14章和第35章。
3.3.10 受托用户
  为了使某些软件(如UUCP)能够正确地生效,就必须能够告诉sendmail邮件是谁发来的。这要求软件与From:中指出的用户运行在不同的uid上。T命令列出这些用户的受托用户。所有包含在信头的其他用户将收到一个警告。
Troot daemon uucp
  这个T命令指出有三个用户是受托用户。它们是root(UNIX系统中的上帝),daemon(sendmail通常以伪用户daemon身份运行),以及uucp。
3.3.11 key数据库
  一些认证信息,例如UUCP主机列表等,最好在sendmail.cf外维护。外部的数据库(叫作keyed数据库)提供了更快的访问速度。Key数据库在8.6版中引入了几种格式,如:
Kuucp hash /etc/mail/uucphosts
  这个K命令声明一个key数据库叫uucp,类型是hash,文件为/etc/mail/uucphost。
3.3.12 环境变量
  sendmail程序的安全是十分重要的。一种破坏的的方法是运行时伪造一些环境变量。为了阻止它,8.0版的sendmail将在启动时去除所有的环境变量。然后根据预先设置的值进行设置。设置环境变量使用E命令。
EPOSTGRESHOME=/home/postgres
  在此,环境变量POSTGRESHOME被赋予值/home/postgres。这个程序使用postgres数据库访问信息。
邮件中枢与分发代理
6. 邮件中枢与分发代理
  使用一个强大的中心机器处理所有的邮件,比让网络中所有的工作站自己处理自己的邮件好得多。这样的一个中心机器就叫作邮件中枢(Mail hub),它就象美国联邦快运公司处理包裹一样工作。在过去,当你通过联邦快运公司将包裹从旧金山寄到巴黎,包裹将首先被送到孟菲斯的田纳西,甚至你想寄到洛杉机,它也是先送到孟菲斯(参见图6-1)。这是因为孟菲斯是联邦快运公司的处理中心。所有的包,不管它们从哪来,到哪去,都先送到处理中心(中枢,hub),然后再从那里发送出来。
  这种处理方法的好处就是,联邦外运公司只有处理中心需要知道如何发往全世界(当然,联邦快运是有多个处理中心的),而其它地方的分支机构只要知道如何发往处理中心就可以了。
  类似地,你的工作站也可以将自己看成分支机构(客户机),将处理邮件的中心机器看成处理中心。这个邮件中枢将为整个机构处理邮件,这样做有许多好处:
  1) 所有发往这个机构的信都发给邮件中枢,而不直接发往客户机。由邮件中枢来处理有几个优点:客户机无需运行sendmail守候进程来侦听邮件。而且客户机的名字无需告知外部,因此更容易安全地将客户机与Internet隔离。
  2) 所有从机构往外发的邮件都先发给邮件中枢,然后由邮件中枢转发到最终目的地,而不是由客户机直接向外发送。这个机制可以使客户机无须一直观察Internet的变化;所有的待发邮件都保存在邮件中枢中,而不是客户机处,这样管理起来更简单;而且一个单一的sendmail.cf文件就可为所有的客户机服务。
  3) 所有发出去的邮件都将被修改,使得其看起来象来自邮件中枢的邮件。这样回复的邮件就不会直接返回到每一个客户机。这样做,所有的邮件好象都来自一台机器,一台很大的机器。
  4) 所有发往本地用户的邮件都将传送到邮件中枢,存放在spool中。而无需每台机器都建一个spool目录来存放收到的邮件。这样做的优点是所有本地的邮件都由一个机器处理,所有本地机器都无需进行处理。而且这样管理spool也更加容易。
  但如果你的机构的电脑网络是不同体系结构的电脑组成的,或散在许多网络中,使用邮件中枢就不是太好了:
  1) 如果一个机构经常有数量巨大的邮件收发,那么这台邮件中枢就可能负载过大,以使所有的邮件都被缓存,一直等待发送。如果负载厉害的话,甚至可能使本地邮件转发也会出现这样的现象,那是十分可怕的。
  2) 为了让邮件中枢正常工作,它需要知道系统中所有用户的登录名,也就是意味着需要一个主/etc/passwd文件,它是所有主机上的/etc/passwd的集合,或者使用NIS系统来构建。
  3) 因为所有的邮件都通过邮件中枢传送,而不是直接送给接收者,这就意味着一定会延迟。对于一些小的机构,这个延迟可以忽略不计,而让邮件的总量上去时,这会成为一个严重的问题。
  4) 如果一个客户机是直接使用UUCP连接,或是与多个网络连接,那样配置文件会变得十分复杂。
4.1 client.cf文件
  这个教程的目的是产生一个简单的邮件中枢的sendmail.cf文件。为了区别与前面几个章节中的sendmail.cf文件区分开来,在此我们把它称为client.cf文件。我们将在后面的几个小节中逐段地生成这个文件,并做一些相应的说明。本章中生成的文件将完成两个任务:
  1) 它将指示sendmail运行为邮件中枢,发送所有给其它机器的mail服务器。
  2) 它将使所有外出的邮件表现为从邮件中枢发出的一样。
  在这章中,我们主要处理第一个任务:如何让客户机上的邮件送到邮件中枢。
4.2 定义一个邮件分发代理
  sendmail除了在TCP/IP网络转发邮件外,并不能自己处理邮件传送。而是调用一个程序来实现。这个程序就叫做分发代理。哪个代理程序处理哪类邮件分发任务在sendmail.cf文件中定义。
  加入你的client.cf文件中的第一项是定义负责将信件转发给邮件中枢的转发代理程序。最初,sendmail只需要转发代理程序的名字与路径。设置形如:
# This is a comment
V7& # this is another comment
# Delivery agent definition to forward mail to hub
Mhub, P=[IPC], A=IPC $h
  这是一个最小的配置文件。将这些行加入到client.cf文件中。配置的第二行定义了一个分发代理。它包含三个部分,每个部分使用逗号隔开。
  以M开始的行用于定义邮件分发代理。紧跟着在后面的hub是分发代理的标识名。
  这个标识名供你以后写的配置文件部分参考。
  P=用于设置路径。这一句配置用来指出处理邮件分发的程序的全路径名,在这里使用的是[IPC]。([IPC]是一个Sendmail内部使用的专有名称,说明它有能力在TCP/IP网络上完成邮件分发工作。)而对于其它情况下,则设置为其转发程序的名称,如/bin/mail等。
  A=后面跟着参数列表,用来指定P=指定的程序运行时的参数。第0个参数就是程序的名称(在此就是IPC,注意没有包含括号)。而其它的参数就是在A=后面指定的,这此例中仅有一个:$h。这个$h是一个宏,表示接收者的主机名。我们会在第7章中更详细地说明宏。它通常是关于分发代理定义的最后一项。
4.2.1 测试client.cf文件
  在命令行下执行:
% /usr/lib/sendmail CoQ/tmp CCclient.cf Cbp
  注意,你需要在命令行中加上-oQ/tmp,它将阻止sendmail改变mqueue目录。如果你忽略这个开关,sendmail会出现混乱、错误:
cannot chdir((null)):Bad file number
  而-Cclient.cf开关则告诉sendmail使用当前目录中的client.cf文件,而不是系统中的/etc/sendmail.cf文件。而-bp开关则是让sendmail打印出队列的内容。以上命令行将产生如下所示的输出:
No local mailer defined
  然而,缺少一个local mailer并没有什么大不了的。Sendmail程序在输出它后,就结束了,说明没有发现其它错误。
4.3 本地分发代理
  当你运行了sendmail,它曾抱怨没发现本地分发代理定义。为了让它更快乐,我们就将下面的定义加入到client.cf文件中去。你可以使用以下命令,从/etc/sendmail.cf中抄过来:
% grep “^Mlocal” /etc/sendmail.cf && client.cf
  注意,^M是真实的两个字符:^和M,而不是CTRL-M。现在,
  我们启动编辑器,然后调入client.cf文件,你将看到类似下面的内容:
# This is a comment
V7& # this is another comment
# Delivery agent definition to forward mail to hub
Mhub, P=[IPC], A=IPC $h
Mlocal, P=/bin/mail, F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  你将注意到有三个新的等式,它比我们原来的hub等式复杂。这个新的M配置命令声明一个符号名,就象hub一样。在这里,我们用的名字是local。尽管,local定义对于一个真正在运行的sendmail.cf配置来说是十分重要的,而在此呢,我们仅仅是为了让sendmail不抱怨。
  这个新的分发代理定义是由六个部分组成的(每个部分使用逗号隔开),一个符号名和五个等号。其中F=、S=和R=是新出现的。而关于M,P=和A=都在介绍hub那一节中介绍过了。
  M 所有的邮件分发代理的定义都是从M开始的,如:
Mhub,& P=[IPC],A=IPC $h
Mlocal, P=/bin/mail, F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  分发代理的符号名就紧跟在M命令之后,中间没有空格。在以上的例子中,符号名是hub和local。名叫hub的分发代理用于将邮件转发给邮件中枢。而local分发代理则将邮件分发给本机的用户。
  P=在等号后面指出邮件分发程序的全路径名:
Mhub,& P=[IPC],A=IPC $h
Mlocal, P=/bin/mail,& F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  你的程序名可能与这里不同,但通常,local邮件分发代理都是将邮件放入用户的邮件spool文件中。
  A= 在等号后面指定这个邮件分发代理运行时的参数。
Mhub,& P=[IPC],A=IPC $h
Mlocal, P=/bin/mail,& F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  注意,在local中使用了$u宏,而hub则使用了$h宏。$u宏包含接收者的名字(如bob),而$h宏则是包含接收主机的名字(如here.us.edu)。宏将在下一章说明。习惯中,这个部分一般放在最后。
  以下三个部分是在local定义中新出现的,在hub的定义中并未使用。
  F= 在等号后面指定确定的标记,用来告诉sendmail更多关于分发代理的东西。每一个标记都是单个字符(要么设置,要么不设置)。
Mhub,& P=[IPC],A=IPC $h
Mlocal, P=/bin/mail,& F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  这儿有许多标志可供选择。这些标志将在第30章分发代理中说明,而在后面的几章中也会说明一些。
  S= 在等号后指定使用哪一个规则集来重写发送者地址:
Mhub,& P=[IPC],A=IPC $h
Mlocal, P=/bin/mail,& F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  由于不同的分发代理使用的地址格式不尽相同,所以有时需要重写发送者地址。
  例如,[IPC]代理使用user@host.domain的格式,而uucp代理则使用host!user格式。
  再此,指定了分发代理使用第10规则集来重写发送者地址。我们将在第8章:地址和规则中详细地说明。
  R= 在等号后面指定使用哪一个规则集来重写发送者地址:
Mhub,& P=[IPC],A=IPC $h
Mlocal, P=/bin/mail,& F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  同样的道理,我们需要重写接收者地址。在此,指定使用规则集20重写信封地址,使用规则集40重写信头地址。
  而从sendmail 8.7版开始,引入了一个新的定义:
  T= 这用来指定一些相关的信息,如:
Mlocal, …, T=DNS/RFC822/X-Unix
  第一个信息是MTA使用的(这儿是DNS,因为sendmail是使用DNS来查寻地址的);接着在“/”之后的第二个信息是地址使用的(这儿是RFC822,也可以是X.400);最后是错误消息类型(这儿是X-Unix,说明/bin/mail将产生Unix的错误)。
4.3.1 略过规则集
  由于我们有时并不需要转换规则集,这很简单,我们只需将S=和R=后面的规则集做如下的修改就可以了。
Mhub,& P=[IPC],A=IPC $h
Mlocal, P=/bin/mail,& F=lsDFMAw5:/|@rmn, S=0, R=0, A=mail Cd $u
  规则集设为0,代表不使用规则集。
4.3.2 增加注释
  注释对于每一个配置文件都是十分重要的部分,它将提醒你现在在做什么,以及以前做过什么。现在编辑client.cf文件,拿掉两行原来的注释,加入一行新的注释,使其内容为:
# Delivery agent definition to forward mail to hub
Mhub, P=[IPC], A=IPC $h
# Sendmail requires this,but we won’t use it.
Mlocal, P=/bin/mail, F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  我们拿掉的那两行注释语句是没有意义的两名,它们只是演示用的,并无法起到注释的作用。
4.3.3 增加注释
  现在,我们采用不同的方式运行sendmail:
% /usr/lib/sendmail Cd0.15 CCclient.cf Cbt
  -d0.5是一个调试开关,它告诉sendmail显示你定义的分发代理是如何处理的。而-bt使得sendmail以规则测试模式来运行。以上命令将产生如下的输入。
mailer 0 (prog):P=/bin/sh S=0/0 R=0/0 M=0 U=0:0 F=Dlos L=0 E=
T=DNS/RFC822/X-Unix A=sh Cc $u
mailer 1 (*file*):P=[FILE] S=0/0 R=0/0 M=0 U=0:0 F=DEFMPlosu L=0 E=
T=DNS/RFC822/X-Unix A=FILE
mailer 2 (*include*):P=/dev/null S=0/0 R=0/0 M=0 U=0:0 F=su L=0 E=
  这个输出,将彻底地解释client.cf文件,通过M=、U=、L=和E=提示出来。
  在前面的输出中,大家可以发现有几个等式并未在定义中定义。如hub的定义中只包含了A=和P=:
Mhub, P=[IPC], A=IPC $h
  而当sendmail看到这个定义,将使其复杂化,加上了E=(换行符),T=
mailer 3 (hub):P=[IPC] s=0/0 R=0/0 M=0 U=0:0 F= L=0 E=
  注意,当F=0时,就表示空列表,没有定义标记。
4.4 为Mhub增加缺少的部分
  最后一步,我们为Mhub增加它缺少的那部分:F=、S=、R=和T=。
  编辑client.cf文件,然后增加Mhub那么,使其成为:
# Delivery agent definition to forward mail to hub
Mhub, P=[IPC], S=0, R=0, F=mDFMuXa, T=DNS/RFC822/SMTP, A=IPC $h
  在此,我们让S=和R=都为0.S=用来指定重写发送者地址的规则集,而R=用来指定重写接收者的地址规则集。然而在此不需要地址重写,因此被赋予0值。
  而T=部分则与local的定义类似,唯一不同的是,它使用SMTP代替了X-Unix,即local是报告UNIX的错误消息,而hub则是SMTP错误消息。关于这一点,我们在后面会专门说明。
  而标志列表F=mDFMuXa,是最典型的设置。你可以根据自己的需要修改。所有的可用的标志在第30章中有详细说明。以下是一个概括性的说明表。
m 这个代替能够同时为超过一个用户分发
D 在信头中包括Date:(日期)
F 在信头中包括From:(信从哪来)
M 在信头中包括Message-ID:(消息ID编号)
u 保持接收者姓名
X 遇到单独的点,变为“..”(两个点)
A 运行扩展的SMTP协议
  关于邮件分发代替的定义,就简单地说到这里。
  在sendmail.cf文件中有一个十分重要的组成部分,就是那些使用代表文本的符号。这与bsh和csh中的变量的使用极为类似:
REMOTE=mailhost&& (bsh)
set REMOTE=mailhost&& (csh)
D{REMOTE}mailhost(sendmail.cf)
  以上几个语句都是定义了一个名为REMOTE的变量,被为其赋值为mailhost。
  而要使用变量中存储的值,可以使用以下表达式:
$REMOTE& (bsh)
$REMOTE& (csh)
${REMOTE}(sendmail.cf)
  也就是说,以上表达式将得到存储在变量REMOTE是值,在这个例子中就是文本字符mailhost。一经定义了REMOTE的值为mailhost,你就可以在任何地方使用以上表达式来代替文本字符mailhost。
  宏能极大地简化您的工作。它允许你在一个集中的地方定义一些文本符号。而你只需修改这里的文本字符,则改变将自己传播到文件中其它部分。例如,假设我们在sendmail.cf文件中定义了:
D{REMOTE}mailhost
  如果你在sendmail.cf文件的其它地方都使用${REMOTE},则只需简单修改定义D{REMOTE}mailhost中的字符串,就将使所有表达式${REMOTE}的值改变。
  宏定义的语法格式如下:
  必须使用字符D开始。这个字母D的后面紧跟着宏的名字(在这就是X),注意中间并没有空格隔开。接着在宏名的后面紧跟着值,注意在宏名与值之间也没有用空格隔开。这个值从宏名开始,直到本行结束。
  宏名可以由一个字符组成,也可以由多个字符组成。如果你使用多个字符做为宏名,就必须使用“{ }”把它们括起来。如果是使用单个字符做宏名,则也应该使用“{ }”包括起来,而在V8.7之前也可以不使用“{ }”。
DRmailhost (sendmail V8.7以前版本)
D{R}mailhost
D{REMOTE}mailhost
  通常,当读取配置文件的时候就会自动展开宏。因此,你必须在使用宏之间定义它们:
D{ROLE} son
S${ROLE}(此时的值是son)
D{ROLE}mother
S${ROLE}(此时的值是mother)
  在这里,ROLE首先被赋值为son,当处理到第一个S命令时,sendmail会将${ROLE}替换为前面定义的值:son,因此得到:
  而后,配置文件又将ROLE的值修改为了为mother,所以在处理到第二个S命令时,sendmail会将${ROLE}替换为ROLE的值mother,因此得到:
  不过请注意这是一个十分不好的风格,通常,为了不产生混乱,每个宏应该只被定义一次。
5.2 定义宏
  在上一章里,我们粗略了解了分发代理hub和local本地分发代理的定义。我们可以看到,在这两个分发代理的定义中的最后一部分“A=”都使用到了宏。
# Delivery agent definition to forward mail to hub
Mhub, P=[IPC],S=0,R=0,F=mDFMuXa,T=DNS/RFC822/SMTP, A=IPC $h
# Sendmail requires this,but we won’t use it.
Mlocal, P=/bin/mail, F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  宏有两种:一种是你自己定义的,而另一种则是sendmail定义的。你自己定义的宏,宏名一定要以大写字母开始;如果宏名是以小写字母开始的,如h、u,则是sendmail定义的宏。
  你已经看到过一个以大写字母开始的宏:
D{REMOTE}mailhost
  在你的网络中,邮件中枢机器会使用了mailhost或类似的(如mailrelay)的别名,然而有时则不存在这样的别名。此时你必须使用它的实际机器名(如mail.us.edu)。现在,我们编辑client.cf,然后加入第一个宏{REMOTE}。
# Defined macros
D{REMOTE}mailhost # The name of the mail hub
# Delivery agent definition to forward mail to hub
Mhub, P=[IPC],S=0,R=0,F=mDFMuXa,T=DNS/RFC822/SMTP, A=IPC $h
# Sendmail requires this,but we won’t use it.
Mlocal, P=/bin/mail, F=lsDFMAw5:/|@rmn, S=10, R=20/40, A=mail Cd $u
  在此,我们在client.cf文件中新增了三行。第一行是一个注释语句,第三行则是一个空行,有来可视地分隔开宏定义部分与分发代理定义部分。第二行是新的宏定义。正如注释中说的,这个{ROMOTE}宏将包含邮件将转发到的机器名。
  现在我们花一些时间来测试一下这个新的client.cf文件:
% ./sendmail CCclient.cf Cbt &/dev/null
  sendmail程序将读取并分析client.cf文件。由于在这个配置文件中并没有错误,所以sendmail将不会打印错误信息。
5.3预定义宏
  在sendmail中,有一些内置的宏。你已经在分发代理的定义中看到过了u(接收者的用户名)和h(接收者的主机名)。它们无须在配置文件中定义,它们是sendmail定义的。这种宏,我们称之为预定义宏。下表中列出部分预定义宏:
宏名&& 描述
n&&&&& 发送者错误消息标志符
v&&&&& 当前运行的sendmail的版本
w&&&&& 短主机名
j&&&&& 规范的主机名
m&&&&& 域名
k&&&&& UUCP节点名
b&&&&& RFC1123格式的日期
_&&&&& 身份鉴别信息
opMode 当前操作模式(在V8.7版之后才有)
  在运行sendmail时,只需加上-d35.9参数,就可以显示出所有宏的定义:
% ./sendmail Cd35.9 CCclient.cf Cbt &/dev/null
  尽管client.cf文件如此小,但这个命令的输出惊人地长:
define(* as $*)
define(+ as $+)
define(- as $-)
define(= as $=)
define(~ as $~)
define(# as $#)
define(@ as $@)
define(: as $:)
define(& as $&)
define(? as $?)
define(| as $|)
define(. as $.)
define( [ as $[)
define(] as $])
define(( as $()
define() as $))
define(& as $&)
define(0 as $0)
define(1 as $1)
define(2 as $2)
define(3 as $3)
define(4 as $4)
define(5 as $5)
define(6 as $6)
define(7 as $7)
define(8 as $8)
define(9 as $9)
define(n as $MAILER-DAEMON)
& define(v as 8.8.4)
define(w as here.us.edu)
define(j as here.us.edu)
define(m as us.edu)
define(k as here)
define(b as Fri,13 Dec :47 C0700 (PDT))
define(_ as you@localhost)
define(opMode as t)
redefine(w as here)
define(REMOTE as mailhost)
  不同版本的sendmail的输出将不同。例如,l、o和e在V8.7以前的版本中存在,而在8.7以后的版本中就没有了。前面27行显示出了sendmail为operators(操作者,将在下一章中具体说明)预留的宏。而后面的11行则是我们现在所感兴趣的。这11行中,前10行都是senmail程序预定义的,最后1行则是用户自己定义的。
  这些输出可以显示出另一个概念。一些内部宏是在读取配置文件之前定义的,你可以在client.cf文件中改变。例如我们要改为w,则只需在配置文件中加入一行:
Dwmyhost.my.domain
  使用了这行配置文件后,宏w的值就从here.us.edu变成了myhost.my.domain了。
  注意,在以上输出中并没有显示h和u宏。这些宏,尽管在内部定义了,但它们是直到邮件发送后才被赋予实际的值的。你不能够在你的配置文件中修改它们,因为它们在配置文件被读取之后才定义的。
  最后,请注意只有V8的sendmail会为宏设置适当的缺省值。所有老版本的sendmail需要你手动地在client.cf文件中设置e、l、n、o以及q的缺省值。
5.3.1 主机名
  本地主机名由两部分组成。主机名部分就是机器名,不包括“.”(如here)。而域名部分则至少有由“.”隔开的两个部分(如us.edu)。而全规范名(fully qualified)则是由主机名加上“.”,然后再加上域名构成。(例如:here.us.edu)。全规范名才能唯一标识一台机器。
  本地机器的主机名也需要规范化。一台机器可以有多个名字(如mailhost或printserver等等),但只能有一个是正式的。你可以执行hostname命令来获取这个正式的名字:
% hostname
here.us.edu
  下面我们就来看一下sendmail是如何解释你的本地主机名。我们以-d0.1的参数来执行sendmail:
% ./sendmail CCclient.cf Cd0.1 Cbt &/dev/null
version 8.8.4
Compiled with:LOG NAMED_BIND NDBM NETINET NETUNIX NIX SCANF XDEBUG
= = = = = = = = = SYSTEM IDENTITY (after readcf) = = = = = = = = =
&& (short domain name) $w = here
&& (canonical domain name) $j = here.us.edu
& (subdomain name) $m = us.edu
&& (node name) $k = here
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  这里经常容易出错。例如,如果你并未与Internet连接,你可能就不会有一个合法的域名。或者你可能运行NIS而使得在hosts.byname映射中只有短主机名。一个很重要的事情就是观察以上输出中,sendmail是否正确地发现了你的短主机名和规范主机名:
(short domain name) $w = here
(canonical domain name) $j = here.us.edu
(subdomain name) $m = us.edu
  如果这里有错误,你需要修复引起这个错误的系统问题。在系统级,调查以下问题:
  1)/etc/hosts文件。你可能在这个文件中仅列出了短主机名。对于sendmail 8.7以前的版本,它需要你在这个文件的最开始一行列出全规范主机名。而从sendmail 8.7开始,新版的sendmail只需要在这个文件中存在全规范主机名就可以了。
  2)nis映射。确认主机名能够被DNS查寻。
  3)nsswitch.conf或svc.conf文件。确定正确的主机名查寻方法在此列出。
  如果你无法发现,或没有足够的权限去做系统级的事情,你可以在你的client.cf文件中指定。例如,我们假设全规范名显示成了:
(canonical domain name) $j = here
  为了修复这个错误,你可以在client.cf文件中重新定义宏j,也就是在client.cf中加入:
Dj$w,$m # The local official domain name
  这个定义使得全规范名变成了主机名加“.”再加域名。这时,你可以再让sendmail显示一下,肯定会出现:
(canonical domain name) $j = here.us.edu
6. 地址与规则
  在研究到规则的内部工作原理之前,我们需要新建一个虚构的网络以提供一个公用的环境,以支持我们要谈论的mail地址。
6.1 一个虚构的网络
  我们拥有一个如图8-1所示的网络。它包括三个站点(每个云图表示一个站点),三个站点之间使用高速网络相连(有线连接)。每个站点都是一个由许多独立的计算机组成的一个DNS域。每一个域的设置都不相同,但从用户角度来看,发给一封信给本域内的用户与发一封信给其它域用户并没有什么区别。
  图8-1 在我们这个虚拟网络中的域分布
  一个域名是从右往左解释的。例如,acme.com是指acme是顶级域名com(供商业组织使用)的一部分。类似的,edu是供教育机构使用的顶级域名,gov是供政府组织使用的顶级域名。
  一个域可以包括许多机器。每一台

我要回帖

更多关于 移动apn接入点设置 的文章

 

随机推荐