Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->Linux程序设计 ->正文

程序员眼中的qmail(qmail源代码分析)

来源:5dmail.net 作者:未知  时间:2007-04-22 点击: [收藏] [投稿]

  很多人对qmail smtp的认证机制,环境变量,执行顺序不太了解。

  仔细看完这一大篇代码后相信你会明白很多你过去不太明白的问题。

  当然你要有一点点c语言基础。也只要一点点。

  Come from: ChongQing Gearbox co.,ltd

  这份文件还不完善,如果您完善了它请发一份给我: beggar110@163.com

  这份文件是给想深入了解qmail和想hacker qmail的人读的,如果你只是想建立一个能够运作的mail服务器,没有必要读下去了。它将浪费你很多的时间。

  如果你对qmail控制文件还不是很了解,阅读这份文件之前,请先阅读rainbow的《qmail控制文件详解》

  在这里你可以找到www.chinaunix.net/forum/viewtopic.php?t=1126

  好的。开始我们qmail内部的漫游吧!!!Let's go!

  代码:

  qmail 总览

  tcpserver MUA

  | |

  V V

  qmail-smtpd qmail-inject

  | |

  +----------->qmail-queue<-----------+

  |

  |

  qmail-send

  |

  +------------+------------+

  | |

  V V

  qmail-rspawn qmail-lspawn

  | |

  V V

  qmail-remote qmail-local

  | |

  | |

  V V

  INTERNET <----qmail-pop3d

  |

  |

  vchkpw

  |

  |

  qmail-popup

  |

  |

  tcpserver--+

  qmail-smtpd.c源代码分析(去掉了所有include)

  qmail -smtpd是由tcpserver或由tcp-env启动。tcpserver负责监听端口,如果指定了-x rule.cbd,tcpserver会先决断是断开连接还是启动qmail子进程。如果没有指定-x参数启动tcpserver,那么直接启动 qmail-smtpd.启动qmail-smtpd之前将来自网络的数据连接重定向到qmail-smtpd的fd0,fd1.还会初始化一些 qmail-smtpd需要的环境变量,如TCPREMOTEIP.

  tcp-env只会初始化qmail-smtpd的环境变量,不负责监听端口及重定向网络连接。所以tcp-env要和inetd配合使用。当然,由于初始化环境变量的工作tcpserver也会作,所以没有必要tcpserver和tcp-env配合使用.

  qmail-smtpd完成邮件smtp命令的接收,并调用相应的处理程序。

  检查mail 中的地址是否在control/badmailfrom中定义(MAIL命令)

  检查是否设置了RELAYCLIENT环境变量或 rcpt 中的地址是否是control/rcpthosts中定义(RCPT命令)

  需要明确的是qmail-smtpd只是简单的接收邮件内容传送给qmail-queue,并不对邮件进行转发(DATA命令)。

  当然还要向qmail-queue传送mailfrom,mailto

  代码:

  #define MAXHOPS 100

  unsigned int databytes = 0; //邮件最大长度:0=无限

  int timeout = 1200; //默认超时20分钟

  //向网络写,超时值为control/timeoutsmtpd指定的值。没有这个文件则取默认值20分钟

  int safewrite(fd,buf,len) int fd; char *buf; int len;

  {

  int r;

  r = timeoutwrite(timeout,fd,buf,len);

  if (r <= 0) _exit(1);

  return r;

  }

  char ssoutbuf[512];

  substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);

  void flush() { substdio_flush(&ssout); }

  void out(s) char *s; { substdio_puts(&ssout,s); }

  //错误处理函数

  void die_read() { _exit(1); }

  void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); }

  void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); }

  void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); }

  void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }

  void straynewline() { out("451 See pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }

  void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }

  void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }

  void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }

  void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }

  void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }

  void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }

  void err_noop() { out("250 ok\r\n"); }

  void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }

  void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }

  stralloc greeting = {0};

  //输出提示信息*code

  void smtp_greet(code) char *code;

  {

  substdio_puts(&ssout,code);

  substdio_put(&ssout,greeting.s,greeting.len);

  }

  void smtp_help()

  {

  out("214 qmail home page:

  void>pobox.com/~djb/qmail.html\r\n");

  }

  void

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:使用 Flex 和 Bison 更好地进行错误处理   下一篇:GNU 线性编程工具包(线性优化简介)

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号