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


289

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

$ cat mysqldbbackup.sql | mailx backup@email.com

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

虽然可以满足我的要求,但我认为它可能会更好,是否可以使用Shell脚本或其他方式将压缩的.tar文件作为附件发送到外发电子邮件中? 这样就不必处理非常长的电子邮件,其中包含标头数据并且经常出现换行问题等。


1
您可以共享备份MySQL数据库的脚本吗?
Almino Melo 2014年

抱歉,我已经有一段时间没有这样做了。我知道它涉及调用mysqldump,然后将输出附加到电子邮件(带有mutt)。我什至可能还执行了将输出也压缩到zip / tar.gz的步骤...
Kit Roed 2014年

1
纯粹出于好奇,为什么要通过电子邮件将备份与scp或rsync同步?
jchook

Answers:


298

那些笨蛋都没有为我工作。它以为该电子邮件地址是附件的一部分。不得不做:

echo "This is the message body" | mutt -a "/path/to/file.to.attach" -s "subject of message" -- recipient@domain.com

1
我使用的是Mutt 1.5.21(2010-09-15),它要求-a参数
nurettin 2014年

在openSUSE Leap 42.1上使用Mutt 1.5.24(2015-08-30)为我工作。
Antonio Vinicius Menezes Medei 2016年

3
@fugitive表示“选项结束”。看看unix.stackexchange.com/questions/11376/…–
rynop

有没有办法检查异常并重试发送?
ti034

79

或者,失败的mutt:

gzip -c mysqldbbackup.sql | uuencode mysqldbbackup.sql.gz  | mail -s "MySQL DB" backup@email.com

26
这将内联而不是作为附件发送uuencoded部分。但是,许多邮件客户端都可以识别并显示 uuencoded部分作为附件。
FuePi'7

4
在这个时代不要使用uuencode。MIME稍微复杂些,但更加用户友好。
Tripleee 2012年

@DavidGiven:例如(快速浏览)此问题的所有其他答案。
Tripleee 2013年

6
他们都不使用邮件!
大卫·

然后,例如stackoverflow.com/questions/3317174/…,并替换text/html为对您的附件有意义的任何MIME类型。(对于这个具体的例子,我猜想是application/gzip。)
Tripleee'April

43

根据您的linux版本,它可能称为mail。在上面引用@David:

mail -s "Backup" -a mysqldbbackup.sql backup@email.com < message.txt

或者:

cat message.txt | mail -s "Backup" -a mysqldbbackup.sql backup@email.com 

@KarelBílek:另一个选择怎么样?
内森·费尔曼

两种解决方案都不适合我。我收到的电子邮件与Outlook 2013邮件只包含文件名
nickel715

2
我的手册上写道:-a, --append=HEADER: VALUE append given header to the message being sent
exhuma

2
内森(Nathan),看来您对戴维(David)的引用是错误的-他使用的mutt命令不是mail。正如其他人指出的那样,mutt现在似乎需要--在地址前加一个参数。而且我看到@exhuma和我实际上同意该-a选项的mail作用-我在那儿感到困惑;)
nealmcb 2015年

7
而不是-a,您应该使用-A: -a, --append=HEADER: VALUE append given header to the message being sent -A, --attach=FILE attach FILE
Victor

41

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

echo "This is the message body" | mutt -a file.to.attach -s "subject of message" recipient@domain.com

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


谢谢!那确实成功了,我很难让笨蛋默默地做动作。
Kit Roed

10
请参阅下面的答案(stackoverflow.com/a/9524359/10608),因为显然mutt的语法已更改,现在需要使用--
亚历山大·伯德

29

我使用为这种情况创建的SendEmail。它是为Ubuntu打包的,所以我认为它可用

sendemail -f sender@some.where -t receiver@some.place -m "Here are your files!" -a file1.jpg file2.zip

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


我相信,在您的示例中,它应该是“ sendEmail”而不是“ sendemail”。
2014年

1
是的,没有-源(里海)使用大写字母E,而这是命令行工具少见的命名策略(在Unix世界),至少该软件的Ubuntu的包装既提供sendemailsendEmail/usr/bin/
Fredrik Wendt 2014年

我的Xubuntu 14.04.3尚未安装SendEmail
Vitaly Zdanevich 2015年

3
使用“ sudo apt install sendemail”安装sendemail并在命令字段中添加“ -f required@email.com”为必填字段。 sendemail -f mandatory@email.com-t to@some.one -m "Here are your files!" -a file1.jpg file2.zip
Sailendra Pinupolu

28

我用的是mpack。

mpack -s subject file user@example.com

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

mpack -s subject /dev/stdin loser@example.com < file

这对于s​​tdin来说可能是有用的。我没有mpack,所以我没有尝试:mpack -s subject /dev/stdin loser@example.com <(stdout_generating_program)
thomasa88

23
 echo 'These are contents of my mail' | mailx -s 'This is my email subject' -a /path/to/attachment_file.log email_id@example.com

4
这应该是公认的答案。使用默认mailx并完美运行。Mutt v1.5.21在使用cron时拒绝发送> 1MB的附件。
约瑟夫

我一直在寻找可以在EC2中使用的东西,而且效果很好。
奇点

6
mailx没有正确标准化。任何建议它的答案都应指出此警告。常用的至少有三个不兼容的变体。
Tripleee '18

13

我曾经在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
在GNU / Linux上,可以使用base64命令代替perl进行编码
MestreLion,2012年

12

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

mutt -s "Backup" -a mysqldbbackup.sql backup@email.com < message.txt

2
至少从mutt 1.5.21(受信任的Ubuntu)开始,您需要将-a选项放在接收者之后: mutt -s "Backup" backup@email.com -a mysqldbbackup.sql < message.txt,或者在该--选项之前使用该选项,如rynop的答案所示。
nealmcb 2015年

10

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

(
  /usr/bin/uuencode attachfile.txt myattachedfilename.txt; 
  /usr/bin/echo "Body of text"
) | mailx -s 'Subject' youremail@gmail.com

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

( /usr/bin/uuencode /home/el/attachfile.txt myattachedfilename.txt; /usr/bin/echo "Body of text" ) | mailx -s 'Subject' youremail@gmail.com

确保您具有/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="el@defiant.com"
export MAILTO="youremail@gmail.com"
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文件并放入 /home/el pdf-test.pdf

创建一个名为/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
对我来说,它反过来起作用。(echo 'Email Body'; uuencode filename filename) | mailx -s 'Subject' user@domain.com
Vicky

uuencode正确的附件。它只是在其他一些文本的中间嵌入了计算机可读的Blob。当没有更好的机制时,它曾经可以正常工作,但是那是20年前了。
Tripleee '18

9

这里有几个答案建议 mailmailx因此这更是一个背景,以帮助您在上下文中解释这些。

历史笔记

Unix的起源mail可以追溯到Bell Labs Unix™(1969?)的早期历史的迷雾,我们可能不希望在这里介绍其完整的家谱。可以说,有许多程序从中继承代码或重新实现(或从重新实现继承代码)mail并且没有单个代码库可以明确地标识为“ the” mail

但是,该位置的竞争者之一当然是“ Berkeley Mail”,它最初Mail在2BSD(1978)中以大写字母M 命名;但在3BSD(1979)中,它也替换了小写字母mail命令,从而引起了一些新的混乱。SVR3(1986)包含一个称为的衍生物mailx。的x大概是添加,使其独特而鲜明的; 但这现在也已被复制,重新实现并被肢解,因此没有确定的单个版本。

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

MIME是在1990年代初期引入的,旨在解决电子邮件的一些问题,包括在单个字符集中支持除纯文本以外的各种类型的内容,该内容仅真正适用于英语的子集(据我们所知,夏威夷语是)。这引入了对多部分消息,国际化,丰富内容类型等的支持,并在1990年代迅速吸引了人们的注意。

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

当前产品

截至2018年,Debian拥有三个包含mailor mailx命令的软件包。(您可以搜索Provides: 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是相对简单的mailx,似乎支持发送MIME附件。请参阅其手册页,请注意,默认情况下,这是您希望在* BSD系统(包括MacOS)上找到的那个。
  • heirloom-mailx现在被调用,s-nail并且确实支持通过发送MIME附件-a。参见其手册页,以及更一般的Heirloom项目
  • mailutilsaka GNU Mailutils包含一个mail/ mailx兼容性包装程序,它确实支持通过以下方式发送MIME附件:-A

考虑到这些问题,如果您需要代码可移植并且可以依赖于稍微复杂的程序包,则可移植的简单方法是使用 MIME附件mutt


我最初将其发布为对一个颇受欢迎的重复问题stackoverflow.com/questions/902591/…
Tripleee

4

另一种选择-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

2

metamail具有metasend工具

metasend -f mysqlbackup.sql.gz -t backup@email.com -s Backup -m application/x-gzip -b

过去几乎可以在任何地方安装此工具,但几乎从未使用过。由于长时间未维护(并且仍然是AFAIK),因此已将其从许多平台上的事实上的标准工具集中删除。
6

2

我用了

echo "Start of Body" && uuencode log.cfg readme.txt | mail -s "subject" "a@b.c" 

这对我来说很好。


1

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

mailx -s "Sending Files" -a First_LocalConfig.conf -a
Second_LocalConfig.conf Recipient@myemail.com

This is the content of my msg.

.

1

对我来说最快捷的方法是

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" ph.gachoud@gmail.com

好消息是我可以使用Ctrl + r调用它来发送另一个文件...


大括号不会给您带来什么好处,但是要完全移植,您应该在变量周围使用双引号。另请参见stackoverflow.com/questions/10067266/…–
Tripleee,

1

从源机器

mysqldump --defaults-extra-file=sql.cnf database | gzip | base64 | mail me@myemail.com

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

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

0

只需加上2美分,我就可以编写自己的PHP脚本:

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

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


2
并非每个服务器都可能安装了PHP。如果您真的想沿“编写自己的脚本”路径走,那么perl或python更适合,因为它们通常默认情况下可用。
2014年

sh甚至无处不在。有重复的问题,答案带有很好的例子;这是我的。
三月

0

mailx确实有一个-a附件选项。


2
“ -a”选项用于标题
Yves Martin

男人邮件[X],版本的10年10月9日12.5(前几年)明确表示-a文件附加给定文件的message.`
fche

4
一些版本mailx。我相信有两种实现。一个-a是附件,另一个是标题。
exhuma 2014年

1
Ubuntu中mailx的版本来自GNU,并且-a表示添加标头。 manpages.ubuntu.com/manpages/lucid/zh/man1/mailx.1.html 附件是哪个系统和哪个mailx?
nealmcb 2015年

3
在新的实现中,“-a”用于标题,“-A”用于标题
Avi Mehenwal 2015年

0

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

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


0

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

MAIL="`whereis mail | awk '{print $2}'`"
WHOAMI="`whoami`"
HOSTNAME="`hostname`"
EMAIL"your@email.address"
LOGDIR="/var/log/aide"
LOGNAME="`basename "$0"`_`date "+%Y%m%d_%H%M"`"
# Arhiveerime ning kui hästi, saadame edasi:
/bin/tar -zcvf ${LOGDIR}/${LOGNAME}.tgz "${LOGDIR}/${LOGNAME}.log" > /dev/null 2>&1
if [ $? -eq 0 ]; then
    cd ${LOGDIR}
    # This works too. The message content will be taken from text file below
    # echo 'Hello!' >/root/scripts/audit_check.sh.txt
    # echo "Arhiivifail manuses" | ${MAIL} -s "${HOSTNAME} Aide report" -q /root/scripts/audit_check.sh.txt -a ${LOGNAME}.tgz -S from=${WHOAMI}@${HOSTNAME} ${EMAIL}
    echo "Arhiivifail manuses" | ${MAIL} -s "${HOSTNAME} Aide report" -a ${LOGNAME}.tgz -S from=${WHOAMI}@${HOSTNAME} ${EMAIL}
    /bin/rm "${LOGDIR}/${LOGNAME}.log"
fi

你为什么要定义WHOAMIHOSTNAME 两次?
David C. Rankin

这有几个shell编码样式错误。shellcheck.net将指出其中的一些但不是全部。
Tripleee '18

0

如果文件是文本,则可以通过以下方式在体内最简单地发送它:

sendmail recipient@example.com < message.txt

1
这不会以附件或邮件正文的形式发送。Sendmail期望其输入是完整的,格式正确的RFC5322电子邮件,如果不是,则可能会以有趣的方式失败。
Tripleee '18

0

使用mailx命令

 echo "Message Body Here" | mailx -s "Subject Here" -a file_name user@example.com

使用sendmail

#!/bin/ksh

fileToAttach=data.txt

`(echo "To: user@company.com"
  echo "Cc: user@company.com"
  echo "From: Application"
  echo "Subject: your subject"
  echo  your body
  uuencode $fileToAttach $fileToAttach
  )| eval /usr/sbin/sendmail -t `;

1
sendmail是一个很好的例子,很高兴我在这里找到了它。
Honza P.

请注意,在“您的正文”的开头需要一个空行,否则正文将消失在标题中,或者可能会完全破坏该消息。另请参见其他地方有关避免uuencode使用MIME的说明。
Tripleee

eval整个装置周围的怪异和神秘的倒叙在这里完全没有必要。
Tripleee

0

Mailutils使这成为小菜一碟

echo "Body" | mail.mailutils -M -s "My Subject" -A attachment.pdf mail@example.org
  • -A file 附加文件
  • -M 启用MIME,以便您可以具有附件和纯文本主体。

如果尚未安装,请运行

sudo apt install mailutils

0

根据您的邮件命令选项(使用进行检查man mail)和版本,您可以执行

echo yourBody|mail -s yoursubject -A /your/attachment/file john@doe.com


这似乎可以在不添加任何新内容的情况下复制现有答案,最值得注意的是,该-A选项特定于我的答案中所指出的GNU mailutils版本mail以及@rumpel的
Tripleee

-1

如果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*
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.