Як надіслати файл у вигляді вкладення електронної пошти за допомогою командного рядка Linux?


289

Я створив сценарій, який працює щовечора на моєму сервері Linux, який використовує mysqldumpдля створення резервної копії кожної з моїх баз даних MySQL до файлів .sql і пакує їх разом у вигляді стиснутого файлу .tar. Наступним кроком, який я хочу виконати, є надсилання цього файлу tar через електронну пошту на віддалений сервер електронної пошти для збереження. Мені вдалося надіслати необроблений скрипт у тілі електронною поштою, відстеживши текстовий файл резервної копії mailxтаким чином:

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

catповторюється текст файлу резервного копіювання, який передається в mailxпрограму, передаючи електронну адресу одержувача як аргумент.

Хоча це виконує те, що мені потрібно, я думаю, що це може бути на один крок краще, чи є якийсь спосіб за допомогою скриптів оболонки чи іншим чином відправити стислий файл .tar до вихідного повідомлення електронної пошти як вкладення ? Це не може мати справу з дуже довгими повідомленнями електронної пошти, які містять дані заголовків і часто мають проблеми із перенесенням текстів тощо.


1
Чи можете ви поділитися сценарієм, який створює резервну копію ваших баз даних MySQL?
Almino Melo

Вибачте, я цього не роблю вже деякий час. Я знаю, що це стосується виклику, mysqldumpа потім приєднання виводу до електронної пошти (з mutt). У мене, можливо, був навіть крок, який також стиснув вихід на zip / tar.gz ...
Kit Roed

1
Суто цікаво, чому надіслати електронною поштою резервні копії vs scp або rsync їх?
jchook

Відповіді:


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

Працював для мене за допомогою Mutt 1.5.24 (2015-08-30) у openSUSE Leap 42.1.
Антоніо Вініцій Менез Медей

3
@fugitive означає "кінець варіантів". Подивіться на unix.stackexchange.com/questions/11376/…
rynop

Чи є спосіб перевірити винятки та спробувати надсилання?
ti034

79

Або невдалий шум:

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

26
Це посилає частину закодованої частини inline, а не як вкладення . Багато поштових клієнтів розпізнають це, хоча і відображають частину коду, що не використовується, як додаток.
FuePi

4
Не використовуйте uuencode у цей день та вік. MIME трохи складніший, але набагато зручніший для користувачів.
tripleee

@DavidGiven: Див. Наприклад (швидким поглядом) всі інші відповіді на це питання.
трійка

6
Жоден з них не використовує пошту!
Давид Дано

Потім, наприклад, stackoverflow.com/questions/3317174/… і замініть text/htmlбудь-яким типом MIME, який має сенс для вашого вкладення. (Напевно, на цей конкретний приклад application/gzip.)
трійка

43

Залежно від вашої версії Linux він може називатися поштою. Цитувати @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: Як щодо іншого варіанту?
Натан Фелман

Обидва рішення для мене не працюють. Я отримав електронний лист із перспективою 2013 року, і пошта містить лише ім'я файлу
nickel715,

2
моя сторінка -a, --append=HEADER: VALUE append given header to the message being sent
написана

2
Натане, схоже, ваша цитата від Девіда помилкова - він використав muttкоманду, ні mail. Крім того, як інші вказували, тепер, як видається, mutt вимагає --аргументу перед адресою. І я бачу, що @exhuma, і я дійсно згоден на те, що робить -aваріант mail- я заплутався там на хвилину;)
nealmcb

7
замість -а вам слід використовувати -A: -a, --append=HEADER: VALUE append given header to the message being sent -A, --attach=FILE attach FILE
Віктор Перов

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" у вашому прикладі.
Давіт

1
Так і ні - джерело (каспійський) використовує великі регістри E, тоді як це нечасто стратегія іменування інструментів командного рядка (у світі Unix), принаймні упаковка Ubuntu цього програмного забезпечення забезпечує і те, sendemailі sendEmailін /usr/bin/.
Фредрік Вендт

Мій Xubuntu 14.04.3 не встановленоSendEmail
Віталій Зданевич,

3
"sudo apt install sendemail", щоб встановити sendemail та додати "-f обов'язковий@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. Але наступна робота, і її можна легко загорнути в псевдонім (оболонку) або сценарій:

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

Це могло б працювати в баш для stdin. У мене немає 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 відмовляється відправляти> 1 МБ вкладень при використанні cron.
Йосиф

Я шукав щось, що працює в EC2, і це спрацювало чудово.
сингулярність

6
mailxне є належним чином стандартизованим. Будь-яка відповідь, яка його рекомендує, повинна вказувати на цей застереження. Існує щонайменше три несумісні варіанти загального користування.
трійка

13

Одного разу я написав цю функцію для ksh на Solaris (використовує 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

12

Ви можете використовувати mutt для надсилання електронного листа із вкладенням

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

2
Принаймні, що стосується mutt 1.5.21 (Ubuntu trusty), вам потрібно поставити -aопцію після одержувача: mutt -s "Backup" backup@email.com -a mysqldbbackup.sql < message.txtабо використати --параметр перед одержувачем, як показано у відповіді rynop.
nealmcb

10

Надішліть електронний лист із тілом Plaintext з одним вкладеним текстом у форматі 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, прочитайте це: /unix/16277/how-do-i-get-uuencode-to-work

У Linux надсилайте HTML-адресу електронної пошти із вкладенням PDF із sendmail:

Переконайтеся, що у вас встановлено ksh: yum info ksh

Переконайтеся, що у вас встановлена ​​та налаштована sendmail.

Переконайтеся, що у вас встановлено і доступно uuencode: /unix/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
Вікі

uuencodeне є належним чином вкладення. Він просто вбудовує текстовий текст, що читається на комп'ютері, посередині якогось іншого тексту. Це працювало чудово, коли не було жодного кращого механізму, але це було 20+ років тому.
трійка

9

Є кілька відповідей тут пропонуючи mailабо mailxтак це скоріше фон , щоб допомогти вам інтерпретувати їх в контексті.

Історичні записки

Витоки Unix mailсягають туман ранньої історії Bell Labs Unix ™ (1969?), І ми, мабуть, не можемо сподіватися тут перейти до його повної генеалогії. Досить сказати, що існує багато програм, які успадковують код від або повторного втілення (або успадковують код від повторного втілення) mailі що немає єдиної бази коду, яку можна однозначно ідентифікувати як "the" mail.

Однак, одним із претендентів на цю посаду, безумовно, є "Берклі Пошта", яку спочатку називали Mailвеликим регістром М у 2BSD (1978); але в 3BSD (1979) вона також замінила малу mailкоманду, що призвело до певної плутанини. SVR3 (1986) включав похідну, яку називали mailx. xІмовірно додав , щоб зробити його унікальним і різні; але це теж тепер було скопійовано, повторно доповнено та знято, щоб не було єдиної окремої версії, яка була б остаточною.

Ще в той час фактично стандарт для надсилання бінарних файлів електронною поштою був uuencode. Він все ще існує, але має численні проблеми у користуванні; якщо це взагалі можливо, слід надіслати MIME-вкладення замість цього, якщо ви конкретно не прагнете мати можливість спілкуватися з кінцем 1980-х.

MIME був введений на початку 1990-х для вирішення декількох проблем з електронною поштою, включаючи підтримку різних типів вмісту, крім звичайного тексту, в одному наборі символів, який дійсно підходить для підмножини англійською мовою (і, як нам кажуть, гавайський ). Це запровадило підтримку багаточастинних повідомлень, інтернаціоналізації, багатих типів вмісту тощо, і швидко набуло тяги протягом 90-х років.

( Примітки про Реліквію mail/ mailxісторію були найбільш корисними при складанні цього тексту, і, безумовно, варто ознайомитися, якщо ви займаєтесь подібною справою.)

Поточні пропозиції

Станом на 2018 рік у Debian є три пакети, до яких входить команда mailабо 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 отримує ці пакети.)

З цим питанням, якщо вам потрібно, щоб ваш код був переносним і може залежати від дещо складного пакету, простий спосіб переносити вкладені файли 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) він був видалений з де - факто стандартного набору інструментів на багатьох платформах.
трійка

2

я використав

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

і це добре спрацювало для мене ....


1

Зазвичай я використовую лише команду пошти на RHEL. Я спробував 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/en/function.mail.php

Існує маса способів зробити вкладення у прикладах на цій сторінці.


2
Не на кожному сервері може бути встановлено PHP. Якщо ви дійсно хочете піти по шляху "написати власний скрипт", то perl або python набагато краще підходять, оскільки вони зазвичай доступні за замовчуванням.
ексгума

shє ще більш всюдисущим. Є повторювані запитання з відповідями з хорошими прикладами; ось моя.
трійчатка

0

mailx-aтепер є опція для вкладень.


2
Варіант "-a" призначений для заголовків
Ів Мартін,

man mail [x], версія 12.5 від 10.10.10 (кілька років тому) чітко говорить
-файл

4
деякі версії mailxdo. Я вважаю, що є дві реалізації. На одній -a- для вкладень, на іншій - для заголовків.
ексгума

1
Версія mailx в Ubuntu походить від GNU, а там - означає додати заголовок. manpages.ubuntu.com/manpages/lucid/en/man1/mailx.1.html Яка система та яка пошта надає вкладення?
nealmcb

3
У новій реалізації "-a" призначений для заголовків, а "-a" - для вкладень
Avi Mehenwal

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

Чому ти визначаєш WHOAMIі HOSTNAME двічі?
Девід К. Ранкін

Тут є кілька помилок стилю кодування оболонки. shellcheck.net вкаже на деякі, але не всі з них.
трійка

0

Якщо файл є текстовим, ви можете надіслати його найпростіше в тілі як:

sendmail recipient@example.com < message.txt

1
Це не надсилається як вкладення або навіть як тіло повідомлення. Sendmail очікує, що його вклад буде повноцінним, добре сформованим повідомленням електронної пошти RFC5322, і може виявитися невдалим цікавим чином, якщо цього не буде.
трійка

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 - хороший приклад, радий, що знайшов його тут.
Гонза П.

Зауважте, що на початку "свого тіла" вам потрібен порожній рядок, інакше тіло зникне в заголовках або, можливо, буде повністю порушено повідомлення. Також дивіться примітки в іншому місці про уникнення uuencodeна користь MIME.
трійка

І чудовищні evalта таємничі підґрунтя навколо усієї контрацепції тут абсолютно непотрібні.
трійка

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варіант є специфічним для mailutilsверсії GNU, mailяк було зазначено у моїй відповіді, а також @ rumpel's
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*
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.