Bash : Configuring email-provider for bash-script - linux

I am working on writing a script to run on our Debian server(Debian 3.2.68-1+deb7u5 x86_64 GNU/Linux), which will monitor a specific port we have and when there is no process running on that port, or that port is available, then I will have to send out an email. I intend to run the script every 15 minutes and then send out an email.
We have an email-server and I want to add it's configuration in the script, but I am not sure how I can do that.
When in Java, I am using the configuration in this manner :
Properties props = new Properties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", "EMAIL-HOST-NAME");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.port", "PORT-PROVIDED");
Currently, I have the script as follows, any suggestions to script are also welcome. Thank you.
#!/bin/bash
server=0.0.0.0 // localhost
port=PORT-NUMBER
if nc $server $port &> /dev/null; then
// do nothing
else
// send email
fi
Thank you.

Both mailx and sendmail can send full e-mails from CLI; most systems feature both preinstalled.
Example with 'mailx':
echo "This is the message body and contains the message" | mailx -v \
-r "someone#example.com" \
-s "This is the subject" \
-S smtp="mail.example.com:587" \
-S smtp-use-starttls \
-S smtp-auth=login \
-S smtp-auth-user="someone#example.com" \
-S smtp-auth-password="abc123" \
-S ssl-verify=ignore \
yourfriend#gmail.com

Related

Preventing expansion/evaluation of parameter in ssh command

I have a shell script that runs a docker container on a remote server.
I'm trying to send the hostname of the remote server into the container but i just get the hostname of my local computer where i run the script.
The command looks like this in the script:
ssh $remote "docker run -h '`hostname`' \
-e 'VARIABLE=$SCRIPT_VAR' \
-e 'HOST_HOSTNAME=`hostname`' \
..."
Both hostname and the environment variable host.hostname becomes the name of my local computer.
I know I can use singlequotes like this:
ssh $remote 'echo "`hostname`"'
and it will work. But then i cannot use scriptvariables like the $SCRIPT_VAR
How can i get it to evaluate on the remote server instead while also being able to use variables?
You still need to ensure that the expansion of $SCRIPT_VAR is quoted to prevent it from being subjected to word splitting or pathname expansion.
ssh $remote 'docker run -h "$(hostname)" \
-e "VARIABLE='"$SCRIPT_VAR"'" \
-e "HOST_HOSTNAME=$(hostname)" \
...'

Error output with cron emails via msmtp 0x004e#012

Usually I install msmtp as the local mailer, setup is much easier than postfix/others and it's quite capable.
With this content in /etc/msmtprc
defaults
tls_trust_file /etc/ssl/certs/ca-bundle.crt
account default
host smtp.gmail.com
port 587
tls on
auth on
user redacted#example.com
password password
from redacted#example.com
logfile /var/log/msmtp.log
aliases /etc/aliases
I am having the error:
CROND[1587]: (ec2-user) MAIL (mailed 580 bytes of output but got status 0x004e#012)
For all the cron that should send email for ec2-user
Sending with mailx works fine:
echo "TEX" | mailx -s "TEST" redacted#example.com
Any tips on debugging this issue? I can't find much information about the status code I'm getting
Answering myself, I found a way to trigger the error on a verbose way, basically you have to send a mail using sendmail:
echo "From: root \
To: ec2-user \
Subject: Hello World \
\
This is the email body" | sudo sendmail -d -t ec2-user
On the error message I'm getting there the error explanation:
sendmail: /etc/aliases: line 11: invalid address 'postmaster'
Because there where some entries created on the /etc/aliases file (probably they where already there in the ec2 image) with an structure like this:
mailer-daemon: postmaster
Since postmaster does not have any meaning for msmtp, it's throwing the error. After commenting out this lines (#) the mail is being sent normally

run yum command and email results... all in a cron bash shell job

I am cobbling my first Linux shell command. This command runs a yum command and email results in a periodic cron bash shell job. I am OK up to the email part where I get a "No such file or dir" error on email address(!). Can someone unravel syntax and provide method that works. Can be other shell scripting language if bash is not best for this. Seem to be having trouble with multiple line commands.
#!/bin/bash
body="Some Text"
## output yum command to a work file
echo $body > /home/security_check.txt
yum --security check-update >> /home/security_check.txt
## this works!
## mail -s 'Linux Security patches required' bob#example.com < /home/security_check.txt
## this does not
mail \
-a "From: root#example.com" \
-a "MIME-Version: 1.0" \
-a "Content-Type: text/html" \
-s "Linux Security patches required" \
bob#example.com \
< /home/security_check.txt
## error message:
## From: root#example.com: No such file or directory
Take a look at this post on sending HTML email with Unix mail.
https://unix.stackexchange.com/questions/15405/how-do-i-send-html-email-using-linux-mail-command
Seems that your need for the -a flag is to send HTML mail.
Here is solution that worked for me. Requires the mailx, yum and yum-plugin-security modules. It seems that mailx behaves differently on different distributions. Comments welcome
#!/bin/bash
## script name: yum_security_patch_report.sh
## description: emails list of security patches, saved in /etc/cron.monthly so it will be sent monthly
## generate yum security report
yum --security check-update > /home/security_check.txt
## get server hostname
HOSTNAME=echo hostname
## compose subject
SUBJECT="List of Linux security patches required - for server $HOSTNAME"
## set up TO and CC
TO="bob#example.com"
CC="sue#example.com"
## get report summary from file saved, uses $(code) notation to catch as variable
SUMMARY=$(grep 'needed for security' /home/yum_security_check.txt)
RUNFROM=($"$0")
## compose body of email
MAILBODY="Find enclosed report of Linux modules that require security patches.
$SUMMARY
This report comes from server: $HOSTNAME. This script is being run from: $RUNFROM"
## send email with mailx command
echo "$MAILBODY" | mailx -v -s "$SUBJECT" -c "$CC" -a /home/security_check.txt "$TO"

virtualbox + perl + shared folder == fail

This is a convoluted one so bear with me. I have a Perl script that is located on a Windows VirtualBox guest. I want to call this script from the Linux host and have it read a shared folder from the host. The reading of the folder fails.
On the host I call this script and it gives me the following output:
host:~/$ ./script.pl /nfs/nasi/temp
[2014-04-02 10:50:55] Uploading file records to localhost
[2014-04-02 10:50:55] Running VirtualBox for Kaspersky
fatal: opendir(E:\nasi\temp) failed: No such file or directory
[2014-04-02 10:50:56] Uploading malware samples data to localhost
host:$
The script converts the argument /nfs/nasi/temp to E:\nasi\temp and calls the script using the following command:
/usr/bin/VBoxManage guestcontrol <guest> execute \
--image "C:\strawberry\perl\bin \perl.exe" \
--username <user> --password <pass> \
--wait-stdout --wait-stderr --wait-exit -- \
"C:\antivirus\kaspersky.pl" "E:\nasi\temp"
When I run this same script using the same option from the guest directly however I get the following:
C:\antivirus>C:\strawberry\perl\bin\perl.exe C:\antivirus\kaspersky.pl E:\nasi\temp
[2014-04-02 10:54:19] Running Kaspersky Antivirus
[2014-04-02 10:54:20] Parsing Kaspersky report
[2014-04-02 10:54:20] Uploading Kaspersky results to 10.0.0.1
C:\antivirus>
But wait, it gets weirder. When instead of providing the shared directory E:\ I instead point it to C:\ it has no problem reading the directory and just happily keeps going. So the error only shows up when I run the command from the host through VirtualBox and point it to the share.
Here is the relevant code:
sub createSamplesMap {
opendir( my $dh, $ARGV[0] ) or
die "fatal: opendir($ARGV[0]) failed: $!\n";
my #files = readdir( $dh );
foreach my $file ( #files ) {
if (! -d $file ) {
...
}
}
closedir($dh);
}
I tried different ways of reading the filenames from the directory but they didn't work. Here's what I tried.
my #files = <$ARGV[0]\\*>;
my #files = glob( $ARGV[0] . '\\*' );
I don't know whether to blame perl or virtualbox. Anyone have any ideas on what the problem might be?
Windows 7, Strawberry Perl v5.18.2
Ubuntu 12.04.04, Perl v5.14.2
VirtualBox 4.2.16r86992
crosspost: https://forums.virtualbox.org/viewtopic.php?f=2&t=61011
I've found the problem. As mentioned on the virtualbox forum there was a problem with the environment variables set when running the perl script. After much googling I also found a blog post from kissmyarch where he describes how he solved the problem.
You can set environment variables using the --environment option in VBoxManage guestcontrol and according to kissmyarch you need to set USERPROFILE to get it to work. This did not work for me.
So instead I used the following code from the script to figure out what environment variables were set:
foreach $key (sort keys(%ENV)) {
print "$key = $ENV{$key}\n";
}
and ran that both on the guest and from guestcontrol to compare the environments. My command now looks like this:
/usr/bin/VBoxManage guestcontrol <vm> execute \
--image "C:\strawberry\perl\bin\perl.exe" \
--username <user> --password <pass> \
--environment "USERPROFILE=C:\Users\<user>" \
--environment "APPDATA=C:\Users\<user>\AppData\Roaming" \
--environment "LOCALAPPDATA=C:\Users\<user>\AppData\Local" \
--environment "HOMEDRIVE=C:" \
--environment "HOMEPATH=\Users\<user>" \
--environment "LOGONSERVER=\\\<server>" \
--environment "SESSIONNAME=Console" \
--environment "TEMP=C:\Users\<user>\AppData\Local\Temp" \
--environment "TMP=C:\Users\<user>\AppData\Local\Temp" \
--environment "USERDOMAIN=<domain>" \
--environment "USERNAME=<user>" \
--wait-stdout --wait-stderr --wait-exit \
-- "C:\antivirus\kaspersky.pl" "E:\nasi\temp"
Somewhere in that big pile of environment variables is one that is important.
Thanks to all that helped.

Using curl to send email

How can I use the curl command line program to send an email from a gmail account?
I have tried the following:
curl -n --ssl-reqd --mail-from "<sender#gmail.com>" --mail-rcpt "<receiver#server.tld>" --url smtps://smtp.gmail.com:465 -T file.txt
With file.txt being the email's contents, however, when I run this command I get the following error:
curl: (67) Access denied: 530
Is it possible to send an email from an account that is hosted by a personal server, still using curl? Does that make the authentication process easier?
curl --ssl-reqd \
--url 'smtps://smtp.gmail.com:465' \
--user 'username#gmail.com:password' \
--mail-from 'username#gmail.com' \
--mail-rcpt 'john#example.com' \
--upload-file mail.txt
mail.txt file contents:
From: "User Name" <username#gmail.com>
To: "John Smith" <john#example.com>
Subject: This is a test
Hi John,
I’m sending this mail with curl thru my gmail account.
Bye!
Additional info:
I’m using curl version 7.21.6 with SSL support.
You don't need to use the --insecure switch, which prevents curl from performing SSL connection verification. See this online resource for further details.
It’s considered a bad security practice to pass account credentials thru
command line arguments. Use --netrc-file. See the documentation.
You must turn on access for less secure apps or the newer App passwords.
if one wants to send mails as carbon copy or blind carbon copy:
curl --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
--mail-from 'username#gmail.com' --mail-rcpt 'john#example.com' \
--mail-rcpt 'mary#gmail.com' --mail-rcpt 'eli#example.com' \
--upload-file mail.txt --user 'username#gmail.com:password' --insecure
From: "User Name" <username#gmail.com>
To: "John Smith" <john#example.com>
Cc: "Mary Smith" <mary#example.com>
Subject: This is a test
a BCC recipient eli is not specified in the data, just in the RCPT list.
Crate a simple email.conf file like so
Username: hi#example.com
Password: OKbNGRcjiV
POP/IMAP Server: mail.example.com
And simply run sendmail.sh, like so after making it executable (sudo chmod +x sendmail.sh)
./sendmail.sh
Code
#!/bin/bash
ARGS=$(xargs echo $(perl -anle 's/^[^:]+//g && s/:\s+//g && print' email.conf) < /dev/null)
set -- $ARGS "$#";
declare -A email;
email['user']=$1
email['pass']=$2
email['smtp']=$3
email['port']='587';
email['rcpt']='your-email-address#gmail.com';
email_content='From: "The title" <'"${email['user']}"'>
To: "Gmail" <'"${email['rcpt']}"'>
Subject: from '"${email['user']}"' to Gmail
Date: '"$(date)"'
Hi Gmail,
'"${email['user']}"' is sending email to you and it should work.
Regards
';
echo "$email_content" | curl -s \
--url "smtp://${email['smtp']}:${email['port']}" \
--user "${email['user']}:${email['pass']}" \
--mail-from "${email['user']}" \
--mail-rcpt "${email['rcpt']}" \
--upload-file - # email.txt
if [[ $? == 0 ]]; then
echo;
echo 'okay';
else
echo "curl error code $?";
man curl | grep "^ \+$? \+"
fi
more
Mind that the form of mail.txt seems to be important / CRLF for win, LF for Linux, special characters etc.
Finally after struggling 2 hours, it works for me for GMX (they tell their SMPT port to be 587 - and further down in small letters the hint: "also 465 can be used with SSL"):
UNDER Linux (TinyCore Linux on Raspberry 3B+ with curl.tcz installed):
curl --ssl-reqd --url 'smtps://mail.gmx.net:465' --user 'mymail#gmx.at:mymailPassword' --mail-from 'mymail#gmx.at' --mail-rcpt 'mymail#gmx.at' --upload-file mail.txt
UNDER Windows:
curl --ssl-reqd --url "smtps://mail.gmx.net:465" --user "mymail#gmx.at:mymailPassword" --mail-from "mymail#gmx.at" --mail-rcpt "mymail#gmx.at" --upload-file mail_win.txt
with mail.txt:
From: "User Name" <mymail#gmx.at>
To: "John Smith" <mymail#gmx.at>
Subject: This is a test
Hi John,
Im sending this mail with curl thru my gmx account.
Bye!
Note that if Perl's "system()" function is used to execute the curl command, each argument 'word' is a separate item in the argument array, and words must NOT be quoted.
Also note that if sending via Gmail after May 30, 2022, the gmail account must be set up with 2-factor authentication and then you must create an "App Password". The App Password is a long character string that acts as an alternative password and replaces the usual password on the "--user" parameter.

Resources