如何使用 Linux 命令行将文件作为电子邮件附件发送?

How do I send a file as an email attachment using Linux command line?

提问人:Kit Roed 提问时间:8/20/2008 最后编辑:Stephen OstermillerKit Roed 更新时间:12/7/2022 访问量:751966

问:

我创建了一个脚本,每天晚上在我的 Linux 服务器上运行,用于将我的每个 MySQL 数据库备份到 .sql 文件,并将它们打包为压缩的 .tar 文件。我要完成的下一步是通过电子邮件将该 tar 文件发送到远程电子邮件服务器进行保管。我已经能够通过管道将备份文本文件发送到正文中的原始脚本一封电子邮件,如下所示:mysqldumpmailx

$ cat mysqldbbackup.sql | mailx [email protected]

cat回显备份文件的文本,该文本通过管道传递到程序中,收件人的电子邮件地址作为参数传递。mailx

虽然这完成了我需要的,但我认为它可以更好一步,有没有办法使用 shell 脚本或其他方式将压缩的 .tar 文件作为附件发送到传出电子邮件?这将胜过必须处理包含标题数据并且经常有自动换行问题等的非常长的电子邮件。

Linux 电子邮件 命令行

评论

1赞 Almino Melo 11/26/2014
您可以共享备份MySQL数据库的脚本吗?
0赞 Kit Roed 12/10/2014
对不起,我已经有一段时间没有这样做了。我知道它涉及调用然后将输出附加到电子邮件(带有)。我什至可能有一个步骤将输出压缩为 zip/tar.gz......mysqldumpmutt
1赞 jchook 4/5/2018
纯粹是好奇,为什么要通过电子邮件发送您的备份而不是 scp 或 rsync 它们?
0赞 user3648948 9/2/2021
猫爸爸 |mailx [email protected] 在 Python 程序中对我来说非常有效,其中 dados 是一个包含程序结果的文件。我编写了一个函数来捕获程序的结果,“dados”,然后行os.system('cat dados | mailx [email protected]')已将文件发送到我的电子邮件。完善!

答:

41赞 Chris N 8/20/2008 #1

从 来看,mailx 程序没有附加文件的选项。您可以使用其他程序,例如 mutt。man mailx

echo "This is the message body" | mutt -a file.to.attach -s "subject of message" [email protected]

mutt 的命令行选项可以用 来显示。mutt -h

评论

0赞 Kit Roed 9/25/2008
谢谢!这成功了,我很难让杂音默默地做这个动作。
10赞 Alexander Bird 9/17/2012
请参阅下面的答案 (stackoverflow.com/a/9524359/10608),因为显然 mutt 的语法发生了变化,现在需要 .--
0赞 tripleee 8/20/2022
请参阅我的回答,以更深入地解释为什么没有真正明确定义。man mailx
13赞 David Schlosnagle 8/20/2008 #2

您可以使用 mutt 发送带有附件的电子邮件

mutt -s "Backup" -a mysqldbbackup.sql [email protected] < message.txt

评论

2赞 nealmcb 1/15/2015
至少从 mutt 1.5.21 (Ubuntu trusty) 开始,您需要将选项放在收件人之后:,或者在收件人之前使用该选项,如 rynop 的答案所示。-amutt -s "Backup" [email protected] -a mysqldbbackup.sql < message.txt--
52赞 Nathan Fellman 8/20/2008 #3

根据您的 Linux 版本,它可能被称为邮件。引用上面@David:

mail -s "Backup" -a mysqldbbackup.sql [email protected] < message.txt

或者:

cat message.txt | mail -s "Backup" -a mysqldbbackup.sql [email protected]

评论

0赞 nickel715 8/26/2014
这两种解决方案都不适合我。我收到了带有 Outlook 2013 的电子邮件,但邮件仅包含文件名
0赞 Nathan Fellman 8/27/2014
@nickel715:难道你的系统上有别名吗?mail
2赞 exhuma 10/27/2014
我的手册页是这样写的:-a, --append=HEADER: VALUE append given header to the message being sent
2赞 nealmcb 1/15/2015
内森,看起来你对大卫的引用是错误的——他使用了命令,而不是.同样正如其他人所指出的,mutt 现在似乎需要在地址之前有一个参数。我看到@exhuma,我实际上同意该选项的作用 - 我在那里困惑了一分钟;)muttmail---amail
13赞 Victor Perov 10/22/2015
您应该使用 -A 而不是 -a:-a, --append=HEADER: VALUE append given header to the message being sent -A, --attach=FILE attach FILE
80赞 Daniel Fone 8/20/2008 #4

或者,失败的 mutt:

gzip -c mysqldbbackup.sql | uuencode mysqldbbackup.sql.gz  | mail -s "MySQL DB" [email protected]

评论

27赞 FuePi 7/6/2011
这会以内联方式发送 uuencoded 部件,而不是作为附件发送。不过,许多邮件客户端都认识到了这一点,并将 uuencoded 部分显示为附件。
4赞 tripleee 9/25/2012
在这个时代不要使用 uuencode。MIME 稍微复杂一些,但对用户更友好。
0赞 tripleee 9/12/2013
@DavidGiven:例如,请参阅(快速浏览)此问题的所有其他答案。
6赞 David Given 9/12/2013
他们都不使用邮件!
0赞 tripleee 4/7/2018
然后,例如 stackoverflow.com/questions/3317174/...,并替换为任何对你的附件有意义的MIME类型。(对于这个具体的例子,我猜。text/htmlapplication/gzip
2赞 Gunstick 9/17/2008 #5

Metamail 有工具 Metasend

metasend -f mysqlbackup.sql.gz -t [email protected] -s Backup -m application/x-gzip -b

评论

1赞 tripleee 6/13/2019
这曾经几乎无处不在,但几乎从未使用过。由于它很长一段时间没有维护(现在仍然是 AFAIK),它已从许多平台上的事实标准工具集中删除。
29赞 Torkel Bjørnson 9/24/2009 #6

我使用mpack。

mpack -s subject file [email protected]

不幸的是,mpack 无法将 '-' 识别为 stdin 的别名。但是以下工作,可以很容易地包装在(shell)别名或脚本中:

mpack -s subject /dev/stdin [email protected] < file

评论

0赞 thomasa88 4/1/2014
这可以在 stdin 的 bash 中工作。我没有mpack,所以我没有尝试过:mpack -s subject /dev/stdin [email protected] <(stdout_generating_program)
14赞 glenn jackman 2/3/2011 #7

我曾经在 Solaris 上为 ksh 编写过这个函数(使用 Perl 进行 base64 编码):

# usage: email_attachment to cc subject body attachment_filename
email_attachment() {
    to="$1"
    cc="$2"
    subject="$3"
    body="$4"
    filename="${5:-''}"
    boundary="_====_blah_====_$(date +%Y%m%d%H%M%S)_====_"
    {
        print -- "To: $to"
        print -- "Cc: $cc"
        print -- "Subject: $subject"
        print -- "Content-Type: multipart/mixed; boundary=\"$boundary\""
        print -- "Mime-Version: 1.0"
        print -- ""
        print -- "This is a multi-part message in MIME format."
        print -- ""
        print -- "--$boundary"
        print -- "Content-Type: text/plain; charset=ISO-8859-1"
        print -- ""
        print -- "$body"
        print -- ""
        if [[ -n "$filename" && -f "$filename" && -r "$filename" ]]; then
            print -- "--$boundary"
            print -- "Content-Transfer-Encoding: base64"
            print -- "Content-Type: application/octet-stream; name=$filename"
            print -- "Content-Disposition: attachment; filename=$filename"
            print -- ""
            print -- "$(perl -MMIME::Base64 -e 'open F, shift; @lines=<F>; close F; print MIME::Base64::encode(join(q{}, @lines))' $filename)"
            print -- ""
        fi
        print -- "--${boundary}--"
    } | /usr/lib/sendmail -oi -t
}

评论

8赞 MestreLion 11/1/2012
在 GNU/Linux 上,可以使用命令而不是 perl 进行编码base64
308赞 rynop 3/2/2012 #8

没有一个对我有用。它认为电子邮件地址是附件的一部分。必须做:

echo "This is the message body" | mutt -a "/path/to/file.to.attach" -s "subject of message" -- [email protected]

评论

1赞 nurettin 1/30/2014
我正在使用 mutt 1.5.21 (2010-09-15),它需要 -a 参数位于收件人电子邮件之后
0赞 Antônio Medeiros 10/21/2016
在 openSUSE Leap 42.1 上使用 Mutt 1.5.24 (2015-08-30) 为我工作。
3赞 rynop 2/10/2017
@fugitive 的意思是“期权的结束”。看看 unix.stackexchange.com/questions/11376/...
1赞 ti034 7/17/2018
有没有办法检查异常并重试发送?
0赞 tripleee 12/7/2022
这是一个复杂的后续问题。粗略地说,有两种失败模式:失败,你可以拿起它的退出代码;或者,发送成功,但您最终会收到送达通知(退回),然后必须对此做出反应。后者足够复杂,可以正确处理,这是几家公司的经营理念。mutt
0赞 Mike Graf 9/25/2012 #9

只是为了增加我的 2 美分,我会编写我自己的 PHP 脚本:

http://php.net/manual/en/function.mail.php

在该页面上的示例中,有很多方法可以执行附件。

评论

2赞 exhuma 10/27/2014
并非每个服务器都安装了 PHP。如果你真的想走“编写自己的脚本”的道路,那么 perl 或 python 更适合,因为它们通常默认可用。
0赞 tripleee 11/18/2018
sh更是无处不在。有重复的问题,答案很好的例子;这是我的。
11赞 user1651561 1/8/2013 #10

使用 mailx 发送带有一个明文附件的明文正文电子邮件:

(
  /usr/bin/uuencode attachfile.txt myattachedfilename.txt; 
  /usr/bin/echo "Body of text"
) | mailx -s 'Subject' [email protected]

下面是与上面相同的命令,没有换行符

( /usr/bin/uuencode /home/el/attachfile.txt myattachedfilename.txt; /usr/bin/echo "Body of text" ) | mailx -s 'Subject' [email protected]

请确保您有一个使用以下内容定义的文件:/home/el/attachfile.txt

<html><body>
Government discriminates against programmers with cruel/unusual 35 year prison
sentences for making the world's information free, while bankers that pilfer 
trillions in citizens assets through systematic inflation get the nod and 
walk free among us.
</body></html>

如果您没有 uuencode,请阅读以下内容:https://unix.stackexchange.com/questions/16277/how-do-i-get-uuencode-to-work

在 Linux 上,使用 sendmail 发送带有 PDF 附件的 HTML 正文电子邮件:

确保您已安装 ksh:yum info ksh

确保您已安装并配置了 sendmail。

确保您已安装 uuencode 并可用:https://unix.stackexchange.com/questions/16277/how-do-i-get-uuencode-to-work

创建一个新文件调用并将其放在主目录中:test.sh/home/el

将以下代码放入:test.sh

#!/usr/bin/ksh
export MAILFROM="[email protected]"
export MAILTO="[email protected]"
export SUBJECT="Test PDF for Email"
export BODY="/home/el/email_body.htm"
export ATTACH="/home/el/pdf-test.pdf"
export MAILPART=`uuidgen` ## Generates Unique ID
export MAILPART_BODY=`uuidgen` ## Generates Unique ID

(
 echo "From: $MAILFROM"
 echo "To: $MAILTO"
 echo "Subject: $SUBJECT"
 echo "MIME-Version: 1.0"
 echo "Content-Type: multipart/mixed; boundary=\"$MAILPART\""
 echo ""
 echo "--$MAILPART"
 echo "Content-Type: multipart/alternative; boundary=\"$MAILPART_BODY\""
 echo ""
 echo "--$MAILPART_BODY"
 echo "Content-Type: text/plain; charset=ISO-8859-1"
 echo "You need to enable HTML option for email"
 echo "--$MAILPART_BODY"
 echo "Content-Type: text/html; charset=ISO-8859-1"
 echo "Content-Disposition: inline"
 cat $BODY
 echo "--$MAILPART_BODY--"

 echo "--$MAILPART"
 echo 'Content-Type: application/pdf; name="'$(basename $ATTACH)'"'
 echo "Content-Transfer-Encoding: uuencode"
 echo 'Content-Disposition: attachment; filename="'$(basename $ATTACH)'"'
 echo ""
 uuencode $ATTACH $(basename $ATTACH)
 echo "--$MAILPART--"
) | /usr/sbin/sendmail $MAILTO

更改顶部的导出变量以反映您的地址和文件名。test.sh

下载一个测试pdf文档,并将其放入名为pdf-test的.pdf/home/el

创建一个名为 /home/el/email_body.htm 的文件,并将以下行放入其中:

<html><body><b>this is some bold text</b></body></html>

确保 pdf 文件具有足够的 755 权限。

运行脚本./test.sh

检查您的电子邮件收件箱,文本应为 HTML 格式,pdf 文件应自动解释为二进制文件。注意不要在一天内使用此功能超过 15 次,即使您将电子邮件发送给自己,gmail 中的垃圾邮件过滤器也可以将喷出电子邮件的域列入黑名单,而不会让您选择让它们通过。你会发现这不再有效,或者它只允许通过附件,或者电子邮件根本没有通过。如果您必须对此进行大量测试,请将它们分散在几天内,否则您将被标记为垃圾邮件发送者,并且此功能将不再起作用。

评论

1赞 Vicky 9/18/2013
对我来说,它正好相反。(echo 'Email Body'; uuencode filename filename) | mailx -s 'Subject' [email protected]
1赞 tripleee 2/3/2018
uuencode是正确的附件。它只是在其他一些文本的中间嵌入一个可读的文本块。当没有更好的机制时,它曾经工作得很好,但那是 20+ 年前的事了。
0赞 tripleee 7/23/2022
这里的代码似乎都没有使用任何功能。如果你有一些不适用于 POSIX 的东西,可能更喜欢 Bash 而不是 ,它通常使用相同的语法。kshshksh
31赞 Fredrik Wendt 10/31/2013 #11

我使用为此方案创建的 SendEmail。它是为 Ubuntu 打包的,所以我认为它是可用的

sendemail -f [email protected] -t rece[email protected] -m "Here are your files!" -a file1.jpg file2.zip

http://caspian.dotconf.net/menu/Software/SendEmail/

评论

0赞 Davit 6/30/2014
我相信,在您的示例中应该是“sendEmail”而不是“sendemail”。
1赞 Fredrik Wendt 7/1/2014
是的,也不是 - 源代码(caspian)使用大写的 E,虽然这是命令行工具(在 Unix 世界中)不常见的命名策略,但至少该软件的 Ubuntu 打包同时提供了 和 .sendemailsendEmail/usr/bin/
0赞 Vitaly Zdanevich 9/17/2015
我的 Xubuntu 14.04.3 没有安装SendEmail
3赞 Sailendra Pinupolu 12/5/2016
“sudo apt install sendemail” 安装 sendemail 并添加 “-f [email protected]” 命令的必填 from 字段。sendemail -f [email protected] [email protected] -m "Here are your files!" -a file1.jpg file2.zip
1赞 golimar 11/24/2020
可能是 Ubuntu 中最好的选择:不会弄乱不同的 mail/mailx/Mail 包,可以附加文件并可以指定自定义发件人地址(而不是丑陋的默认值 [email protected])
0赞 Allan Pinto 12/29/2013 #12

mailx现在确实有附件选项。-a

评论

2赞 Yves Martin 2/14/2014
“-a”选项用于标头
0赞 fche 8/12/2014
man mail[x],10/9/10 的 12.5 版(几年前)清楚地说 -a file 将给定的文件附加到邮件中。
4赞 exhuma 10/27/2014
某些版本的 do.我相信有两种实现方式。一个用于附件,另一个用于标头。mailx-a
1赞 nealmcb 1/14/2015
Ubuntu 中的 mailx 版本来自 GNU,其中 -a 表示添加标头。manpages.ubuntu.com/manpages/lucid/en/man1/mailx.1.html哪个系统和哪个 mailx 做附件?
3赞 avimehenwal 8/18/2015
在新的实现中,“-a”表示标头,“-A”表示标记
0赞 Yoav 6/30/2014 #13

不是一种发送电子邮件的方法,但您可以使用在线 Git 服务器(例如 Bitbucket 或类似服务)。

这样,您可以使用命令,所有版本都将以压缩和有组织的方式存储。git push

1赞 Alejandro Santillan 8/12/2014 #14

我通常只在 RHEL 上使用 mail 命令。我尝试过mailx,它非常有效。

mailx -s "Sending Files" -a First_LocalConfig.conf -a
Second_LocalConfig.conf [email protected]

This is the content of my msg.

.
0赞 Pipo 4/15/2015 #15

对我来说,最短的路是

file=filename_or_filepath;uuencode $file $file|mail -s "optional subject" email_address

所以对于你的例子来说,它将是

file=your_sql.log;gzip -c $file;uuencode ${file}.gz ${file}|mail -s "file with magnets" [email protected]

好的部分是我可以用 Ctrl+r 调用它以发送另一个文件......

评论

0赞 tripleee 6/13/2019
大括号对你没有多大好处,但为了完全可移植,你应该在变量周围使用双引号。另请参阅 stackoverflow.com/questions/10067266/...
24赞 Sourabh Potnis 5/22/2015 #16
 echo -e 'Hi, \n These are contents of my mail. \n Thanks' | mailx -s 'This is my email subject' -a /path/to/attachment_file.log -b [email protected] -c [email protected] -r [email protected] to[email protected] [email protected] [email protected]

评论

5赞 Pavin Joseph 5/6/2016
这应该是公认的答案。使用默认的 mailx 并且工作得很好。Mutt v1.5.21 在使用 cron 时拒绝发送 >1MB 的附件。
0赞 singularity 6/28/2016
我一直在寻找在 EC2 中工作的东西,这工作正常。
8赞 tripleee 2/3/2018
mailx没有适当的标准化。任何建议它的答案都应该指出这一点。通常至少有三种不相容的变体。
1赞 tripleee 2/9/2022
(此外,任何使用的东西都不应该得到赞成票,尽管我还没有沮丧到为此而投反对票。echo -e
1赞 poncho 8/4/2015 #17

我用过

echo "Start of Body" && uuencode log.cfg readme.txt | mail -s "subject" "[email protected]" 

这对我来说效果很好......

评论

0赞 tripleee 3/28/2022
这里是无用的;它会将文本输出到终端,而不是输出到管道中。与这里的其他类似答案一样,不是“附件”,尽管一些电子邮件客户端会帮助隐藏丑陋之处,以便如果您不仔细观察,它看起来是一个。echomailuuencode
0赞 dagorv 9/4/2015 #18

这是我在 CentOS 中处理一个大型日志文件的方式:

#!/bin/sh
MAIL_CMD="$(which mail)"
WHOAMI="$(whoami)"
HOSTNAME="$(hostname)"
EMAIL"[email protected]"
LOGDIR="/var/log/aide"
LOGNAME="$(basename "$0")_$(date "+%Y%m%d_%H%M")"

if cd ${LOGDIR}; then
  /bin/tar -zcvf "${LOGDIR}/${LOGNAME}".tgz "${LOGDIR}/${LOGNAME}.log" > /dev/null 2>&1
  if [ -n "${MAIL_CMD}" ]; then
  # This works too. The message content will be taken from text file below
  # echo 'Hello!' >/root/scripts/audit_check.sh.txt
  # echo "Attachment" | ${MAIL_CMD} -s "${HOSTNAME} Aide report" -q /root/scripts/audit_check.sh.txt -a ${LOGNAME}.tgz -S from=${WHOAMI}@${HOSTNAME} ${EMAIL}
    echo "Attachment" | ${MAIL_CMD} -s "${HOSTNAME} Aide report" -a "${LOGNAME}.tgz" -S from="${WHOAMI}@${HOSTNAME}" "${EMAIL}"
    /bin/rm "${LOGDIR}/${LOGNAME}.log"
  fi
fi

评论

0赞 David C. Rankin 9/4/2015
你为什么要定义和两次?WHOAMIHOSTNAME
0赞 tripleee 2/3/2018
这有几个 shell 编码样式错误。shellcheck.net 将指出其中的一些,但不是全部。
0赞 tripleee 8/20/2022
用于查找您的程序,以便您可以使用完整路径调用它是......傻的,而且不能正确携带。只需使用而不是无处不在,即可获得完全相同的效果,具有更好的坚固性和便携性。与 POSIX 兼容的正确等价物是 或 ,但您在这里不需要任何这些。whichPATHmail${MAIL_CMD}whichcommand -vtype
1赞 Konchog 1/22/2017 #19

从源计算机

mysqldump --defaults-extra-file=sql.cnf database | gzip | base64 | mail [email protected]

在目标计算机上。将收到的邮件正文另存为 db.sql.gz.b64;然后。。

base64 -D -i db.sql.gz.b64 | gzip -d | mysql --defaults-extra-file=sql.cnf

评论

1赞 tripleee 3/28/2022
这样可以传递数据,但缺少 MIME 标头来告诉用户如何处理它。除非他们知道它是什么,否则他们可能无法弄清楚如何使用它。正确的 MIME 结构至少会将 base64 数据显示为附件,而不是实际的消息文本。
0赞 Konchog 3/28/2022
你把我带到了那里@tripleee - 我并没有真正考虑对第三方使用这种机制。我认识的大多数人都不知道该如何处理它,即使他们确实有 Mime 标题来帮助他们。
0赞 nurp 2/23/2017 #20

如果文件是文本,则可以在正文中将其发送为:

sendmail [email protected] < message.txt

评论

1赞 tripleee 2/3/2018
这不会将其作为附件发送,甚至不会将其作为邮件正文发送。Sendmail 希望其输入是完整、格式正确的 RFC5322 电子邮件,如果不是,可能会以有趣的方式失败。
-1赞 Paras Singh 5/16/2017 #21

如果mutt不工作或未安装,请尝试以下操作-

*#!/bin/sh

FilePath=$1
FileName=$2
Message=$3
MailList=$4

cd $FilePath

Rec_count=$(wc -l < $FileName)
if [ $Rec_count -gt 0 ]
then
(echo "The attachment contains $Message" ; uuencode $FileName $FileName.csv ) | mailx -s "$Message" $MailList
fi*

评论

0赞 tripleee 2/9/2022
这有许多编码错误,这将使它看起来可以处理琐碎的例子,但在现实生活中却会中断。请参阅 shellcheck.net 以获取一些建议,但它不会告诉您要避免uuencode
6赞 Alexander Yancharuk 9/5/2017 #22

另一种选择 - Swaks(SMTP的瑞士军刀)。

swaks -tls \
    --to ${MAIL_TO} \
    --from ${MAIL_FROM} \
    --server ${MAIL_SERVER} \
    --auth LOGIN \
    --auth-user ${MAIL_USER} \
    --auth-password ${MAIL_PASSWORD} \
    --header "Subject: $MAIL_SUBJECT" \
    --header "Content-Type: text/html; charset=UTF-8" \
    --body "$MESSAGE" \
    --attach mysqldbbackup.sql

评论

1赞 ikaerom 3/4/2023
这绝对是辉煌的。这是最终允许我使用服务器和应用程序密码(support.google.com/accounts/answer/185833#app-passwords)从命令行发送电子邮件的唯一解决方案。显然,自 90 年代初以来,当我最后一次从 CLI 发送电子邮件时,发生了很多变化。smtp.gmail.com
1赞 Girdhar Singh Rathore 9/8/2017 #23

使用 mailx 命令

 echo "Message Body Here" | mailx -s "Subject Here" -a file_name [email protected]

使用 Sendmail

#!/bin/ksh

fileToAttach=data.txt

`(echo "To: [email protected]"
  echo "Cc: [email protected]"
  echo "From: Application"
  echo "Subject: your subject"
  echo  your body
  uuencode $fileToAttach $fileToAttach
  )| eval /usr/sbin/sendmail -t `;

评论

1赞 Honza P. 11/22/2018
sendmail 就是一个很好的例子,很高兴我在这里找到了它。
0赞 tripleee 6/13/2019
请注意,您需要在“your body”的开头有一个空行,否则正文将消失在标题中,或者可能完全破坏消息。另请参阅其他地方有关避免使用 MIME 的注释。uuencode
0赞 tripleee 6/13/2019
而围绕整个装置的可怕和神秘的反蜱在这里是完全没有必要的。eval
11赞 tripleee 2/3/2018 #24

这里有几个答案,或者说这更像是一个背景,以帮助你在上下文中解释这些。但是在接近尾声时有一些实用的建议。mailmailx

历史笔记

Unix邮件的起源可以追溯到贝尔实验室Unix™(1969?)的早期历史的迷雾中,我们可能不能指望在这里了解它的完整谱系。我只想说,有许多程序继承了代码或重新实现(或从重新实现中继承了代码),并且没有一个单一的代码库可以被明确地标识为“the”。mailmail

然而,该职位的竞争者之一当然是“伯克利邮报”,它最初在 2BSD (1978) 中以大写字母 M 命名;但在 3BSD(1979 年)中,它也取代了小写命令,导致了一些新的混乱。SVR3 (1986) 包括一种称为 .据推测,添加它是为了使其独特而与众不同;但现在,这也被复制、重新实现和肢解,因此没有一个单独的版本是确定的。Mailmailmailxx

过去,通过电子邮件发送二进制文件的实际标准是 uuencode。它仍然存在,但存在许多可用性问题;如果可能的话,您应该改为发送 MIME 附件,除非您特别努力能够与 1980 年代后期进行通信。

MIME 于 1990 年代初引入,旨在解决电子邮件的几个问题,包括支持除单个字符集中的纯文本以外的各种类型的内容,这些内容实际上只适合英语的一个子集(我们被告知,夏威夷语)。这引入了对多部分消息、国际化、丰富内容类型等的支持,并在整个 1990 年代迅速获得关注。

Heirloom mail/mailx 历史笔记在撰写本文时最有帮助,如果您喜欢这种东西,当然值得一读。

当前产品/服务

截至 2018 年,Debian 有三个软件包,其中包含 or 命令。(您可以搜索 .)mailmailxProvides: mailx

debian$ aptitude search ~Pmailx
i   bsd-mailx                       - simple mail user agent
p   heirloom-mailx                  - feature-rich BSD mail(1)
p   mailutils                       - GNU mailutils utilities for handling mail

(我不是要把 Debian 单独列为推荐,这是我使用的,所以我对它很熟悉;它提供了一种通过引用它们各自的软件包名称来明确区分各种替代方案的方法。它显然也是 Ubuntu 获取这些软件包的发行版。

  • bsd-mailx是一个相对简单的,似乎不支持发送 MIME 附件。请参阅其手册页,并注意这是您希望在 *BSD 系统(包括 MacOS)上默认找到的手册。mailx
  • heirloom-mailx现在正在被调用,并且支持发送带有 的 MIME 附件。请参阅其手册页,以及更一般的 Heirloom 项目s-nail-a
  • mailutils又名 GNU Mailutils 包含一个 mail/mailx 兼容性包装器,它确实支持使用-A

有了这些顾虑,如果你需要你的代码是可移植的,并且可以依赖于一个有点复杂的包,那么可移植地发送MIME附件的简单方法是使用。mutt

如果你知道自己在做什么,你可以借助 和 和 来组装一个任意的 MIME 结构,例如 qprint(或自产的替代品;两者都可以很容易地实现为 Perl 单行)并将其输送到;但正如本页上的其他几个答案生动地说明的那样,你可能不知道。echobase64base64qprintsendmail

( printf '%s\n' \
    "From: myself <[email protected]>" \
    "To: backup address <[email protected]>" \
    "Subject: Backup of $(date)" \
    "MIME-Version: 1.0" \
    "Content-type: application/octet-stream; filename=\"mysqldbbackup.sql\"" \
    "Content-transfer-encoding: base64" \
    ""
  base64 < mysqldbbackup.sql ) |
sendmail -oi -t

这假设它在你的 ;有时它不是(当然,有时它根本没有安装)。查看 、 或 等;或查询您的包管理器。找到它后,您可能希望在脚本中扩充您的路径名,或者将完整路径名硬编码为(对于任何其他非标准二进制文件,这些二进制文件可能会或可能不会安装在您的系统上)。sendmailPATH/usr/lib/usr/sbin/usr/libexecPATHsendmail

这仍然没有尝试为需要发送非 ASCII Unicode 文本或行长于 SMTP 允许的长度等情况提供任何解决方案。对于一个强大的解决方案,我会求助于现有的工具,如 ,或现代脚本语言,如 Python;https://docs.python.org/3/library/email.examples.html 提供了许多常见用例的示例。mutt

评论

0赞 tripleee 2/3/2018
我最初发布此内容是为了回答一个中等流行的重复问题 stackoverflow.com/questions/902591/......
0赞 tripleee 11/3/2022
有关MIME结构的快速而肮脏的介绍,也许可以查看 stackoverflow.com/questions/48562935/...
0赞 tripleee 12/8/2022
据称,简单的示例 shell 脚本不适用于 Outlook;我的建议是在这种情况下摆脱 Outlook,但如果不能,请尝试在附件前添加一个无用的文本部分。
3赞 rumpel 2/17/2019 #25

Mailutils 使这成为小菜一碟

echo "Body" | mail.mailutils -M -s "My Subject" -A attachment.pdf [email protected]
  • -A file附加文件
  • -M启用 MIME,以便您可以拥有附件和纯文本正文。

如果尚未安装,请运行

sudo apt install mailutils