views:

139

answers:

5

I have Ubuntu Linux. I found one command will let me download unread message subjects from Gmail:

curl -u USERNAME:PASSWORD --silent "https://mail.google.com/mail/feed/atom" | tr -d '\n' | awk -F '<entry>' '{for (i=2; i<=NF; i++) {print $i}}' | sed -n "s/<title>\(.*\)<\/title.*name>\(.*\)<\/name>.*/\2 - \1/p"

...and then another command to let me send mail easily (once I installed the sendemail command via apt-get):

sendEmail -f [email protected] -v -t [email protected] -u Gmail Notifier -m test -s MAILSERVER:PORT -xu [email protected] -xp PASSWORD

(Note when in production I'll probably swap -v above with -q.)

So, if one command downloads one line subjects, how can I pipe these into the sendEmail command?

For instance, I tried using a pipe character between the two, where I used "$1" after the -m parameter, but what happened was that when I had no unread emails it would still send me at least one empty message.

If you help me with this, I'll use this information to share on StackOverflow how to build a Gmail Notifier that one can hook up to SMS messages on their phone.

A: 

I'd look at the xargs command, which provides all the features you need (as far as I can tell).

http://unixhelp.ed.ac.uk/CGI/man-cgi?xargs

pavpanchekha
On xargs, if I have just an empty line, it's firing the command through a pipe from xargs into the sendEmail command. But when I don't pipe and instead fire the command within xargs, I get a syntax error on xargs because it doesn't know how to send all the parameters to the sendEmail command. So I tried setting that command with $(command) (or also `command`) but both did not work -- syntax error.
Volomike
The above comment post did not work out. The word "command" with grey background above was actually a statement in backticks, which is the same as $(command).
Volomike
You probably want sed/awk/perl/other to catch invalid lines of input, say to kill off empty lines.
pavpanchekha
Yeah, I'm able to get it to work now by editing the Perl script for sendEmail (apt-get install sendemail) and telling the script to quit if $message is empty after a trim. (BTW, to my shock I learned that Perl doesn't have trim() like PHP and had to do it the hard way.) However, oddly now when I put into /etc/crontab, the thing isn't running and I don't yet know why.
Volomike
Perl has chop/chomp commands to trim; but they are slightly differemtn from PHP or python trim/strip commands.
terson
A: 

Maybe something like this:

curl_command > some_file
if [[ `wc -l some_file` != "0 some_file" ]] ; then
  email_command < some_file
fi
viraptor
+1  A: 

Try this structure:

while read line
do
    sendemailcommand ... -m $line ...
done < <(curlcommand)
Dennis Williamson
This would work only if `curlcommand` were a file.
Tim
Sorry, I'll make it more explicit.
Dennis Williamson
+1  A: 

You do know you can do that directly in gmail by using a filter and your SMS email gateway, right?

But back to the question...

You can get control in a shell script for command output with the following design pattern:

command1 | while read a b c restofline; do
    : execute commands here
    : command2
done

Read puts the first word in a, the second in b, and the rest of the line in restofline. If the loop consists of only a single command, the xargs program will probably just do what you want. Read in particular about the -I parameter which allows you to place the substituted argument anywhere in the command.

Sometimes the loop looks like ... | while read x; do, which puts the entire line into x.

DigitalRoss
Yeah, but it sends the entire message and I have no way in Gmail to limit that. All I care about are message subjects.Tried using for and while loop techniques, but the problem is that any line break is considered data and is thus firing the command even if there's nothing on that line.
Volomike
+1  A: 

I think if you mix viraptor & DigitalRoss' answers you get what you want. I created a sample test by creating a fake file with the following input:

File contents:

foo

bar

baz

Then I ran this command:

% cat ~/tmp/baz | while read x; do if [[ $x != "" ]]; then echo "x: '$x'"; fi; done

This will only print lines with input out. I'm not familiar with sendEmail; does it need the body to be on stdin or can you pass it on the cmdline?

terson