如何通过邮件从shell脚本发送特殊字符?

时间:2010-06-25 17:44:24

标签: email shell encoding

我有一个在cron上运行的脚本,它输出一些我们发送到'mail'程序的文本。总路线是这样的:

./command.sh | mail -s "My Subject" destination@address.com -- -F "Sender Name" -f sender@address.com

问题是脚本生成的文本有一些特殊的字符 - é,ã,ç - 因为它不是英文的。收到电子邮件后,每个字符都被??。

替换

现在我明白这很可能是由于未正确设置的编码造成的。解决这个问题的最简单方法是什么?

8 个答案:

答案 0 :(得分: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" me@mail.com

答案 1 :(得分:10)

你认为这是一个字符集问题你是对的。您需要将适当的环境变量设置为crontab的开头。

这样的事情应该有效:

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

可选择使用LC_ALL代替LC_CTYPE。

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

编辑:在shell中运行它时显示正常的原因可能是因为上面的env变量已在shell中设置。

要验证,请在shell中执行' locale ',然后与运行相同命令的cronjob的输出进行比较。

重新编辑:好的,所以这不是一个env var问题。

我假设你正在使用mailx,因为它是现在最常见的。这是manpage说的:

  

传出的字符集   消息不一定相同   作为终端上使用的那个。如果   传出的短信包含   字符不能代表   US-ASCII,正在使用的字符集   必须在其标题内声明。   可以声明允许的值   使用sendcharsets变量,

因此,在调用mail时尝试添加以下参数:

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

答案 2 :(得分:4)

我写了一个bash函数来向收件人发送电子邮件。该函数通过执行base64编码发送utf-8编码的邮件并在主题和内容中使用utf-8字符。

发送纯文本电子邮件:

send_email "plain" "from@domain.com" "subject" "contents" "to@domain.com" "to2@domain.com" "to3@domain.com" ...

发送HTML电子邮件:

send_email "html" "from@domain.com" "subject" "contents" "to@domain.com" "to2@domain.com" "to3@domain.com" ...

这是功能代码。

# 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()

答案 3 :(得分:3)

只是为了向KumZ回答提供更多信息: 如果您需要使用-a开关指定更多标题,请随意添加它们,如下所示(注意-a的polyusage)。

echo /path/to/file | mail -s "Some subject" recipient@theirdomain.com -a "From: Human Name <noreply@mydomain.com>" -a "Content-Type: text/plain; charset=UTF-8"

答案 4 :(得分:2)

您可以在没有sendmail包装器/帮助器的情况下直接使用mail命令 它将允许您生成“原始”UTF-8正文所需的所有标题 (提问者的评论中提到了UTF-8),

警告-1
标头中的非7位/ ASCII个字符(例如Subject:From:To:)需要special encoding
警告-2
sendmail可能会破坏长行(&gt; 990字节)。

SENDER_ADDR=sender@address.com
SENDER_NAME="Sender Name"
RECIPIENT_ADDR=destination@address.com
(
# 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

答案 5 :(得分: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并非完全无关紧要。

答案 6 :(得分:0)

使用选项-o message-charset="utf-8",就像那样:

sendemail -f your_email -t destination_email -o message-charset="utf-8" -u "Subject" -m "Message" -s smtp-mail.outlook.com:587 -xu your_mail -xp your_password

答案 7 :(得分:0)

rfc2045-(5)(软换行符)Quoted-Printable编码要求编码的行长不能超过76个字符。对于bash shell脚本代码:

#!/bin/bash
subject_encoder(){
  echo -n "$1" | xxd -ps -c3 |awk -Wposix 'BEGIN{
    BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    printf " =?UTF-8?B?"; bli=8
  }
  function encodeblock (strin){
    b1=sprintf("%d","0x" substr(strin,1,2))
    b2=sprintf("%d","0x" substr(strin,3,2))
    b3=sprintf("%d","0x" substr(strin,5,2))
    o=substr(BASE64,b1/4 + 1,1) substr(BASE64,(b1%4)*16 + b2/16 + 1,1)
    len=length(strin)
    if(len>1) o=o substr(BASE64,(b2%16)*4 + b3/64 + 1,1); else o=o"="
    if(len>2) o=o substr(BASE64,b3%64 +1 ,1); else o=o"="
    return o
  }{
    bs=encodeblock($0)
    bl=length(bs)
    if((bl+bli)>64){
      printf "?=\n =?UTF-8?B?"
      bli=bl
    }
    printf bs
    bli+=bl
  }END{
    printf "?=\n"
  }'
}
SUBJECT="Relatório de utilização"
SUBJECT=`subject_encoder "${SUBJECT}"`
echo '<html>test</html>'| mail -a "Subject:${SUBJECT}" -a "MIME-Version: 1.0" -a "Content-Type: text/html; charset=UTF-8" you@domain.net