Since I did not find solution to the problem description here, I decided to use sysread
and syswrite
for dialog with smtp server. Below is my test code:
sub test {
my ($dbh) = @_;
my $server = "smtp.mail.ru";
my $ip = $server;
$ip = inet_aton($ip);
$ip = inet_ntoa($ip);
$ip = &ip2long($ip);
my $port = 465;
my $pid = 0;
my $is_ssl = 1;
my $answer;
my $user = 'my_mail@mail.ru';
my $buff = 8192;
if (&choose_proxy($ip, $port, $dbh, $pid)) {
if (&connect($ip, $port, $is_ssl, $pid, $server)){
data_read($buff);
my $ehlo = "ehlo mydomain.com\n";
data_send($ehlo);
data_read($buff);
my $auth = "auth login\n";
data_send($auth);
data_read($buff);
my $smtpuser = encode_base64($user);
my $smtppassword = encode_base64('password');
data_send($smtpuser);
data_read($buff);
data_send($smtppassword);
data_read($buff);
my $mail = "mail from: <$user>\n";
data_send($mail);
data_read($buff);
my $to = 'my_mail@mail.ru';
$to = "rcpt to: <$to>\n";
data_send($to);
data_read($buff);
my $start = "DATA\n";
syswrite($socket, $start, length($start));
data_read($buff);
my $data = "test message\n";
data_send($data);
my $end .= ".\n";
data_send($end);
data_read($buff);
my $quit = "quit\n";
data_send($quit);
data_read($buff);
return $socket;
}
}
}
sub data_send {
my $data = shift;
if ($debug_smtp) {
print ">> $data";
}
syswrite($socket, $data, length($data));
}
sub data_read {
my $buff = shift;
my $data;
sleep(1);
sysread($socket, $data, $buff);
if ($debug_smtp) {
print "<< $data";
}
}
I had a lot of questions and errors that I can't solve.
At first, sometimes! i get:Use of uninitialized value $data in concatenation (.) or string at ...
after end of data(data_send($end);
).
Secondly, data_send($end)
not working on Gmail, all this code not working on GMX.
Thirdly, code while {sysread($socket, $data, $buff);}
not work, and i use sleep(1)
, its bad.
Finally, i received file with headers and body of message, but syswrite
not work for variable that contains the file content.
I would be grateful for any help, thank you.
Here's my beta code, it works for most popular smtp server.
sub send_message {
my ($dbh, $server, $port, $is_ssl, $user, $pass, $to, $pid) = @_;
my $ip = $server;
$ip = inet_aton($ip);
$ip = inet_ntoa($ip);
$ip = &ip2long($ip);
my @to = @{$to};
if (&choose_proxy($ip, $port, $dbh, $pid)) {
if (&connect($ip, $port, $is_ssl, $pid, $server)){
if (data_read($pid) ne 220) { &debug(3, $pid, $smtp_error) and return (0, $smtp_error) }
greeting($socks_name, $pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
if ( $is_ssl eq 2 ) {
starttls($pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
IO::Socket::SSL->start_SSL($socket, SSL_version => 'SSLv23', SSL_ca_file => SSL_CA_FILE, SSL_verify_mode => SSL_VERIFY_PEER) or &debug(3, $pid, "Cannot start TLS! $@\n") and return 0;
}
auth_login($pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
auth($user, $pass, $pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
mail($user, $pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
to(\@to, $pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
start_data($pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
my $filename = "file_name";
my $dir = "/path/to/dir";
my @is_ok = &read_file_send($dir, $filename, $pid);
my $no_error = $is_ok[0];
my $error_text = $is_ok[1];
if (!$no_error) {
&debug(3, $pid, $error_text);
$is_ok[1] = "System error!";
return (0, $smtp_error);
}
end_data($pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
quit($pid) or &debug(3, $pid, $smtp_error) and return (0, $smtp_error);
close($socket);
print "socket closed\n";
return (1, "");
}
}
}
sub read_file_send {
my ($dir, $filename, $pid) = @_;
my $buffer;
my $buffer_size = 1024*16;
if (-d $dir ) {
open (FILE,"$dir/$filename");
binmode(FILE);
&debug(3, $pid, "Sending data");
while( sysread(FILE, $buffer , $buffer_size) ) {
print $socket $buffer;
usleep(100000);
}
print "....................OK\n";
close (FILE);
return (1, "");
} else {
return (0, my $error = "Couldn't found directory");
}
}
sub greeting {
my ($socks_name, $pid) = @_;
my $greet = "EHLO $socks_name.domain.com\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $greet") }
print $socket $greet;
if (data_read($pid) ne 250) { print $socket "QUIT\r\n" and return }
return 1;
}
sub starttls {
my $pid = shift;
my $tls = "STARTTLS\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $tls") }
print $socket $tls;
if (data_read($pid) ne 220) { print $socket "QUIT\r\n" and return }
return 1;
}
sub auth_login {
my $pid = shift;
my $auth = "AUTH LOGIN\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $auth") }
print $socket $auth;
if (data_read($pid) ne 334) { print $socket "QUIT\r\n" and return }
return 1;
}
sub auth {
my ($user, $pass, $pid) = @_;
$user = encode_base64($user);
$pass = encode_base64($pass);
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $user") }
print $socket $user;
if (data_read($pid) ne 334) { print $socket "QUIT\r\n" and return }
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $pass") }
print $socket $pass;
if (data_read($pid) ne 235) { print $socket "QUIT\r\n" and return }
return 1;
}
sub mail {
my ($mail, $pid) = @_;
$mail = "MAIL FROM:<$mail>\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $mail") }
print $socket $mail;
if (data_read($pid) ne 250) { print $socket "QUIT\r\n" and return }
return 1;
}
sub to {
my ($to, $pid) = @_;
my @to = @{$to};
foreach my $to (@to) {
$to = "RCPT TO:<$to>\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $to") }
print $socket $to;
if (data_read($pid) ne 250) { print $socket "QUIT\r\n" and return }
}
return 1;
}
sub start_data {
my $pid = shift;
my $start = "DATA\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $start") }
print $socket $start;
if (data_read($pid) ne 354) { print $socket "QUIT\r\n" and return }
return 1;
}
sub end_data {
my $pid = shift;
my $end = "\r\n.\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: .\n") }
print $socket $end;
if (data_read($pid) ne 250) { print $socket "QUIT\r\n" and return }
return 1;
}
sub quit {
my $pid = shift;
my $quit = "QUIT\r\n";
if ($debug_smtp eq 1) { &debug(3, $pid, "-->>: $quit") }
print $socket $quit;
if (data_read($pid) ne 221) { return }
return 1;
}
sub data_read {
my $pid = shift;
my ($receive, $code, $reply, $end_time);
my $buffer_size = 1024*16;
my ($index, $end) = 0;
undef $smtp_error;
my $start_time = gettimeofday;
usleep(200000);
do {
sysread($socket, $receive, $buffer_size);
$end_time = gettimeofday;
if ( int($end_time-$start_time) > 10 ) { $end = 1 }
} until ( defined $receive or $end);
if ( defined $receive and length $receive) {
if ($debug_smtp eq 1) {
my @lines = split /^/m, $receive;
foreach my $line (@lines) {
&debug(3, $pid, "<<--: $line");
if ($index eq $#lines) { $code = $line }
$index++;
}
}
$reply = substr($code, 0, 3);
$smtp_error = $receive;
} else {
$smtp_error = "No response from server\n";
$reply = '000';
}
return $reply;
}