Commit 89ea7423 89ea7423fc240601e018851dbb219a07d476e1d4 by Sergey Poznyakoff

Rewrite SMTP mailer.

* libproto/mailer/smtp.c: Rewrite using new SMTP API.
* libproto/mailer/smtp_quit.c (mu_smtp_quit): Return immediately
if already in closed state.

* libmailutils/ticket.c (mu_ticket_get_cred): Return MU_ERR_FAILURE
if all methods fail.
* mail/send.c: Port 23321cf7 from patches-2.2
(msg_to_pipe): Return status code.
(save_dead_message, send_message): New functions, extracted from
mail_send0.
(mail_send0): Call save_dead_message if sending failed.
1 parent 7b5902b4
...@@ -211,7 +211,9 @@ mu_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge, ...@@ -211,7 +211,9 @@ mu_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge,
211 } 211 }
212 arg [strlen (arg) - 1] = '\0'; /* nuke the trailing line. */ 212 arg [strlen (arg) - 1] = '\0'; /* nuke the trailing line. */
213 } 213 }
214 214 else
215 return MU_ERR_FAILURE;
216
215 if (pplain) 217 if (pplain)
216 { 218 {
217 *pplain = strdup (arg); 219 *pplain = strdup (arg);
......
...@@ -37,6 +37,8 @@ mu_smtp_quit (mu_smtp_t smtp) ...@@ -37,6 +37,8 @@ mu_smtp_quit (mu_smtp_t smtp)
37 return EINVAL; 37 return EINVAL;
38 if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR)) 38 if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
39 return MU_ERR_FAILURE; 39 return MU_ERR_FAILURE;
40 if (smtp->state == MU_SMTP_CLOS)
41 return 0;
40 status = mu_smtp_write (smtp, "QUIT\r\n"); 42 status = mu_smtp_write (smtp, "QUIT\r\n");
41 MU_SMTP_CHECK_ERROR (smtp, status); 43 MU_SMTP_CHECK_ERROR (smtp, status);
42 status = mu_smtp_response (smtp); 44 status = mu_smtp_response (smtp);
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 #include <fcntl.h> 23 #include <fcntl.h>
24 24
25 static int isfilename (const char *); 25 static int isfilename (const char *);
26 static void msg_to_pipe (const char *cmd, mu_message_t msg); 26 static int msg_to_pipe (const char *cmd, mu_message_t msg);
27 27
28 28
29 /* Additional message headers */ 29 /* Additional message headers */
...@@ -338,6 +338,82 @@ fill_body (mu_message_t msg, FILE *file) ...@@ -338,6 +338,82 @@ fill_body (mu_message_t msg, FILE *file)
338 return 0; 338 return 0;
339 } 339 }
340 340
341 static int
342 save_dead_message (compose_env_t *env)
343 {
344 if (mailvar_get (NULL, "save", mailvar_type_boolean, 0) == 0)
345 {
346 FILE *fp = fopen (getenv ("DEAD"),
347 mailvar_get (NULL, "appenddeadletter",
348 mailvar_type_boolean, 0) == 0 ?
349 "a" : "w");
350
351 if (!fp)
352 {
353 util_error (_("Cannot open file %s: %s"), getenv ("DEAD"),
354 strerror (errno));
355 return 1;
356 }
357 else
358 {
359 char *buf = NULL;
360 size_t n;
361 rewind (env->file);
362 while (getline (&buf, &n, env->file) > 0)
363 fputs (buf, fp);
364 fclose (fp);
365 free (buf);
366 }
367 }
368 return 0;
369 }
370
371 static int
372 send_message (mu_message_t msg)
373 {
374 char *sendmail;
375 int status;
376
377 if (mailvar_get (&sendmail, "sendmail", mailvar_type_string, 0) == 0)
378 {
379 if (sendmail[0] == '/')
380 status = msg_to_pipe (sendmail, msg);
381 else
382 {
383 mu_mailer_t mailer;
384
385 status = mu_mailer_create (&mailer, sendmail);
386 if (status == 0)
387 {
388 if (mailvar_get (NULL, "verbose", mailvar_type_boolean, 0) == 0)
389 {
390 mu_debug_t debug = NULL;
391 mu_mailer_get_debug (mailer, &debug);
392 mu_debug_set_level (debug,
393 MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT));
394 }
395 status = mu_mailer_open (mailer, MU_STREAM_RDWR);
396 if (status == 0)
397 {
398 status = mu_mailer_send_message (mailer, msg, NULL, NULL);
399 mu_mailer_close (mailer);
400 }
401 else
402 util_error (_("Cannot open mailer: %s"), mu_strerror (status));
403 mu_mailer_destroy (&mailer);
404 }
405 else
406 util_error (_("Cannot create mailer: %s"),
407 mu_strerror (status));
408 }
409 }
410 else
411 {
412 util_error (_("Variable sendmail not set: no mailer"));
413 status = ENOSYS;
414 }
415 return status;
416 }
341 417
342 /* mail_send0(): shared between mail_send() and mail_reply(); 418 /* mail_send0(): shared between mail_send() and mail_reply();
343 419
...@@ -471,41 +547,16 @@ mail_send0 (compose_env_t * env, int save_to) ...@@ -471,41 +547,16 @@ mail_send0 (compose_env_t * env, int save_to)
471 free (buf); 547 free (buf);
472 } 548 }
473 549
474 /* If interrupted dump the file to dead.letter. */ 550 /* If interrupted, dump the file to dead.letter. */
475 if (int_cnt) 551 if (int_cnt)
476 { 552 {
477 if (mailvar_get (NULL, "save", mailvar_type_boolean, 0) == 0) 553 save_dead_message (env);
478 {
479 FILE *fp = fopen (getenv ("DEAD"),
480 mailvar_get (NULL, "appenddeadletter",
481 mailvar_type_boolean, 0) == 0 ?
482 "a" : "w");
483
484 if (!fp)
485 {
486 util_error (_("Cannot open file %s: %s"), getenv ("DEAD"),
487 strerror (errno));
488 }
489 else
490 {
491 char *buf = NULL;
492 size_t n;
493 rewind (env->file);
494 while (getline (&buf, &n, env->file) > 0)
495 fputs (buf, fp);
496 fclose (fp);
497 free (buf);
498 }
499 }
500
501 fclose (env->file); 554 fclose (env->file);
502 remove (filename); 555 remove (filename);
503 free (filename); 556 free (filename);
504 return 1; 557 return 1;
505 } 558 }
506 559
507 fclose (env->file); /* FIXME: freopen would be better */
508
509 /* In mailx compatibility mode, ask for Cc and Bcc after editing 560 /* In mailx compatibility mode, ask for Cc and Bcc after editing
510 the body of the message */ 561 the body of the message */
511 if (mailvar_get (NULL, "mailx", mailvar_type_boolean, 0) == 0) 562 if (mailvar_get (NULL, "mailx", mailvar_type_boolean, 0) == 0)
...@@ -521,12 +572,12 @@ mail_send0 (compose_env_t * env, int save_to) ...@@ -521,12 +572,12 @@ mail_send0 (compose_env_t * env, int save_to)
521 file = fopen (filename, "r"); 572 file = fopen (filename, "r");
522 if (file != NULL) 573 if (file != NULL)
523 { 574 {
524 mu_mailer_t mailer;
525 mu_message_t msg = NULL; 575 mu_message_t msg = NULL;
526 int rc; 576 int rc;
577 int status = 0;
527 578
528 mu_message_create (&msg, NULL); 579 mu_message_create (&msg, NULL);
529 580
530 /* Fill the body. */ 581 /* Fill the body. */
531 rc = fill_body (msg, file); 582 rc = fill_body (msg, file);
532 fclose (file); 583 fclose (file);
...@@ -561,11 +612,10 @@ mail_send0 (compose_env_t * env, int save_to) ...@@ -561,11 +612,10 @@ mail_send0 (compose_env_t * env, int save_to)
561 { 612 {
562 /* Pipe to a cmd. */ 613 /* Pipe to a cmd. */
563 if (env->outfiles[i][0] == '|') 614 if (env->outfiles[i][0] == '|')
564 msg_to_pipe (&(env->outfiles[i][1]), msg); 615 status = msg_to_pipe (env->outfiles[i] + 1, msg);
565 /* Save to a file. */ 616 /* Save to a file. */
566 else 617 else
567 { 618 {
568 int status;
569 mu_mailbox_t mbx = NULL; 619 mu_mailbox_t mbx = NULL;
570 status = mu_mailbox_create_default (&mbx, 620 status = mu_mailbox_create_default (&mbx,
571 env->outfiles[i]); 621 env->outfiles[i]);
...@@ -585,64 +635,36 @@ mail_send0 (compose_env_t * env, int save_to) ...@@ -585,64 +635,36 @@ mail_send0 (compose_env_t * env, int save_to)
585 } 635 }
586 if (status) 636 if (status)
587 util_error (_("Cannot create mailbox %s: %s"), 637 util_error (_("Cannot create mailbox %s: %s"),
588 env->outfiles[i], mu_strerror (status)); 638 env->outfiles[i],
639 mu_strerror (status));
589 } 640 }
590 } 641 }
591 } 642 }
592 643
593 /* Do we need to Send the message on the wire? */ 644 /* Do we need to Send the message on the wire? */
594 if (compose_header_get (env, MU_HEADER_TO, NULL) 645 if (status == 0 &&
595 || compose_header_get (env, MU_HEADER_CC, NULL) 646 (compose_header_get (env, MU_HEADER_TO, NULL) ||
596 || compose_header_get (env, MU_HEADER_BCC, NULL)) 647 compose_header_get (env, MU_HEADER_CC, NULL) ||
648 compose_header_get (env, MU_HEADER_BCC, NULL)))
597 { 649 {
598 char *sendmail; 650 mu_message_set_header (msg, env->header, NULL);
599 if (mailvar_get (&sendmail, "sendmail", 651 env->header = NULL;
600 mailvar_type_string, 0) == 0) 652 status = send_message (msg);
601 { 653 if (status)
602 mu_message_set_header (msg, env->header, NULL); 654 save_dead_message (env);
603 env->header = NULL;
604 if (sendmail[0] == '/')
605 msg_to_pipe (sendmail, msg);
606 else
607 {
608 int status = mu_mailer_create (&mailer, sendmail);
609 if (status == 0)
610 {
611 if (mailvar_get (NULL, "verbose",
612 mailvar_type_boolean, 0) == 0)
613 {
614 mu_debug_t debug = NULL;
615 mu_mailer_get_debug (mailer, &debug);
616 mu_debug_set_level (debug,
617 MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT));
618 }
619 status = mu_mailer_open (mailer, MU_STREAM_RDWR);
620 if (status == 0)
621 {
622 mu_mailer_send_message (mailer, msg,
623 NULL, NULL);
624 mu_mailer_close (mailer);
625 }
626 else
627 util_error (_("Cannot open mailer: %s"),
628 mu_strerror (status));
629 mu_mailer_destroy (&mailer);
630 }
631 else
632 util_error (_("Cannot create mailer: %s"),
633 mu_strerror (status));
634 }
635 }
636 else
637 util_error (_("Variable sendmail not set: no mailer"));
638 } 655 }
639 } 656 }
657 fclose (env->file);
640 mu_message_destroy (&msg, NULL); 658 mu_message_destroy (&msg, NULL);
641 remove (filename); 659 remove (filename);
642 free (filename); 660 free (filename);
643 return 0; 661 return status;
644 } 662 }
645 } 663 }
664 else
665 save_dead_message (env);
666
667 fclose (env->file);
646 668
647 remove (filename); 669 remove (filename);
648 free (filename); 670 free (filename);
...@@ -662,26 +684,33 @@ isfilename (const char *p) ...@@ -662,26 +684,33 @@ isfilename (const char *p)
662 684
663 /* FIXME: Should probably be in util.c. */ 685 /* FIXME: Should probably be in util.c. */
664 /* Call popen(cmd) and write the message to it. */ 686 /* Call popen(cmd) and write the message to it. */
665 static void 687 static int
666 msg_to_pipe (const char *cmd, mu_message_t msg) 688 msg_to_pipe (const char *cmd, mu_message_t msg)
667 { 689 {
668 FILE *fp = popen (cmd, "w"); 690 mu_stream_t progstream, msgstream;
669 if (fp) 691 int status, rc;
692
693 status = mu_prog_stream_create (&progstream, cmd, MU_STREAM_WRITE);
694 if (status)
670 { 695 {
671 mu_stream_t stream = NULL; 696 util_error (_("Cannot pipe to %s: %s"), cmd, mu_strerror (status));
672 char buffer[512]; 697 return status;
673 size_t n = 0;
674 /* FIXME: Use mu_stream_copy */
675 mu_message_get_streamref (msg, &stream);
676 while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0
677 && n != 0)
678 {
679 buffer[n] = '\0';
680 fprintf (fp, "%s", buffer);
681 }
682 mu_stream_destroy (&stream);
683 pclose (fp);
684 } 698 }
685 else 699
686 util_error (_("Piping %s failed"), cmd); 700 mu_message_get_streamref (msg, &msgstream);
701 status = mu_stream_copy (progstream, msgstream, 0, NULL);
702 rc = mu_stream_close (progstream);
703
704 if (status == 0 && rc)
705 status = rc;
706
707 mu_stream_destroy (&progstream);
708 mu_stream_destroy (&msgstream);
709
710 if (status)
711 {
712 util_error (_("Sending data to %s failed: %s"), cmd,
713 mu_strerror (status));
714 }
715 return status;
687 } 716 }
......