This question already has answers here:
Sending a mail from a linux shell script
(11 answers)
Closed 5 years ago.
I am on linux machine and I monitor a process usage. Most of the time I will be away from my system and I have access to internet on my device. So I planned to write a shell-script that can mail me the output of the process.
Is it possible?
If so how to make a shell-script send me mail?
Please provide a snippet to get started.
Yes it works fine and is commonly used:
$ echo "hello world" | mail -s "a subject" someone#somewhere.com
Basically there's a program to accomplish that, called "mail". The subject of the email can be specified with a -s and a list of address with -t. You can write the text on your own with the echo command:
echo "This will go into the body of the mail." | mail -s "Hello world" you#youremail.com
or get it from other files too:
mail -s "Hello world" you#youremailid.com < /home/calvin/application.log
mail doesn't support the sending of attachments, but Mutt does:
echo "Sending an attachment." | mutt -a file.zip -s "attachment" target#email.com
Note that Mutt's much more complete than mail.
You can find better explanation here
PS: thanks to #slhck who pointed out that my previous answer was awful. ;)
sendmail works for me on the mac (10.6.8)
echo "Hello" | sendmail -f my#email.com my#email.com
mail -s "Your Subject" your#email.com < /file/with/mail/content
(/file/with/mail/content should be a plaintext file, not a file attachment or an image, etc)
#!/bin/sh
#set -x
LANG=fr_FR
# ARG
FROM="foo#bar.com"
TO="foo#bar.com"
SUBJECT="test é"
MSG="BODY éé"
FILES="fic1.pdf fic2.pdf"
# http://fr.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions
SUB_CHARSET=$(echo ${SUBJECT} | file -bi - | cut -d"=" -f2)
SUB_B64=$(echo ${SUBJECT} | uuencode --base64 - | tail -n+2 | head -n+1)
NB_FILES=$(echo ${FILES} | wc -w)
NB=0
cat <<EOF | /usr/sbin/sendmail -t
From: ${FROM}
To: ${TO}
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=frontier
Subject: =?${SUB_CHARSET}?B?${SUB_B64}?=
--frontier
Content-Type: $(echo ${MSG} | file -bi -)
Content-Transfer-Encoding: 7bit
${MSG}
$(test $NB_FILES -eq 0 && echo "--frontier--" || echo "--frontier")
$(for file in ${FILES} ; do
let NB=${NB}+1
FILE_NAME="$(basename $file)"
echo "Content-Type: $(file -bi $file); name=\"${FILE_NAME}\""
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=\"${FILE_NAME}\""
#echo ""
uuencode --base64 ${file} ${FILE_NAME}
test ${NB} -eq ${NB_FILES} && echo "--frontier--" || echo
"--frontier"
done)
EOF
Well, the easiest solution would of course be to pipe the output into mail:
vs#lambda:~$ cat test.sh
sleep 3 && echo test | mail -s test your#address
vs#lambda:~$ nohup sh test.sh
nohup: ignoring input and appending output to `nohup.out'
I guess sh test.sh & will do just as fine normally.
top -b -n 1 | mail -s "any subject" your_email#domain.com
Related
I run a bash script, and looping as much line in text file. to cURL the site listed in the txt file.
here is my script :
SECRET_KEY='zuhahaha'
FILE_NAME=""
case "$1" in
"sma")
FILE_NAME="sma.txt"
;;
"smk")
FILE_NAME="smk.txt"
;;
"smp")
FILE_NAME="smp.txt"
;;
"sd")
FILE_NAME="sd.txt"
;;
*)
echo "not in case !"
;;
esac
function save_log()
{
printf '%s\n' \
"Header Code : $1" \
"Executed at : $(date)" \
"Response Body : $2" \
"====================================================================================================="$'\r\n\n' >> output.log
}
while IFS= read -r line;
do
HTTP_RESPONSE=$(curl -L -s -w "HTTPSTATUS:%{http_code}\\n" -H "X-Gitlab-Event: Push Hook" -H 'X-Gitlab-Token: '$SECRET_KEY --insecure $line 2>&1) &
HTTP_BODY=$(echo $HTTP_RESPONSE | sed -e 's/HTTPSTATUS\:.*//g') &
HTTP_STATUS=$(echo $HTTP_RESPONSE | tr -d '\n' | sed -e 's/.*HTTPSTATUS://') &
save_log "$HTTP_STATUS" "$HTTP_BODY" &
done < $FILE_NAME
how i can run threading or make the loop fast in bash ?
You should be able to do this relatively easily. Don't try to background each command, but instead put the body of your while loop into a subshell and background that. That way, your commands (which clearly depend on each other) run sequentially, but all the lines in the file can be process in parallel.
while IFS= read -r line;
do
(
HTTP_RESPONSE=$(curl -L -s -w "HTTPSTATUS:%{http_code}\\n" -H "X-Gitlab-Event: Push Hook" -H 'X-Gitlab-Token: '$SECRET_KEY --insecure $line 2>&1)
HTTP_BODY=$(echo $HTTP_RESPONSE | sed -e 's/HTTPSTATUS\:.*//g')
HTTP_STATUS=$(echo $HTTP_RESPONSE | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
save_log "$HTTP_STATUS" "$HTTP_BODY" ) &
done < $FILE_NAME
My favourite was to do this is generate a file that lists all the commands you wish to perform. If you have a script that performs your operations create a file like:
$ cat commands.txt
echo 1
echo 2
echo $[12+3]
....
For example this could be hundreds of commands long.
To execute each line in parallel, use the parallel command with, say, at most 3 jobs running in parallel at any time.
$ cat commands.txt | parallel -j
1
2
15
For your curl example you could generate thousands of curl commands, execute them say 30 in parallel at any one time.
This question already has answers here:
How do I send a file as an email attachment using Linux command line?
(25 answers)
Closed 4 years ago.
I want to send an email using sendmail command in bash. The email should get it's body by reading Input_file_HTML and it should send same input file as an attachment too. To do so I have tried the following.
sendmail_touser() {
cat - ${Input_file_HTML} << EOF | /usr/sbin/sendmail -oi -t
From: ${MAILFROM}
To: ${MAILTO}
Subject: $1
Content-Type: text/html; charset=us-ascii
cat ${Input_file_HTML}
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0
Content-Disposition: attachment; filename: ${Input_file_HTML}
EOF
}
The above command is giving an email with only the attachment of Input_file_HTML and it is not writing it in the body of email. Could you please help/guide me on same? I am using outlook as the email client. I have even removed the cat command in above command, but it also is not working.
Use mutt instead?
echo "This is the message body" | mutt -a "/path/to/file.to.attach" -s "subject of message" -- recipient#domain.com
To install mutt on Debian systems:
sudo apt-get install -y mutt
EDIT Try this if you can only use sendmail:
sendmail_attachment() {
FROM="$1"
TO="$2"
SUBJECT="$3"
FILEPATH="$4"
CONTENTTYPE="$5"
(
echo "From: $FROM"
echo "To: $TO"
echo "MIME-Version: 1.0"
echo "Subject: $SUBJECT"
echo 'Content-Type: multipart/mixed; boundary="GvXjxJ+pjyke8COw"'
echo ""
echo "--GvXjxJ+pjyke8COw"
echo "Content-Type: text/html"
echo "Content-Disposition: inline"
echo "<p>Message contents</p>"
echo ""
echo "--GvXjxJ+pjyke8COw"
echo "Content-Type: $CONTENTTYPE"
echo "Content-Disposition: attachment; filename=$(basename $FILEPATH)"
echo ""
cat $FILEPATH
echo ""
) | /usr/sbin/sendmail -t
}
Use like this:
sendmail_attachment "to#example.com" "from#example.com" "Email subject" "/home/user/file.txt" "text/plain"
I am new to shell programming. I have two files:
eg.txt
file.sh
The eg.txt file has some HTML content and file.sh cotains a shell script.
In the script a value is assigned to the temp variable, and that value should be injected into the HTML file.
eg.txt
<html>
Hi MGM ,<br/>
One alert has been received !!<br/>
Here is the event Data.<br/><br/>
<font size=‘1’>{temp}</font>
<br/><br/>
Regards,
WDTS Supports.
</html>
file.sh
echo $1
temp=56
(
echo "To:"$1
echo "Subject: Alert Updates !! "
echo "Content-Type: text/html"
echo cat eg.txt
) | /usr/sbin/sendmail -t
echo "Mail sent !!"
With sed :
sed "s/{temp}/$temp/" eg.txt | /usr/sbin/sendmail -t
You can also use printf to inject variables in your template :
file.sh
temp=56
tpl=$(cat "eg.txt")
printf "$tpl" "$1" "$temp" | /usr/sbin/sendmail -t
eg.txt
To:%s
Subject: Alert Updates !!
Content-Type: text/html
<html>
Hi MGM ,<br/>
One alert has been received !!<br/>
Here is the event Data.<br/><br/>
<font size=‘1’>%s</font>
<br/><br/>
Regards,
WDTS Supports.
</html>
Update:
If multiple variables, just write multiple substitute commands (and update placeholders in eg.txt):
sed "s/{temp1}/$temp1/;s/{temp2}/$temp2/" eg.txt | /usr/sbin/sendmail -t
I have introduced some error checking to your code :
#!/bin/bash
temp=56
if [ -z "$1" ]
then
echo "Usage : ./file.sh user_name_to_mail to"
exit -1
else
if id "$1" >/dev/null 2>&1 #Check if user exists, suppress stdout, stderr
then
mail_header=$(echo -e "To: $1\nSubject: Alert Updates"'!!'"\nContent-Type: text/html\n")
mail_body=$(awk -v var="$temp" '{print gensub(/{temp}/,var,"g"$0)}' eg.txt)
echo -e "$mail_header\n$mail_body" | sendmail -t
else
echo -e "Sorry! Invalid User\n"
exit -1 # The error code is set to detect failure
fi
fi
To prevent the mails going to spam you need to have a valid SPF record for domain from which you're sending email. Check [ this ] for a starting point.
Note:
! is a special character to bash, it is used to refer to previous command. To work around this problem I have used ..Updates"'!!'"\nContent-Type...
Inside the single quotes the ! loses its special meaning.
Interesting reads :
What is an [ SPF ] record?
Open SPF [ documentation ] .
echo $1
temp=56
(
echo "To:"$1
echo "Subject: Alert Updates !! "
echo "Content-Type: text/html"
awk -F "" -v var=$temp '{gsub(/{temp}/,var,$0); print}' < eg.txt
) | /usr/sbin/sendmail -t
echo "Mail sent !!"
added awk to '|' where the temp is stored in awk variable : var which is later replaced
awk -F "" -v var=$temp '{gsub(/{temp}/,var,$0); print}'
I have a requirement like, i need to export the sql query result set to a .csv file and send it as an attachment. but here i need to include the body with html formatting and wanted to include sample rows of the .csv file in body as well in html format.
csv file contains :
Id ID_CNT
a 3
b 6
and i want to display the mail body with sample rows.
I have tried below two ways
mutt -e "set content_type=text/html" -a query_gen23.csv -s "abc" abc#gmail.com
export CONTENT="test.html"
export SUBJECT="$subject"
#(
# echo "To: "
# echo "Subject: $SUBJECT"
# echo "MIME-Version: 1.0"
# echo "Content-Type: text/html"
# echo "Content-Disposition: inline"
# cat $CONTENT
#) | /usr/sbin/sendmail $MAILTO
mutt -s "$subject" -a "$subject".csv -a test.html "$MAILTO" </dev/null
Thanks in Advance!
It's a long time since I had used mutt, but if I remember right, it expects the body of the mail from standard input. In your script, you input-redirect from /dev/null !
I would divide the task into two steps: One creates the body (HTML code with the CSV sample lines), and the second step pipes this file into mutt. I think this is much easier than trying to do everything at once.
Following works fine for me :
#!/usr/bin/ksh
export MAILTO="spam#ebay.com"
export SUBJECT="Mail Subject"
export BODY="/tmp/email_body.html"
export ATTACH="/tmp/attachment.txt"
(
echo "To: $MAILTO"
echo "Subject: $SUBJECT"
echo "MIME-Version: 1.0"
echo 'Content-Type: multipart/mixed; boundary="-q1w2e3r4t5"'
echo
echo '---q1w2e3r4t5'
echo "Content-Type: text/html"
echo "Content-Disposition: inline"
cat $BODY
echo '---q1w2e3r4t5'
echo 'Content-Type: application; name="'$(basename $ATTACH)'"'
echo "Content-Transfer-Encoding: base64"
echo 'Content-Disposition: attachment; filename="'$(basename $ATTACH)'"'
uuencode -m $ATTACH $(basename $ATTACH)
echo '---q1w2e3r4t5--'
) | /usr/sbin/sendmail $MAILTO
I wrote script to send mail automatically using an SMTP connection but when I execute the script, sometimes it works and sometimes it is not sending mail. Behavior is quite ambiguous.
Environment : Linux Server Fedora 14
Mailing Client : Lotus Notes 8.5.2
Please find script below.
# Function for sending email
sendemail(){
date=`date '+%d-%m-%Y'`
dbDir=/var/lib/MYSQLBACKUP/$date
dbname='DBNAME'
log_file="${dbDir}/${dbname}_${date}.log"
attached_file="${dbname}_${date}.log"
echo $log_file
echo $attached_file
encoded_log_file=`cat $log_file | openssl base64`
#echo $encoded_log_file
( echo open 172.40.201.31 25
sleep 8
echo helo 172.40.201.31
echo mail from:Pratik.Vyas#gmail.com
echo rcpt to:Pratik.Vyas#gmail.com
echo data
echo to:Pratik.Vyas#gmail.com
echo from:Pratik.Vyas#gmail.com
echo "subject: SPARC CQ DB Backup Report : $date :"
echo "MIME-Version: 1.0"
#echo "Content-Type: text/plain; charset=UTF-8"
#echo "Please view attached file"
echo "Content-Type: text/x-log;name="$attached_file""
echo "Content-Disposition:attachment;filename="$attached_file""
echo "Content-Transfer-Encoding: base64"
echo $encoded_log_file
echo $1
sleep 15
echo .
echo ^]
echo quit ) | telnet
echo "status:$?"
echo "Hello done"
}
sendemail
Here's a rewrite using /usr/lib/sendmail. This is not necessarily the correct location for your system, but you should be able to adapt it.
# Function for sending email
sendemail(){
date=$(date '+%d-%m-%Y') # prefer $(...) over `...`
dbDir=/var/lib/MYSQLBACKUP/$date
dbname='DBNAME'
log_file="${dbDir}/${dbname}_${date}.log"
attached_file="${dbname}_${date}.log"
echo $log_file
echo $attached_file
encoded_log_file=$(openssl base64 < "$log_file") # notice UUCA fix + quoting
#echo $encoded_log_file
# You should configure sendmail to use 172.40.201.31 as your smarthost
/usr/lib/sendmail -oi -t <<________HERE
to: Pratik.Vyas#gmail.com
from: Pratik.Vyas#gmail.com
subject: SPARC CQ DB Backup Report : $date :
MIME-Version: 1.0
Content-Type: text/x-log; name="$attached_file"
Content-Disposition: attachment; filename="$attached_file"
Content-Transfer-Encoding: base64
X-Ample: notice empty line between headers and body! # <-- look
$encoded_log_file
$1
________HERE
echo "status:$?"
echo "Hello done"
}
sendemail
I would recommend using a library or command line program (like mail or mailx) to send mail instead of trying to implement SMTP in a shell script.