10/23/2008

如何在命令列下寄信

在Unix的系統管理上我們常會把各式各樣指令的輸出導到檔案去,但是檔案在系統上想看一下內容難免還得要登入進去。於是懶惰的人就會把這些輸出寄出來給相關的人,這樣就不需要連進去系統了。
在Unix下寄mail是一件很平常的事,有人可能會覺得這個有點老生常談,但事實是還是有人會來問我命令列下要怎麼寄mail,而這個問題在網路上應該還是FAQ中的FAQ。

在Unix下最常被用來寄信的指令應該非mail莫屬,因為它普遍的存在各種不同版本不同平台的Unix系統上。或許你習慣用它的加強版mailx。不過這二個用起來差不多我也不清楚到底有什麼差別,知道的人跟我講一下吧。另外有一個指令叫mutt 它是一個功能相當強大的MUA軟體,如果你有安裝的話也可以使用它來寄mail。
現在我們就來看個簡單的例子。假設你想把/etc/hosts的內容傳到你的電腦上,你不需要使用ftp來把它抓到你的電腦,只要使用指令來將它寄給你自己。

# cat /etc/hosts |mailx -s 'hosts table' jerry@abc.com

許多人應該都知道要怎麼用,而且也很多人應該是這樣子用的。上面的指令並沒有錯,只是可以直接把檔案導入給mailx,為什麼要cat給mailx呢?公司薪水給的又不多,實在沒必要多花時間在處理公事上,所以字能少打就少打吧。

# mailx -s 'hosts table' jerry@abc.com < /etc/hosts

-s(Subject)是主旨,如果主旨有空白字元的話,記得要用單引號(')或是雙引號(")括起來。最後一個參數是收件人,如果收件人有多個的時候要用逗號(,)分隔,如jerry@abc.com,jerry@abc.com.tw
或者你在Linux下而且又裝了mutt。你也可以使用mutt來寄信,mutt的參數和mail差不多。

# mutt -s 'hosts table' jerry@abc.com 

可是這樣子寄,/etc/hosts的內容是在信裡面呀,我想把它變成附件可以嗎?當然可以,只要跟其他的程式配合就可以了。

# uuencode /etc/hosts hosts.txt | mailx -s 'hosts table' jerry@abc.com

利用uuencode把/etc/hosts編碼過後丟給mailx就可以了,uuencode第一個參數是要編碼的檔案,第二個參數是編碼後的檔名,在這裡就是附件的檔名。下面的例子示範了把tar檔變成附件直接寄出。

# tar cf - /etc/* | uuencode etc.tar | mailx -s 'hosts table' jerry@abc.com 

如果你用的是mutt那就更簡單了。只要加個-a(attach file)

# echo '/etc/hosts'|mutt -a /etc/hosts -s 'hosts table' jerry@abc.com

有人會問說「Jerry,我不要只是寄純文字的mail,可以寄html格式的mail嗎?」在我回答之前,可以容許我先打你一拳嗎? 如果你有mutt(1.5.x 以上才行)的話要寄html格式的mail就很容易了(什麼,到這個時候還沒發現mutt有多好用嗎?還不快去裝起來。)。一行指令就可以搞定。


# mutt -e 'set content_type="text/html"' jerry@abc.com" -s 'html format'

mutt允許我們對要寄出的mail修改它的檔頭(header),所以可以使用-e來設定檔頭的變數content_type為"text/html",這個變數名稱content_type和真正檔頭Content-type的字不一樣哦!不要搞錯了。最後再導入一個html格式的檔案給它就可以了。記住,-e後面那一串字不能錯哦!(1.5.x 以上才有這個變數。)
如果沒有mutt呢!裝一個,不然就繼續看下去。絕大多數的Unix系統應該都有內建sendmail,而sendmail有個參數-t可以達成我們的要求。看看下面的範例。

# echo 'Mime-Version: 1.0
> Content-type: text/html; charset="iso-8859-1"
> From: jerry@abc.com
> To: jerry@abc.com.tw
> Subject: test.......
>
> html file
> ' | sendmail -t

使用echo把檔頭和所要html的內容全部輸出給sendmail這樣子就可以了。不過我想沒人會真的在命令列這樣使用,多半會用在script裡面。下面提供一個script範例給你參考,主要的部份在被#包住的那個區塊,把你要的輸出做成html格式就 可以了。

#!/bin/sh
fromuser=jerry@abc.com
touser=jerry@abc.com,abc,boss@abc.com
subject="`uname -n` df output"
sendmail="/usr/sbin/sendmail -t"

header="Mime-Version: 1.0
Content-type: text/html; charset="iso-8859-1"
From: $fromuser
To: $touser
Subject: $subject
"

footer="
"

{
echo "$header"
### replace your code here. ###
df -k |awk '/^\//{$5=sprintf("%2d%",$5) ; print $0}'
###############################
echo "$footer"
} | $sendmail

下面二個script,第一個是shell script;第二個是perl script,你可以把要輸出的內容存成html檔,再用sendhtml直接寄出html格式的mail。寫的不怎麼樣,但最少可以使用啦!也給你一個想法做參考,你可以以此延伸然後寫一個符合你的script。
使用的方法如下,
sendhtml.pl "my subject" jerry@abc.com my_file.html

#!/bin/sh
## usage : sendhtml.sh subject To_User html_file
subject="$1"
touser="$2"
htmlfile="$3"
fromuser="jerry@abc.com"
sendmail="/usr/sbin/sendmail -t"

header="Mime-Version: 1.0
Content-type: text/html; charset=\"iso-8859-1\"
From: $fromuser
To: $touser
Subject: $subject"
{
echo "$header"
cat "$htmlfile"
} | $sendmail

#!/usr/bin/perl -w
# usage : sendhtml.pl subject To_User html_file
my $sendmail = "/usr/sbin/sendmail";
my $fromuser = "jerry\@abc.com";
$subject = $ARGV[0];
$touser = $ARGV[1];
$htmlfile = $ARGV[2];

$header="Mime-Version: 1.0
Content-type: text/html; charset=\"iso-8859-1\"
From: $fromuser
To: $touser
Subject: $subject\n";

open(fd2, "| $sendmail -t");
print fd2 $header;
open(fd1, $htmlfile);
while(my $line=) {
print fd2 "$line\n";
}
close(fd2);
close(fd1);

在寄附件的部份能不用uuencode就不要用,因為uuencode+mailx所寄出來的mail並不會在檔頭的部份加入MIME編碼的訊息,而現在有越來越多的郵件程式不會正確讀取此種格式的mail。如yahoo, MSN....等webmail,在開啟這些mail時都會顯示亂碼,而不是正確的附檔。所以建議儘量使用別的程式來取代。
在命令列下寄mail的方法不只這些,如使用nail(已經改名叫mailx)或是使用perl、php....等也是可以, 但以一般需求來講,我覺得這些應該已經夠了。如果你有什麼好的方法,歡迎你和大家分享。

沒有留言: