首页 | 邮件资讯 | 技术教程 | 解决方案 | 产品评测 | 邮件人才 | 邮件博客 | 邮件系统论坛 | 软件下载 | 邮件周刊 | 热点专题 | 工具
网络技术 | 操作系统 | 邮件系统 | 客户端 | 电子邮箱 | 反垃圾邮件 | 邮件安全 | 邮件营销 | 移动电邮 | 邮件软件下载 | 电子书下载

邮件服务器

技术前沿 | Qmail | IMail | MDaemon | Exchange | Domino | 其它 | Foxmail | James | Kerio | JavaMail | WinMail | Sendmail | Postfix | Winwebmail | Merak | CMailServer | 邮件与开发 | 金笛 |
首页 > 邮件服务器 > Postfix > 基于postfix实现邮件用户的分布式处理 > 正文

基于postfix实现邮件用户的分布式处理

出处:www.extmail.org 作者:xyb 时间:2006-10-25 18:03:00
基于一些特殊的考虑,现在邮件系统经常面临把用户分散在几个不同服务器上的需求。这里谈一下我在使用postfix完成该功能时的一点认识和实践,需求所限,没有涉及到用户通过SMTP或者POP3登录收发邮件的部分。请各位朋友谅解并指正。

一般分布情况下,MX和用户所在的服务器是分离的;本文所描述的即是这种设计。下面把用户所在的服务器简称为单元(UNIT)。

MX

MX是接受邮件的关键,可以由一台或一组服务器组成。它对外开放SMTP端口,负责接受邮件并转投到收件人所在单元服务器。

简单的说,一封信投递到我们的系统中,首先会进入MX,MX检查收件人是否存在,然后根据用户的信息把信通过smtp协议转发到他所在的UNIT上。

由于用户分散在不同主机中,所以MX对用户进行查证的工作必须进行特殊的处理;这里大家可以集思广益,设计一两百种方案我看是没什么问题。不过,我们的任务是说明postfix如何处理用户分布的情况,所以我们假定已经有一个写好了的函数,调用它就可以查证用户了。我们利用它,就可以实现dict_unit这个map。利用选项 local_recipient_maps,使外部发信到我们的用户时,调用我们指定的接口对用户查证;输入为收件人的邮件地址。
local_recipient_maps = unit:smtpcheck

这里dict_unit的实现在后面详细解释。

用户查证是在访问者发出“RCPT ”指令时,如果postfix确认了该用户存在,就开始准备接收“DATA”指令发过来的邮件正文了。成功收到邮件后,通过配置好的 transport_maps,postfix可以询问我们的dict_unit,获得下一步处理的指令。比如,输入收件人邮件地址“user@my.com”,输出“smtp:unit12.my.com”,这就会让postfix通过smtp把信转投到unit12.my.com域名的这台机器上。
transport_maps = unit:transportmx


UNIT

邮件系统中的用户通过注册、转移等方式,被存放在不同的单元服务器中。他们负责接收从MX转投过来的信件,并最终放入存储系统中。

在这里,一样会使用local_recipient_maps检查收件人是否真实存在。但与MX不同的是,这是信件的最终目的地,transport_maps查询的结果就不能再是“smtp:unit12.my.com”,要设置成合适的本地处理程序,比如local或者指定mda的名称(在etc/master.cf中设置)等。

local_recipient_maps = unit:smtpcheck
transport_maps = unit:transportunit


自定义的map

这里是dict_unit的实现示意。通过这个map,我们可以把前面提到的用户查证、转发邮件、处理邮件的所有指引工作在一起完成;实际上,它相当于一个多向的阀门,可以让邮件流向不同的方向。

注意,这仅仅是示意的代码。有需要做开发的朋友请自行参考dict_pam[1]的实现,那是真正可执行的代码。请不要写信询问我如何编写并调试可用的dict,google[2]postfix官方网站[3]上都可以查到。

这个函数负责处理用户查证的工作。
static int dict_unit_smtpcheck(const char *name, char *result)
{
char userhost[128] = {0};

if (msg_verbose)
msg_info("dict_unit: lookup smtp user: %s", name);
ret = getuser(name, &userhost);
if (ret != 0){
if (msg_verbose)
msg_warn("dict_unit: lookup smtp failed, name: %s", name);
return 1;
}
if (msg_verbose)
msg_info("dict_unit: lookup transport successed, name: %s, host: %s, path: %s",
name,
userhost);

strncpy(result, userhost, sizeof(userhost));
return 0;
}


这个函数负责控制MX服务中邮件的流向。

static int dict_unit_transportmx(const char *name, char *result)
{
char userhost[128] = {0};

if (msg_verbose)
msg_info("dict_unit: lookup transport user: %s", name);

ret = getuser(name, &userhost);
if (ret != 0){
if (msg_verbose)
msg_warn("dict_unit: lookup transport failed, name: %s", name);
return 1;
}
if (msg_verbose)
msg_info("dict_unit: lookup transport successed, name: %s, host: %s,",
name,
userhost);

/* result formal like: "smtp:unit12.my.com" */
strncpy(result, "smtp:", sizeof(userhost));
strncat(result, userhost, sizeof(userhost)-strlen("smtp:"));
return 0;
}


这个函数负责控制UNIT中的邮件的流向。值得一提的是,这里我们使用了var_myhostname来鉴别该用户是不是本机的(很简陋,演示嘛),要正确编译的话,在src/global/dict_unit.c中,必须加入这一行:
#include "mail_params.h"

要正确运行的话,则必须再在etc/main.cf中配置好正确的本机域名:
myhostname = unit12.my.com

最后,我们这里的是调用了一个定制的MDA程序“mymda”来完成最终信件的投递。要让它能正确运行,得配置etc/master.cf,请自行查阅手册。

static int dict_unit_transportunit(const char *name, char *result)
{
char userhost[128] = {0};

if (msg_verbose)
msg_info("dict_unit: lookup transport user: %s", name);

ret = getuser(name, &userhost);
if (ret != 0){
if (msg_verbose)
msg_warn("dict_unit: lookup transport failed, name: %s", name);
return 1;
}
if (msg_verbose)
msg_info("dict_unit: lookup transport successed, name: %s, host: %s",
name,
userhost);

/* for local user, result is: "mymda:"
* for remote user, result is: "smtp:mx.my.com"
*/
if (0==strnstr(userhost, var_myhostname, sizeof(userhost)))
/* MX can delivery it */
strncpy(result, "smtp:mx.my.com", sizeof(userhost));
else
/* local MDA is ok */
strncpy(result, "mymda:", sizeof(userhost));

return 0;
}


最后,为了让上面的三个lookup能真正工作起来,要在dict对外提供的接口处调用他们。这个分流是通过lookup时传入的dict->service来辨认的,也就是在main.cf中的配置“unit:smtpcheck”冒号后面的部分。

static const char *dict_unit_lookup(DICT *dict, const char *name)
{
DICT_unit *dp = (DICT_unit *) dict;
char result[128] = {0};
int ret;

if (0 == strcmp(vstring_str(dp->service), "smtpcheck"))
ret = dict_unit_smtpcheck(name, result);
else if (0 == strcmp(vstring_str(dp->service), "transportmx"))
ret = dict_unit_transportmx(name, result);
else if (0 == strcmp(vstring_str(dp->service), "transportunit"))
ret = dict_unit_transportunit(name, result);
else
{
if (msg_verbose)
msg_error("dict_unit: lookup unknown service %s, name %s.",
vstring_str(dp->service), name);
return (0);
}
if ((0 != ret) || (0 == result[0]))
return (0);

succ:
if (msg_verbose)
msg_info("dict_unit: service %s, name: %s, result: %s.",
vstring_str(dp->service), name, result);
vstring_strncpy(dp->result, result, sizeof(result));
return vstring_str(dp->result);
}


组装在一起,这个控制邮件流向的大阀门就算是完工了。

以上是利用postfix实现用户分布的一次实践。当然,方案并非只有一种,大家各有不同。请大家多多讨论,共同进步。

本文基于创作共用协议[4]之“署名-保持一致”[5]许可证发表,使用前请阅读该协议。-- xyb

参考
[1] http://d.scn.ru/proj/postfix/dict_pam/
[2] http://www.google.com/
[3] http://www.postfix.org/
[4] http://www.creativecommons.cn/
[5] http://creativecommons.cn/licenses/by-sa/1.0/
相关文章 热门文章
  • postfix+dovecot+postfixadmin+mysql架设邮件服务器
  • FreeBSD上建立一个功能完整的邮件服务器(POSTFIX)
  • CentOS5.1上安装基于postfix的全功能邮件服务器(二)
  • CentOS5.1上安装基于postfix的全功能邮件服务器
  • CentOS安装配置Postfix邮件服务器
  • 在CentOS下用Postfix配置邮件服务器
  • 3分钟安装配置Postfix邮件服务器
  • 基于Postfix的大型邮件系统
  • 19.4.3 让Postfix可监听Internet来收发信件
  • 19.4.1 Postfix的产生
  • 关于postfix的loops back to myself错误
  • 成功将qmail用户迁移到postfix(extmail+extman)下
  • Install and configure Postfix with Cyrus-SASL+Cyr...
  • 在FreeBSD上建立一个功能完整的邮件服务器
  • postfix 邮件病毒过滤
  • 在Fedora上建立自己的邮件服务器
  • Postfix + SpamAssassin 安裝手冊
  • Postfix + Courier-IMAP + Cyrus-SASL + MySQL + IMP...
  • Postfix + Cyrus-SASL + Cyrus-IMAPD + PgSQL HOWTO
  • 在FreeBSD5.1簡單安裝Postfix+Qpopper+Openwebmail
  • 在RHEL 4 上配置全功能的Postfix 服务器
  • Postfix + Cyrus-IMAP + Cyrus-SASL + MySQL + IMP 完..
  • 我的POSTFIX安装笔记
  • Postfix电子邮局的配置步骤
  • 自由广告区
     
    最新软件下载
  • SharePoint Server 2010 部署文档
  • Exchange 2010 RTM升级至SP1 教程
  • Exchange 2010 OWA下RBAC实现的组功能...
  • Lync Server 2010 Standard Edition 标..
  • Lync Server 2010 Enterprise Edition...
  • Forefront Endpoint Protection 2010 ...
  • Lync Server 2010 Edge 服务器部署文档
  • 《Exchange 2003专家指南》
  • Mastering Hyper-V Deployment
  • Windows Server 2008 R2 Hyper-V
  • Microsoft Lync Server 2010 Unleashed
  • Windows Server 2008 R2 Unleashed
  • 今日邮件技术文章
  • 腾讯,在创新中演绎互联网“进化论”
  • 华科人 张小龙 (中国第二代程序员 QQ...
  • 微软推出新功能 提高Hotmail密码安全性
  • 快压技巧分享:秒传邮件超大附件
  • 不容忽视的邮件营销数据分析过程中的算..
  • 国内手机邮箱的现状与未来发展——访尚..
  • 易观数据:2011Q2中国手机邮箱市场收入..
  • 穿越时空的爱恋 QQ邮箱音视频及贺卡邮件
  • Hotmail新功能:“我的朋友可能被黑了”
  • 入侵邻居网络发骚扰邮件 美国男子被重..
  • 网易邮箱莫子睿:《非你莫属》招聘多过..
  • 中国电信推广189邮箱绿色账单
  • 最新专题
  • 鸟哥的Linux私房菜之Mail服务器
  • Exchange Server 2010技术专题
  • Windows 7 技术专题
  • Sendmail 邮件系统配置
  • 组建Exchange 2003邮件系统
  • Windows Server 2008 专题
  • ORF 反垃圾邮件系统
  • Exchange Server 2007 专题
  • ISA Server 2006 教程专题
  • Windows Vista 技术专题
  • “黑莓”(BlackBerry)专题
  • Apache James 专题
  • 分类导航
    邮件新闻资讯:
    IT业界 | 邮件服务器 | 邮件趣闻 | 移动电邮
    电子邮箱 | 反垃圾邮件|邮件客户端|网络安全
    行业数据 | 邮件人物 | 网站公告 | 行业法规
    网络技术:
    邮件原理 | 网络协议 | 网络管理 | 传输介质
    线路接入 | 路由接口 | 邮件存储 | 华为3Com
    CISCO技术 | 网络与服务器硬件
    操作系统:
    Windows 9X | Linux&Uinx | Windows NT
    Windows Vista | FreeBSD | 其它操作系统
    邮件服务器:
    程序与开发 | Exchange | Qmail | Postfix
    Sendmail | MDaemon | Domino | Foxmail
    KerioMail | JavaMail | Winwebmail |James
    Merak&VisNetic | CMailServer | WinMail
    金笛邮件系统 | 其它 |
    反垃圾邮件:
    综述| 客户端反垃圾邮件|服务器端反垃圾邮件
    邮件客户端软件:
    Outlook | Foxmail | DreamMail| KooMail
    The bat | 雷鸟 | Eudora |Becky! |Pegasus
    IncrediMail |其它
    电子邮箱: 个人邮箱 | 企业邮箱 |Gmail
    移动电子邮件:服务器 | 客户端 | 技术前沿
    邮件网络安全:
    软件漏洞 | 安全知识 | 病毒公告 |防火墙
    攻防技术 | 病毒查杀| ISA | 数字签名
    邮件营销:
    Email营销 | 网络营销 | 营销技巧 |营销案例
    邮件人才:招聘 | 职场 | 培训 | 指南 | 职场
    解决方案:
    邮件系统|反垃圾邮件 |安全 |移动电邮 |招标
    产品评测:
    邮件系统 |反垃圾邮件 |邮箱 |安全 |客户端
    广告联系 | 合作联系 | 关于我们 | 联系我们 | 繁體中文
    版权所有:邮件技术资讯网©2003-2010 www.5dmail.net, All Rights Reserved
    www.5Dmail.net Web Team   粤ICP备05009143号