smtp.c
上传用户:xxcykj
上传日期:2007-01-04
资源大小:727k
文件大小:5k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * smtp.c -- code for speaking SMTP to a listener port
  3.  *
  4.  * Concept due to Harry Hochheiser.  Implementation by ESR.  Cleanup and
  5.  * strict RFC821 compliance by Cameron MacPherson.
  6.  *
  7.  * Copyright 1997 Eric S. Raymond
  8.  * For license terms, see the file COPYING in this directory.
  9.  */
  10. #include <stdio.h>
  11. #include <unistd.h>
  12. #include <string.h>
  13. #include "fetchmail.h"
  14. #include "socket.h"
  15. #include "smtp.h"
  16. #include "config.h"
  17. struct opt
  18. {
  19.     const char *name;
  20.     int value;
  21. };
  22. static struct opt extensions[] =
  23. {
  24.     {"8BITMIME", ESMTP_8BITMIME},
  25.     {"SIZE",     ESMTP_SIZE},
  26.     {"ETRN", ESMTP_ETRN},
  27.     {(char *)NULL, 0},
  28. };
  29. char smtp_response[MSGBUFSIZE];
  30. static char smtp_mode = 'S';
  31. void SMTP_setmode(char sl)
  32. /* set whether we are speaking SMTP or LMTP */
  33. {
  34.     smtp_mode = sl;
  35. }
  36. int SMTP_helo(int sock,const char *host)
  37. /* send a "HELO" message to the SMTP listener */
  38. {
  39.   int ok;
  40.   SockPrintf(sock,"HELO %srn", host);
  41.   if (outlevel >= O_MONITOR)
  42.       report(stdout, "SMTP> HELO %sn", host);
  43.   ok = SMTP_ok(sock);
  44.   return ok;
  45. }
  46. int SMTP_ehlo(int sock, const char *host, int *opt)
  47. /* send a "EHLO" message to the SMTP listener, return extension status bits */
  48. {
  49.   struct opt *hp;
  50.   SockPrintf(sock,"%cHLO %srn", (smtp_mode == 'S') ? 'E' : smtp_mode, host);
  51.   if (outlevel >= O_MONITOR)
  52.       report(stdout, "%cMTP> %cHLO %sn", 
  53.     smtp_mode, (smtp_mode == 'S') ? 'E' : smtp_mode, host);
  54.   
  55.   *opt = 0;
  56.   while ((SockRead(sock, smtp_response, sizeof(smtp_response)-1)) != -1)
  57.   {
  58.       int  n = strlen(smtp_response);
  59.       if (smtp_response[strlen(smtp_response)-1] == 'n')
  60.   smtp_response[strlen(smtp_response)-1] = '';
  61.       if (smtp_response[strlen(smtp_response)-1] == 'r')
  62.   smtp_response[strlen(smtp_response)-1] = '';
  63.       if (n < 4)
  64.   return SM_ERROR;
  65.       smtp_response[n] = '';
  66.       if (outlevel >= O_MONITOR)
  67.   report(stdout, "SMTP< %sn", smtp_response);
  68.       for (hp = extensions; hp->name; hp++)
  69.   if (!strncasecmp(hp->name, smtp_response+4, strlen(hp->name)))
  70.       *opt |= hp->value;
  71.       if ((smtp_response[0] == '1' || smtp_response[0] == '2' || smtp_response[0] == '3') && smtp_response[3] == ' ')
  72.   return SM_OK;
  73.       else if (smtp_response[3] != '-')
  74.   return SM_ERROR;
  75.   }
  76.   return SM_UNRECOVERABLE;
  77. }
  78. int SMTP_from(int sock, const char *from, const char *opts)
  79. /* send a "MAIL FROM:" message to the SMTP listener */
  80. {
  81.     int ok;
  82.     char buf[MSGBUFSIZE];
  83.     if (strchr(from, '<'))
  84. sprintf(buf, "MAIL FROM: %s", from);
  85.     else
  86. sprintf(buf, "MAIL FROM:<%s>", from);
  87.     if (opts)
  88. strcat(buf, opts);
  89.     SockPrintf(sock,"%srn", buf);
  90.     if (outlevel >= O_MONITOR)
  91. report(stdout, "%cMTP> %sn", smtp_mode, buf);
  92.     ok = SMTP_ok(sock);
  93.     return ok;
  94. }
  95. int SMTP_rcpt(int sock, const char *to)
  96. /* send a "RCPT TO:" message to the SMTP listener */
  97. {
  98.   int ok;
  99.   SockPrintf(sock,"RCPT TO:<%s>rn", to);
  100.   if (outlevel >= O_MONITOR)
  101.       report(stdout, "%cMTP> RCPT TO:<%s>n", smtp_mode, to);
  102.   ok = SMTP_ok(sock);
  103.   return ok;
  104. }
  105. int SMTP_data(int sock)
  106. /* send a "DATA" message to the SMTP listener */
  107. {
  108.   int ok;
  109.   SockPrintf(sock,"DATArn");
  110.   if (outlevel >= O_MONITOR)
  111.       report(stdout, "%cMTP> DATAn", smtp_mode);
  112.   ok = SMTP_ok(sock);
  113.   return ok;
  114. }
  115. int SMTP_rset(int sock)
  116. /* send a "RSET" message to the SMTP listener */
  117. {
  118.   int ok;
  119.   SockPrintf(sock,"RSETrn");
  120.   if (outlevel >= O_MONITOR)
  121.       report(stdout, "%cMTP> RSETn", smtp_mode);
  122.   ok = SMTP_ok(sock);
  123.   return ok;
  124. }
  125. int SMTP_quit(int sock)
  126. /* send a "QUIT" message to the SMTP listener */
  127. {
  128.   int ok;
  129.   SockPrintf(sock,"QUITrn");
  130.   if (outlevel >= O_MONITOR)
  131.       report(stdout, "%cMTP> QUITn", smtp_mode);
  132.   ok = SMTP_ok(sock);
  133.   return ok;
  134. }
  135. int SMTP_eom(int sock)
  136. /* send a message data terminator to the SMTP listener */
  137. {
  138.   int ok;
  139.   SockPrintf(sock,".rn");
  140.   if (outlevel >= O_MONITOR)
  141.       report(stdout, "%cMTP>. (EOM)n", smtp_mode);
  142.   /* 
  143.    * When doing LMTP, must process many of these at the outer level. 
  144.    */
  145.   if (smtp_mode == 'S')
  146.       ok = SMTP_ok(sock);
  147.   else
  148.       ok = SM_OK;
  149.   return ok;
  150. }
  151. int SMTP_ok(int sock)
  152. /* returns status of SMTP connection */
  153. {
  154.     while ((SockRead(sock, smtp_response, sizeof(smtp_response)-1)) != -1)
  155.     {
  156. int  n = strlen(smtp_response);
  157. if (smtp_response[strlen(smtp_response)-1] == 'n')
  158.     smtp_response[strlen(smtp_response)-1] = '';
  159. if (smtp_response[strlen(smtp_response)-1] == 'r')
  160.     smtp_response[strlen(smtp_response)-1] = '';
  161. if (n < 4)
  162.     return SM_ERROR;
  163. smtp_response[n] = '';
  164. if (outlevel >= O_MONITOR)
  165.     report(stdout, "%cMTP< %sn", smtp_mode, smtp_response);
  166. if ((smtp_response[0] == '1' || smtp_response[0] == '2' || smtp_response[0] == '3') && smtp_response[3] == ' ')
  167.     return SM_OK;
  168. else if (smtp_response[3] != '-')
  169.     return SM_ERROR;
  170.     }
  171.     return SM_UNRECOVERABLE;
  172. }
  173. /* smtp.c ends here */