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 backup@email.com

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.


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" -- recipient@domain.com

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" backup@email.com

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 backup@email.com < message.txt

ou também:

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

@ 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" recipient@domain.com

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


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 sender@some.where -t receiver@some.place -m "Here are your files!" -a file1.jpg file2.zip

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


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 required@email.com" um campo obrigatório de para que o comando funcione. sendemail -f mandatory@email.com-t to@some.one -m "Here are your files!" -a file1.jpg file2.zip
Sailendra Pinupolu

28

Eu uso mpack.

mpack -s subject file user@example.com

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 loser@example.com < file

Isso poderia funcionar no bash para stdin. Eu não tenho mpack, então eu não tentei: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
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
}

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 backup@email.com < message.txt

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" backup@email.com -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' youremail@gmail.com

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' youremail@gmail.com

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

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.


1
Para mim, funcionou o contrário. (echo 'Email Body'; uuencode filename filename) | mailx -s 'Subject' user@domain.com
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.


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

2

metamail tem a ferramenta metasend

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

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" "a@b.c" 

e isso funcionou bem para mim ....


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 Recipient@myemail.com

This is the content of my msg.

.

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

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


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 me@myemail.com

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

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.


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.


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.


0

É assim que estou fazendo com um arquivo de log grande no 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

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 recipient@example.com < message.txt

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 user@example.com

usando 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 é 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 mail@example.org
  • -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

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 john@doe.com


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*
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.