Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Examples  

smtp.c

Go to the documentation of this file.
00001 /*! \file smtp.c
00002     This file implements the SMTP client API.
00003  */
00004 
00005 #include <unistd.h>
00006 #include "my_smtp.h"
00007 
00008 /*! \brief Internet address of the SMTP server.
00009  */
00010 
00011 static struct sockaddr_in tcp_add;
00012 
00013 /*! \brief Socket descriptor associated with the TCP connexion.
00014  */
00015 
00016 static int tcp_sock = -1;
00017 
00018 /*! \brief This function is the flex parser itself. Please look at the file 'smtp.lex' for details.
00019  */
00020 
00021 extern int smtp_yylex_memory (char *src);
00022 
00023 /*! \brief Parse the response from the SMTP server.
00024     \param response Pointer to a <b>zero terminated</b> string of characters the response from the SMTP server.
00025     \param data Pointer to a <i>smtp_response</i> data structure that will be used to store information
00026            about the repsonse.
00027     \return The function returns one of the following value:
00028             <UL>
00029               <li>SMTP_SERVER_IDENTIFICATION_OK = 220
00030                   ("220 newsletter.tiscali.fr Simple Mail Transfer Service Ready" - follow the connexion)
00031               <li>SMTP_CLIENT_IDENTIFICATION_OK = 250
00032                   ("250 newsletter.tiscali.fr" - Follow the command HELO or EHLO)
00033               <li>SMTP_FROM_OK = 250
00034                   ("250 OK" - Follow the command MAIL FROM)
00035               <li>SMTP_RCPT_OK = 250
00036                   ("250 OK" - Follow the command RCPT TO)
00037               <li>SMTP_DATA_OK = 354
00038                   ("354 Start mail input; end with...", Follow the command DATA)
00039               <li>SMTP_END_OF_DATA_OK = 250
00040                   ("250 OK" - Follow the &lt;CRLF&gt;.&lr;CRLF&gt; that marks the end of the data part.
00041               <li>SMTP_INVALID_ANSWER = -1
00042                   This means that the response is not well formated.
00043             </UL>
00044  */
00045 
00046 static int response_parser (char *response, struct smtp_response *data)
00047 {
00048   int rc;
00049 
00050   rc = smtp_yylex_memory(response);
00051 
00052   /* ---------------------------------------------- */
00053   /* Please look at the file 'smtp.lex': the value  */
00054   /* of rc can be:                                  */
00055   /*                                                */
00056   /*  o 220                                         */
00057   /*  o 250                                         */
00058   /*  o 354                                         */
00059   /*  o -1                                          */
00060   /*  o 0                                           */
00061   /* ---------------------------------------------- */
00062 
00063   if ((rc == 0) || (rc == -1)) { return SMTP_INVALID_ANSWER; }
00064 
00065   return rc;
00066 }
00067 
00068 
00069 
00070 
00071 
00072 
00073 /*! \brief Open a connexion to the SMTP server.
00074     \param conf Pointer to a configuration structure.
00075     \param result Pointer to <i>smtp_res</i> structure.
00076     \return Upon successful completion, the function returns a positive number that represents the socket
00077             descriptor associated with the connexion. In this case, the field <i>ellapsed</i> contains
00078             the ellapsed time of the connexion in milli-seconds.
00079 
00080             Otherwise the function returns the value -1. In this case the field <i>error_code</i> of
00081             <i>result</i> contains a value that identifies the failure. This value may be:
00082 
00083             <UL>
00084               <li>An error code from the function <i>open_tcp_connexion()</i> (of the Common C Library). See the
00085                   detailed description of <i>open_tcp_connexion()</i> for full details.
00086               <li>An error code from the function <i>read_from_socket()</i>(of the Common C Library). See the
00087                   detailed description of <i>read_from_socket()</i> for full details.
00088               <li>The value SMTP_WRITE_ERROR. This means that the system call write failed.
00089               <li>The value SMTP_BAD_ANSWER. This means that the response from the SMTP server was not valid.
00090             </UL>
00091  */
00092 
00093 int client_smtp_connect ( 
00094                           struct smtp_connexion_config *conf,
00095                           struct smtp_res *result
00096                         )
00097 {
00098   int                   sock, rc;
00099   char                  iobuff[SMTP_BUFFER_SIZE];
00100   size_t                read_bytes;
00101   struct smtp_response  smtp_res;
00102   long                  ellapsed;
00103   
00104 
00105   result->error_code = 0;
00106   result->ellapsed   = 0;
00107   tcp_sock           = -1;
00108 
00109   /* ----------------------------------------------- */
00110   /* Open the TCP connexion                          */
00111   /* ----------------------------------------------- */
00112 
00113   sock = open_tcp_connexion(
00114                              &tcp_add,
00115                              conf->host,
00116                              conf->port,
00117                              conf->connect_timeout_sec,
00118                              conf->connect_timeout_micro,
00119                              &ellapsed
00120                            );
00121 
00122   if (sock < 0)
00123   {
00124     result->error_code = sock;
00125     return -1;
00126   }
00127 
00128   result->ellapsed += ellapsed;
00129 
00130   /* ----------------------------------------------- */
00131   /* Read server's identification                    */
00132   /* ----------------------------------------------- */
00133 
00134   rc = read_from_socket (
00135                            sock,
00136                            iobuff,
00137                            SMTP_BUFFER_SIZE-1,
00138                            &read_bytes,
00139                            conf->read_timeout_sec,
00140                            conf->read_timeout_micro,
00141                            &ellapsed
00142                         );
00143 
00144   if (rc != SCK_READ_OK)
00145   {
00146     smtp_disconnect();
00147     result->error_code = rc;
00148     return -1;
00149   }
00150 
00151   result->ellapsed += ellapsed;
00152 
00153   iobuff[read_bytes] = 0;
00154 
00155   /* ----------------------------------------------- */
00156   /* Check the answer                                */
00157   /* ----------------------------------------------- */
00158 
00159   rc = response_parser (iobuff, &smtp_res);
00160 
00161   if (rc != SMTP_SERVER_IDENTIFICATION_OK)
00162   {
00163     smtp_disconnect();
00164     result->error_code = SMTP_BAD_ANSWER;
00165     return -1;
00166   }
00167 
00168   /* ----------------------------------------------- */
00169   /* Send client's identificator                     */
00170   /* ----------------------------------------------- */
00171 
00172   if (write (sock, conf->id, strlen(conf->id)) !=  strlen(conf->id))
00173   {
00174     smtp_disconnect();
00175     result->error_code = SMTP_WRITE_ERROR;
00176     return -1;
00177   }
00178 
00179   /* ----------------------------------------------- */
00180   /* Read the answer from the SMTP server            */
00181   /* ----------------------------------------------- */
00182 
00183   rc = read_from_socket (
00184                            sock,
00185                            iobuff,
00186                            SMTP_BUFFER_SIZE-1,
00187                            &read_bytes,
00188                            conf->read_timeout_sec,
00189                            conf->read_timeout_micro,
00190                            &ellapsed
00191                         );
00192 
00193   if (rc != SCK_READ_OK)
00194   {
00195     smtp_disconnect();
00196     result->error_code = rc;
00197     return -1;
00198   }
00199 
00200   result->ellapsed += ellapsed;
00201 
00202   iobuff[read_bytes] = 0;
00203 
00204   /* ----------------------------------------------- */
00205   /* Check the answer                                */
00206   /* ----------------------------------------------- */
00207 
00208   rc = response_parser (iobuff, &smtp_res);
00209 
00210   if (rc != SMTP_CLIENT_IDENTIFICATION_OK)
00211   {
00212     smtp_disconnect();
00213     result->error_code = SMTP_BAD_ANSWER;
00214     return -1;
00215   }
00216 
00217   /* ----------------------------------------------- */
00218   /* Everything is OK, set 'tcp_sock' to the socket  */
00219   /* descriptor.                                     */
00220   /* ----------------------------------------------- */
00221 
00222   tcp_sock = sock;
00223 
00224   return 0;
00225 }
00226 
00227 /*! \brief Close the connexion between the SMTP client ant the server.
00228  */
00229 
00230 void smtp_disconnect() { if (tcp_sock >= 0) { close(tcp_sock); } }
00231 
00232 /*! \brief Send an email to the SMTP server.
00233     \param conf Pointer to a configuration structure.
00234     \param email Pointer to a <i>smtp_mail</i> structure that contains the mail's data.
00235     \param result Pointer to <i>smtp_res</i> structure.
00236     \return Upon successfull completion the function returns 0, therwise it returns -1 and <b>the connexion is
00237             closed</b>.
00238 
00239             If the returned value is 0 (success), then the field <i>ellapsed</i> of the structure pointed by
00240             <i>result</i> contains the ellapsed time of the action in milli-seconds.
00241 
00242             If the returned value is -1 (error), then the field <i>error_code</i> of the structure pointed by
00243             <i>result</i> contains an error code that describes the failure. This value may be:
00244 
00245             <UL>
00246               <li>An error code from the function <i>read_from_socket()</i>(of the Common C Library). See the
00247                   detailed description of <i>read_from_socket()</i> for full details.
00248               <li>The value SMTP_WRITE_ERROR. This means that the system call write failed.
00249               <li>The value SMTP_BAD_ANSWER. This means that the response from the SMTP server was not valid.
00250               <li>The value SMTP_BUFFER_OVERFLOW. This means that one of the input arguments "from" or "rcpt"
00251                   is too long.
00252             </UL>
00253 
00254 
00255  */
00256 
00257 int smtp_send_email (
00258                       struct smtp_connexion_config  *conf,
00259                       struct smtp_mail              *email,
00260                       struct smtp_res               *result
00261                     )
00262 {
00263   int                   i, rc;
00264   char                  iobuff[SMTP_BUFFER_SIZE];
00265   size_t                read_bytes;
00266   struct smtp_response  smtp_res;
00267   long                  ellapsed;
00268 
00269   result->error_code = 0;
00270   result->ellapsed   = 0;
00271 
00272   /* ----------------------------------------------- */
00273   /* Check for buffer overflows                      */  
00274   /* ----------------------------------------------- */
00275 
00276   if (
00277        (
00278          strlen(email->from)
00279          +
00280          strlen(SMTP_FROM_TAG_START)
00281          +
00282          strlen(SMTP_FROM_TAG_STOP)
00283        )
00284        >
00285        SMTP_BUFFER_SIZE - 1
00286      )
00287      { 
00288        smtp_disconnect();
00289        result->error_code = SMTP_BUFFER_OVERFLOW;
00290        return -1;
00291      }
00292 
00293   sprintf (iobuff, "%s%s%s", SMTP_FROM_TAG_START, email->from, SMTP_FROM_TAG_STOP); 
00294 
00295   /* ----------------------------------------------- */
00296   /* Send the FROM command                           */  
00297   /* ----------------------------------------------- */
00298 
00299   if (write (tcp_sock, iobuff, strlen(iobuff)) !=  strlen(iobuff))
00300   {
00301     smtp_disconnect();
00302     result->error_code = SMTP_WRITE_ERROR;
00303     return -1;
00304   }
00305 
00306   /* ----------------------------------------------- */
00307   /* Read answer from SMTP server                    */
00308   /* ----------------------------------------------- */
00309 
00310   rc = read_from_socket (
00311                            tcp_sock,
00312                            iobuff,
00313                            SMTP_BUFFER_SIZE-1,
00314                            &read_bytes,
00315                            conf->read_timeout_sec,
00316                            conf->read_timeout_micro,
00317                            &ellapsed
00318                         );
00319 
00320   if (rc != SCK_READ_OK)
00321   {
00322     smtp_disconnect();
00323     result->error_code = rc;
00324     return -1;
00325   }
00326 
00327   result->ellapsed += ellapsed;
00328 
00329   iobuff[read_bytes] = 0;
00330 
00331   /* ----------------------------------------------- */
00332   /* Check the answer from the SMTP server           */
00333   /* ----------------------------------------------- */
00334 
00335   rc = response_parser (iobuff, &smtp_res);
00336 
00337   if (rc != SMTP_FROM_OK)
00338   {
00339     smtp_disconnect();
00340     result->error_code = SMTP_BAD_ANSWER;
00341     return -1;
00342   }
00343 
00344   /* ----------------------------------------------- */
00345   /* Send all RCPT data                              */
00346   /* ----------------------------------------------- */
00347 
00348   for (i=0; i<email->rcpt_number; i++)
00349   {
00350 
00351     /* --------------------------------------------- */
00352     /* Check for buffer overflows                    */
00353     /* --------------------------------------------- */
00354 
00355     if (
00356          (
00357            strlen(email->rcpt)
00358            +
00359            strlen(SMTP_RCPT_TAG_START)
00360            +
00361            strlen(SMTP_RCPT_TAG_STOP)
00362          )
00363          >
00364          SMTP_BUFFER_SIZE - 1
00365        )
00366        {
00367          smtp_disconnect();
00368          result->error_code = SMTP_BUFFER_OVERFLOW;
00369          return -1;
00370        }
00371 
00372     sprintf (iobuff, "%s%s%s", SMTP_RCPT_TAG_START, email->rcpt, SMTP_RCPT_TAG_STOP);
00373 
00374     /* --------------------------------------------- */
00375     /* Send the RCPT command                         */
00376     /* --------------------------------------------- */
00377 
00378     if (write (tcp_sock, iobuff, strlen(iobuff)) !=  strlen(iobuff))
00379     {
00380       smtp_disconnect();
00381       result->error_code = SMTP_WRITE_ERROR;
00382       return -1;
00383     }
00384 
00385     /* --------------------------------------------- */
00386     /* Read the response from the SMTP server        */
00387     /* --------------------------------------------- */
00388 
00389     rc = read_from_socket (
00390                              tcp_sock,
00391                              iobuff,
00392                              SMTP_BUFFER_SIZE-1,
00393                              &read_bytes,
00394                              conf->read_timeout_sec,
00395                              conf->read_timeout_micro,
00396                              &ellapsed
00397                           );
00398 
00399     if (rc != SCK_READ_OK)
00400     {
00401       smtp_disconnect();
00402       result->error_code = rc;
00403       return -1;
00404     }
00405 
00406     result->ellapsed += ellapsed;
00407 
00408     iobuff[read_bytes] = 0;
00409 
00410     /* --------------------------------------------- */
00411     /* Check the answer from the SMTP server         */
00412     /* --------------------------------------------- */
00413 
00414     rc = response_parser (iobuff, &smtp_res);
00415 
00416     if (rc != SMTP_RCPT_OK)
00417     {
00418       smtp_disconnect();
00419       result->error_code = SMTP_BAD_ANSWER;
00420       return -1;
00421     }
00422   }
00423 
00424   /* ----------------------------------------------- */
00425   /* Now send the DATA command                       */
00426   /* ----------------------------------------------- */
00427 
00428   strcpy (iobuff, "DATA\r\n");
00429 
00430   if (write (tcp_sock, iobuff, strlen(iobuff)) !=  strlen(iobuff))
00431   {
00432     smtp_disconnect();
00433     result->error_code = SMTP_WRITE_ERROR;
00434     return -1;
00435   }
00436 
00437   /* ----------------------------------------------- */
00438   /* Read answer from SMTP server                    */
00439   /* ----------------------------------------------- */
00440 
00441   rc = read_from_socket (
00442                            tcp_sock,
00443                            iobuff,
00444                            SMTP_BUFFER_SIZE-1,
00445                            &read_bytes,
00446                            conf->read_timeout_sec,
00447                            conf->read_timeout_micro,
00448                            &ellapsed
00449                         );
00450 
00451   if (rc != SCK_READ_OK)
00452   {
00453     smtp_disconnect();
00454     result->error_code = rc;
00455     return -1;
00456   }
00457 
00458   result->ellapsed += ellapsed;
00459 
00460   iobuff[read_bytes] = 0;
00461 
00462   /* ----------------------------------------------- */
00463   /* Check the answer from the SMTP server           */
00464   /* ----------------------------------------------- */
00465 
00466   rc = response_parser (iobuff, &smtp_res);
00467 
00468   if (rc != SMTP_DATA_OK)
00469   {
00470     smtp_disconnect();
00471     result->error_code = SMTP_BAD_ANSWER;
00472     return -1;
00473   }
00474 
00475   /* ----------------------------------------------- */
00476   /* Send the body itself                            */
00477   /* ----------------------------------------------- */
00478 
00479   if (write (tcp_sock, email->data, strlen(email->data)) !=  strlen(email->data))
00480   {
00481     smtp_disconnect();
00482     result->error_code = SMTP_WRITE_ERROR;
00483     return -1;
00484   }
00485 
00486   /* ----------------------------------------------- */
00487   /* Read answer from SMTP server                    */
00488   /* ----------------------------------------------- */
00489 
00490   rc = read_from_socket (
00491                            tcp_sock,
00492                            iobuff,
00493                            SMTP_BUFFER_SIZE-1,
00494                            &read_bytes,
00495                            conf->read_timeout_sec,
00496                            conf->read_timeout_micro,
00497                            &ellapsed
00498                         );
00499 
00500   if (rc != SCK_READ_OK)
00501   {
00502     smtp_disconnect();
00503     result->error_code = rc;
00504     return -1;
00505   }
00506 
00507   result->ellapsed += ellapsed;
00508 
00509   iobuff[read_bytes] = 0;
00510 
00511   /* ----------------------------------------------- */
00512   /* Check the answer from the SMTP server           */
00513   /* ----------------------------------------------- */
00514 
00515   rc = response_parser (iobuff, &smtp_res);
00516 
00517   if (rc != SMTP_END_OF_DATA_OK)
00518   {
00519     smtp_disconnect();
00520     result->error_code = SMTP_BAD_ANSWER;
00521     return -1;
00522   }
00523 
00524   /* ----------------------------------------------- */
00525   /* Send the QUIT command and close the connexion   */
00526   /* ----------------------------------------------- */
00527 
00528   strcpy (iobuff, "QUIT\r\n");
00529 
00530   if (write (tcp_sock, iobuff, strlen(iobuff)) !=  strlen(iobuff))
00531   {
00532     smtp_disconnect();
00533     result->error_code = SMTP_WRITE_ERROR;
00534     return -1;
00535   }
00536 
00537   smtp_disconnect();
00538 
00539   return 0;
00540 }

Generated on Thu Apr 3 16:23:44 2003 for Common_C_libraries by doxygen1.3-rc1