Sending email in telnet with bash script, unexpected token 'newline' with MAIL FROM:<> - bash

I am trying to send an email using telnet in a bash script, I was able to do this without the bash script but wanted to make it more user friendly. I thought the newline was important for telnet to process information, but it's telling me it's producing an error.
#!/bin/bash
echo 'Enter your email'
read email
echo 'Enter your password'
read password
echo 'Enter who you want to send an email to'
read recipient
echo 'Enter your subject'
read subject
echo 'Enter your message'
read message
newPassword=$(echo -ne $password | base64)
newEmail=$(echo -ne $email | base64)
(
telnet -z ssl smtp.gmail.com 465
echo 'Sleeping: about to run HELO'
sleep 2
HELO hellogoogle
echo 'Sleeping: about to run AUTH'
sleep 2
AUTH LOGIN
echo 'Sleeping: about to enter email'
sleep 2
newEmail
echo 'Sleeping: about to enter password'
sleep 2
newPassword
echo 'Sleeping: about to run FROM'
sleep 2
MAIL FROM:<email>
echo 'Sleeping: about to run TO'
sleep 2
RCPT TO:<recipient>
echo 'Sleeping: about to run DATA'
sleep 2
DATA
echo 'Sleeping: about to enter subject'
sleep 2
Subject: subject
echo 'Sleeping: about to enter message'
sleep 2
message
.
) | telnet
I tried to do this without the parenthesis and it still did not work. Since it takes some time for telnet to open up I added sleep in between each command, along with an output letting me know what is happening.
I am trying to send an email to myself using telnet with a bash script.

You might have better luck using a heredoc which can contain variables. Here's a basic example of sending a command to webserver using netcat:
file='index.html'
cat <<EOT | nc www.example.com 80
GET /$file HTTP/1.0
EOT
I don't have telnet which is why I'm using netcat. There's a new version that supports ssl. The heredoc should also work with telnet.

Related

How to adjust this bash script to run telnet commands successfully while being in SSH?

I am attempting to write a bash script that will do the following work flow:
Telnet into networked device via IP address on port 9100 telnet x.x.x.x 9100
Run SGD command ! U1 getvar \"internal_wired.ip.timeout.value\".
Expect output value of "10".
Here is the bash script I've written so far:
#!/bin/bash
IP=(x.x.x.x)
for i in ${IP}
do
echo " "
echo "Welcome! This script will check the timeout value of this networked device."
echo "The expected output should be `"10`". Let's get started!!"
echo " "
sleep 4
echo "5....."
sleep 1
echo "4...."
sleep 1
echo "3..."
sleep 1
echo "2.."
sleep 1
echo "1."
sleep 1
echo " "
telnet ${i} 9100 << END_SSH
sleep 5
getvar \"internal_wired.ip.timeout.value\"
sleep 5
END_SSH
done
When I run this script via bash mycode.sh, I get the following output in Terminal.app:
$ bash mycode.sh
Welcome! This script will check the timeout value of this networked device.
The expected output should be "10". Let's get started!!
5.....
4....
3...
2..
1.
Trying x.x.x.x...
Connected to x.x.x.x.
Escape character is '^]'.
Connection closed by foreign host.
[user#server ~]$
x.x.x.x is an IP placeholder just to add.
In theory, after the Escape character is '^]'. line, the script should have ran the ! U1 getvar "internal_wired.ip.timeout.value\" command.
Also, we should have had an expected output of "10".
When I first wrote this script, I initially did not have the END_SSH command in it. A colleague introduced that to me and said to wrap the telnet commands in the END_SSH because of how Terminal technically jumps out of SSH when you are in telnet. I've tried utilizing END_SSH, but am not successful.
How do I get the telnet command to run successfully and get the expected output value?
You misunderstand what "END_SSH" is. It's not a "command" - it's what's called "Here-document" in bash.
Essentially the text between the <<END_SSH and the END_SSH is a "here-document" that is piped into stdin of telnet ${i} 9100. So, the sleep 5 commands are never actually executed and the input reaches EOF before the connection is even established.
I don't know what exactly you are trying to accomplish, but I would guess that the following will work better. Oh, and what's with that weird IP=(x.x.x.x) declaration? Is that supposed to be an array?
#!/bin/bash
declare -a IP=(1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4)
for i in "${IP[#]}"; do
echo " "
echo "Welcome! This script will check the timeout value of this networked device."
echo "The expected output should be \"10\". Let's get started!!"
sleep 4
for j in {5..1}; do
echo $j
sleep 1
done
{ sleep 5; echo -n $'! U1 getvar "internal_wired.ip_timeout.value"\n'; sleep 5; } | telnet ${i} 9100
done
so here is what I suggest to use for the telnet part. Connect is a function being called later in a while loop, which will run over IPs ready from a file.
Connect()
{
(
sleep 10 # depending upon your network and device response, better to keep this first sleep value a little high
echo "command 1"
sleep 2
echo "command 2"
sleep 2
) | telnet $1 9100 | tee -a ${1}.log
}
while read -r IP
do
Connect $IP
done < filewithIPs

Expect: how to spawn a command containing a backslash?

I have the following script:
#!/bin/bash
echo -n "Enter user name: "
read USER
echo -n "Enter password: "
read -s PWD
cat $HOME/etc/switches.txt | while read IP SWITCH
do
echo ${SWITCH}
/usr/bin/expect <<EOD
# Change to 1 to Log to STDOUT
log_user 1
# Change to 1 to enable verbose debugging
exp_internal 1
# Set timeout for the script
set timeout 20
spawn ssh -l {$USER} -oCheckHostIP=no -oStrictHostKeyChecking=no -q $IP
match_max [expr 32 * 1024]
expect "Password:"
send $PWD
send "\n"
expect "#"
send "show fcip summary | grep TRNK\n"
EOD
echo
done
When I run it, the backslash in the username disappears, giving these result:
Enter user name: corp\user
Enter password:
=== ss3303-m-esannw-m01a ===
spawn ssh -l corpuser -oCheckHostIP=no -oStrictHostKeyChecking=no -q 10.247.184.70
[...]
I suspect my problem is due in part to embedding my expect script inside a bash script. I've tried using $USER and "$USER" as well, with the same results. Using corp\\\\user (yes, four backslashes!) does work but is inconvenient. I'm seriously considering using sed or something to multiply the backslashes, but would love to hear other ideas.
You might have better luck passing the variables through the environment so expect can access them directly, instead of relying on the shell to substitute the values into the heredoc:
#!/bin/bash
read -p "Enter user name: " USER
read -sp "Enter password: " PWD
export USER PWD IP
while read IP SWITCH
do
echo ${SWITCH}
# the heredoc is single quoted below
/usr/bin/expect <<'EOD'
# Change to 1 to Log to STDOUT
log_user 1
# Change to 1 to enable verbose debugging
exp_internal 1
# Set timeout for the script
set timeout 20
match_max [expr {32 * 1024}]
spawn ssh -l $env(USER) -oCheckHostIP=no -oStrictHostKeyChecking=no -q $env(IP)
expect "Password:"
send -- "$env(PWD)\r"
expect "#"
send "show fcip summary | grep TRNK\r"
expect eof
EOD
echo
done <$HOME/etc/switches.txt
Notes:
the heredoc is single-quoted: the shell will not try to interpolate variables
exported the shell variables used in the expect code
use \r to "press enter" for the send command.
tidied up the input of the username and password
tidied up reading the text file

Check if mail was sent succesfully in bash

I have this bash script that sends to my email the new IP address if it has changed running on a crontab.
SUBJ="My new IP is "
EMAIL="myemail#gmail.com"
ip1=""
ip2=""
read ip1 < ip.txt
ip2=$(wget -qO- ifconfig.me/ip)
if [ "$ip1" = "$ip2" ]
then
exit
else
echo "$ip2" > ip.txt
echo "$ip2" | mail -s "$SUBJ""$ip2" $EMAIL
exit
fi
The problem is that if for any reason the email could not been sent, the ip.text file would still change, and the next time that the script runs "$ip1" = "$ip2" would be true and never send the email.
How can I check if the mail was sent successfully?
I followed this tutorial:
If you just want to ensure that the mail program ran successfully, use
echo "$ip2" | mail -s "$SUBJ $ip2" && echo "$ip2" > ip.txt
If you actually care about the mail being successfully delivered after mail sends it to your local mail transfer agent, there's not much you can do.

BASH catching <&3 into var

Trying to understand how the <&3 redirect can be caught into a var in bash.
When I run the code below it stops at line 9 with the MSG to SEND being printed as if the cat <&3 is being run without catching it in the var myRcvMsg. If I open another shell and nc on the port it continues to printout each line sent (this is what I want, just need to trap it rather than print it)
If I change line to myRcvMsg="$(<&3)" then lines 10,11 execute but no var prints out.
what am I doing wrong?
thx
Art
#!/bin/bash
echo "Starting Script"
exec nc -p 18000 -l &
sleep 1 # wait for port to open
exec 3<>/dev/tcp/192.168.1.1/18000
echo "MSG to SEND" >&3
echo "MSG has been sent"
myRcvMsg="$(cat <&3)"
echo "MSG should have been RCV'd"
echo "This is the RCV msg:${myRcvMsg}"
The execution of nc puts it into listen mode, but it will write its output to stdout instead of echoing it back through the net. See Echo server with bash for ideas how to make it into an echo server.
On my machine I had to use 127.0.0.1 to get a connection.
Next problem is that you have to make sure that your message is not stuck in a buffer. While you wait on the out-end of &3 for nc to echo something, nc may not have actually seen your message. In my test the $(cat <&3) just hangs.
The following kind of works.
#!/bin/bash
set -x
echo "Starting Script"
exec nc -p 18000 -l -c "xargs -n1 echo" &
sleep 1 # wait for port to open
exec 3<>/dev/tcp/127.0.0.1/18000
cat <&3 >ttt &
sleep 1
echo "MSG to SEND" >&3
echo "MSG has been sent"
sleep 1
myRcvMsg=$(cat ttt)
echo "MSG should have been RCV'd"
echo "This is the RCV msg:\"${myRcvMsg}\""
For more information, see http://www.ict.griffith.edu.au/anthony/info/shell/co-processes.hints, where the buffering problem is highlighted in 3/ Buffered Output problem.
Try to read from
myRcvMsg="$(cat /dev/fd/3)"

FTP Connection Confirmation Required in Bash Script

I am using the below code to connect with ftp node. I just want to know that how would I check if I am unable to connect with ftp server or ftp server is not responding. In any case it would alert me ftp server is ok or down. Actually I want to embed the normal bash code for checking of connectivity.
#!/bin/ksh
ftp -nv <<EOF
open xxx.xx.xx.xx
user xxx xxxxxxxxx
bye
EOF
How about grepping the output from ftp? I'm not sure what your version of ftp returns when it's done a successful upload, but something like:
#!/bin/ksh
(
ftp -nv <<EOF
open xxx.xx.xx.xx
user xxx xxxxxxxxx
bye
EOF
) | grep -i "success"
if [[ "$?" -eq "0" ]]
then
echo "FTP SUCCESS"
else
echo "FTP FAIL"
fi
Should work..
I've got the same problem before, solved it with checking the output from the ftp command. Still, found it quite weird, so i decided to use PERL for it.
#!/usr/bin/perl
use strict;
use warnings;
use Net::FTP;
# open connection
my $ftp = Net::FTP->new("127.0.0.1");
if (! $ftp) {
print "connection failed!";
exit 1;
}
# in case you would need to test login too
# if (! $ftp->login("username", "password")) {
# print "login failed!";
# exit 2;
#}
$ftp->close();
exit 0;
Use this command to check whether an ftp-server is available:
sleep 1 | telnet ftp.example.com 21 2> /dev/null | grep -c 'FTP'
What it does:
Establishes a connection to ftp.example.com via port 21 (use port 22 for sftp)
Waits one second and then terminates the connection
Ignores the "Connection closed by remote host"-response from telnet with "2> /dev/null"
Returns "1" if the response from the addressed server contains "FTP" and "0" if it does not.
You might have to adjust the grep pattern 'FTP' if the expected welcome response from the ftp server you want to check differs from the standard response, which usually reads something like this:
Trying 93.184.216.34...
Connected to ftp.example.com.
Escape character is '^]'.
220 FTP Service

Resources