Como envio um arquivo como anexo de email usando a linha de comando do Linux?

289

Eu criei um script que é executado todas as noites no meu servidor Linux que usa mysqldumppara fazer backup de cada um dos meus bancos de dados MySQL em arquivos .sql e os empacota como um arquivo .tar compactado. O próximo passo que desejo realizar é enviar esse arquivo tar por email para um servidor de email remoto por segurança. Consegui enviar um email ao script bruto no corpo, canalizando o arquivo de texto de backup mailxpara:

$ cat mysqldbbackup.sql | mailx [email protected]

catecoa o texto do arquivo de backup que é canalizado para o mailxprograma com o endereço de email do destinatário passado como argumento.

Enquanto isso realiza o que eu preciso, acho que poderia ser um passo melhor. Existe alguma maneira, usando scripts de shell ou de outra forma, enviar o arquivo .tar compactado para uma mensagem de email de saída como anexo ? Isso exigiria lidar com mensagens de email muito longas que contêm dados de cabeçalho e geralmente têm problemas de quebra de linha, etc.

Kit Roed
fonte
1
Você pode compartilhar o script que faz backup de seus bancos de dados MySQL?
Almino Melo 25/11
Desculpe, eu não faço isso há um tempo agora. Eu sei que envolvia invocar mysqldumpe anexar a saída a um email (com mutt). I pode mesmo ter tido um passo que comprimido a saída para um zip / tar.gz bem ...
Kit Roed
1
Puramente curioso, por que enviar por email seus backups vs scp ou rsync-los?
jchook

Respostas:

298

Nenhum dos vira-latas funcionou para mim. Ele achava que o endereço de e-mail fazia parte do attachemnt. Tive que fazer:

echo "This is the message body" | mutt -a "/path/to/file.to.attach" -s "subject of message" -- [email protected]
rynop
fonte
1
Estou usando o mutt 1.5.21 (15-09-2010) e ele exige que um parâmetro seja após o email do destinatário
nurettin
Trabalhei para mim usando o Mutt 1.5.24 (30/08/2015) no openSUSE Leap 42.1.
Antonio Vinicius Menezes Medei 21/10
3
@ fugitivo significa "fim das opções". Dê uma olhada em unix.stackexchange.com/questions/11376/…
rynop
Existe uma maneira de verificar exceções e tentar enviar novamente?
ti034
79

Ou, falha na vira-lata:

gzip -c mysqldbbackup.sql | uuencode mysqldbbackup.sql.gz  | mail -s "MySQL DB" [email protected]
Daniel Fone
fonte
26
Isso envia a peça codificada em linha e não como um anexo . Muitos clientes de email reconhecem isso e exibem a parte codificada como um anexo.
FuePi 06/07/11
4
Não use o uuencode hoje em dia. MIME é um pouco mais complexo, mas muito mais fácil de usar.
tripleee
@ DavidDiven: Veja, por exemplo (rapidamente) todas as outras respostas a esta pergunta.
tripleee
6
Nenhum deles usa correio!
David Given
Então, por exemplo, stackoverflow.com/questions/3317174/… e substitua text/htmlpor qualquer tipo MIME que faça sentido para o seu anexo. (Para este exemplo concreto, eu acho application/gzip.)
tripleee
43

Dependendo da sua versão do Linux, pode ser chamado de correio. Para citar @ David acima:

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

ou também:

cat message.txt | mail -s "Backup" -a mysqldbbackup.sql [email protected] 
Nathan Fellman
fonte
@ KarelBílek: E a outra opção?
21912 Nathan Fellman
Ambas as soluções não funcionam para mim. I recebeu o e-mail com o Outlook 2013 e o e-mail contém apenas o nome do arquivo
nickel715
2
minha página de manual diz:-a, --append=HEADER: VALUE append given header to the message being sent
exhuma 27/10
2
Nathan, parece que sua citação de David está errada - ele usou o muttcomando, não mail. Além disso, como outros já apontaram, o mutt agora parece exigir um --argumento antes do endereço. E eu vejo que @exhuma e eu realmente concordar com o que a -aopção mailfaz - Fiquei confuso por um minuto;)
nealmcb
7
em vez de -a você deve usar -A: # -a, --append=HEADER: VALUE append given header to the message being sent -A, --attach=FILE attach FILE
Victor Perov #
41

De uma olhada man mailx, o programa mailx não tem uma opção para anexar um arquivo. Você pode usar outro programa como o mutt.

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

Opções de linha de comando para mutt podem ser mostradas com mutt -h.

Chris N
fonte
Obrigado! Isso fez o truque, eu estava tendo problemas para ficar vira-lata para fazer a ação silenciosamente.
Kit Roed
10
Veja a resposta abaixo ( stackoverflow.com/a/9524359/10608 ) porque, aparentemente, a sintaxe foi alterada para mutt, que agora requer a --.
Alexander Bird
29

Eu uso o SendEmail, que foi criado para este cenário. É empacotado para o Ubuntu, então eu presumo que esteja disponível

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

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

Fredrik Wendt
fonte
Eu acredito que deve ser "sendEmail" em vez de "sendemail" no seu exemplo.
03:
1
Sim e não - a fonte (Cáspio) usa uma maiúscula E, enquanto isso é estratégia de nomeação incomum para ferramentas de linha de comando (no mundo Unix), pelo menos a embalagem Ubuntu deste software fornece tanto sendemaile sendEmailem /usr/bin/.
Fredrik Wendt
Meu Xubuntu 14.04.3 não está instaladoSendEmail
Vitaly Zdanevich
3
"sudo apt install sendemail" para instalar o sendemail e adicione "-f [email protected]" um campo obrigatório de para que o comando funcione. sendemail -f [email protected] [email protected] -m "Here are your files!" -a file1.jpg file2.zip
Sailendra Pinupolu
28

Eu uso mpack.

mpack -s subject file [email protected]

Infelizmente o mpack não reconhece '-' como um pseudônimo para stdin. Mas o trabalho a seguir e pode ser facilmente envolvido em um alias (shell) ou em um script:

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

fonte
Isso poderia funcionar no bash para stdin. Eu não tenho mpack, então eu não tentei:mpack -s subject /dev/stdin [email protected] <(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 protected]
Sourabh Potnis
fonte
4
Essa deve ser a resposta aceita. Usa o mailx padrão e funciona perfeitamente. O Mutt v1.5.21 se recusa a enviar anexos> 1 MB ao usar o cron.
528 Joseph
Eu estava procurando por algo que funcione no EC2 e isso funcionou bem.
singularidade
6
mailxnão está adequadamente padronizado. Qualquer resposta que o recomende deve apontar esta advertência. Existem pelo menos três variantes incompatíveis em uso comum.
tripleee
13

Certa vez, escrevi esta função para o ksh no Solaris (usa Perl para codificação 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
}
Glenn Jackman
fonte
8
No GNU / Linux, pode-se usar o base64comando em vez do perl para codificação
MestreLion 1/12/12
12

Você pode usar o mutt para enviar o email com anexo

mutt -s "Backup" -a mysqldbbackup.sql [email protected] < message.txt
David Schlosnagle
fonte
2
Pelo menos a partir do mutt 1.5.21 (Ubuntu confiável), você precisa colocar a -aopção após o destinatário: mutt -s "Backup" [email protected] -a mysqldbbackup.sql < message.txtou usar a --opção antes do destinatário, conforme mostrado na resposta do rynop.
Nellmcb
10

Envie um email de corpo sem formatação com um anexo de texto sem formatação com mailx:

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

Abaixo está o mesmo comando acima, sem as novas linhas

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

Verifique se você tem um arquivo /home/el/attachfile.txtdefinido com este conteúdo:

<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>

Se você não tiver o uuencode, leia isto: /unix/16277/how-do-i-get-uuencode-to-work

No Linux, envie email do corpo em HTML com um anexo em PDF com o sendmail:

Verifique se você tem o ksh instalado: yum info ksh

Verifique se o sendmail está instalado e configurado.

Verifique se o uuencode está instalado e disponível: /unix/16277/how-do-i-get-uuencode-to-work

Crie um novo arquivo chamado test.she coloque-o em seu diretório pessoal:/home/el

Coloque o seguinte código em 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

Altere as variáveis ​​de exportação na parte superior test.shpara refletir seu endereço e nomes de arquivos.

Faça o download de um documento PDF de teste e coloque-o em /home/elpdf-test.pdf

Crie um arquivo chamado /home/el/email_body.htm e coloque esta linha:

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

Verifique se o arquivo pdf possui 755 permissões suficientes.

Execute o script ./test.sh

Verifique sua caixa de entrada de e-mail, o texto deve estar no formato HTML e o arquivo pdf interpretado automaticamente como um arquivo binário. Tome cuidado para não usar esta função mais do que digamos 15 vezes por dia, mesmo se você enviar os e-mails para si mesmo, os filtros de spam do Gmail podem colocar na lista negra um domínio que vomite e-mails sem oferecer a opção de deixá-los passar. E você descobrirá que isso não funciona mais, ou apenas deixa passar o anexo, ou o email não chega. Se você precisar fazer muitos testes, espalhe-os por dias ou será rotulado como spammer e essa função não funcionará mais.

user1651561
fonte
1
Para mim, funcionou o contrário. (echo 'Email Body'; uuencode filename filename) | mailx -s 'Subject' [email protected]
Vicky
uuencodenão é adequadamente um anexo. Ele simplesmente incorpora um blob de texto legível para o computador no meio de algum outro texto. Costumava funcionar bem quando não havia mecanismo melhor, mas isso foi há mais de 20 anos.
tripleee
9

Há várias respostas aqui sugerindo, mailou mailxseja, isso é mais um pano de fundo para ajudá-lo a interpretá-las no contexto.

Notas históricas

As origens do Unix mailremontam às brumas da história inicial do Bell Labs Unix ™ (1969?), E provavelmente não podemos esperar entrar em sua genealogia completa aqui. Basta dizer que existem muitos programas que herdam código ou reimplementam (ou herdam código de uma reimplementação de) maile que não existe uma base de código única que possa ser inequivocamente identificada como "o" mail.

No entanto, um dos candidatos a essa posição é certamente "Berkeley Mail", que foi originalmente chamado Mailcom M maiúsculo em 2BSD (1978); mas em 3BSD (1979), também substituiu o mailcomando em minúsculas , levando a uma nova confusão. SVR3 (1986) incluiu um derivado que foi chamado mailx. O xfoi, presumivelmente, para torná-lo único e distinto; mas isso também já foi copiado, reimplementado e mutilado para que não exista uma versão individual definitiva.

Naquela época, o padrão de fato para o envio de binários pelo correio eletrônico era uuencode. Ainda existe, mas tem vários problemas de usabilidade; se possível, você deve enviar anexos MIME, a menos que se esforce especificamente para poder se comunicar com o final dos anos 80.

O MIME foi introduzido no início dos anos 90 para resolver vários problemas com o email, incluindo suporte para vários tipos de conteúdo, além de texto sem formatação, em um único conjunto de caracteres que realmente é adequado apenas para um subconjunto de inglês (e, segundo nos dizem, havaiano) ) Isso introduziu o suporte a mensagens multipartes, internacionalização, tipos de conteúdo sofisticado etc., e rapidamente ganhou força ao longo dos anos 90.

(As notas da herança mail/ mailxhistória foram mais úteis ao compor isso e certamente valem a pena ser lidas se você gosta desse tipo de coisa.)

Ofertas atuais

A partir de 2018, o Debian possui três pacotes que incluem um comando mailou mailx. (Você pode procurar 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

(Eu não estou destacando o Debian como uma recomendação; é o que eu uso, por isso estou familiarizado com ele; e fornece um meio de distinguir as várias alternativas sem ambiguidade, consultando os respectivos nomes de pacotes. É obviamente também a distro de qual Ubuntu obtém esses pacotes.)

Com essas preocupações, se você precisar que seu código seja portátil e possa depender de um pacote um pouco complexo, a maneira mais simples de enviar anexos MIME de forma portável é usar mutt.

triplo
fonte
Originalmente, eu postei isso como uma resposta a um moderadamente populares duplicado questão stackoverflow.com/questions/902591/...
tripleee
4

Outra alternativa - Swaks (canivete suíço para 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
Alexander Yancharuk
fonte
2

metamail tem a ferramenta metasend

metasend -f mysqlbackup.sql.gz -t [email protected] -s Backup -m application/x-gzip -b
Gunstick
fonte
Isso costumava ser instalado em quase todos os lugares, mas quase nunca era usado. Por não ter sido mantido por muito tempo (e ainda é o AFAIK), foi removido do conjunto de ferramentas padrão de fato em muitas plataformas.
tripleee
2

eu usei

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

e isso funcionou bem para mim ....

poncho
fonte
1

Normalmente, uso apenas o comando mail no RHEL. Eu tentei o mailx e é bastante eficiente.

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

This is the content of my msg.

.
Alejandro Santillan
fonte
1

o caminho mais curto para mim é

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

Então, para o seu exemplo, será

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

a parte boa é que consigo me lembrar com Ctrl + r para enviar outro arquivo ...

Pipo
fonte
As chaves não farão muito bem, mas para ser completamente portátil, você deve usar aspas duplas em torno das variáveis. Veja também stackoverflow.com/questions/10067266/…
tripleee 13/06/19
1

Da máquina de origem

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

Na máquina de destino. Salve o corpo do email recebido como db.sql.gz.b64 ; então..

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

Apenas para adicionar meus 2 centavos, eu escreveria meu próprio script PHP:

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

Existem várias maneiras de fazer o anexo nos exemplos dessa página.

Mike Graf
fonte
2
Nem todo servidor pode ter o PHP instalado. Se você realmente deseja seguir o caminho "escreva seu próprio script", então perl ou python são muito mais adequados, pois geralmente estão disponíveis por padrão.
Exhuma
shé ainda mais onipresente. Existem perguntas duplicadas com respostas com bons exemplos; aqui é minha.
Tripleee
0

mailx-aagora tem uma opção para anexos.

Allan Pinto
fonte
2
A opção "-a" é para cabeçalhos
Yves Martin
homem do correio [x], versão 12.5 de 10/9/10 (há alguns anos) diz claramente -a arquivo Anexe o arquivo dado ao message.`
fche
4
algumas versões do mailxdo. Eu acredito que existem duas implementações. Por um lado, -aé para anexos, por outro, por cabeçalhos.
Exhuma
1
A versão do mailx no Ubuntu vem do GNU e -a significa adicionar um cabeçalho. manpages.ubuntu.com/manpages/lucid/en/man1/mailx.1.html Qual sistema e qual mailx faz um anexo?
Nellmcb
3
Na nova "-a" implementação é para cabeçalhos e "-A" é para attchments
Avi Mehenwal
0

Não é um método para enviar email, mas você pode usar um servidor Git online (por exemplo, Bitbucket ou um serviço semelhante) para isso.

Dessa forma, você pode usar git pushcomandos e todas as versões serão armazenadas de forma compactada e organizada.

Yoav
fonte
0

É assim que estou fazendo com um arquivo de log grande no CentOS:

MAIL="`whereis mail | awk '{print $2}'`"
WHOAMI="`whoami`"
HOSTNAME="`hostname`"
EMAIL"[email protected]"
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
dagorv
fonte
Por que você está definindo WHOAMIe HOSTNAME duas vezes?
David C. Rankin
Isso tem vários erros de estilo de codificação de shell. O shellcheck.net indicará alguns deles, mas não todos.
tripleee
0

Se o arquivo for texto, você poderá enviá-lo mais facilmente no corpo, como:

sendmail [email protected] < message.txt
nurp
fonte
1
Isso não o envia como anexo, nem como corpo da mensagem. O Sendmail espera que sua entrada seja uma mensagem de email RFC5322 completa e bem formada e pode falhar de maneiras interessantes, se não for.
tripleee
0

usando o comando mailx

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

usando 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 `;
Girdhar Singh Rathore
fonte
1
sendmail é um bom exemplo, feliz por ter encontrado aqui.
Honza P.
Observe que você precisa de uma linha vazia no início de "seu corpo", caso contrário, o corpo desaparecerá nos cabeçalhos ou possivelmente quebrará a mensagem completamente. Veja também notas em outros lugares sobre como evitar a uuencodefavor do MIME.
tripleee
E as costas monstruosas evale misteriosas em torno de toda a engenhoca são completamente desnecessárias aqui.
tripleee
0

Mailutils faz deste um pedaço de bolo

echo "Body" | mail.mailutils -M -s "My Subject" -A attachment.pdf [email protected]
  • -A file anexa um arquivo
  • -M ativa o MIME, para que você possa ter um corpo de anexo e texto sem formatação.

Se ainda não estiver instalado, execute

sudo apt install mailutils
rumpel
fonte
0

Dependendo das opções de comando do correio (verifique com man mail) e da versão que você pode fazer

echo yourBody|mail -s yoursubject -A /your/attachment/file [email protected]

Pipo
fonte
Isso parece duplicar as respostas existentes sem adicionar nada de novo, principalmente a -Aopção é específica da mailutilsversão GNU domail como foi salientado na minha resposta, bem como de @ rumpel
tripleee
-1

Se o mutt não estiver funcionando ou não estiver instalado, tente o seguinte:

*#!/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*
Paras Singh
fonte