2010-06-25 114 views
16

我有一個運行在cron上的腳本,輸出一些我們發送給'郵件'程序的文本。總路線是這樣的:如何通過郵件從shell腳本發送特殊字符?

./command.sh | mail -s "My Subject" [email protected] -- -F "Sender Name" -f [email protected] 

問題是由腳本生成的文本有一些特殊字符 - E,A和C - 因爲它是不是英文。當收到電子郵件時,每個字符都被??取代。

現在我明白,這很可能是由於編碼設置不正確。解決這個問題的最簡單方法是什麼?

+0

我的文本是從shell腳本直接ECHO的。從控制檯執行時,特殊字符顯示正確。 – JohnWithoutArms 2010-06-25 17:51:06

+0

電子郵件的標題顯示此內容: Content-Transfer-Encoding:7bit – JohnWithoutArms 2010-06-25 17:52:22

+0

我正在嘗試這樣做:echo「maçã」|郵件[email protected]。 而在電子郵件上收到的結果是:ma ????。 LANG設置爲pt_BR.UTF-8,LC_CTYPE也一樣。 – JohnWithoutArms 2010-06-25 17:56:50

回答

0

這可能不是一個命令行問題,而是一個字符集問題。通常當發送電子郵件時,字符集將是iso-8859-1。最有可能的是你放入該過程的文本不是iso-8859-1編碼的。看看你從中獲取文本的任何數據源的編碼是什麼。

強制性「好讀」鏈接:The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

回覆您的更新:在這種情況下,如果你手動輸入特殊字符,您的終端可以使用UTF-8編碼。例如,您應該能夠使用iconv轉換文件的字符集。另一種方法是告訴mail使用UTF-8編碼,但是IIRC不是完全無關緊要的。

9

你說得對,這是一個字符集問題。您需要將適當的環境變量設置到您的crontab的開頭。

像這樣的東西應該工作:

LANG=en_US.UTF-8 
LC_CTYPE=en_US.UTF-8 

到位LC_CTYPE的可以選擇使用LC_ALL。

參考:http://opengroup.org/onlinepubs/007908799/xbd/envvar.html

編輯:當您在shell中運行它,它顯示正常的原因可能是因爲上述ENV瓦爾在你的shell設置。

要驗證,請在shell中執行'區域設置',然後與運行相同命令的cronjob的輸出進行比較。

重新編輯:好的,所以它不是一個env var問題。

我假設你使用的是mailx,因爲它是現今最常見的。它的手冊頁說:

The character set for outgoing messages is not necessarily the same as the one used on the terminal. If an outgoing text message contains characters not representable in US-ASCII, the character set being used must be declared within its header. Permissible values can be declared using the sendcharsets variable,

所以,嘗試添加下面的參數調用郵件時:

-S sendcharsets=utf-8,iso-8859-1 
+0

這將使我的upvote,如果它的作品。我不完全確定它是否會出現在這種情況下,因爲違規字符可能已經是UTF-8格式(已經手動輸入)並且「郵件」幾乎無法以任何方式處理它們?但也許我忽略了一些東西。我們會看到。 – 2010-06-25 17:54:58

+0

我已經檢查過,並且LANG和LC_CTYPE環境變量都是按照您的建議設置的。 – JohnWithoutArms 2010-06-25 17:55:13

+0

有趣。 在我的系統上,/ usr/bin/mail是/ usr/bin/mailx的一個符號鏈接,其手冊頁爲: 傳出消息的字符集不一定與終端上使用的字符集相同。如果外發文本消息包含不能用US-ASCII表示的字符,則必須在其標題內聲明正在使用的字符集。允許值可以使用sendcharsets變量來聲明。 – Casey 2010-06-25 18:01:21

20

/usr/bin/mail被鏈接到/etc/alternatives/mail這也是符號鏈接到/usr/bin/bsd-mailx

我必須指定我自己是郵件頭的編碼。 (這裏不支持-S。)

cat myutf8-file | mail -a "Content-Type: text/plain; charset=UTF-8" -s "My Subject" [email protected]

+3

我得到以下錯誤,運行該命令錯誤:''Content-Type:text/plain; charset = UTF-8:沒有這樣的文件或目錄'在查閱'mail'的手冊頁後,看起來'-a '選項應該用於指定附件 – 2013-03-01 04:25:08

+2

@GeorgeEdison這可能是特定分發版的,在Ubuntu 12.04上'-a'定義了額外的頭字段(使用'bsd-mailx'軟件包)。 _「mailx實用程序符合IEEE Std 1003.1-2008(」POSIX.1「)規範。標誌[-abcdeEIv]是該規範的**擴展**。「_因此,在POSIX.1規範中沒有定義'-a'。 – 2013-04-03 13:56:59

+0

設置LC_CTYPE環境變量要乾淨得多。信任你設置LC_CTYPE使郵件知道你正在發送給他的信息,並讓他僞造一個正確的郵件頭 – 2013-05-30 15:28:19

4

我寫了一個bash函數來發送電子郵件給收件人。該函數通過執行base64編碼發送utf-8編碼的郵件,並在主題和內容中使用utf-8字符。

要發送純文本電子郵件:

send_email "plain" "[email protected]" "subject" "contents" "[email protected]" "[email protected]" "[email protected]" ... 

要發送HTML電子郵件:

send_email "html" "[email protected]" "subject" "contents" "[email protected]" "[email protected]" "[email protected]" ... 

下面是函數代碼。

# Send a email to recipients. 
# 
# @param string $content_type Email content mime type: 'html' or 'plain'. 
# @param string $from_address Sender email. 
# @param string $subject Email subject. 
# @param string $contents Email contents. 
# @param array $recipients Email recipients. 
function send_email() { 
    [[ ${#} -lt 5 ]] && exit 1 

    local content_type="${1}" 
    local from_address="${2}" 
    local subject="${3}" 
    local contents="${4}" 

    # Remove all args but recipients. 
    shift 4 

    local encoded_contents="$(base64 <<< "${contents}")" 
    local encoded_subject="=?utf-8?B?$(base64 --wrap=0 <<< "${subject}")?=" 

    for recipient in ${@}; do 
    if [[ -n "${recipient}" ]]; then 
    sendmail -f "${from_address}" "${recipient}" \ 
     <<< "Subject: ${encoded_subject} 
MIME-Version: 1.0 
From: ${from_address} 
To: ${recipient} 
Content-Type: text/${content_type}; charset=\"utf-8\" 
Content-Transfer-Encoding: base64 
Content-Disposition: inline 

${encoded_contents}" 
    fi 
    done 

    return 0 
} # send_message() 
2

爲了給更多的信息KUMZ答案: 如果你需要使用-a開關指定更多的頭部,隨意將它們加起來,像這樣的(注意-a的polyusage)。

echo /path/to/file | mail -s "Some subject" [email protected] -a "From: Human Name <[email protected]>" -a "Content-Type: text/plain; charset=UTF-8" 
2

您可以直接使用sendmail命令而不mail包裝/幫手。
這將讓你產生所需的所有頭 「原始」 UTF-8的身體
(UTF-8是提問者的評論中提到),

警告-1
非7位/ ASCII字符報頭(例如Subject:From:To:)要求special encoding
警告-2
sendmail的可能斷裂長行(> 990個字節)

[email protected] 
SENDER_NAME="Sender Name" 
[email protected] 
(
# BEGIN of mail generation chain of commands 
# "HERE" document with all headers and headers-body separator 
cat << END 
Subject: My Subject 
From: $SENDER_NAME <$SENDER_ADDR> 
To: $RECIPIENT_ADDR 
MIME-Version: 1.0 
Content-Type: text/plain; charset=UTF-8 
Content-Transfer-Encoding: 8bit 

END 
# custom script to generate email body 
./command.sh 
# END of mail generation chain of commands 
) | /usr/sbin/sendmail -i -f$SENDER_ADDR -F"$SENDER_NAME" $RECIPIENT_ADDR