/[mailutils]/mailutils/mailbox/smtp.c
ViewVC logotype

Diff of /mailutils/mailbox/smtp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.26 by gray, Tue Oct 29 12:44:30 2002 UTC revision 1.27 by gray, Sun Nov 3 12:51:58 2002 UTC
# Line 50  Line 50 
50  #include <mailer0.h>  #include <mailer0.h>
51  #include <registrar0.h>  #include <registrar0.h>
52    
53  static struct _record _smtp_record =  static struct _record _smtp_record = {
 {  
54    MU_SMTP_SCHEME,    MU_SMTP_SCHEME,
55    _url_smtp_init,      /* url init.  */    _url_smtp_init,               /* url init.  */
56    NULL,                /* Mailbox init.  */    NULL,                         /* Mailbox init.  */
57    &_mailer_smtp_init,  /* Mailer init.  */    &_mailer_smtp_init,           /* Mailer init.  */
58    NULL, /* Folder init.  */    NULL,                         /* Folder init.  */
59    NULL, /* No need for a back pointer.  */    NULL,                         /* No need for a back pointer.  */
60    NULL, /* _is_scheme method.  */    NULL,                         /* _is_scheme method.  */
61    NULL, /* _get_url method.  */    NULL,                         /* _get_url method.  */
62    NULL, /* _get_mailbox method.  */    NULL,                         /* _get_mailbox method.  */
63    NULL, /* _get_mailer method.  */    NULL,                         /* _get_mailer method.  */
64    NULL  /* _get_folder method.  */    NULL                          /* _get_folder method.  */
65  };  };
66  /* We export : url parsing and the initialisation of  /* We export : url parsing and the initialisation of
67     the mailbox, via the register entry/record.  */     the mailbox, via the register entry/record.  */
# Line 75  struct _smtp Line 74  struct _smtp
74    char *localhost;    char *localhost;
75    
76    /* IO buffering. */    /* IO buffering. */
77    char *buffer; /* Must be freed. */    char *buffer;                 /* Must be freed. */
78    size_t buflen;    size_t buflen;
79    
80    char *ptr;    char *ptr;
# Line 89  struct _smtp Line 88  struct _smtp
88      SMTP_ENV_RCPT, SMTP_MAIL_FROM, SMTP_MAIL_FROM_ACK, SMTP_RCPT_TO,      SMTP_ENV_RCPT, SMTP_MAIL_FROM, SMTP_MAIL_FROM_ACK, SMTP_RCPT_TO,
89      SMTP_RCPT_TO_ACK, SMTP_DATA, SMTP_DATA_ACK, SMTP_SEND, SMTP_SEND_ACK,      SMTP_RCPT_TO_ACK, SMTP_DATA, SMTP_DATA_ACK, SMTP_SEND, SMTP_SEND_ACK,
90      SMTP_SEND_DOT      SMTP_SEND_DOT
91    } state;    }
92      state;
93    
94    int extended;    int extended;
95    
96    char* mail_from;    char *mail_from;
97    address_t rcpt_to; /* Destroy this if not the same as argto below. */    address_t rcpt_to;            /* Destroy this if not the same as argto below. */
98    address_t rcpt_bcc;    address_t rcpt_bcc;
99    size_t rcpt_to_count;    size_t rcpt_to_count;
100    size_t rcpt_bcc_count;    size_t rcpt_bcc_count;
101    size_t rcpt_index;    size_t rcpt_index;
102    size_t rcpt_count;    size_t rcpt_count;
103    int bccing;    int bccing;
104    message_t msg; /* Destroy this if not same argmsg. */    message_t msg;                /* Destroy this if not same argmsg. */
105    
106    off_t offset;    off_t offset;
107    
# Line 111  struct _smtp Line 111  struct _smtp
111    address_t argto;    address_t argto;
112  };  };
113    
114  typedef struct _smtp * smtp_t;  typedef struct _smtp *smtp_t;
115    
116  static void smtp_destroy (mailer_t);  static void smtp_destroy (mailer_t);
117  static int smtp_open (mailer_t, int);  static int smtp_open (mailer_t, int);
# Line 122  static int smtp_readline (smtp_t); Line 122  static int smtp_readline (smtp_t);
122  static int smtp_read_ack (smtp_t);  static int smtp_read_ack (smtp_t);
123  static int smtp_write (smtp_t);  static int smtp_write (smtp_t);
124    
125  static int _smtp_set_from (smtp_t, message_t , address_t);  static int _smtp_set_from (smtp_t, message_t, address_t);
126  static int _smtp_set_rcpt (smtp_t, message_t , address_t);  static int _smtp_set_rcpt (smtp_t, message_t, address_t);
127    
128  /* Useful little macros, since these are very repetitive. */  /* Useful little macros, since these are very repetitive. */
129    
# Line 173  CLEAR_STATE (smtp_t smtp) Line 173  CLEAR_STATE (smtp_t smtp)
173     as that which is ongoing. Check this. */     as that which is ongoing. Check this. */
174  static int  static int
175  smtp_check_send_resumption (smtp_t smtp,  smtp_check_send_resumption (smtp_t smtp,
176                         message_t msg, address_t from, address_t to)                              message_t msg, address_t from, address_t to)
177  {  {
178    if(smtp->state == SMTP_NO_STATE)    if (smtp->state == SMTP_NO_STATE)
179      return 0;      return 0;
180    
181    /* FIXME: state should be one of the "send" states if its not    /* FIXME: state should be one of the "send" states if its not
# Line 248  _mailer_smtp_init (mailer_t mailer) Line 248  _mailer_smtp_init (mailer_t mailer)
248    if (mailer->data == NULL)    if (mailer->data == NULL)
249      return ENOMEM;      return ENOMEM;
250    
251    smtp->mailer = mailer; /* Back pointer.  */    smtp->mailer = mailer;        /* Back pointer.  */
252    smtp->state = SMTP_NO_STATE;    smtp->state = SMTP_NO_STATE;
253    
254    mailer->_destroy = smtp_destroy;    mailer->_destroy = smtp_destroy;
# Line 267  _mailer_smtp_init (mailer_t mailer) Line 267  _mailer_smtp_init (mailer_t mailer)
267  }  }
268    
269  static void  static void
270  smtp_destroy(mailer_t mailer)  smtp_destroy (mailer_t mailer)
271  {  {
272    smtp_t smtp = mailer->data;    smtp_t smtp = mailer->data;
273    
274    CLEAR_STATE(smtp);    CLEAR_STATE (smtp);
275    
276    /* Not our responsability to close.  */    /* Not our responsability to close.  */
277    
# Line 334  smtp_open (mailer_t mailer, int flags) Line 334  smtp_open (mailer_t mailer, int flags)
334          }          }
335        /* Fetch our local host name.  */        /* Fetch our local host name.  */
336    
337        status = mu_get_host_name(&smtp->localhost);        status = mu_get_host_name (&smtp->localhost);
338    
339        if (status != 0)        if (status != 0)
340          {          {
# Line 346  smtp_open (mailer_t mailer, int flags) Line 346  smtp_open (mailer_t mailer, int flags)
346    
347        /* allocate a working io buffer.  */        /* allocate a working io buffer.  */
348        if (smtp->buffer == NULL)        if (smtp->buffer == NULL)
349          {          {
350            smtp->buflen = 512; /* Initial guess.  */            smtp->buflen = 512;   /* Initial guess.  */
351            smtp->buffer = malloc (smtp->buflen + 1);            smtp->buffer = malloc (smtp->buflen + 1);
352            if (smtp->buffer == NULL)            if (smtp->buffer == NULL)
353              {              {
354                CHECK_ERROR (smtp, ENOMEM);                CHECK_ERROR (smtp, ENOMEM);
355              }              }
356            smtp->ptr = smtp->buffer;            smtp->ptr = smtp->buffer;
357          }          }
358    
359        /* Create a TCP stack if one is not given.  */        /* Create a TCP stack if one is not given.  */
360        if (mailer->stream == NULL)        if (mailer->stream == NULL)
361          {          {
362            status = tcp_stream_create (&mailer->stream, smtp->mailhost, port, mailer->flags);            status =
363                tcp_stream_create (&mailer->stream, smtp->mailhost, port,
364                                   mailer->flags);
365            CHECK_ERROR (smtp, status);            CHECK_ERROR (smtp, status);
366            stream_setbufsiz (mailer->stream, BUFSIZ);            stream_setbufsiz (mailer->stream, BUFSIZ);
367          }          }
# Line 412  smtp_open (mailer_t mailer, int flags) Line 414  smtp_open (mailer_t mailer, int flags)
414          }          }
415    
416      case SMTP_HELO:      case SMTP_HELO:
417        if (!smtp->extended) /* FIXME: this will always be false! */        if (!smtp->extended)      /* FIXME: this will always be false! */
418          {          {
419            status = smtp_write (smtp);            status = smtp_write (smtp);
420            CHECK_EAGAIN (smtp, status);            CHECK_EAGAIN (smtp, status);
# Line 437  smtp_open (mailer_t mailer, int flags) Line 439  smtp_open (mailer_t mailer, int flags)
439        break;        break;
440      }      }
441    
442    CLEAR_STATE(smtp);    CLEAR_STATE (smtp);
443    
444    return 0;    return 0;
445  }  }
# Line 486  message_set_header_value (message_t msg, Line 488  message_set_header_value (message_t msg,
488  }  }
489    
490  static int  static int
491  message_has_bcc(message_t msg)  message_has_bcc (message_t msg)
492  {  {
493    int status;    int status;
494    header_t header = NULL;    header_t header = NULL;
# Line 547  smtp_send_message (mailer_t mailer, mess Line 549  smtp_send_message (mailer_t mailer, mess
549    smtp_t smtp = NULL;    smtp_t smtp = NULL;
550    int status;    int status;
551    
552    if(mailer == NULL)    if (mailer == NULL)
553      return EINVAL;      return EINVAL;
554    
555    smtp = mailer->data;    smtp = mailer->data;
# Line 572  smtp_send_message (mailer_t mailer, mess Line 574  smtp_send_message (mailer_t mailer, mess
574        CHECK_ERROR (smtp, status);        CHECK_ERROR (smtp, status);
575    
576        /* Clear the Bcc: field if we found one. */        /* Clear the Bcc: field if we found one. */
577        if (message_has_bcc(smtp->argmsg))        if (message_has_bcc (smtp->argmsg))
578          {          {
579            smtp->msg = NULL;            smtp->msg = NULL;
580            status = message_create_copy (&smtp->msg, smtp->argmsg);            status = message_create_copy (&smtp->msg, smtp->argmsg);
# Line 630  smtp_send_message (mailer_t mailer, mess Line 632  smtp_send_message (mailer_t mailer, mess
632          CHECK_ERROR (smtp, status);          CHECK_ERROR (smtp, status);
633    
634          /* Add the Bcc: field back in for recipient. */          /* Add the Bcc: field back in for recipient. */
635          if(smtp->bccing)          if (smtp->bccing)
636          {            {
637            status = message_set_header_value (smtp->msg, MU_HEADER_BCC, to);              status = message_set_header_value (smtp->msg, MU_HEADER_BCC, to);
638            CHECK_ERROR (smtp, status);              CHECK_ERROR (smtp, status);
639          }            }
640    
641          status = smtp_writeline (smtp, "RCPT TO: %s\r\n", to);          status = smtp_writeline (smtp, "RCPT TO: %s\r\n", to);
642    
# Line 686  smtp_send_message (mailer_t mailer, mess Line 688  smtp_send_message (mailer_t mailer, mess
688        smtp->offset = 0;        smtp->offset = 0;
689        smtp->state = SMTP_SEND;        smtp->state = SMTP_SEND;
690    
691        if((smtp->mailer->flags & MAILER_FLAG_DEBUG_DATA) == 0)        if ((smtp->mailer->flags & MAILER_FLAG_DEBUG_DATA) == 0)
692          MAILER_DEBUG0 (smtp->mailer, MU_DEBUG_PROT, "> (data...)\n");          MAILER_DEBUG0 (smtp->mailer, MU_DEBUG_PROT, "> (data...)\n");
693    
694      case SMTP_SEND:      case SMTP_SEND:
695        {        {
696          stream_t stream;          stream_t stream;
697          size_t n = 0;          size_t n = 0;
698          char data[256] = "";          char data[256] = "";
699            
700          /* We may be here after an EAGAIN so check if we have something          /* We may be here after an EAGAIN so check if we have something
701             in the buffer and flush it.  */             in the buffer and flush it.  */
702          status = smtp_write (smtp);          status = smtp_write (smtp);
703          CHECK_EAGAIN (smtp, status);          CHECK_EAGAIN (smtp, status);
704    
705          message_get_stream (smtp->msg, &stream);          message_get_stream (smtp->msg, &stream);
706          while ((status = stream_readline (stream, data, sizeof (data) - 1,          while ((status = stream_readline (stream, data, sizeof (data) - 1,
707                                            smtp->offset, &n)) == 0 && n > 0)                                            smtp->offset, &n)) == 0 && n > 0)
# Line 862  _smtp_set_from (smtp_t smtp, message_t m Line 866  _smtp_set_from (smtp_t smtp, message_t m
866    return status;    return status;
867  }  }
868    
869    int
870    smtp_address_add (address_t *paddr, const char *value)
871    {
872      address_t addr = NULL;
873      int status;
874    
875      status = address_create (&addr, value);
876      if (status)
877        return status;
878      status = address_union (paddr, addr);
879      address_destroy (&addr);
880      return status;
881    }
882    
883  static int  static int
884  _smtp_set_rcpt (smtp_t smtp, message_t msg, address_t to)  _smtp_set_rcpt (smtp_t smtp, message_t msg, address_t to)
885  {  {
886    int status = 0;    int status = 0;
887    header_t header = NULL;    header_t header = NULL;
888    char *toaddrv[3] = { NULL, NULL };    char *value;
889    char *bccaddr = NULL;    
   address_t rcpt_to = NULL;  
   address_t rcpt_bcc = NULL;  
   
890    /* Get RCPT_TO from TO, or the message. */    /* Get RCPT_TO from TO, or the message. */
891    
 /* FIXME: even if there are TO addresses on the command-line, I have  
    to blank out the Bcc: header in the message!  
    */  
892    if (to)    if (to)
893      {      {
894        /* Use the specified address_t. */        /* Use the specified address_t. */
# Line 889  _smtp_set_rcpt (smtp_t smtp, message_t m Line 901  _smtp_set_rcpt (smtp_t smtp, message_t m
901        smtp->rcpt_to = to;        smtp->rcpt_to = to;
902        address_get_count (smtp->rcpt_to, &smtp->rcpt_to_count);        address_get_count (smtp->rcpt_to, &smtp->rcpt_to_count);
903    
904        return status;        if (status)
905            return status;
906      }      }
907    
908    if ((status = message_get_header (msg, &header)))    if ((status = message_get_header (msg, &header)))
909      return status;      return status;
910    
911    status = header_aget_value (header, MU_HEADER_TO, toaddrv + 0);    status = header_aget_value (header, MU_HEADER_TO, &value);
912    
913    if (status && status != ENOENT)    if (status == 0)
914        {
915          smtp_address_add (&smtp->rcpt_to, value);
916          free (value);
917        }
918      else if (status && status != ENOENT)
919      goto end;      goto end;
920    
921    status = header_aget_value (header, MU_HEADER_CC, toaddrv + 1);    status = header_aget_value (header, MU_HEADER_CC, &value);
922    
923    if (status && status != ENOENT)    if (status == 0)
924        {
925          smtp_address_add (&smtp->rcpt_to, value);
926          free (value);
927        }
928      else if (status && status != ENOENT)
929      goto end;      goto end;
930    
931    status = header_aget_value (header, MU_HEADER_BCC, &bccaddr);    status = header_aget_value (header, MU_HEADER_BCC, &value);
932      if (status == 0)
933    if (status && status != ENOENT)      {
934          smtp_address_add (&smtp->rcpt_bcc, value);
935          free (value);
936        }
937      else if (status && status != ENOENT)
938      goto end;      goto end;
939    
   status = 0;  
   
   {  
     const char **av = (const char **) toaddrv;  
     int tostatus = address_createv (&rcpt_to, av, 2);  
   
     /* Any error other than EMPTY_ADDRESS is fatal */  
     if (tostatus)  
       {  
         if (tostatus == MU_ERR_EMPTY_ADDRESS)  
           tostatus = MU_ERR_MAILER_NO_RCPT_TO;  
         else  
           goto end;  
       }  
   
     if (!bccaddr)  
       status = MU_ERR_EMPTY_ADDRESS;  
     else  
       {  
         status = address_create (&rcpt_bcc, bccaddr);  
   
         if (status)  
           {  
             if (status == MU_ERR_EMPTY_ADDRESS)  
               status = MU_ERR_MAILER_NO_RCPT_TO;  
             else  
               goto end;  
           }  
       }  
   
     /* If both to and bcc are empty, it is fatal */  
     if (status == MU_ERR_EMPTY_ADDRESS && tostatus == status)  
       goto end;  
   
     /* otherwise, at least rcpt_to or rcpt_bcc is defined */  
     status = 0;  
   }  
   
940    /* If to or bcc is present, the must be OK. */    /* If to or bcc is present, the must be OK. */
941    if (rcpt_to && (status = mailer_check_to (rcpt_to)))    if (smtp->rcpt_to && (status = mailer_check_to (smtp->rcpt_to)))
942      goto end;      goto end;
943    
944    if (rcpt_bcc && (status = mailer_check_to (rcpt_bcc)))    if (smtp->rcpt_bcc && (status = mailer_check_to (smtp->rcpt_bcc)))
945      goto end;      goto end;
946    
947  end:  end:
948    
   if (toaddrv[0])  
     free (toaddrv[0]);  
   
   if (toaddrv[1])  
     free (toaddrv[1]);  
   
   if (bccaddr)  
     free (bccaddr);  
   
949    if (status)    if (status)
950      {      {
951        address_destroy (&rcpt_to);        address_destroy (&smtp->rcpt_to);
952        address_destroy (&rcpt_bcc);        address_destroy (&smtp->rcpt_bcc);
953      }      }
954    else    else
955      {      {
       smtp->rcpt_to = rcpt_to;  
   
956        if (smtp->rcpt_to)        if (smtp->rcpt_to)
957          address_get_count (smtp->rcpt_to, &smtp->rcpt_to_count);          address_get_count (smtp->rcpt_to, &smtp->rcpt_to_count);
958    
       smtp->rcpt_bcc = rcpt_bcc;  
   
959        if (smtp->rcpt_bcc)        if (smtp->rcpt_bcc)
960          address_get_count (smtp->rcpt_bcc, &smtp->rcpt_bcc_count);          address_get_count (smtp->rcpt_bcc, &smtp->rcpt_bcc_count);
961    
962          if (smtp->rcpt_to_count + smtp->rcpt_bcc_count == 0)
963            status = MU_ERR_MAILER_NO_RCPT_TO;
964      }      }
965    
966    return status;    return status;
967  }  }
968    
969  /* C99 says that a conforming implementations of snprintf ()  /* C99 says that a conforming implementations of snprintf ()
970     should return the number of char that would have been call     should return the number of char that would have been call
971     but many GNU/Linux && BSD implementations return -1 on error.     but many GNU/Linux && BSD implementations return -1 on error.
# Line 1026  smtp_writeline (smtp_t smtp, const char Line 1006  smtp_writeline (smtp_t smtp, const char
1006    while (len > 0 && isspace (smtp->buffer[len - 1]))    while (len > 0 && isspace (smtp->buffer[len - 1]))
1007      len--;      len--;
1008    
1009    if (    if ((smtp->state != SMTP_SEND && smtp->state != SMTP_SEND_DOT)
1010        (smtp->state != SMTP_SEND && smtp->state != SMTP_SEND_DOT)        || smtp->mailer->flags & MAILER_FLAG_DEBUG_DATA)
       ||  
       smtp->mailer->flags & MAILER_FLAG_DEBUG_DATA  
       )  
1011      {      {
1012        MAILER_DEBUG2 (smtp->mailer, MU_DEBUG_PROT, "> %.*s\n", len,        MAILER_DEBUG2 (smtp->mailer, MU_DEBUG_PROT, "> %.*s\n", len,
1013                       smtp->buffer);                       smtp->buffer);

Legend:
Removed from v.1.26  
changed lines
  Added in v.1.27

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26