1

Below is the code. I'm not getting output in tabular format. Can someone help?

#!/bin/bash
df -h > /home/test/space.txt
tmp="/home/test/tmp.html"
input="/home/test/space.txt"
echo '<html><body><table border=1>' > "$tmp"
awk '{print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print "</table></body></html>"}' "$input" >> "$tmp"
 cat $tmp | mail -s "$(echo -e "Test\nContent-Type: text/html")" -r yourmailaddress@...com

In email receiving output like below.

<html><body><table border=1> <tr> <td>Use%</td> <td>Avail</td> <td>Used</td> <td>Filesystem</td> </tr> <tr> <td>47%</td> <td>100G</td> <td>90G</td> <td>rootfs</td> </tr> 
Victory
  • 121
  • 1
  • 3
  • 18
  • @davis herring.. sorry it's typo – Victory Dec 10 '18 at 00:50
  • That's the problem with closing this question related to new features of some `mailx` that are NOT mentioned in ANY of the duplicate questions. Closing this as a dup will prevent any visitor of any prior questions from learning that the `s-nail` current implementation of Heirloom-mailx contains the `-M` option allowing the user to specify the `Content-type` (such as `"text/html"`) for body-text redirected from `stdin`. `s-nail` is the most active/current of all packages masquerading as `mailx` on modern Linux systems. – David C. Rankin Dec 10 '18 at 09:15

1 Answers1

2

The problem is likely your mail program which will encode your piped input as:

Content-Type: text/plain; charset=us-ascii

(given your mail is likely snail, Berkeley mailx, or heirloom_mailx -- all derived from various iterations of Berkeley mail with the latest, currently maintained version s-nail 14.9.11-1 (Homepage))

If your mail is one of the derivations that provides the -a (attach) option, that is probably the way to go. While the body of your e-mail will still be Content-Type: text/plain, your attachment will come through as Content-Type: text/html, which most mail readers will display within the e-mail itself (which appears to be your goal).

With just a few tweaks to your routine preparing the output from df as a table, what you have works quite well. The only tweaks made (optional, but help), were to use a quick sed substitution to replace "Mounted on" with "Mounted_on" to provide a consistent number of fields for awk to work with, and then to set the table "width=60%" to prevent the table from rendering scrunched (technical term).

For example, including the tweaks, you could do:

tmp=/home/david/tmp/df.html
echo '<html><body><table border=1 width=60%>' > "$tmp"
df | sed 's/Mounted\son/Mounted_on/' | 
awk '{print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} 
    END
    {print "</table></body></html>"}' >> "$tmp"
echo "df attached" | mailx -s "wizard df" -a "$tmp" david@nirvana

(obvious note: change the path assigned to tmp as required for your system as well as the e-mails)

Aside from the tweaks, the only change as mentioned above is to "attach" the html file to the message rather than dumping it into the message. Most variations of mail (but not all) provide the -a (attach) option. This provides a simple mechanism for sending files as a properly formed and encoded attachment. To provide the body of the mail message, I just included a simple "df attached" and used echo to pipe the text to the mail command. As shown above, the mail command was:

echo "df attached" | mailx -s "wizard df" -a "$tmp" david@nirvana

Then checking in an older version of Thunderbird, you find your tabular output of the df information, e.g.

e-mail results of html by attachment

Look things over and let me know if this is what you were attempting and whether you were able to find the -a (attach) option in your version of the command line mailer (if not, I'd recommend checking whether your distro provides s-nail or heirloom-mailx. For a tiny package, those two implementations provide robust command line mail capabilities)

Edit Per-Request to Encode as "text/html" in Body of Message

Here is where much will depend on which mail/mailx/s-nail package you have. With s-nail (which is generally aliased as mailx as well), the -M option allows you to specify the Content-type for text received on stdin for the body of the e-mail. In this case, all you need to is redirect "$tmp" to your mail command while specifying -M "text/html" as an option, e.g. change the last line above to:

 mailx -M "text/html" -s "wizard df redir -M" david@nirvana < "$tmp"

With s-nail/mailx that results in:

s-nail -M "text/html"

(note: I had to send from another machine, e.g. Archlinux packages s-nail as mailx while OpenSuSE packages heirloom-mailx)

With other packages like heirloom-mailx it appears the attachment is the only way to have mailx set Content-type based on extension. It does so by reading a MIME types file with syntax of the form:

 type/subtype      extension [extension . . .]

So in this case, it looks like you would have to either do a mail header re-write, or manually create the body of the mail message including the Content-type for the table part of the message similar to:

Content-Type: text/html; charset=us-ascii

(or whatever your charset should be)

That's why I suggested, if you are not using the mail/mailx based on s-nail, then go see if your distro offers the s-nail package, or it would even be worth building from source and dropping in /usr/local/bin.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thanks for your help. I need output in the email body content. Is possible? – Victory Dec 10 '18 at 02:44
  • I'm sure it is possible, I tried just dumping it into the body of the e-mail, but without setting the `Content-Type` manually, you will just be left with the html as plain/text in the body. Ironically, [@cody](https://stackoverflow.com/users/6124411/cody) was correct in his answer regarding the need to set the content-type, but with your version of `mail -a` (luckily) was looking for an attachment (which is why you received file-not-found). If you have `s-nail` you can use the `-M` option to specify content for `stdin` as `text/html`, it takes more without that option - what is your `mail`? – David C. Rankin Dec 10 '18 at 07:20
  • mailx version $ mailx -V 12.4 7/29/08 – Victory Dec 10 '18 at 08:43
  • Yep, you are stuck with attachments or re-writing the e-mail header to change the content type from `"text/plain"` to `"text/html"`. If it were me, I'd download the current [s-nail-14.9.11 source](https://www.sdaoden.eu/downloads/s-nail-14.9.11.tar.xz) and just build it and drop it in `/usr/local/bin`. If you check `man mailx` on your system, I suspect the man page ends describing `HEIRLOOM-MAILX 2010`. Opensuse has `mailx-12.5-25` and that lacks any ability to specify the content-type from `stdin`. – David C. Rankin Dec 10 '18 at 09:06
  • yes.. you are right... – Victory Dec 10 '18 at 09:24
  • in the above code to change output into HTML. I tried to change the font size and face for the table but unluckily I'm unable to change the say why? ****
    – Victory Dec 11 '18 at 10:37
  • *"I'm unable to ... say why?"* -- I suspect that is only due to the html parser in whatever mail client you are using forcing it to render as html for you (and you only). It is not a solution and will not work in most mail clients. The `Content-type:` remains `"text/plain"`. The only portable solution is to ensure the content type is `"text/html"` for it to render properly in mail clients supporting html. – David C. Rankin Dec 11 '18 at 11:30
  • now I sent email content through python. It's working perfectly but unable to change the table font size and face. – Victory Dec 11 '18 at 11:39
  • Python will be doing a great deal behind the scene. Depending on which version and what library you are loading in python, you should be able to add CSS to set the size and face. Remember the `` was deprecated in HTML long ago. (I believe in HTML 3). So you will likely need to embed CSS in the tag with, e.g. `style="font-size: 1em; font-family: sans-serif;"`
    – David C. Rankin Dec 11 '18 at 11:47
  • Python 2.6.6 and python7. I need one more help. if my output is separated by commas how to change into HTML? ***tmp=/home/david/tmp/df.html echo '' > "$tmp" df | sed 's/Mounted\son/Mounted_on/' | awk '{print "";for(i=1;i<=NF;i++)print "";print ""} END {print "
    " $i"
    "}' >> "$tmp"***
    – Victory Dec 13 '18 at 08:26
  • If the problem is `awk` injecting the commas, use `printf` instead of `print` to more further control the format. – David C. Rankin Dec 13 '18 at 08:30
  • sorry. I'm new to shell script. I'm just trying to convert csv into html but i couldn't. – Victory Dec 13 '18 at 08:41
  • Post a line or two from the `.csv` file you are trying to convert. If you are just trying to split each field as a new line, then `awk` is the tool for that. `awk -F',' '{for (i=1; i <= NF; i++) print $i}' file`. If you are just trying to replace or delete the commas, then `tr` is the tool. – David C. Rankin Dec 13 '18 at 10:20
  • Working perfectly. Thanks again – Victory Dec 13 '18 at 11:32