]> granicus.if.org Git - fcron/commitdiff
Set From: header on emails. Added mailfrom() option.
authorThibault Godouet <fcron@free.fr>
Sun, 12 Oct 2014 10:20:04 +0000 (11:20 +0100)
committerThibault Godouet <fcron@free.fr>
Sun, 12 Oct 2014 10:20:18 +0000 (11:20 +0100)
12 files changed:
cl.c
cl.h
conf.c
convert-fcrontab.c
doc/en/changes.sgml
doc/en/fcrontab.5.sgml
doc/en/todo.sgml
doc/fcron-doc.mod.in
fileconf.c
job.c
save.c
save.h

diff --git a/cl.c b/cl.c
index a02c9bc9f1358bfb2b4055cf369cc1fe7e288cd0..3280b9826a1aa459e9d4b34cb096102c2af33ff8 100644 (file)
--- a/cl.c
+++ b/cl.c
@@ -51,7 +51,9 @@ dups_cl(cl_t * orig)
     debug("%s: Set cl->cl_runas=%s", __func__,
           (cl->cl_runas == NULL) ? "null" : cl->cl_runas);
 
+    cl->cl_mailfrom = NULL;
     cl->cl_mailto = NULL;
+    Set(cl->cl_mailfrom, orig->cl_mailfrom);
     Set(cl->cl_mailto, orig->cl_mailto);
 
     cl->cl_tz = NULL;
@@ -67,6 +69,7 @@ free_line(cl_t * cl)
     if (cl != NULL) {
         Free_safe(cl->cl_shell);
         Free_safe(cl->cl_runas);
+        Free_safe(cl->cl_mailfrom);
         Free_safe(cl->cl_mailto);
         Free_safe(cl->cl_tz);
         Free_safe(cl);
diff --git a/cl.h b/cl.h
index 0dde2d558d5ffdd363859495313401dace4d3f43..1a2def52b9834f658433b4ac10930a60911e0a9a 100644 (file)
--- a/cl.h
+++ b/cl.h
@@ -41,6 +41,7 @@ typedef struct cl_t {
     struct cf_t *cl_file;       /* the file in which the line is           */
     char *cl_shell;             /* shell command                           */
     char *cl_runas;             /* determine permissions of the job        */
+    char *cl_mailfrom;          /* use this as email From header           */
     char *cl_mailto;            /* mail output to cl_mailto                */
     char *cl_tz;                /* time zone of the line                   */
     unsigned long cl_id;        /* line's unique id number                 */
diff --git a/conf.c b/conf.c
index 5f808d1776d5df72698792dcff12ea4b68c49c73..1ac0ba832b5bdd4fc1e1e50804bdf0de19430580 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -652,6 +652,11 @@ read_file(const char *file_name, cf_t * cf, int is_system_startup)
             Read_strn(cl->cl_runas, size, "Error while reading runas field");
             break;
 
+        case S_MAILFROM_T:
+            Read_strn(cl->cl_mailfrom, size,
+                      "Error while reading mailfrom field");
+            break;
+
         case S_MAILTO_T:
             Read_strn(cl->cl_mailto, size, "Error while reading mailto field");
             break;
@@ -781,6 +786,7 @@ read_file(const char *file_name, cf_t * cf, int is_system_startup)
         /* line is not yet in the line list of the file : free it */
         Free_safe(cl->cl_shell);
         Free_safe(cl->cl_runas);
+        Free_safe(cl->cl_mailfrom);
         Free_safe(cl->cl_mailto);
         Free_safe(cl);
     }
@@ -830,11 +836,19 @@ add_line_to_file(cl_t * cl, cf_t * cf, uid_t runas, char *runas_str,
      * struct cf_t may be required */
     cl->cl_file = cf;
 
-    /* check if the mailto field is valid */
+    /* check if the mailfrom and mailto fields are safe */
+    if (cl->cl_mailfrom && (*(cl->cl_mailfrom) == '-' ||
+                            strcspn(cl->cl_mailfrom,
+                                    " \t\n;|") != strlen(cl->cl_mailfrom))) {
+        error
+            ("mailfrom field \'%s\' is not safe : unsetting to use default value.",
+             cl->cl_mailfrom);
+        Free_safe(cl->cl_mailfrom);
+    }
     if (cl->cl_mailto && (*(cl->cl_mailto) == '-' ||
                           strcspn(cl->cl_mailto,
-                                  " \t\n") != strlen(cl->cl_mailto))) {
-        error("mailto field \'%s\' is not valid : set to owner %s.",
+                                  " \t\n;|") != strlen(cl->cl_mailto))) {
+        error("mailto field \'%s\' is not safe : setting to owner %s.",
               cl->cl_mailto, cl->cl_file->cf_user);
         Set(cl->cl_mailto, cl->cl_file->cf_user);
     }
index c40c62e4aa0a8761e64c7282eced194fdc735da9..a06cfe0adbbc3da679a7c224ab93f84fa3cc80b5 100644 (file)
@@ -116,6 +116,7 @@ delete_file(cf_t * file)
     while ((line = cur_line) != NULL) {
         cur_line = line->cl_next;
         Free_safe(line->cl_shell);
+        Free_safe(line->cl_mailfrom);
         Free_safe(line->cl_mailto);
         Free_safe(line->cl_runas);
         Free_safe(line);
index 0f78fe2d3c6c15e9a4188ec732c111594e77f5f7..d8d43ce20ddd024e5408fcfaa72b949a62227675 100644 (file)
@@ -13,7 +13,15 @@ A copy of the license is included in gfdl.sgml.
       <title>Changes</title>
 
       <itemizedlist>
-        <title>From version 3.1.3 to 3.2.0</title>
+        <title>From version 3.2.0 to 3.2.1</title>
+           <listitem>
+             <para>add From: header to emails. Similarly to other crons, use: "From: %s (fcron)" with %s
+             being either the user the job is run as or the value of MAILFROM.</para>
+           </listitem>
+      </itemizedlist>
+
+      <itemizedlist>
+         <title>From version 3.1.3 to 3.2.0</title>
            <listitem>
               <para>Print date as %Y-%m-%d (the ISO 8601 date format), to avoid being ambiguous in international context.  Also always use the ':' as hour:minute separator (there was a couple of 'h' instead).</para>
            </listitem>
index d66b8307a8eda2bb788a5acbf78264349a52aaec..907101d25f293580875f29a247973e89909444a7 100644 (file)
@@ -72,11 +72,11 @@ overridden by settings in the &fcrontabf;, but <envar>USER</envar> may not.
 Every other environment assignments defined in the user &fcrontabf; are then
 made, and the command is executed.</para>
             <para>By default, fcron will send emails using the email "Content-Type:" header of "text/plain" with the "charset=" parameter set to the charmap / codeset of the locale in which <link linkend="fcron.8">&fcron;(8)</link> is started up - i.e. either the default system locale, if no LC_* environment variables are set, or the locale specified by the LC_* environment variables (see locale(7)). You can use different character encodings for emailed fcron job output by setting the CONTENT_TYPE and CONTENT_TRANSFER_ENCODING variables in fcrontabs, to the correct values of the mail headers of those names.</para>
-           <para>Plus, the special variable <varname>MAILTO</varname> allows
-you to tell &fcron; to whom it has to mail the command's output. Note that
-<varname>MAILTO</varname> is in fact equivalent to a global declaration of the
-option &optmailto; (see below). It is only used for backward compatibility, so
-you should use the option &optmailto; directly.
+           <para>Additionally, the special variables <varname>MAILFROM</varname> and
+<varname>MAILTO</varname> allow you to tell &fcron; from/to whom it should email
+the command's output. Note that these are in fact equivalent to global declarations of the
+options &optmailfrom; and &optmailto; (see below). They are used for backward compatibility,
+and it is recommended that you use the options &optmailfrom; and &optmailto; directly instead.
 </para>
        </refsect2>
 
@@ -666,6 +666,20 @@ system load average values.</para>
                    </listitem>
                </varlistentry>
 
+               <varlistentry id="fcrontab.5.mailfrom">
+                   <term>mailfrom</term>
+                   <listitem>
+                       <para><emphasis><type>email-address</type></emphasis>(<constant>user job is run as</constant>)</para>
+                       <para>Use this as the 'From:' address when mailing job outputs.
+                        It can be either a single user-name or a fully qualified email address.
+                        In the former case, &fcron; will add the hostname automatically.
+                        Setting &optmailfrom; to an empty value is equivalent to
+resetting it to the default value of the name of the user the job is run as.</para>
+                       <para>&seealso; options &optmail;, &optforcemail;,
+&opterroronlymail;, &optnolog;, &optmailto;.</para>
+                   </listitem>
+               </varlistentry>
+
                <varlistentry id="fcrontab.5.mailto">
                    <term>mailto</term>
                    <listitem>
@@ -673,10 +687,11 @@ system load average values.</para>
 of file's owner</constant>)</para>
                        <para>Mail output (if needed) to
 "<replaceable>email-address</replaceable>". It can be either a single user-name
-or a fully qualified email address. A &optmailto; declared and empty (string
+or a fully qualified email address. In the former case, &fcron; will add the hostname automatically.
+A &optmailto; declared and empty (string
 "") is equivalent to "<token>mail(false)</token>".</para>
                        <para>&seealso; options &optmail;, &optforcemail;,
-&opterroronlymail;, &optnolog;.</para>
+&opterroronlymail;, &optnolog;, &optmailfrom;.</para>
                    </listitem>
                </varlistentry>
 
index 0c439e5d127afce75c8fc6b88c4ad78b90cd9ec3..6c5956fbcced9baf4e018c170082ff0b1c84c32b 100644 (file)
@@ -23,10 +23,6 @@ A copy of the license is included in gfdl.sgml.
       <sect2>
         <title>High priority</title>
         <itemizedlist>
-           <listitem>
-              <para>add From: to emails. Similarly to other crons, use: "From: %s (fcron Daemon)" with %s
-               being either the user fcron runs at (typically 'fcron') or the value of MAILFROM.</para>
-           </listitem>
            <listitem>
               <para>Option to compile and install from git sources without generating the doc</para>
            </listitem>
index 572e1669eecfac29d584f73d826bd779596c78b5..dee0081297d729cb4980825740851c291d22bc4f 100644 (file)
@@ -94,6 +94,7 @@
 <!ENTITY optlavgonce '<link linkend="fcrontab.5.lavgonce"><varname>lavgonce</varname></link>'>
 <!ENTITY optlavgor '<link linkend="fcrontab.5.lavgor"><varname>lavgor</varname></link>'>
 <!ENTITY optmail '<link linkend="fcrontab.5.mail"><varname>mail</varname></link>'>
+<!ENTITY optmailfrom '<link linkend="fcrontab.5.mailfrom"><varname>mailfrom</varname></link>'>
 <!ENTITY optmailto '<link linkend="fcrontab.5.mailto"><varname>mailto</varname></link>'>
 <!ENTITY optnice '<link linkend="fcrontab.5.nice"><varname>nice</varname></link>'>
 <!ENTITY optnolog '<link linkend="fcrontab.5.nolog"><varname>nolog</varname></link>'>
index 9de85c77bd526dceaa185795c15e9559335635ad..49a1c8017915d18d9cb3ea0171501c42eab5eaad 100644 (file)
@@ -283,6 +283,7 @@ read_file(char *filename, int fd)
         error_e("could not fflush() file_name");
 
     Free_safe(default_line.cl_runas);
+    Free_safe(default_line.cl_mailfrom);
     Free_safe(default_line.cl_mailto);
     Free_safe(default_line.cl_tz);
 
@@ -345,10 +346,15 @@ read_env(char *ptr, cf_t * cf)
         return;
     }
 
-    /* the MAILTO assignment is, in fact, an fcron option :
+    /* the MAILFROM/MAILTO assignment is, in fact, an fcron option :
      *  we don't store it in the same way. */
     /* please note that we check if the mailto is valid in conf.c */
-    if (strcmp(name, "MAILTO") == 0) {
+    if (strcmp(name, "MAILFROM") == 0) {
+        Set(default_line.cl_mailfrom, val);
+    }
+    else if (strcmp(name, "MAILTO") == 0) {
+        /* cl_mailto must not be NULL (as expected in
+         * conf.c:add_line_to_file()), so we check if the length is >= 0 */
         if (strcmp(val, "\0") == 0) {
             clear_mail(default_line.cl_option);
             clear_mailzerolength(default_line.cl_option);
@@ -868,6 +874,27 @@ read_opt(char *ptr, cl_t * cl)
                 fprintf(stderr, "  Opt : \"%s\" %d\n", opt_name, i);
         }
 
+        else if (strcmp(opt_name, "mailfrom") == 0) {
+            int len = -1;
+
+            if (!in_brackets) {
+                Handle_err;
+            }
+
+            /* Also please note that we check if the mailfrom is valid in conf.c */
+            len = assign_option_string(&(cl->cl_mailfrom), ptr);
+            if (len < 0) {
+                Handle_err;
+            }
+            else {
+                ptr += len;
+            }
+
+            if (debug_opt)
+                fprintf(stderr, "  Opt : \"%s\" \"%s\"\n", opt_name,
+                        cl->cl_mailfrom);
+        }
+
         else if (strcmp(opt_name, "mailto") == 0) {
             int len = -1;
 
diff --git a/job.c b/job.c
index abb0405e76fbc2bcbaeb3bf1b797cb695b43b0d8..c0f271ee6c1fe1d11644b0ebcae590524c865073 100644 (file)
--- a/job.c
+++ b/job.c
@@ -286,42 +286,49 @@ create_mail(cl_t * line, char *subject, char *content_type, char *encoding,
     int mailfd = temp_file(NULL);
     FILE *mailf = fdopen(mailfd, "r+");
     char hostname[USER_NAME_LEN];
-    /* is this a complete mail address ? (ie. with a "@", not only a username) */
-    char add_hostname = 0;
+    char *mailfrom = line->cl_runas;    /* default value if not explicitely defined for that cl */
+    /* hostname to add to email addresses (depending on if they have a '@') */
+    char *hostname_from = "";
+    char *hostname_to = "";
     int i = 0;
 
     if (mailf == NULL)
         die_e("Could not fdopen() mailfd");
 
+    if (line->cl_mailfrom != NULL) {
+        mailfrom = line->cl_mailfrom;
+    }
+
 #ifdef HAVE_GETHOSTNAME
-    if (gethostname(hostname, sizeof(hostname)) != 0) {
+    /* first letter will be '@' if hostname is defined */
+    if (gethostname((hostname + 1), sizeof(hostname) - 1) != 0) {
         error_e("Could not get hostname");
         hostname[0] = '\0';
     }
     else {
         /* it is unspecified whether a truncated hostname is NUL-terminated */
-        hostname[USER_NAME_LEN - 1] = '\0';
+        hostname[0] = '@';
+        hostname[sizeof(hostname) - 1] = '\0';
 
-        /* check if mailto is a complete mail address */
-        add_hostname = (strchr(line->cl_mailto, '@') == NULL) ? 1 : 0;
+        /* check if mailfrom/mailto are complete email addresses */
+        hostname_from = (strchr(mailfrom, '@') == NULL) ? hostname : "";
+        hostname_to = (strchr(line->cl_mailto, '@') == NULL) ? hostname : "";
     }
 #else                           /* HAVE_GETHOSTNAME */
     hostname[0] = '\0';
 #endif                          /* HAVE_GETHOSTNAME */
 
     /* write mail header */
-    if (add_hostname)
-        fprintf(mailf, "To: %s@%s\n", line->cl_mailto, hostname);
-    else
-        fprintf(mailf, "To: %s\n", line->cl_mailto);
+    fprintf(mailf, "From: %s%s (fcron)\n", mailfrom, hostname_from);
+    fprintf(mailf, "To: %s%s\n", line->cl_mailto, hostname_to);
 
     if (subject)
-        fprintf(mailf, "Subject: fcron <%s@%s> %s: %s\n",
-                line->cl_file->cf_user, (hostname[0] != '\0') ? hostname : "?",
+        fprintf(mailf, "Subject: fcron <%s%s> %s: %s\n",
+                line->cl_file->cf_user, (hostname[0] != '\0') ? hostname : "@?",
                 subject, line->cl_shell);
     else
-        fprintf(mailf, "Subject: fcron <%s@%s> %s\n", line->cl_file->cf_user,
-                (hostname[0] != '\0') ? hostname : "?", line->cl_shell);
+        fprintf(mailf, "Subject: fcron <%s%s> %s\n", line->cl_file->cf_user,
+                (hostname[0] != '\0') ? hostname : "@?", line->cl_shell);
 
     if (content_type == NULL) {
         fprintf(mailf, "Content-Type: text/plain; charset=%s\n",
diff --git a/save.c b/save.c
index 7e4fe870882e94bde5097307122aec5b62d004b1..1311a3bbf7318e820a4c93ddd7f7f7d6a498f93b 100644 (file)
--- a/save.c
+++ b/save.c
@@ -273,6 +273,10 @@ write_file_to_disk(int fd, struct cf_t *file, time_t time_date)
             Save_lint(fd, S_JITTER_T, line->cl_jitter, write_buf,
                       &write_buf_used);
         }
+        if (line->cl_mailfrom != NULL && line->cl_mailfrom[0] != '\0') {
+            Save_str(fd, S_MAILFROM_T, line->cl_mailfrom, write_buf,
+                     &write_buf_used);
+        }
 
         if (is_freq(line->cl_option)) {
             /* save the frequency to run the line */
diff --git a/save.h b/save.h
index 162e9ba671bb03fb90aea8be5a370405c2426bdf..883de1bc796316bdc913183a473398940e7c741e 100644 (file)
--- a/save.h
+++ b/save.h
@@ -81,5 +81,6 @@ extern int save_file_safe(cf_t * file, char *final_path, char *prog_name,
 #define S_FIRST_T      2018     /* wait time before first execution */
 #define S_TZ_T         2019     /* time zone of the line */
 #define S_JITTER_T     2020     /* jitter of the line */
+#define S_MAILFROM_T   2021     /* use as email From header */
 
 #endif                          /* __SAVE_H__ */