We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › for loop doesn't loop in 'mail pre_auth script'
Page Index Toggle Pages: 1
for loop doesn't loop in 'mail pre_auth script' (Read 1289 times)
for loop doesn't loop in 'mail pre_auth script'
Dec 18th, 2009, 2:41am
 
hello,

i'm new to the forum - and quite new to processing.
i'm working my way through tom igoe's 'making things talk' book.
right now i'm at the 'networked cat' project.

in the book, when the cat get's on the mat, processing starts a http GET request, and a php script sends out a mail using mail().

my provider requires to 'pre auth' before sending a mail, which isn't supported by mail(). i could install PEAR which would provide a function supporting 'pre auth' - but 1st, this looks complex as i'm new to php, too, and 2nd, i want to find a solution using processing.

i am able to send a message via terminal and telnet, using pre auth. this communication i want to replicate using processing.

tom provides a script for the http GET request ( makingthingstalk.com/chapter3/44/#more-44 )  which i modified for my script.


i use a 'for loop' for sending out the commands for the mail server. after every command i want to wait for the answer to send the next one.

but, it always send out only the first command 'EHLO server4'

in the script below i replaced my personal data, such as username, and password, but you should be able to replicate the 'bug' by just copy and paste the script into processing.

Code:

/*

project: send mail preauth script

HTTP sender

language: processing

uses the processing net library to send a mail

*/

import processing.net.*; // gives you access to the net library

Client client; // a new net client
boolean requestInProgress; // whether a net requet is in progress
String responseString = ""; // string of test received by client
// boolean mailSent;
String hello = "EHLO server4";
String auth = "AUTH LOGIN";
String user = "username";  // username encrypted in base64
String pass = "password=";  // password encrypted in base64
String from = "mail from: me@example.com";  // sender email address
String to = "rcpt to: someoneelse@example.com";  // recipient email address
String data = "data";
String subject = "mail subject";
String message= "mail message";
String content = "subject: " + subject + "\n" + message + "\r\n.\r\n";
String quit = "quit";

String conversation[] = {hello, auth, user, pass, from, to, data, content, quit};


// - - - - V O I D   S E T U P - - - -

void setup() {
 // check if array is assembled as wanted
 for (int i = 0; i < 9; i++) {
   println("test: " + conversation[i]);
 }

 // later the applet should stop after mail is sent
 //mailSent = false;

 //open a connection to the host:
 client = new Client(this, "server4.domaincamp.de", 25);
 requestInProgress = true;
}



// - - - - V O I D   D R A W - - - -

void draw() {

 // if (mailSent == false) {
 waitForResponse1();


 for (int i = 0; i < 9; i++) {
   if (requestInProgress == false) {
     println(conversation[i]);
     client.write(conversation[i] + "\r\n");

     // note that you've got a request in progress:
     requestInProgress = true;
     waitForResponse2();
   }
 }
}

// - - - - O T HE R   V O I D S - - - -

void waitForResponse1 () {
 //  println(mailSent + " before");
 //available() returns how many bytes have been received by the client:
 while (client.available() > 0) {

   // read a byte, convert it to a character and add it to the string:
   responseString += char(client.read());

   // add to a line of |'s on the screen (crude progress bar):
   print("|");
   // println(responseString);
 }

 // if there's no byte available, either the response hasn't started yet,
 // or it's done:
 if (client.available() == 0) {

   // if responseString is longer thAn 0 bytes, the response has started:
   if (responseString.length() > 0) {

     // you've got some bytes, but now ther's no more to read. stop:
     if (requestInProgress == true) {

       // print the response:
       println("\n"+ responseString);

       // note that the request is over:
       requestInProgress = false;

       // reset the string for future requests:
       responseString = "";

       println("end of waitForResponse_1");
       // println("mailSent_1 == " + mailSent);
       println("requestInProgress_1 == " + requestInProgress);
     }
   }
 }
}

void waitForResponse2 () {
 //  println(mailSent + " before");
 //available() returns how many bytes have been received by the client:
 while (client.available() > 0) {

   // read a byte, convert it to a character and add it to the string:
   responseString += char(client.read());

   // add to a line of |'s on the screen (crude progress bar):
   print("|");
   // println(responseString);
 }
 // if there's no byte available, either the response hasn't started yet,
 // or it's done:
 if (client.available() == 0) {

   // if responseString is longer thAn 0 bytes, the response has started:
   if (responseString.length() > 0) {

     // you've got some bytes, but now ther's no more to read. stop:
     if (requestInProgress == true) {

       // print the response:
       println("\n"+ responseString);

       // note that the request is over:
       requestInProgress = false;

       // reset the string for future requests:
       responseString = "";

       println("end of waitForResponse_2");
       //  println("mailSent_2 == " + mailSent);
       println("requestInProgress_2 == " + requestInProgress);
     }
   }
 }
}


i duplicated 'waitForResponse()' to see that only the first on, 'waitForResponse1(), is called.
i tried to change 'if()-else()' against 'while()-if()', but that doesn't make a difference.

i may should use 'return()' for the 'for loop' to wait for, but i don't know if this would be really a better approach.

any help?
many thanks,
kai
Re: for loop doesn't loop in 'mail pre_auth script'
Reply #1 - Dec 18th, 2009, 3:47pm
 
I haven't run this code, but by looking at it, it appears as though it will never set requestInProgress to False if you received a zero byte response from the server. As a result it will not send any more "conversation"s. This situation will occur if client.available() returns 0 and responseString is empty.

I'm not familiar with that API but it doesn't look like you sent it a command at all, just opened the connection to the server.

BTW The if (client.available() == 0) check is at least redundant, or produces divergent behavior. Again I don't know this API but if client.available is synchronous then you know .available() returns 0 because that was the sole terminating condition from the while loop above.
Re: for loop doesn't loop in 'mail pre_auth script'
Reply #2 - Dec 18th, 2009, 5:34pm
 
hi lollypop,
thanks for your reply.

actually the 'conversation' starts over and over again.

that's what processing prints, when you run the script:
Code:

test: EHLO server4
test: AUTH LOGIN
test: username
test: password=
test: mail from: me@example.com
test: rcpt to: someoneelse@example.com
test: data
test: subject: mail subject
mail message
.

test: quit
||||||||||||||||||||||||||||||||||||||||||||||||||||||
220 server4.domaincamp.de ESMTP Postfix (Debian/GNU)

end of waitForResponse_1
requestInProgress_1 == false
EHLO server4
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
250-server4.domaincamp.de
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

end of waitForResponse_1
requestInProgress_1 == false
EHLO server4
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
250-server4.domaincamp.de
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

end of waitForResponse_1
requestInProgress_1 == false
EHLO server4

...and so on...


it sends the 1st command 'EHLO server4', waits for the answer until the server stops sending any byte, but then repeats sending the 1st command, never the 2nd, 'PRE AUTH'.
__
the if (client.available() == 0) may be redundant.

i changed

if (client.available() > 0) {...
...} else {...

to

while (client.available() > 0) {...
... }
if (client.available() == 0) {...

just to see if this may help.

any more ideas?

Re: for loop doesn't loop in 'mail pre_auth script'
Reply #3 - Dec 22nd, 2009, 8:39am
 
hi,

apologies for the delay, i was away from the internet! okay, so i don't have processing installed on this computer so I can't investigate your code closely, but it's clear from the logging output that the inner-most conditions of waitForResponse2 is never called. For this to occur, you would either have to momentarily get zero bytes back from the server, or the total response from the server would be zero bytes long. As a result requestInProgress will never be set back to False.

I believe what may be happening is that client.available() temporarily returns 0 (because the server hasn't sent anything), which causes the while loop to exit. However immediately after the server has data available so client.available() returns a value > 0. This means the if predicate is False and the code inside does not execute.

I suggest modifying the draw for loop a little, and see what the output is:

Code:

for (int i = 0; i < 9; i++) {
   if (requestInProgress == false) {
     // keep as before...
   }
   else {
     println("skipping " + i);
   }
}


and then also the wait functions as well:

Code:

 while (client.available() > 0) {
   // keep as before
 }

 if (client.available() > 0) {
   // keep as before
 } else {
   println('received additional bytes');
 }


This will help identify which situation is occurring.
Page Index Toggle Pages: 1