1 |
/* GNU mailutils - a suite of utilities for electronic mail |
/* GNU Mailutils -- a suite of utilities for electronic mail |
2 |
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. |
3 |
|
|
4 |
This program is free software; you can redistribute it and/or modify |
GNU Mailutils is free software; you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation; either version 2, or (at your option) |
the Free Software Foundation; either version 2, or (at your option) |
7 |
any later version. |
any later version. |
8 |
|
|
9 |
This program is distributed in the hope that it will be useful, |
GNU Mailutils is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
GNU General Public License for more details. |
13 |
|
|
14 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
15 |
along with this program; if not, write to the Free Software |
along with GNU Mailutils; if not, write to the Free Software |
16 |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
17 |
|
|
18 |
#include <mail.local.h> |
#include <mail.local.h> |
43 |
|
|
44 |
const char *argp_program_version = "mail.local (" PACKAGE_STRING ")"; |
const char *argp_program_version = "mail.local (" PACKAGE_STRING ")"; |
45 |
static char doc[] = |
static char doc[] = |
46 |
"GNU mail.local -- the local MDA" |
N_("GNU mail.local -- the local MDA" |
47 |
"\v" |
"\v" |
48 |
"Debug flags are:\n" |
"Debug flags are:\n" |
49 |
" g - guimb stack traces\n" |
" g - guimb stack traces\n" |
51 |
" P - network protocols (MU_DEBUG_PROT)\n" |
" P - network protocols (MU_DEBUG_PROT)\n" |
52 |
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n" |
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n" |
53 |
" l - sieve action logs\n" |
" l - sieve action logs\n" |
54 |
" 0-9 - Set mail.local debugging level\n"; |
" 0-9 - Set mail.local debugging level\n"); |
55 |
|
|
56 |
static char args_doc[] = "recipient [recipient ...]"; |
static char args_doc[] = N_("recipient [recipient ...]"); |
57 |
|
|
58 |
#define ARG_MULTIPLE_DELIVERY 1 |
#define ARG_MULTIPLE_DELIVERY 1 |
59 |
#define ARG_QUOTA_TEMPFAIL 2 |
#define ARG_QUOTA_TEMPFAIL 2 |
61 |
static struct argp_option options[] = |
static struct argp_option options[] = |
62 |
{ |
{ |
63 |
{ "ex-multiple-delivery-success", ARG_MULTIPLE_DELIVERY, NULL, 0, |
{ "ex-multiple-delivery-success", ARG_MULTIPLE_DELIVERY, NULL, 0, |
64 |
"Don't return errors when delivering to multiple recipients", 0 }, |
N_("Don't return errors when delivering to multiple recipients"), 0 }, |
65 |
{ "ex-quota-tempfail", ARG_QUOTA_TEMPFAIL, NULL, 0, |
{ "ex-quota-tempfail", ARG_QUOTA_TEMPFAIL, NULL, 0, |
66 |
"Return temporary failure if disk or mailbox quota is exceeded", 0 }, |
N_("Return temporary failure if disk or mailbox quota is exceeded"), 0 }, |
67 |
{ "from", 'f', "EMAIL", 0, |
{ "from", 'f', "EMAIL", 0, |
68 |
"Specify the sender's name" }, |
N_("Specify the sender's name") }, |
69 |
{ NULL, 'r', NULL, OPTION_ALIAS, NULL }, |
{ NULL, 'r', NULL, OPTION_ALIAS, NULL }, |
70 |
#ifdef USE_DBM |
#ifdef USE_DBM |
71 |
{ "quota-db", 'q', "FILE", 0, |
{ "quota-db", 'q', "FILE", 0, |
72 |
"Specify path to quota database", 0 }, |
N_("Specify path to quota database"), 0 }, |
73 |
#endif |
#endif |
74 |
{ "sieve", 'S', "PATTERN", 0, |
{ "sieve", 'S', "PATTERN", 0, |
75 |
"Set name pattern for user-defined sieve mail filters", 0 }, |
N_("Set name pattern for user-defined sieve mail filters"), 0 }, |
76 |
#ifdef WITH_GUILE |
#ifdef WITH_GUILE |
77 |
{ "source", 's', "PATTERN", 0, |
{ "source", 's', "PATTERN", 0, |
78 |
"Set name pattern for user-defined mail filters", 0 }, |
N_("Set name pattern for user-defined mail filters"), 0 }, |
79 |
#endif |
#endif |
80 |
{ "debug", 'x', "FLAGS", 0, |
{ "debug", 'x', "FLAGS", 0, |
81 |
"Enable debugging", 0 }, |
N_("Enable debugging"), 0 }, |
82 |
{ "timeout", 't', "NUMBER", 0, |
{ "timeout", 't', "NUMBER", 0, |
83 |
"Set timeout for acquiring the lockfile" }, |
N_("Set timeout for acquiring the lockfile") }, |
84 |
{ NULL, 0, NULL, 0, NULL, 0 } |
{ NULL, 0, NULL, 0, NULL, 0 } |
85 |
}; |
}; |
86 |
|
|
129 |
case 'f': |
case 'f': |
130 |
if (from != NULL) |
if (from != NULL) |
131 |
{ |
{ |
132 |
argp_error (state, "multiple --from options"); |
argp_error (state, _("multiple --from options")); |
133 |
return EX_USAGE; |
return EX_USAGE; |
134 |
} |
} |
135 |
from = arg; |
from = arg; |
188 |
if (isdigit (*optarg)) |
if (isdigit (*optarg)) |
189 |
debug_level = *optarg - '0'; |
debug_level = *optarg - '0'; |
190 |
else |
else |
191 |
argp_error (state, "%c is not a valid debug flag", *arg); |
argp_error (state, _("%c is not a valid debug flag"), *arg); |
192 |
break; |
break; |
193 |
} |
} |
194 |
} |
} |
230 |
|
|
231 |
message_get_uid (msg, &uid); |
message_get_uid (msg, &uid); |
232 |
|
|
233 |
asprintf (&text, "%s on msg uid %d", action, uid); |
asprintf (&text, _("%s on msg uid %d"), action, uid); |
234 |
if (fmt && strlen (fmt)) |
if (fmt && strlen (fmt)) |
235 |
{ |
{ |
236 |
char *diag = NULL; |
char *diag = NULL; |
237 |
vasprintf (&diag, fmt, ap); |
vasprintf (&diag, fmt, ap); |
238 |
syslog (LOG_NOTICE, "(user %s) %s: %s", (char*) user_name, text, diag); |
syslog (LOG_NOTICE, _("(user %s) %s: %s"), (char*) user_name, text, diag); |
239 |
free (diag); |
free (diag); |
240 |
} |
} |
241 |
else |
else |
242 |
syslog (LOG_NOTICE, "(user %s) %s", (char*) user_name, text); |
syslog (LOG_NOTICE, _("(user %s) %s"), (char*) user_name, text); |
243 |
free (text); |
free (text); |
244 |
} |
} |
245 |
|
|
257 |
free (loc); |
free (loc); |
258 |
} |
} |
259 |
else |
else |
260 |
syslog (LOG_ERR, "(user %s) %s", (char*)user_name, text); |
syslog (LOG_ERR, _("(user %s) %s"), (char*)user_name, text); |
261 |
free (text); |
free (text); |
262 |
return 0; |
return 0; |
263 |
} |
} |
286 |
|
|
287 |
if ((rc = mu_debug_create (&mudebug, NULL))) |
if ((rc = mu_debug_create (&mudebug, NULL))) |
288 |
{ |
{ |
289 |
mu_error ("mu_debug_create failed: %s\n", mu_errstring (rc)); |
mu_error (_("mu_debug_create failed: %s\n"), mu_errstring (rc)); |
290 |
exit (EX_TEMPFAIL); |
exit (EX_TEMPFAIL); |
291 |
} |
} |
292 |
if ((rc = mu_debug_set_level (mudebug, debug_flags))) |
if ((rc = mu_debug_set_level (mudebug, debug_flags))) |
293 |
{ |
{ |
294 |
mu_error ("mu_debug_set_level failed: %s\n", |
mu_error (_("mu_debug_set_level failed: %s\n"), |
295 |
mu_errstring (rc)); |
mu_errstring (rc)); |
296 |
exit (EX_TEMPFAIL); |
exit (EX_TEMPFAIL); |
297 |
} |
} |
298 |
if ((rc = mu_debug_set_print (mudebug, _mu_debug_printer, NULL))) |
if ((rc = mu_debug_set_print (mudebug, _mu_debug_printer, NULL))) |
299 |
{ |
{ |
300 |
mu_error ("mu_debug_set_print failed: %s\n", |
mu_error (_("mu_debug_set_print failed: %s\n"), |
301 |
mu_errstring (rc)); |
mu_errstring (rc)); |
302 |
exit (EX_TEMPFAIL); |
exit (EX_TEMPFAIL); |
303 |
} |
} |
310 |
|
|
311 |
if (!argc) |
if (!argc) |
312 |
{ |
{ |
313 |
mu_error ("Missing arguments. Try --help for more info"); |
mu_error (_("Missing arguments. Try --help for more info.")); |
314 |
return EX_USAGE; |
return EX_USAGE; |
315 |
} |
} |
316 |
|
|
362 |
if (access (progfile, R_OK)) |
if (access (progfile, R_OK)) |
363 |
{ |
{ |
364 |
if (debug_level > 2) |
if (debug_level > 2) |
365 |
syslog (LOG_DEBUG, "access to %s failed: %m", progfile); |
syslog (LOG_DEBUG, _("access to %s failed: %m"), progfile); |
366 |
} |
} |
367 |
else |
else |
368 |
{ |
{ |
370 |
rc = sieve_machine_init (&mach, auth->name); |
rc = sieve_machine_init (&mach, auth->name); |
371 |
if (rc) |
if (rc) |
372 |
{ |
{ |
373 |
mu_error ("can't initialize sieve machine: %s", |
mu_error (_("can't initialize sieve machine: %s"), |
374 |
mu_errstring (rc)); |
mu_errstring (rc)); |
375 |
} |
} |
376 |
else |
else |
491 |
tempfile = mu_tempname (NULL); |
tempfile = mu_tempname (NULL); |
492 |
if ((status = file_stream_create (&stream, tempfile, MU_STREAM_RDWR))) |
if ((status = file_stream_create (&stream, tempfile, MU_STREAM_RDWR))) |
493 |
{ |
{ |
494 |
mailer_err ("unable to open temporary file: %s", mu_errstring (status)); |
mailer_err (_("unable to open temporary file: %s"), mu_errstring (status)); |
495 |
exit (exit_code); |
exit (exit_code); |
496 |
} |
} |
497 |
|
|
498 |
if ((status = stream_open (stream))) |
if ((status = stream_open (stream))) |
499 |
{ |
{ |
500 |
mailer_err ("unable to open temporary file: %s", mu_errstring (status)); |
mailer_err (_("unable to open temporary file: %s"), mu_errstring (status)); |
501 |
exit (exit_code); |
exit (exit_code); |
502 |
} |
} |
503 |
|
|
528 |
} |
} |
529 |
else |
else |
530 |
{ |
{ |
531 |
mailer_err ("Can't determine sender address"); |
mailer_err (_("Can't determine sender address")); |
532 |
exit (EX_UNAVAILABLE); |
exit (EX_UNAVAILABLE); |
533 |
} |
} |
534 |
if (auth) |
if (auth) |
546 |
|
|
547 |
if (status) |
if (status) |
548 |
{ |
{ |
549 |
mailer_err ("temporary file write error: %s", mu_errstring (status)); |
mailer_err (_("temporary file write error: %s"), mu_errstring (status)); |
550 |
stream_destroy (&stream, stream_get_owner (stream)); |
stream_destroy (&stream, stream_get_owner (stream)); |
551 |
return status; |
return status; |
552 |
} |
} |
563 |
if (status) |
if (status) |
564 |
{ |
{ |
565 |
errno = status; |
errno = status; |
566 |
mailer_err ("temporary file write error: %s", mu_errstring (status)); |
mailer_err (_("temporary file write error: %s"), mu_errstring (status)); |
567 |
stream_destroy (&stream, stream_get_owner (stream)); |
stream_destroy (&stream, stream_get_owner (stream)); |
568 |
return status; |
return status; |
569 |
} |
} |
573 |
|| (status = mailbox_open (*mbox, MU_STREAM_READ)) |
|| (status = mailbox_open (*mbox, MU_STREAM_READ)) |
574 |
|| (status = mailbox_set_stream (*mbox, stream))) |
|| (status = mailbox_set_stream (*mbox, stream))) |
575 |
{ |
{ |
576 |
mailer_err ("temporary file open error: %s", mu_errstring (status)); |
mailer_err (_("temporary file open error: %s"), mu_errstring (status)); |
577 |
stream_destroy (&stream, stream_get_owner (stream)); |
stream_destroy (&stream, stream_get_owner (stream)); |
578 |
return status; |
return status; |
579 |
} |
} |
582 |
if (status) |
if (status) |
583 |
{ |
{ |
584 |
errno = status; |
errno = status; |
585 |
mailer_err ("temporary message creation error: %s", |
mailer_err (_("temporary message creation error: %s"), |
586 |
mu_errstring (status)); |
mu_errstring (status)); |
587 |
stream_destroy (&stream, stream_get_owner (stream)); |
stream_destroy (&stream, stream_get_owner (stream)); |
588 |
return status; |
return status; |
607 |
auth = mu_get_auth_by_name (name); |
auth = mu_get_auth_by_name (name); |
608 |
if (!auth) |
if (!auth) |
609 |
{ |
{ |
610 |
mailer_err ("%s: no such user", name); |
mailer_err (_("%s: no such user"), name); |
611 |
exit_code = EX_UNAVAILABLE; |
exit_code = EX_UNAVAILABLE; |
612 |
return; |
return; |
613 |
} |
} |
621 |
|
|
622 |
if ((status = mailbox_get_stream (imbx, &istream)) != 0) |
if ((status = mailbox_get_stream (imbx, &istream)) != 0) |
623 |
{ |
{ |
624 |
mailer_err ("can't get input message stream: %s", mu_errstring (status)); |
mailer_err (_("can't get input message stream: %s"), mu_errstring (status)); |
625 |
mu_auth_data_free (auth); |
mu_auth_data_free (auth); |
626 |
return; |
return; |
627 |
} |
} |
628 |
|
|
629 |
if ((status = mailbox_create (&mbox, auth->mailbox)) != 0) |
if ((status = mailbox_create (&mbox, auth->mailbox)) != 0) |
630 |
{ |
{ |
631 |
mailer_err ("can't open mailbox %s: %s", |
mailer_err (_("can't open mailbox %s: %s"), |
632 |
auth->mailbox, mu_errstring (status)); |
auth->mailbox, mu_errstring (status)); |
633 |
mu_auth_data_free (auth); |
mu_auth_data_free (auth); |
634 |
return; |
return; |
647 |
return; |
return; |
648 |
if (status != 0) |
if (status != 0) |
649 |
{ |
{ |
650 |
mailer_err ("can't open mailbox %s: %s", path, mu_errstring (status)); |
mailer_err (_("can't open mailbox %s: %s"), path, mu_errstring (status)); |
651 |
mailbox_destroy (&mbox); |
mailbox_destroy (&mbox); |
652 |
return; |
return; |
653 |
} |
} |
660 |
|
|
661 |
if (status) |
if (status) |
662 |
{ |
{ |
663 |
mailer_err ("cannot lock mailbox '%s': %s", path, mu_errstring (status)); |
mailer_err (_("cannot lock mailbox '%s': %s"), path, mu_errstring (status)); |
664 |
mailbox_destroy (&mbox); |
mailbox_destroy (&mbox); |
665 |
exit_code = EX_TEMPFAIL; |
exit_code = EX_TEMPFAIL; |
666 |
return; |
return; |
668 |
|
|
669 |
if ((status = mailbox_get_stream (mbox, &ostream))) |
if ((status = mailbox_get_stream (mbox, &ostream))) |
670 |
{ |
{ |
671 |
mailer_err ("can't get stream for mailbox %s: %s", |
mailer_err (_("can't get stream for mailbox %s: %s"), |
672 |
path, mu_errstring (status)); |
path, mu_errstring (status)); |
673 |
mailbox_destroy (&mbox); |
mailbox_destroy (&mbox); |
674 |
return; |
return; |
676 |
|
|
677 |
if ((status = stream_size (ostream, (off_t *) &size))) |
if ((status = stream_size (ostream, (off_t *) &size))) |
678 |
{ |
{ |
679 |
mailer_err ("can't get stream size (mailbox %s): %s", |
mailer_err (_("can't get stream size (mailbox %s): %s"), |
680 |
path, mu_errstring (status)); |
path, mu_errstring (status)); |
681 |
mailbox_destroy (&mbox); |
mailbox_destroy (&mbox); |
682 |
return; |
return; |
689 |
switch (check_quota (name, size, &n)) |
switch (check_quota (name, size, &n)) |
690 |
{ |
{ |
691 |
case MQUOTA_EXCEEDED: |
case MQUOTA_EXCEEDED: |
692 |
mailer_err ("%s: mailbox quota exceeded for this recipient", name); |
mailer_err (_("%s: mailbox quota exceeded for this recipient"), name); |
693 |
exit_code = EX_QUOTA(); |
exit_code = EX_QUOTA(); |
694 |
failed++; |
failed++; |
695 |
break; |
break; |
700 |
default: |
default: |
701 |
if ((status = stream_size (istream, (off_t *) &isize))) |
if ((status = stream_size (istream, (off_t *) &isize))) |
702 |
{ |
{ |
703 |
mailer_err ("can't get stream size (input message): %s", |
mailer_err (_("can't get stream size (input message): %s"), |
704 |
path, mu_errstring (status)); |
path, mu_errstring (status)); |
705 |
exit_code = EX_UNAVAILABLE; |
exit_code = EX_UNAVAILABLE; |
706 |
failed++; |
failed++; |
707 |
} |
} |
708 |
else if (isize > n) |
else if (isize > n) |
709 |
{ |
{ |
710 |
mailer_err ("%s: message would exceed maximum mailbox size for this recipient", |
mailer_err (_("%s: message would exceed maximum mailbox size for this recipient"), |
711 |
name); |
name); |
712 |
exit_code = EX_QUOTA(); |
exit_code = EX_QUOTA(); |
713 |
failed++; |
failed++; |
756 |
|
|
757 |
if (status) |
if (status) |
758 |
{ |
{ |
759 |
mailer_err ("error writing to mailbox: %s", |
mailer_err (_("error writing to mailbox: %s"), |
760 |
mu_errstring (status)); |
mu_errstring (status)); |
761 |
} |
} |
762 |
} |
} |
921 |
exit_code = EX_UNAVAILABLE; |
exit_code = EX_UNAVAILABLE; |
922 |
} |
} |
923 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|