1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
From: Christian Kastner <ckk@kvr.at>
Date: Sun, 10 Jan 2016 20:32:28 +0100
Subject: Enable setting content headers in email
Set the ContentType: header based on the system locale or cron's environment,
if available.
Implementation taken from Fedora Core's version of cron.
Bug-Debian: https://bugs.debian.org/338051
Bug-Debian: https://bugs.debian.org/309150
Bug-Debian: https://bugs.debian.org/600310
Forwarded: no
Last-Update: 2016-01-10
Index: cron/cron.c
===================================================================
--- cron.orig/cron.c
+++ cron/cron.c
@@ -30,6 +30,7 @@ static char rcsid[] = "$Id: cron.c,v 2.1
#include <sys/types.h>
#include <fcntl.h>
#include <libgen.h>
+#include <strings.h>
static void usage __P((void)),
run_reboot_jobs __P((cron_db *)),
@@ -66,6 +67,7 @@ main(argc, argv)
char *argv[];
{
cron_db database;
+ char *cs;
ProgramName = basename(argv[0]);
@@ -95,6 +97,20 @@ main(argc, argv)
setenv("PATH", _PATH_DEFPATH, 1);
#endif
+ /* Get the default locale character set for the mail
+ * "Content-Type: ...; charset=" header
+ */
+ setlocale(LC_ALL,""); /* set locale to system defaults or to
+ that specified by any LC_* env vars */
+ setlocale(LC_COLLATE, "C"); /* Except for collation, since load_database() uses a-z */
+ /* Except that "US-ASCII" is preferred to "ANSI_x3.4-1968" in MIME,
+ * even though "ANSI_x3.4-1968" is the official charset name. */
+ if ((cs = nl_langinfo(CODESET)) != 0L &&
+ strcasecmp(cs, "ANSI_x3.4-1968") != 0)
+ strncpy(cron_default_mail_charset, cs, MAX_ENVSTR);
+ else
+ strcpy( cron_default_mail_charset, "US-ASCII");
+
/* if there are no debug flags turned on, fork as a daemon should.
*/
# if DEBUGGING
Index: cron/cron.h
===================================================================
--- cron.orig/cron.h
+++ cron/cron.h
@@ -294,6 +294,8 @@ static long GMToff;
int lsbsysinit_mode;
+char cron_default_mail_charset[MAX_ENVSTR] = "";
+
# if DEBUGGING
int DebugFlags;
char *DebugFlagNames[] = { /* sync with #defines */
@@ -312,6 +314,7 @@ extern time_t StartTime;
extern time_min timeRunning;
extern time_min virtualTime;
extern time_min clockTime;
+extern char cron_default_mail_charset[MAX_ENVSTR];
# if DEBUGGING
extern int DebugFlags;
extern char *DebugFlagNames[];
Index: cron/externs.h
===================================================================
--- cron.orig/externs.h
+++ cron/externs.h
@@ -26,6 +26,11 @@
# define WAIT_IS_INT 1
extern char *tzname[2];
# define TZONE(tm) tzname[(tm).tm_isdst]
+/* include locale stuff for mailer "Content-Type":
+ */
+#include <locale.h>
+#include <nl_types.h>
+#include <langinfo.h>
#endif
#if defined(UNIXPC)
Index: cron/do_command.c
===================================================================
--- cron.orig/do_command.c
+++ cron/do_command.c
@@ -470,8 +470,12 @@ child_process(e, u)
if (mailto) {
register char **env;
+ char **jobenv = build_env(e->envp);
auto char mailcmd[MAX_COMMAND];
auto char hostname[MAXHOSTNAMELEN];
+ char *content_type = env_get("CONTENT_TYPE",jobenv),
+ *content_transfer_encoding = env_get("CONTENT_TRANSFER_ENCODING",jobenv);
+
(void) gethostname(hostname, MAXHOSTNAMELEN);
(void) snprintf(mailcmd, sizeof(mailcmd),
@@ -490,7 +494,40 @@ child_process(e, u)
arpadate(&StartTime));
# endif /* MAIL_DATE */
fprintf(mail, "MIME-Version: 1.0\n");
- fprintf(mail, "Content-Transfer-Encoding: 8bit\n");
+
+ if (content_type == 0L) {
+ fprintf(mail, "Content-Type: text/plain; charset=%s\n",
+ cron_default_mail_charset);
+ } else {
+ /* user specified Content-Type header.
+ * disallow new-lines for security reasons
+ * (else users could specify arbitrary mail headers!)
+ */
+ char *nl=content_type;
+ size_t ctlen = strlen(content_type);
+
+ while ((*nl != '\0') &&
+ ((nl=strchr(nl,'\n')) != 0L) &&
+ (nl < (content_type+ctlen))) {
+ *nl = ' ';
+ }
+ fprintf(mail,"Content-Type: %s\n", content_type);
+ }
+
+ if (content_transfer_encoding != 0L) {
+ char *nl=content_transfer_encoding;
+ size_t ctlen = strlen(content_transfer_encoding);
+ while ((*nl != '\0') &&
+ ((nl=strchr(nl,'\n')) != 0L) &&
+ (nl < (content_transfer_encoding+ctlen))) {
+ *nl = ' ';
+ }
+
+ fprintf(mail,"Content-Transfer-Encoding: %s\n",
+ content_transfer_encoding);
+ } else {
+ fprintf(mail,"Content-Transfer-Encoding: 8bit\n");
+ }
for (env = e->envp; *env; env++)
fprintf(mail, "X-Cron-Env: <%s>\n",
Index: cron/crontab.5
===================================================================
--- cron.orig/crontab.5
+++ cron/crontab.5
@@ -121,6 +121,20 @@ override the settings described above no
.I crontab
file itself. Note in particular that if you want a PATH other than
"/usr/bin:/bin", you will need to set it in the crontab file.
+.PP
+By default, cron will send mail using the mail "Content-Type:" header of
+"text/plain" with the "charset=" parameter set to the charmap / codeset of the
+locale in which
+.IR crond (8)
+is started up \(en i.e.\& either the default system locale,
+if no LC_* environment variables are set, or the locale specified by
+the LC_* environment variables
+( see
+.IR locale (7) ).
+You can use different character encodings for mailed cron job output by
+setting the CONTENT_TYPE and CONTENT_TRANSFER_ENCODING variables in crontabs,
+to the correct values of the mail headers of those names.
+.PP
The format of a cron command is very much the V7 standard, with a number of
upward-compatible extensions. Each line has five time and date fields,
followed by a command, followed by a newline character ('\en').
|