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;
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);
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 */
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;
/* 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);
}
* 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);
}
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);
<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>
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>
</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>
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>
<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>
<!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>'>
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);
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);
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;
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",
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 */
#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__ */