Blame view

mh/send.c 17.6 KB
1
/* GNU Mailutils -- a suite of utilities for electronic mail
2
   Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15

   GNU Mailutils is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   GNU Mailutils is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Mailutils; if not, write to the Free Software
16 17
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   MA 02110-1301 USA */
18 19 20 21

/* MH send command */

#include <mh.h>
22 23 24
#include <sys/stat.h>
#include <unistd.h>
#include <stdarg.h>
25
#include <pwd.h>
26

27
const char *program_version = "send (" PACKAGE_STRING ")";
uid65697 authored
28 29
/* TRANSLATORS: Please, preserve the vertical tabulation (^K character)
   in this message */
30 31 32
static char doc[] = N_("GNU MH send\v\
Options marked with `*' are not yet implemented.\n\
Use -help to obtain the list of traditional MH options.");
33 34 35 36 37
static char args_doc[] = N_("file [file...]");

/* GNU options */
static struct argp_option options[] = {
  {"alias",         ARG_ALIAS,         N_("FILE"), 0,
Sergey Poznyakoff authored
38
   N_("Specify additional alias file") },
39
  {"draft",         ARG_DRAFT,         NULL, 0,
40
   N_("Use prepared draft") },
41
  {"draftfolder",   ARG_DRAFTFOLDER,   N_("FOLDER"), 0,
42 43 44
   N_("Specify the folder for message drafts") },
  {"draftmessage",  ARG_DRAFTMESSAGE,  NULL, 0,
   N_("Treat the arguments as a list of messages from the draftfolder") },
45
  {"nodraftfolder", ARG_NODRAFTFOLDER, NULL, 0,
46
   N_("Undo the effect of the last --draftfolder option") },
47
  {"filter",        ARG_FILTER,        N_("FILE"), 0,
48
  N_("* Use filter FILE to preprocess the body of the message") },
49 50 51 52 53 54
  {"nofilter",      ARG_NOFILTER,      NULL, 0,
   N_("* Undo the effect of the last --filter option") },
  {"format",        ARG_FORMAT,        N_("BOOL"), OPTION_ARG_OPTIONAL,
   N_("* Reformat To: and Cc: addresses") },
  {"noformat",      ARG_NOFORMAT,      NULL, OPTION_HIDDEN, "" },
  {"forward",       ARG_FORWARD,       N_("BOOL"), OPTION_ARG_OPTIONAL,
55
   N_("* In case of failure forward the draft along with the failure notice to the sender") },
56 57 58 59 60
  {"noforward",     ARG_NOFORWARD,     NULL, OPTION_HIDDEN, "" },
  {"mime",          ARG_MIME,          N_("BOOL"), OPTION_ARG_OPTIONAL,
   N_("* Use MIME encapsulation") },
  {"nomime",        ARG_NOMIME,        NULL, OPTION_HIDDEN, "" },
  {"msgid",         ARG_MSGID,         N_("BOOL"), OPTION_ARG_OPTIONAL,
61
   N_("Add Message-ID: field") },
62 63
  {"nomsgid",       ARG_NOMSGID,       NULL, OPTION_HIDDEN, ""},
  {"push",          ARG_PUSH,          N_("BOOL"), OPTION_ARG_OPTIONAL,
64
   N_("Run in the backround.") },
65 66 67 68
  {"nopush",        ARG_NOPUSH,        NULL, OPTION_HIDDEN, "" },
  {"split",         ARG_SPLIT,         N_("SECONDS"), 0,
   N_("* Split the draft into several partial messages and send them with SECONDS interval") },
  {"verbose",       ARG_VERBOSE,       N_("BOOL"), OPTION_ARG_OPTIONAL,
69
   N_("Print the transcript of interactions with the transport system") },
70 71
  {"noverbose",     ARG_NOVERBOSE,     NULL, OPTION_HIDDEN, "" },
  {"watch",         ARG_WATCH,         N_("BOOL"), OPTION_ARG_OPTIONAL,
72
   N_("Monitor the delivery of mail") },
73 74 75
  {"nowatch",       ARG_NOWATCH,       NULL, OPTION_HIDDEN, "" },
  {"width",         ARG_WIDTH,         N_("NUMBER"), 0,
   N_("* Make header fields no longer than NUMBER columns") },
76 77
  {"license", ARG_LICENSE, 0,      0,
   N_("Display software license"), -1},
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  { 0 }
};

/* Traditional MH options */
struct mh_option mh_option[] = {
  {"alias",         1, 0, "aliasfile" },
  {"draft",         5, 0, NULL },
  {"draftfolder",   6, 0, "folder" },
  {"draftmessage",  6, 0, "message"},
  {"nodraftfolder", 3, 0, NULL },
  {"filter",        2, 0, "filterfile"},
  {"nofilter",      3, 0, NULL },
  {"format",        4, MH_OPT_BOOL, NULL},
  {"forward",       4, MH_OPT_BOOL, NULL},
  {"mime",          2, MH_OPT_BOOL, NULL},
  {"msgid",         2, MH_OPT_BOOL, NULL},
  {"push",          1, MH_OPT_BOOL, NULL},
  {"split",         1, 0, "seconds"},
  {"verbose",       1, MH_OPT_BOOL, NULL},
  {"watch",         2, MH_OPT_BOOL, NULL},
  {"width",         2, 0, NULL },
  { 0 }
};

102
static int use_draft;            /* Use the prepared draft */
103
static char *draft_folder;       /* Use this draft folder */
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
static int reformat_recipients;  /* --format option */
static int forward_notice;       /* Forward the failure notice to the sender,
				    --forward flag */
static int mime_encaps;          /* Use MIME encapsulation */
static int append_msgid;         /* Append Message-ID: header */
static int background;           /* Operate in the background */

static int split_message;            /* Split the message */
static unsigned long split_interval; /* Interval in seconds between sending two
					successive partial messages */

static int verbose;              /* Produce verbose diagnostics */
static int watch;                /* Watch the delivery process */
static unsigned width = 76;      /* Maximum width of header fields */

119 120
#define DEFAULT_X_MAILER "MH (" PACKAGE_STRING ")"

121 122 123 124 125
#define WATCH(c) do {\
  if (watch)\
    watch_printf c;\
} while (0)

126
static int
127
opt_handler (int key, char *arg, void *unused, struct argp_state *state)
128 129 130 131 132 133
{
  char *p;
  
  switch (key)
    {
    case ARG_ALIAS:
Sergey Poznyakoff authored
134 135
      mh_alias_read (arg, 1);
      break;
136 137 138 139 140
      
    case ARG_DRAFT:
      use_draft = 1;
      break;
	
141
    case ARG_DRAFTFOLDER:
142 143 144
      draft_folder = arg;
      break;
      
145
    case ARG_NODRAFTFOLDER:
146 147 148 149 150 151
      draft_folder = NULL;
      break;
      
    case ARG_DRAFTMESSAGE:
      if (!draft_folder)
	draft_folder = mh_global_profile_get ("Draft-Folder",
152
					      mu_folder_directory ());
153 154
      break;
      
155 156 157 158 159
    case ARG_FILTER:
    case ARG_NOFILTER:
      return 1;
      
    case ARG_FORMAT:
160
      reformat_recipients = is_true (arg);
161 162 163 164 165 166 167
      break;
      
    case ARG_NOFORMAT:
      reformat_recipients = 0;
      break;
      
    case ARG_FORWARD:
168
      forward_notice = is_true (arg);
169 170 171 172 173 174 175
      break;
      
    case ARG_NOFORWARD:
      forward_notice = 0;
      break;
      
    case ARG_MIME:
176
      mime_encaps = is_true (arg);
177 178 179 180 181 182 183
      break;
      
    case ARG_NOMIME:
      mime_encaps = 0;
      break;
      
    case ARG_MSGID:
184
      append_msgid = is_true (arg);
185 186 187 188 189 190 191
      break;
      
    case ARG_NOMSGID:
      append_msgid = 0;
      break;
      
    case ARG_PUSH:
192
      background = is_true (arg);
193 194 195 196 197 198 199 200
      break;
      
    case ARG_NOPUSH:
      background = 0;
      break;
      
    case ARG_SPLIT:
      split_message = 1;
201
      split_interval = strtoul (arg, &p, 10);
202 203
      if (*p)
	{
204
	  argp_error (state, _("Invalid number"));
205 206 207 208 209
	  exit (1);
	}
      break;
      
    case ARG_VERBOSE:
210
      verbose = is_true (arg);
211 212 213 214 215 216 217
      break;
      
    case ARG_NOVERBOSE:
      verbose = 0;
      break;
      
    case ARG_WATCH:
218
      watch = is_true (arg);
219 220 221 222 223 224 225
      break;
      
    case ARG_NOWATCH:
      watch = 0;
      break;
      
    case ARG_WIDTH:
226
      width = strtoul (arg, &p, 10);
227 228
      if (*p)
	{
229
	  argp_error (state, _("Invalid number"));
230 231 232 233
	  exit (1);
	}
      break;
      
234 235 236 237
    case ARG_LICENSE:
      mh_license (argp_program_version);
      break;

238 239 240 241 242
    default:
      return 1;
    }
  return 0;
}
243

244
static void
245 246 247 248 249 250 251 252 253 254
watch_printf (const char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  vfprintf (stderr, fmt, ap);
  fprintf (stderr, "\n");
  va_end (ap);
}

255 256 257 258 259 260 261
struct list_elt           /* Element of the send list */
{
  const char *file_name;  /* Duplicated in msg stream, but there's no way
			     to get it from there */
  mu_message_t msg;       /* Corresponding message */
};

262
static mu_list_t mesg_list;
263 264 265 266 267
static mh_context_t *mts_profile;

int
check_file (char *name)
{
268
  struct list_elt *elt;
269
  mu_message_t msg;
270 271 272
  char *file_name = mh_expand_name (draft_folder, name, 0);
  
  msg = mh_file_to_message (NULL, file_name);
273
  if (!msg)
274 275 276 277
    {
      free (file_name);
      return 1;
    }
278
  if (!mesg_list && mu_list_create (&mesg_list))
279
    {
280
      free (file_name);
281
      mu_error (_("Cannot create message list"));
282 283
      return 1;
    }
284 285 286 287
  elt = xmalloc (sizeof *elt);
  elt->file_name = file_name;
  elt->msg = msg;
  return mu_list_append (mesg_list, elt);
288 289 290 291 292 293
}

void
read_mts_profile ()
{
  char *p;
294 295
  char *hostname = NULL;
  int rc;
296 297
  mh_context_t *local_profile;
  
298 299 300
  p = mh_expand_name (MHLIBDIR, "mtstailor", 0);
  mts_profile = mh_context_create (p, 1);
  mh_context_read (mts_profile);
301 302 303 304 305 306

  p = mu_tilde_expansion ("~/.mtstailor", "/", NULL);
  local_profile = mh_context_create (p, 1);
  if (mh_context_read (local_profile) == 0)
    mh_context_merge (mts_profile, local_profile);
  mh_context_destroy (&local_profile);
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334

  if ((p = mh_context_get_value (mts_profile, "localname", NULL)))
    {
      hostname = p;
      mu_set_user_email_domain (p);
    }
  else if ((rc = mu_get_host_name (&hostname)))
    mu_error (_("Cannot get system host name: %s"), mu_strerror (rc));
  
  if ((p = mh_context_get_value (mts_profile, "localdomain", NULL)))
    {
      char *newdomain;

      if (!hostname)
	exit (1);
      
      newdomain = xmalloc (strlen (hostname) + 1 + strlen (p) + 1);
      strcpy (newdomain, hostname);
      strcat (newdomain, ".");
      strcat (newdomain, p);
      rc = mu_set_user_email_domain (newdomain);
      free (newdomain);
      if (rc)
	{
	  mu_error (_("Cannot set user mail domain: %s"), mu_strerror (rc));
	  exit (1);
	}
    }
335 336 337
}


338
mu_mailer_t
339 340 341 342 343
open_mailer ()
{
  char *url = mh_context_get_value (mts_profile,
				    "url",
				    "sendmail:/usr/sbin/sendmail");
344
  mu_mailer_t mailer;
345 346
  int status;
    
347
  WATCH ((_("Creating mailer %s"), url));
348
  status = mu_mailer_create (&mailer, url);
349 350
  if (status)
    {
351
      mu_error (_("Cannot create mailer `%s'"), url);
352 353 354 355 356 357
      return NULL;
    }

  if (verbose)
    {
      mu_debug_t debug = NULL;
358
      mu_mailer_get_debug (mailer, &debug);
359 360 361
      mu_debug_set_level (debug, MU_DEBUG_TRACE | MU_DEBUG_PROT);
    }

362
  WATCH ((_("Opening mailer %s"), url));
363
  status = mu_mailer_open (mailer, MU_STREAM_RDWR);
364 365
  if (status)
    {
366
      mu_error (_("Cannot open mailer `%s'"), url);
367 368 369 370
      return NULL;
    }
  return mailer;
}
371 372

static void
373
create_message_id (mu_header_t hdr)
374
{
375
  char *p = mh_create_message_id (0);
376
  mu_header_set_value (hdr, MU_HEADER_MESSAGE_ID, p, 1);
377 378 379
  free (p);
}

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
static char *
get_sender_personal ()
{
  char *s = mh_global_profile_get ("signature", getenv ("SIGNATURE"));
  if (!s)
    {
      struct passwd *pw = getpwuid (getuid ());
      if (pw && pw->pw_gecos[0])
	{
	  char *p = strchr (pw->pw_gecos, ',');
	  if (p)
	    *p = 0;
	  s = pw->pw_gecos;
	}
    }
  return s;
}

Sergey Poznyakoff authored
398
static void
399
set_address_header (mu_header_t hdr, char *name, mu_address_t addr)
Sergey Poznyakoff authored
400
{
401
  size_t s = mu_address_format_string (addr, NULL, 0);
Sergey Poznyakoff authored
402
  char *value = xmalloc (s + 1);
403 404
  mu_address_format_string (addr, value, s);
  mu_header_set_value (hdr, name, value, 1);
Sergey Poznyakoff authored
405 406 407 408
  free (value);
}

void
409
expand_aliases (mu_message_t msg)
Sergey Poznyakoff authored
410
{
411 412
  mu_header_t hdr;
  mu_address_t addr_to = NULL,
413 414
               addr_cc = NULL,
               addr_bcc = NULL;
Sergey Poznyakoff authored
415

416 417 418
  mh_expand_aliases (msg, &addr_to, &addr_cc, &addr_bcc);

  mu_message_get_header (msg, &hdr);
Sergey Poznyakoff authored
419 420 421
  if (addr_to)
    {
      set_address_header (hdr, MU_HEADER_TO, addr_to);
422
      mu_address_destroy (&addr_to);
Sergey Poznyakoff authored
423 424 425 426 427
    }

  if (addr_cc)
    {
      set_address_header (hdr, MU_HEADER_CC, addr_cc);
428
      mu_address_destroy (&addr_cc);
Sergey Poznyakoff authored
429 430 431 432 433
    }

  if (addr_bcc)
    {
      set_address_header (hdr, MU_HEADER_BCC, addr_bcc);
434
      mu_address_destroy (&addr_bcc);
Sergey Poznyakoff authored
435 436 437 438
    }
}

void
439
fix_fcc (mu_message_t msg)
Sergey Poznyakoff authored
440
{
441
  mu_header_t hdr;
442
  char *fcc;
Sergey Poznyakoff authored
443
  
444
  mu_message_get_header (msg, &hdr);
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
  if (mu_header_aget_value (hdr, MU_HEADER_FCC, &fcc) == 0)
    {
      int i, argc;
      char **argv;
      int need_fixup = 0;
      size_t fixup_len = 0;
      
      mu_argcv_get (fcc, ",", NULL, &argc, &argv);
      for (i = 0; i < argc; i += 2)
	{
	  if (strchr ("+%~/=", argv[i][0]) == NULL)
	    {
	      need_fixup++;
	      fixup_len ++;
	    }
	  fixup_len += strlen (argv[i]);
	}

      if (need_fixup)
	{
	  char *p;

	  /* the new fcc string contains: folder names - fixup_len characters
	     long, (argc - 2)/2 comma-space pairs and a terminating
	     nul */
	  fcc = realloc (fcc, fixup_len + argc - 2 + 1);
	  for (i = 0, p = fcc; i < argc; i++)
	    {
	      if (i % 2 == 0)
		{
		  if (strchr ("+%~/=", argv[i][0]) == NULL)
		    *p++ = '+';
		  strcpy (p, argv[i]);
		  p += strlen (argv[i]);
		}
	      else
		{
		  *p++ = ',';
		  *p++ = ' ';
		}
	    }
	  *p = 0;
	}

      mu_argcv_free (argc, argv);
490 491 492 493 494 495 496

      if (need_fixup)
	{
	  mu_header_set_value (hdr, MU_HEADER_FCC, fcc, 1);
	  WATCH ((_("fixed fcc: %s"), fcc));
	}
      free (fcc);
497
    }	  
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
}

/* Convert MH-style DCC headers to normal BCC.
   FIXME: Normally we should iterate through the headers to catch
   multiple Dcc occurrences (the same holds true for Fcc as well),
   however at the time of this writing we have mu_header_get_field_value,
   but we miss mu_header_set_field_value. */
void
fix_dcc (mu_message_t msg)
{
  mu_header_t hdr;
  char *dcc;
  
  mu_message_get_header (msg, &hdr);
  if (mu_header_aget_value (hdr, MU_HEADER_DCC, &dcc) == 0)
    {
      char *bcc = NULL;
      
      mu_header_set_value (hdr, MU_HEADER_DCC, NULL, 1);
      mu_header_aget_value (hdr, MU_HEADER_BCC, &bcc);
      if (bcc)
	{
	  char *newbcc = realloc (bcc, strlen (bcc) + 1 + strlen (dcc) + 1);
	  if (!newbcc)
	    {
	      mu_error (_("not enough memory"));
	      free (dcc);
	      free (bcc);
	      return;
	    }
	  bcc = newbcc;
	  strcat (bcc, ",");
	  strcat (bcc, dcc);
	  free (dcc);
	}
      else
	bcc = dcc;
535

536 537 538 539
      WATCH ((_("fixed bcc: %s"), bcc));
      mu_header_set_value (hdr, MU_HEADER_BCC, bcc, 1);
      free (bcc);
    }
540 541 542 543 544 545 546 547
}

void
backup_file (const char *file_name)
{
  char *new_name = xmalloc (strlen (file_name) + 2);
  char *p = strrchr (file_name, '/');
  if (p)
Sergey Poznyakoff authored
548
    {
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
      size_t len = p - file_name + 1;
      memcpy (new_name, file_name, len);
      new_name[len++] = ',';
      strcpy (new_name + len, p + 1);
    }
  else
    {
      new_name[0] = ',';
      strcpy (new_name + 1, file_name);
    }
  WATCH ((_("renaming %s to %s"), file_name, new_name));

  if (unlink (new_name) && errno != ENOENT)
    mu_error (_("Cannot unlink file `%s': %s"), new_name, mu_strerror (errno));
  else if (rename (file_name, new_name))
    mu_error (_("Cannot rename `%s' to `%s': %s"),
	      file_name, new_name, mu_strerror (errno));
  free (new_name);
Sergey Poznyakoff authored
567 568
}

569 570 571
int
_action_send (void *item, void *data)
{
572 573
  struct list_elt *elt = item;
  mu_message_t msg = elt->msg;
574
  int rc;
575 576
  mu_mailer_t mailer;
  mu_header_t hdr;
577
  size_t n;
578

579
  WATCH ((_("Getting message %s"), elt->file_name));
580

581
  if (mu_message_get_header (msg, &hdr) == 0)
582 583 584 585 586
    {
      char date[80];
      time_t t = time (NULL);
      struct tm *tm = localtime (&t);
      
587
      mu_strftime (date, sizeof date, "%a, %d %b %Y %H:%M:%S %z", tm);
588
      mu_header_set_value (hdr, MU_HEADER_DATE, date, 1);
589

590
      if (mu_header_get_value (hdr, MU_HEADER_FROM, NULL, 0, &n))
591 592 593
	{
	  char *from;
	  char *email = mu_get_user_email (NULL);
594 595
	  char *pers = get_sender_personal ();
	  if (pers)
596
	    {
597
	      asprintf (&from, "\"%s\" <%s>", pers, email);
598 599 600 601 602
	      free (email);
	    }
	  else
	    from = email;

603
	  mu_header_set_value (hdr, MU_HEADER_FROM, from, 1);
604 605 606 607
	  free (from);
	}
	  
      if (append_msgid
608
	  && mu_header_get_value (hdr, MU_HEADER_MESSAGE_ID, NULL, 0, &n))
609 610
	create_message_id (hdr);

611 612 613 614 615 616 617 618 619 620 621 622
      if (mu_header_get_value (hdr, MU_HEADER_X_MAILER, NULL, 0, &n))
	{
	  char *p = mh_context_get_value (mts_profile, "x-mailer", "yes");

	  if (!strcmp (p, "yes"))
	    mu_header_set_value (hdr, MU_HEADER_X_MAILER,
				 DEFAULT_X_MAILER, 0);
	  else if (strcmp (p, "no"))
	    mu_header_set_value (hdr, MU_HEADER_X_MAILER, p, 0);
	}
    }
  
Sergey Poznyakoff authored
623 624
  expand_aliases (msg);
  fix_fcc (msg);
625
  fix_dcc (msg);
Sergey Poznyakoff authored
626
  
627 628 629 630
  mailer = open_mailer ();
  if (!mailer)
    return 1;

631
  WATCH ((_("Sending message %s"), elt->file_name));
632
  rc = mu_mailer_send_message (mailer, msg, NULL, NULL);
633 634
  if (rc)
    {
635
      mu_error(_("Cannot send message: %s"), mu_strerror (rc));
636 637 638
      return 1;
    }

639
  WATCH ((_("Destroying the mailer")));
640 641
  mu_mailer_close (mailer);
  mu_mailer_destroy (&mailer);
642 643

  backup_file (elt->file_name);
644 645 646 647
  
  return 0;
}

648
static int
649 650 651
send (int argc, char **argv)
{
  int i, rc;
652 653
  char *p;
  
654
  /* Verify all arguments */
655 656 657 658
  for (i = 0; i < argc; i++)
    if (check_file (argv[i]))
      return 1;

659 660
  /* Process the mtstailor file and detach from the console if
     required */
661 662 663 664
  read_mts_profile ();
  
  if (background && daemon (0, 0) < 0)
    {
665
      mu_error(_("Cannot switch to background: %s"), mu_strerror (errno));
666 667 668
      return 1;
    }

669 670
  /* Prepend url specifier to the folder dir. We won't need this
     when the default format becomes configurable */
671 672 673
  asprintf (&p, "mh:%s", mu_folder_directory ());
  mu_set_folder_directory (p);
  free (p);
674
  
675
  /* Finally, do the work */
676
  rc = mu_list_do (mesg_list, _action_send, NULL);
677 678 679
  return rc;
}
	  
680 681 682 683 684 685 686
int
main (int argc, char **argv)
{
  int index;
  
  mu_init_nls ();
  
687
  mu_argp_init (program_version, NULL);
688
  mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc,
689 690
		 opt_handler, NULL, &index);

Sergey Poznyakoff authored
691 692
  mh_read_aliases ();
  
693 694 695 696 697 698 699
  argc -= index;
  argv += index;

  if (argc == 0)
    {
      struct stat st;
      static char *xargv[2];
700
      xargv[0] = mh_draft_name ();
701 702 703

      if (stat (xargv[0], &st))
	{
704
	  mu_error(_("Cannot stat %s: %s"), xargv[0], mu_strerror (errno));
705 706 707 708 709 710 711 712 713 714
	  return 1;
	}

      if (!use_draft && !mh_usedraft (xargv[0]))
	exit (0);
      xargv[1] = NULL;
      argv = xargv;
      argc = 1;
    }

715
  return send (argc, argv);  
716
}