Verification of Email Addresses from MX using Bash - bash

I want to verify a batch of email addresses in a file (say .txt) using telnet to mx and declaring recipient then checking response.
I need a script that reads email addresses from a file, takes out host after '#', looks up MX, telnets(or mailcmd, whichever you prefer), does the deed, then outputs result in 2 files (valid and invalid)
YES I have searched before posting and a few answers were close but I am a noob at bash and modifying them to suit my needs was not possible for me.
Please help!
PS: Below is what I found but I don't know how to pass email addresses to it, and also it is fixed with a single MX.
#!/bin/bash
# check for valid usage
if [ x$1 = 'x' ]
then
echo "Usage: $0 <email address>"
exit 1
fi
# grabbing fields
user=`echo $1 | cut -f1 -d\#`
host=`echo $1 | cut -f2 -d\#`
mxhost=`host -t mx $host | cut -f7 -d\ `
len=`echo $mxhost | wc -c`
len=`expr $len - 2`
mxhost=`echo $mxhost | cut -b1 -$len`
# compose email commands
echo -ne "helo test.com\r\n" > mailcmd
echo -ne "mail from: test\#test.com\r\n" >> mailcmd
echo -ne "rcpt to: $1\r\n" >> mailcmd
echo -ne "quit\r\n" >> mailcmd
# check for mail results
mailresult=`cat mailcmd | nc $mxhost 25| grep ^550 | wc -c`
if [ $mailresult -eq 0 ]
then
echo $1 "is valid"
exit 0
else
echo $1 "is not valid"
exit 1
fi
# clean up
rm mailcmd

Related

String comparison from nested for returns always false

The main issue is that i try to parse ls to do a mock "Compare directories" but when i do so since i use nested fors i cant properly compare the results from it since the comparison of two filenames/strings even if they are the same it always returns false
I tried erasing the white characters but no results.
var1=$(ls -l $1 | grep -v ^d | tail -n +2 | tr -s " "| cut -d " " -f 9)
var2=$(ls -l $2 | grep -v ^d | tail -n +2 | tr -s " "| cut -d " " -f 9)
for i in $var1 ; do
i=$(printf "$i" | tr -d '[:space:]')
flag=0
var3=$(ls -l $1 | grep -v ^d | tail -n +2 | tr -s " " | grep $i | cut -d " " -f 5)
for j in $var2 ; do
j=$(printf $j | tr -d '[:space:]')
var4=$(ls -l $2 | grep -v ^d | tail -n +2 | tr -s " " | grep $j | cut -d " " -f 5)
if [ "$i" == "$j" ] ; then
if [ "$var3" != "$var4" ] ; then
flag=1
fi
else
flag=1
fi
done
if [ $flag -eq 1 ] ; then
printf "$i file does not exist on the $2 catalog\n"
printf "It 's size is :$var3 \n"
let Sum=$Sum+$var3
fi
done
This is not a string comparison problem, it's a logic problem.
I wrote you a MCVE that demonstrates the same problem with less code and fewer dependencies:
flag=0
target="hello"
for candidate in "hello" "world"
do
if [ "$target" != "$candidate" ]
then
flag=1
fi
done
if [ "$flag" -eq 1 ]
then
echo "The string was not found"
fi
This prints The string was not found every time, just like your script, even though it's clearly there.
The problem here is that the script requires that ALL files match. It should only require that ANY file matches. The easiest way to fix this is to:
Set flag=1 when a MATCH is found (not a mismatch)
Make flag=1 signify that a match was found (rather than no match was found)
Here's the version which correctly finds the string:
flag=0
target="hello"
for candidate in "hello" "world"
do
if [ "$target" = "$candidate" ]
then
flag=1
fi
done
if [ "$flag" -eq 1 ]
then
echo "The string was found"
else
echo "The string was not found"
fi

if statement function to many argumnets

I've overlooked my program for any mistakes and can't find any. Usually when I run into a mistake with BASH the interpreter is off on where the mistake is. I'm trying to customize this script from SANS InfoSec Using Linux Scripts to Monitor Security. Everything is fine until the part where the check function looks at the different protocols. When I uncomment them I get the error: ./report: line 41: [: too many arguments. Here is the program...
#!/bin/bash
if [ "$(id -u)" != "0" ]; then
echo "Must be root to run this script!"
exit 1
fi
##### CONSTANTS -
report=/home/chron/Desktop/report.log
#router=/home/chron/Desktop/router.log
red=`tput bold;tput setaf 1`
yellow=`tput bold;tput setaf 3`
green=`tput bold;tput setaf 2`
blue=`tput bold;tput setaf 4`
magenta=`tput bold;tput setaf 5`
cyan=`tput bold;tput setaf 6`
white=`tput sgr0`
##### FUNCTIONS -
pingtest() {
ping=`ping -c 3 localhost | tail -2`
loss=`echo $ping | cut -d"," -f3 | cut -d" " -f2`
delay=`echo $ping | cut -d"=" -f2 | cut -d"." -f1`
if [ "$loss" = "100%" ]; then
echo -n $red$1$white is not responding at all | mail -s'REPORT' localhost
echo 'You have mail in /var/mail!'
echo `date` $1 is not responding at all >> $report
elif [ "$loss" != "0%" ]; then
echo $yellow$1$white is responding with some packet loss
else
if [ "$delay" -lt 100 ]; then
echo $green$1$white is responding normally
else
echo $yellow$1$white is responding slow
fi
fi
}
check() {
if [ "$2" != "" -a "$2" $3 ] ; then
echo -n $green$1$white' '
else
echo -n $red$1$white' '
echo `date` $1 was not $3 >> $report
fi
}
##### __MAIN__ -
pingtest localhost # hostname or ip
echo "Server Configuration:"
check hostname `hostname -s` '= localhost'
check domain `hostname -d` '= domain.com'
check ipaddress `hostname -I | cut -d" " -f1` '= 10.10.0.6'
check gateway `netstat -nr | grep ^0.0.0.0 | cut -c17-27` '= 10.10.0.1'
echo
echo "Integrity of Files:"
check hostsfile `md5sum /etc/hosts | grep 7c5c6678160fc706533dc46b95f06675 | wc -l` '= 1'
check passwd `md5sum /etc/passwd | grep adf5a9f5a9a70759aef4332cf2382944 | wc -l` '= 1'
#/etc/inetd.conf is missing...
echo
#echo "Integrity of Website:"
#check www/index.html `lynx -reload -dump http://<LOCALIP> 2>&1 | md5sum | cut -d" " -f1 '=<MD5SUM>'
#echo
echo "Incoming attempts:"
#lynx -auth user:password -dump http://10.10.0.1 >> $router 2>&1
check telnet `grep \ 23$ $PWD/router.log | wc -l` '= 0'
check ftp `grep \ 21$ $PWD/router.log | wc -l` '= 0'
check ssh `grep \ 22$ $PWD/router.log | wc -l` '=0'
check smtp `grep \ 25$ $PWD/router.log | wc -l` '=0'
check dns `grep \ 53$ $PWD/router.log | wc -l` '=0'
echo
Some of the lines are commented out for later tweaking. Right now my problem is with the protocols. Not sure what's wrong because it looks like to me there are 3 arguments for the function.
In your last three calls to check, you are missing the required space between the operator and the operand.
check ssh `grep \ 22$ $PWD/router.log | wc -l` '=0'
check smtp `grep \ 25$ $PWD/router.log | wc -l` '=0'
check dns `grep \ 53$ $PWD/router.log | wc -l` '=0'
The final argument to all of these should be '= 0'.
However, this is not a good way to structure your code. If you really need to parameterize the comparison fully (all your calls use = as the operation), pass the operator as a separate argument. Further, written correctly, there is no need to pre-check that $2 is a non-empty string.
check() {
if [ "$2" "$3" "$4" ] ; then
printf '%s%s%s ' "$green" "$1" "$white"
else
printf '%s%s%s ' "$red" "$1" "$white"
printf '%s %s was not %s\n' "$(date)" "$1" "$3" >> "$report"
fi
}
Then your calls to check should look like
check hostname "$(hostname -s)" = localhost
check domain "$(hostname -d)" = domain.com
check ipaddress "$(hostname -I | cut -d" " -f1)" = 10.10.0.6
check gateway "$(netstat -nr | grep ^0.0.0.0 | cut -c17-27)" = 10.10.0.1
etc
Run your code through http://shellcheck.net; there are a lot of things you can correct.
Here is my other problem. I changed it up a bit just to see what's going on.
router=/home/chron/Desktop/router.log
check() {
if [ "$2" "$3" "$4" ]; then
printf "%s%s%s" "$green" "$1" "$white"
else
printf "%s%s%s" "$red" "$1" "$white"
printf "%s %s was not %s\n" "$(date)" "$1" $3" >> report.log
fi
check gateway "$(route | grep 10.10.0.1 | cut -c17-27)" = 10.10.0.1
check telnet "$(grep -c \ 23$ $router)" = 0
check ftp "$(grep -c \ 21$ $router)" = 0
check ssh "$(grep -c \ 22$ $router)" = 0
check smtp "$(grep -c \ 25$ $router)" = 0
check dns "$(grep -c \ 53$ $router)" = 0

Bash Syntax error in conditional expression

I'm trying to make a simple bash script that will iterate through a text file containing IP addresses,
ping them one time, and see if they are alive or not.
This is my work so far:
#!/bin/bash
for ip in $(cat ips.txt); do
if [[ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)"]]
echo $ip
fi
done
Any Suggestions?
Thanks!
This seems to work:
#!/bin/bash
for ip in $(cat ips.txt); do
if [ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)" ]; then
echo $ip
fi
done
You needed the ; then after the if [ ... ] statement (same thing goes for elif, not else), and a space between the last bracket of the statement and the statement's contents. Also this appears to work fine with just single brackets, and this may be more portable (see here).
Works on Bash 4.2.47
Yes. You can use a newline instead of ; if you like, but you always need the then keyword.
if [ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)" ]
then echo $ip
fi
# or
if [ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)" ]
then
echo $ip
fi

Remove one directory component from path (string manipulation)

I'm looking for the easiest and most readable way to remove a field from a path. So for example, I have /this/is/my/complicated/path/here, and I would like to remove the 5th field ("/complicated") from the string, using bash commands, so that it becomes /this/is/my/path.
I could do this with
echo "/this/is/my/complicated/path/here" | cut -d/ -f-4
echo "/"
echo "/this/is/my/complicated/path/here" | cut -d/ -f6-
but I would like this done in just one easy command, something that would like
echo "/this/is/my/complicated/path" | tee >(cut -d/ -f-4) >(cut -d/ -f6-)
except that this doesn't work.
With cut, you can specify a comma separated list of fields to print:
$ echo "/this/is/my/complicated/path/here" | cut -d/ -f-4,6-
/this/is/my/path/here
So, it's not really necessary to use two commands.
How about using sed?
$ echo "/this/is/my/complicated/path/here" | sed -e "s%complicated/%%"
/this/is/my/path/here
This removes the 5th path element
echo "/this/is/my/complicated/path/here" |
perl -F/ -lane 'splice #F,4,1; print join("/", #F)'
just bash
IFS=/ read -a dirs <<< "/this/is/my/complicated/path/here"
newpath=$(IFS=/; echo "${dirs[*]:0:4} ${dirs[*]:5}")
Anything wrong with a bash script?
#!/bin/bash
if [ -z "$1" ]; then
us=$(echo $0 | sed "s/^\.\///") # Get rid of a starting ./
echo " "Usage: $us StringToParse [delimiterChar] [start] [end]
echo StringToParse: string to remove something from. Required
echo delimiterChar: Character to mark the columns "(default '/')"
echo " "start: starting column to cut "(default 5)"
echo " "end: last column to cut "(default 5)"
exit
fi
# Parse the parameters
theString=$1
if [ -z "$2" ]; then
delim=/
start=4
end=6
else
delim=$2
if [ -z "$3" ]; then
start=4
end=6
else
start=`expr $3 - 1`
if [ -z "$4" ]; then
end=6
else
end=`expr $4 + 1`
fi
fi
fi
result=`echo $theString | cut -d$delim -f-$start`
result=$result$delim
final=`echo $theString | cut -d$delim -f$end-`
result=$result$final
echo $result

bash script and greping with command line

new to bash scripting so just wondering if i am doing this code right at all. im trying to search /etc/passwd and then grep and print users.
usage ()
{
echo "usage: ./file.sk user"
}
# test if we have two arguments on the command line
if [ $# != 1 ]
then
usage
exit
fi
if [[ $# < 0 ]];then
usage
exit
fi
# Search for user
fullname=`grep $1 /etc/passwd | cut -f 5 -d :`
firstname=`grep $1 /etc/passwd | cut -f 5 -d : | cut -f 1 -d " "`
#check if there. if name is founf: print msg and line entry
not sure as how to this or if im doing this right...
am i doing this right?
grep $1 /etc/passwd | while IFS=: read -r username passwd uid gid info home shell
do
echo $username: $info
done
This might work for you:
fullname=$(awk -F: '/'$1'/{print $5}' /etc/passwd)
firstname=${fullname/ *}
You're on the right track.
But I think the 2nd if [[ $# < 0 ]] .... fi block doesn't get you much. Your first test case gets the situation right, 'This script requires 1 argument or quits'.
Also, I don't see what you need firstname for, so a basic test is
case "${fullname:--1}" in
-[1] ) printf "No userID found for input=$1\n" ; exit 1 ;;
* )
# assume it is OK
# do what every you want after this case block
;;
esac
You can of course, duplicate this using "${firstname}" if you really need the check.
OR as an equivalent if ... fi is
if [[ "${fullname}" == "" ]] ; then
printf "No userID found for input=$1\n" ; exit 1
fi
note to be more efficient, you can parse ${fullname} to get firstname without all the calls to grep etc, i.e.
firstname=${fullname%% *}
Let me know if you need for me to explain :--1} and %% *} variable modifiers.
I hope this helps.
Instead of this:
fullname=`grep $1 /etc/passwd | cut -f 5 -d :`
firstname=`grep $1 /etc/passwd | cut -f 5 -d : | cut -f 1 -d " "`
Try this:
fullname=$(cut -f5 -d: /etc/passwd | grep "$1")
if [[ $? -ne 0 ]]; then
# not found, do something
fi
firstname=${fullname%% *} # remove the space and everything after
Note that I changed my answer to cut before grep so that it doesn't get false positives if some other field matches the full name you are searching for.
You can simply by reading your input to an array and then printing out your desired fields, something like this -
grep $1 /etc/passwd | while IFS=: read -a arry; do
echo ${arry[0]}:${arry[4]};
done
Test:
jaypal:~/Temp] echo "root:*:0:0:System Administrator:/var/root:/bin/sh" |
while IFS=: read -a arry; do
echo ${arry[0]}:${arry[4]};
done
root:System Administrator

Resources