我创建了一个脚本,每天晚上在我的Linux服务器上运行,它使用mysqldump将我的每个MySQL数据库备份到.sql文件,并将它们打包成一个压缩的.tar文件。我想完成的下一步是通过电子邮件将tar文件发送到远程电子邮件服务器以确保安全。我已经能够通过管道备份文本文件到mailx发送原始脚本正文的电子邮件,就像这样:

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

Cat回显备份文件的文本,该文本通过管道输入mailx程序,并将收件人的电子邮件地址作为参数传递。

虽然这实现了我所需要的,我认为它可以更好的一步,有任何方法,使用shell脚本或其他方式,将压缩的.tar文件作为附件发送到外发电子邮件消息?这将避免处理包含标题数据和经常有换行问题等非常长的电子邮件。


当前回答

这里有几个关于mail或mailx的答案,所以这更多的是一个背景知识,帮助你在上下文中理解它们。但在最后还是有一些实用的建议。

历史记录

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

然而,这个位置的竞争者之一当然是“Berkeley Mail”,它最初在2BSD(1978)中被称为大写M的Mail;但是在3BSD(1979)中,它也取代了小写的邮件命令,导致了一些新的混乱。SVR3(1986)包含了一个叫做mailx的导数。加上x可能是为了使它唯一且不同;但是,这一点现在也被复制、重新实现和破坏,因此没有一个单独的版本是确定的。

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

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

(在撰写本文时,传家宝邮件/mailx历史笔记是最有帮助的,如果你对这类事情感兴趣,当然值得一读。)

当前的产品

截至2018年,Debian有三个包,其中包括一个mail或mailx命令。(你可以搜索providers: 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现在被称为s-nail,并且支持用-a发送MIME附件。查看它的手册页和更一般的传家宝项目 mailutils(又名GNU mailutils)包含一个邮件/邮件兼容包装器,它支持使用-A发送MIME附件

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

如果你知道你在做什么,你可以在echo和base64的帮助下组装一个任意的MIME结构,例如qprint(或本地替换;base64和qprint都可以很容易地实现为Perl一行程序),并将其管道到sendmail;但本页上的其他几个答案生动地说明了,你可能不知道。

( printf '%s\n' \
    "From: myself <sender@example.org>" \
    "To: backup address <backup@email.example>" \
    "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

这假设sendmail在你的PATH上;有时不是(当然,有时根本没有安装)。查看/usr/lib, /usr/sbin, /usr/libexec或etc;或查询您的包管理器。找到它之后,您可能希望在脚本中增加PATH,或者将完整的路径名硬编码到sendmail(对于系统上可能安装也可能没有安装的任何其他非标准二进制文件也是如此)。

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

其他回答

Metamail有metasend工具

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

或者,失败的杂种:

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

我曾经在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
}

如果文件是文本,你可以在正文中最简单地发送它:

sendmail recipient@example.com < message.txt

从源机器

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