]> git.ipfire.org Git - thirdparty/sarg.git/commitdiff
Generate a top user email with the same options as the html report
authorFrederic Marchal <fmarchal@users.sourceforge.net>
Mon, 20 Jul 2015 12:18:26 +0000 (14:18 +0200)
committerFrederic Marchal <fmarchal@users.sourceforge.net>
Mon, 20 Jul 2015 12:18:26 +0000 (14:18 +0200)
The produced e-mail is still plain text but it is possible to sort the
entries and limit the number of lines with the same options as the html
report.

The top user list is the only report currently supporting that feature.

email.c
include/defs.h
report.c
topuser.c

diff --git a/email.c b/email.c
index 2a70dfe19b24dc5daf52902f082cb1dcb7a5edbe..dc5351e00e8ae5574a1df58ea46b7e831ce47cc0 100644 (file)
--- a/email.c
+++ b/email.c
 extern struct globalstatstruct globstat;
 #endif
 
-int geramail(const char *dirname, int debug, const char *email, const char *TempDir)
-{
-       FileObject *fp_in;
-       FILE *fp_top1, *fp_top2, *fp_top3;
-       long long int ttnbytes=0, ttnacc=0, tnacc=0;
-       long long int tnbytes=0, ttnelap=0, tnelap=0;
-       long long int nacc, nbytes, elap;
-       long long int avgacc, avgelap;
-       double perc=0.00;
-       double perc2=0.00;
-       int posicao=0;
-       char olduser[MAX_USER_LEN], csort[MAXLEN];
-       char wger[MAXLEN], top1[MAXLEN], top2[MAXLEN], top3[MAXLEN], user[MAX_USER_LEN];
-       char strip1[MAXLEN], strip2[MAXLEN], strip3[MAXLEN], strip4[MAXLEN], strip5[MAXLEN], strip6[MAXLEN], strip7[MAXLEN];
-       char *buf;
-       char warea[MAXLEN];
-       char Subject[120];
-       int totuser=0;
-       time_t t;
-       struct tm *local;
-       int cstatus;
-       struct getwordstruct gwarea;
-       struct generalitemstruct item;
-       longline line;
-       const struct userinfostruct *uinfo;
+//! Name of the file containing the e-mail to send.
+static char EmailFileName[MAXLEN]="";
 
-       snprintf(wger,sizeof(wger),"%s/sarg-general",dirname);
-       if((fp_in=FileObject_Open(wger))==NULL) {
-               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wger,FileObject_GetLastOpenError());
-               exit(EXIT_FAILURE);
-       }
+/*!
+ * Generate a file name to write the e-mail and open the file.
+ *
+ * \param Module The module for which the e-mail is generated.
+ *
+ * \return The file to which the e-mail can be written.
+ */
+FILE *Email_OutputFile(const char *Module)
+{
+       FILE *fp;
 
-       snprintf(top2,sizeof(top2),"%s/email.int_unsort",dirname);
-       if((fp_top2=fopen(top2,"w"))==NULL) {
-               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top2,strerror(errno));
-               exit(EXIT_FAILURE);
+       if(strcmp(email,"stdout") == 0) {
+               EmailFileName[0]='\0';
+               return(stdout);
        }
 
-       olduser[0]='\0';
-       totuser=0;
-
-       if ((line=longline_create())==NULL) {
-               debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wger);
+       snprintf(EmailFileName,sizeof(EmailFileName),"%s/%s.int_unsort",tmp,Module);
+       if ((fp=fopen(EmailFileName,"w"))==NULL) {
+               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),EmailFileName,strerror(errno));
                exit(EXIT_FAILURE);
        }
+       return(fp);
+}
 
-       while((buf=longline_read(fp_in,line))!=NULL) {
-               ger_read(buf,&item,wger);
-               if(item.total) continue;
-               if(strcmp(olduser,item.user) != 0) {
-                       totuser++;
-
-                       if (olduser[0] != '\0') {
-#if defined(__FreeBSD__)
-                               fprintf(fp_top2,"%s\t%qu\t%qu\t%qu\n",olduser,tnbytes,tnacc,tnelap);
-#else
-                               fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap);
-#endif
-                               ttnbytes+=tnbytes;
-                               ttnacc+=tnacc;
-                               ttnelap+=tnelap;
-                       }
-                       strcpy(olduser,item.user);
-                       tnbytes=0;
-                       tnacc=0;
-                       tnelap=0;
-               }
-
-               tnbytes+=item.nbytes;
-               tnacc+=item.nacc;
-               tnelap+=item.nelap;
-       }
-       if (FileObject_Close(fp_in)) {
-               debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wger,FileObject_GetLastCloseError());
-               exit(EXIT_FAILURE);
-       }
-       longline_destroy(&line);
-
-       if (olduser[0] != '\0') {
-#if defined(__FreeBSD__)
-               fprintf(fp_top2,"%s\t%qu\t%qu\t%qu\n",olduser,tnbytes,tnacc,tnelap);
-#else
-               fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap);
-#endif
-               ttnbytes+=tnbytes;
-               ttnacc+=tnacc;
-               ttnelap+=tnelap;
-       }
+/*!
+ * Send the e-mail.
+ *
+ * \param fp The file opened by Email_OutputFile().
+ */
+void Email_Send(FILE *fp,const char *Subject)
+{
+       char warea[MAXLEN];
+       int cstatus;
 
-       if (fclose(fp_top2)==EOF) {
-               debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top2,strerror(errno));
-               exit(EXIT_FAILURE);
-       }
+       if (fp==stdout) return;//to stdout
 
-#ifdef ENABLE_DOUBLE_CHECK_DATA
-       if (ttnacc!=globstat.nacc || ttnbytes!=globstat.nbytes || ttnelap!=globstat.elap) {
-               debuga(__FILE__,__LINE__,_("Total statistics mismatch when reading \"%s\" to produce the email report\n"),wger);
+       if (fclose(fp)==EOF) {
+               debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),EmailFileName,strerror(errno));
                exit(EXIT_FAILURE);
        }
-#endif
 
-       snprintf(top1,sizeof(top1),"%s/email.int_log",dirname);
-       if (snprintf(csort,sizeof(csort),"sort -n -T \"%s\" -t \"\t\" -r -k 2,2 -o \"%s\" \"%s\"", TempDir, top1, top2)>=sizeof(csort)) {
-               debuga(__FILE__,__LINE__,_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),top2,top1);
-               exit(EXIT_FAILURE);
-       }
-       cstatus=system(csort);
+       snprintf(warea,sizeof(warea),"%s -s \"%s\" \"%s\" <\"%s\"",MailUtility,Subject,email,EmailFileName);
+       if (debug)
+               debuga(__FILE__,__LINE__,_("Sending mail with command: %s\n"),warea);
+       cstatus=system(warea);
        if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-               debuga(__FILE__,__LINE__,_("sort command return status %d\n"),WEXITSTATUS(cstatus));
-               debuga(__FILE__,__LINE__,_("sort command: %s\n"),csort);
+               debuga(__FILE__,__LINE__,_("command return status %d\n"),WEXITSTATUS(cstatus));
+               debuga(__FILE__,__LINE__,_("command: %s\n"),warea);
                exit(EXIT_FAILURE);
        }
-
-       if (!KeepTempLog && unlink(top2)) {
-               debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),top2,strerror(errno));
+       if (!KeepTempLog && unlink(EmailFileName)) {
+               debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),EmailFileName,strerror(errno));
                exit(EXIT_FAILURE);
        }
-
-       if((fp_top1=fopen(top1,"r"))==NULL) {
-               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top1,strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       if(strcmp(email,"stdout") == 0) {
-               fp_top3=stdout;
-       } else {
-               snprintf(top3,sizeof(top3),"%s/report",dirname);
-               if((fp_top3=fopen(top3,"w"))==NULL) {
-                       debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top3,strerror(errno));
-                       exit(EXIT_FAILURE);
-               }
-       }
-
-       safe_strcpy(strip1,_("Squid User Access Report"),sizeof(strip1));
-       strip_latin(strip1);
-       fprintf(fp_top3,"%s\n",strip1);
-
-       safe_strcpy(strip1,_("Decreasing Access (bytes)"),sizeof(strip1));
-       strip_latin(strip1);
-       fprintf(fp_top3,"%s\n",strip1);
-
-       safe_strcpy(strip1,_("Period"),sizeof(strip1));
-       strip_latin(strip1);
-       fprintf(fp_top3,"%s %s\n\n",strip1,period.text);
-
-       safe_strcpy(strip1,_("NUM"),sizeof(strip1));
-       strip_latin(strip1);
-       safe_strcpy(strip2,_("USERID"),sizeof(strip2));
-       strip_latin(strip2);
-       safe_strcpy(strip3,_("CONNECT"),sizeof(strip3));
-       strip_latin(strip3);
-       safe_strcpy(strip4,_("BYTES"),sizeof(strip4));
-       strip_latin(strip4);
-       safe_strcpy(strip5,_("ELAPSED TIME"),sizeof(strip5));
-       strip_latin(strip5);
-       safe_strcpy(strip6,_("MILLISEC"),sizeof(strip6));
-       strip_latin(strip6);
-       safe_strcpy(strip7,pgettext("duration","TIME"),sizeof(strip7));
-       strip_latin(strip7);
-
-       fprintf(fp_top3,"%-7s %-20s %-8s %-15s %%%-6s %-10s %-10s %%%-7s\n------- -------------------- -------- --------------- ------- ---------- ---------- -------\n",strip1,strip2,strip3,strip4,strip4,strip5,strip6,strip7);
-
-       while ((TopUsersNum==0 || posicao<TopUsersNum) && fgets(warea,sizeof(warea),fp_top1)) {
-               fixendofline(warea);
-               getword_start(&gwarea,warea);
-               if (getword(user,sizeof(user),&gwarea,'\t')<0) {
-                       debuga(__FILE__,__LINE__,_("Invalid user ID in file \"%s\"\n"),top1);
-                       exit(EXIT_FAILURE);
-               }
-               if (getword_atoll(&nbytes,&gwarea,'\t')<0) {
-                       debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),top1);
-                       exit(EXIT_FAILURE);
-               }
-               if (getword_atoll(&nacc,&gwarea,'\t')<0) {
-                       debuga(__FILE__,__LINE__,_("Invalid number of accesses in file \"%s\"\n"),top1);
-                       exit(EXIT_FAILURE);
-               }
-               if (getword_atoll(&elap,&gwarea,'\0')<0) {
-                       debuga(__FILE__,__LINE__,_("Invalid elapsed time in file \"%s\"\n"),top1);
-                       exit(EXIT_FAILURE);
-               }
-
-               uinfo=userinfo_find_from_id(user);
-               if (!uinfo) {
-                       debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,top1);
-                       exit(EXIT_FAILURE);
-               }
-
-               perc=(ttnbytes) ? nbytes * 100. / ttnbytes : 0;
-               perc2=(ttnelap) ? elap * 100. / ttnelap : 0;
-
-               posicao++;
-
-#if defined(__FreeBSD__)
-               fprintf(fp_top3,"%7d %20s %8lld %15s %3.2lf%% %10s %10qu %3.2lf%%\n",posicao,uinfo->label,nacc,fixnum(nbytes,1),perc,buildtime(elap),elap,perc2);
-#else
-               fprintf(fp_top3,"%7d %20s %8"PRIu64" %15s %3.2lf%% %10s %10"PRIu64" %3.2lf%%\n",posicao,uinfo->label,(uint64_t)nacc,fixnum(nbytes,1),perc,buildtime(elap),(uint64_t)elap,perc2);
-#endif
-       }
-
-       // output total
-       fputs("------- -------------------- -------- --------------- ------- ---------- ---------- -------\n",fp_top3);
-#if defined(__FreeBSD__)
-       fprintf(fp_top3,"%-7s %20s %8qu %15s %8s %9s %10qu\n",_("TOTAL")," ",ttnacc,fixnum(ttnbytes,1)," ",buildtime(ttnelap),ttnelap);
-#else
-       fprintf(fp_top3,"%-7s %20s %8"PRIu64" %15s %8s %9s %10"PRIu64"\n",_("TOTAL")," ",(uint64_t)ttnacc,fixnum(ttnbytes,1)," ",buildtime(ttnelap),(uint64_t)ttnelap);
-#endif
-
-       // compute and write average
-       if (totuser>0) {
-               tnbytes=(totuser) ? ttnbytes / totuser : 0;
-               avgacc=ttnacc/totuser;
-               avgelap=ttnelap/totuser;
-       } else {
-               tnbytes=0;
-               avgacc=0;
-               avgelap=0;
-       }
-
-       safe_strcpy(strip1,_("AVERAGE"),sizeof(strip1));
-       strip_latin(strip1);
-#if defined(__FreeBSD__)
-       fprintf(fp_top3,"%-7s %20s %8qu %15s %8s %9s %10qu\n",strip1," ",avgacc,fixnum(tnbytes,1)," ",buildtime(avgelap),avgelap);
-#else
-       fprintf(fp_top3,"%-7s %20s %8"PRIu64" %15s %8s %9s %10"PRIu64"\n",strip1," ",(uint64_t)avgacc,fixnum(tnbytes,1)," ",buildtime(avgelap),(uint64_t)avgelap);
-#endif
-
-       if (fclose(fp_top1)==EOF) {
-               debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),top1,strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-       if (!KeepTempLog && unlink(top1)) {
-               debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),top1,strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       t = time(NULL);
-       local = localtime(&t);
-       fprintf(fp_top3, "\n%s\n", asctime(local));
-
-       if(strcmp(email,"stdout") != 0) {
-               if (fclose(fp_top3)==EOF) {
-                       debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top3,strerror(errno));
-                       exit(EXIT_FAILURE);
-               }
-
-               /* TRANSLATORS: The string is formatted using strftime. You can use
-                  any string formatting marker allowed by strftime. */
-               strftime(Subject,sizeof(Subject),_("SARG report, %c"),local);
-               snprintf(warea,sizeof(warea),"%s -s \"%s\" \"%s\" <\"%s\"",MailUtility,Subject,email,top3);
-               if (debug)
-                       debuga(__FILE__,__LINE__,_("Sending mail with command: %s\n"),warea);
-               cstatus=system(warea);
-               if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-                       debuga(__FILE__,__LINE__,_("command return status %d\n"),WEXITSTATUS(cstatus));
-                       debuga(__FILE__,__LINE__,_("command: %s\n"),warea);
-                       exit(EXIT_FAILURE);
-               }
-       }
-
-       //unlinkdir(TempDir,0);
-
-       return (0);
 }
index a40c1cef0b3194206e78345bbeb8db886696eb4b..101ce9a34c15a80753563ae80e517474bd8b9977 100644 (file)
@@ -214,7 +214,8 @@ bool is_download_suffix(const char *url);
 void download_cleanup(void);
 
 // email.c
-int geramail(const char *dirname, int debug, const char *email, const char *TempDir);
+FILE *Email_OutputFile(const char *Module);
+void Email_Send(FILE *fp,const char *Subject);
 
 // exclude.c
 void gethexclude(const char *hexfile, int debug);
index acf37feeb6bf1113cf9dcc6da96dc6912821bb43..dba3cd026bc0db93a069a3068a6ca9cadac8a00d 100644 (file)
--- a/report.c
+++ b/report.c
@@ -100,9 +100,9 @@ void gerarel(void)
                        exit(EXIT_FAILURE);
                }
        } else {
-               if (snprintf(outdirname,sizeof(outdirname),"%semailrep",outdir)>=sizeof(outdirname)) {
+               if (snprintf(outdirname,sizeof(outdirname),"%s/emailrep",tmp)>=sizeof(outdirname)) {
                        debuga(__FILE__,__LINE__,_("Path too long: "));
-                       debuga_more("%semailrep\n",outdir);
+                       debuga_more("%s/emailrep\n",tmp);
                        exit(EXIT_FAILURE);
                }
                my_mkdir(outdirname);
@@ -438,7 +438,7 @@ void gerarel(void)
 
                if(SuccessfulMsg) debuga(__FILE__,__LINE__,_("Successful report generated on %s\n"),outdirname);
        } else {
-               geramail(outdirname, debug, email, tmp);
+               topuser();
 
                if((strcmp(email,"stdout") != 0) && SuccessfulMsg)
                        debuga(__FILE__,__LINE__,_("Successful report generated and sent to %s\n"),email);
index 19bd2bc40d3e2624fb21319aae94c93adc932c48..762478f04f79458fc40d246d77d955fd02c3f1a3 100644 (file)
--- a/topuser.c
+++ b/topuser.c
@@ -393,6 +393,167 @@ static void TopUser_HtmlReport(const char *ListFile,struct TopUserStatistics *St
        }
 }
 
+/*!
+  Generate the top user email report.
+ */
+static void TopUser_TextEmail(const char *ListFile,struct TopUserStatistics *Statis,struct SortInfoStruct *SortInfo)
+{
+       FileObject *fp_top1;
+       FILE *fp_mail;
+       longline line;
+       struct getwordstruct gwarea;
+       char *warea;
+       char user[MAX_USER_LEN];
+       char strip1[MAXLEN], strip2[MAXLEN], strip3[MAXLEN], strip4[MAXLEN], strip5[MAXLEN], strip6[MAXLEN], strip7[MAXLEN];
+       long long int nbytes;
+       long long int nacc;
+       long long int elap, incac, oucac;
+       double perc=0.00;
+       double perc2=0.00;
+       long long int tnbytes=0;
+       long long int avgacc, avgelap;
+       int topcount=0;
+       struct userinfostruct *uinfo;
+       time_t t;
+       struct tm *local;
+       const char *Subject;
+
+       if ((fp_top1=FileObject_Open(ListFile))==NULL) {
+               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ListFile,FileObject_GetLastOpenError());
+               exit(EXIT_FAILURE);
+       }
+
+       fp_mail=Email_OutputFile("topuser");
+
+       if ((line=longline_create())==NULL) {
+               debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),ListFile);
+               exit(EXIT_FAILURE);
+       }
+
+       safe_strcpy(strip1,_("Squid User Access Report"),sizeof(strip1));
+       strip_latin(strip1);
+       fprintf(fp_mail,"%s\n",strip1);
+
+       snprintf(strip1,sizeof(strip1),_("Sort: %s, %s"),SortInfo->sort_field,SortInfo->sort_order);
+       strip_latin(strip1);
+       fprintf(fp_mail,"%s\n",strip1);
+
+       snprintf(strip1,sizeof(strip1),_("Period: %s"),period.text);
+       strip_latin(strip1);
+       fprintf(fp_mail,"%s\n\n",strip1);
+
+       safe_strcpy(strip1,_("NUM"),sizeof(strip1));
+       strip_latin(strip1);
+       safe_strcpy(strip2,_("USERID"),sizeof(strip2));
+       strip_latin(strip2);
+       safe_strcpy(strip3,_("CONNECT"),sizeof(strip3));
+       strip_latin(strip3);
+       safe_strcpy(strip4,_("BYTES"),sizeof(strip4));
+       strip_latin(strip4);
+       safe_strcpy(strip5,_("ELAPSED TIME"),sizeof(strip5));
+       strip_latin(strip5);
+       safe_strcpy(strip6,_("MILLISEC"),sizeof(strip6));
+       strip_latin(strip6);
+       safe_strcpy(strip7,pgettext("duration","TIME"),sizeof(strip7));
+       strip_latin(strip7);
+
+       fprintf(fp_mail,"%-7s %-20s %-9s %-15s %%%-6s %-11s %-10s %%%-7s\n------- -------------------- -------- --------------- ------- ---------- ---------- -------\n",strip1,strip2,strip3,strip4,strip4,strip5,strip6,strip7);
+
+
+       while ((warea=longline_read(fp_top1,line))!=NULL) {
+               getword_start(&gwarea,warea);
+               if (getword(user,sizeof(user),&gwarea,'\t')<0) {
+                       debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),ListFile);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword_atoll(&nbytes,&gwarea,'\t')<0) {
+                       debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),ListFile);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword_atoll(&nacc,&gwarea,'\t')<0) {
+                       debuga(__FILE__,__LINE__,_("Invalid number of accesses in file \"%s\"\n"),ListFile);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword_atoll(&elap,&gwarea,'\t')<0) {
+                       debuga(__FILE__,__LINE__,_("Invalid elapsed time in file \"%s\"\n"),ListFile);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword_atoll(&incac,&gwarea,'\t')<0) {
+                       debuga(__FILE__,__LINE__,_("Invalid in-cache size in file \"%s\"\n"),ListFile);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword_atoll(&oucac,&gwarea,'\n')<0) {
+                       debuga(__FILE__,__LINE__,_("Invalid out-of-cache size in file \"%s\"\n"),ListFile);
+                       exit(EXIT_FAILURE);
+               }
+               if (nacc < 1)
+                       continue;
+               if (TopUsersNum>0 && topcount>=TopUsersNum) break;
+
+               uinfo=userinfo_find_from_id(user);
+               if (!uinfo) {
+                       debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,ListFile);
+                       exit(EXIT_FAILURE);
+               }
+               uinfo->topuser=1;
+
+               perc=(Statis->ttnbytes) ? nbytes * 100. / Statis->ttnbytes : 0;
+               perc2=(Statis->ttnelap) ? elap * 100. / Statis->ttnelap : 0;
+
+               topcount++;
+
+#if defined(__FreeBSD__)
+               fprintf(fp_mail,"%7d %20s %8lld %15s %5.2lf%% %10s %10qu %3.2lf%%\n",topcount,uinfo->label,nacc,fixnum(nbytes,1),perc,buildtime(elap),elap,perc2);
+#else
+               fprintf(fp_mail,"%7d %20s %8"PRIu64" %15s %6.2lf%% %10s %10"PRIu64" %3.2lf%%\n",topcount,uinfo->label,(uint64_t)nacc,fixnum(nbytes,1),perc,buildtime(elap),(uint64_t)elap,perc2);
+#endif
+       }
+       if (FileObject_Close(fp_top1)) {
+               debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),ListFile,FileObject_GetLastCloseError());
+               exit(EXIT_FAILURE);
+       }
+       if (!KeepTempLog && unlink(ListFile)) {
+               debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),ListFile,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       longline_destroy(&line);
+
+       // output total
+       fputs("------- -------------------- -------- --------------- ------- ---------- ---------- -------\n",fp_mail);
+#if defined(__FreeBSD__)
+       fprintf(fp_mail,"%-7s %20s %8qu %15s %8s %9s %10qu\n",_("TOTAL")," ",Statis->ttnacc,fixnum(Statis->ttnbytes,1)," ",buildtime(Statis->ttnelap),Statis->ttnelap);
+#else
+       fprintf(fp_mail,"%-7s %20s %8"PRIu64" %15s %8s %9s %10"PRIu64"\n",_("TOTAL")," ",(uint64_t)Statis->ttnacc,fixnum(Statis->ttnbytes,1)," ",buildtime(Statis->ttnelap),(uint64_t)Statis->ttnelap);
+#endif
+
+       // compute and write average
+       if (Statis->totuser>0) {
+               tnbytes=Statis->ttnbytes / Statis->totuser;
+               avgacc=Statis->ttnacc/Statis->totuser;
+               avgelap=Statis->ttnelap/Statis->totuser;
+       } else {
+               tnbytes=0;
+               avgacc=0;
+               avgelap=0;
+       }
+
+       safe_strcpy(strip1,_("AVERAGE"),sizeof(strip1));
+       strip_latin(strip1);
+#if defined(__FreeBSD__)
+       fprintf(fp_mail,"%-7s %20s %8qu %15s %8s %9s %10qu\n",strip1," ",avgacc,fixnum(tnbytes,1)," ",buildtime(avgelap),avgelap);
+#else
+       fprintf(fp_mail,"%-7s %20s %8"PRIu64" %15s %8s %9s %10"PRIu64"\n",strip1," ",(uint64_t)avgacc,fixnum(tnbytes,1)," ",buildtime(avgelap),(uint64_t)avgelap);
+#endif
+
+       t = time(NULL);
+       local = localtime(&t);
+       fprintf(fp_mail, "\n%s\n", asctime(local));
+
+       /* TRANSLATORS: This is the e-mail subject. */
+       Subject=_("Sarg: top user report");
+       Email_Send(fp_mail,Subject);
+}
+
 /*!
  * Produce a report with the user downloading the most data.
  */
@@ -545,5 +706,8 @@ void topuser(void)
                exit(EXIT_FAILURE);
        }
 
-       TopUser_HtmlReport(top1,&Statis,&SortInfo);
+       if (email[0])
+               TopUser_TextEmail(top1,&Statis,&SortInfo);
+       else
+               TopUser_HtmlReport(top1,&Statis,&SortInfo);
 }