package SMTP; use IO::Socket::INET; use MIME::Base64; use Digest::MD5 "md5"; sub new { my $self = {}; bless($self); $self->{host} = `hostname`; chomp($self->{host}); $self->{authtype} = 'CRAM-MD5'; return $self; } sub test { return "Package SMTP test"; } sub test2 { $self = $_[0]; return $self->{var}; } sub FromAddress { ($self, $FromAddress) = @_; $self->{FromAddress} = $FromAddress; return $self->{FromAddress}; } sub ToAddress { ($self, $ToAddress) = @_; $self->{ToAddress} = $ToAddress; return $self->{ToAddress}; } sub Subject { ($self, $Subject) = @_; $self->{Subject} = $Subject; return $self->{Subject}; } sub Message { ($self, $Message) = @_; $self->{Message} = $Message; return $self->{Message}; } sub host { ($self, $host) = @_; $self->{host} = $host; return $self->{host}; } sub server { ($self, $server) = @_; $self->{server} = $server; return $self->{server}; } sub username { ($self, $username) = @_; $self->{username} = $username; return $self->{username}; } sub password { ($self, $password) = @_; $self->{password} = $password; return $self->{password}; } sub authtype { ($self, $authtype) = @_; $self->{authtype} = $authtype; return $self->{authtype}; } sub connection { ($self, $server, $username, $password, $authtype) = @_; $self->{server} = $server; $self->{username} = $username; $self->{password} = $password; $self->{authtype} = $authtype if defined($authtype); } sub email { ($self, $from, $to, $subject, $message) = @_; $self->{from} = $from; $self->{to} = $to; $self->{subject} = $subject; $self->{message} = $message; } sub send { ($self) = @_; $user= $self->{username}; $pass = $self->{password}; $from = $self->{from}; $to = $self->{to}; $subject = $self->{subject}; $message = $self->{message}; $mail_server = $self->{server}; $local_server = $self->{host}; $auth_type= $self->{authtype}; $userpassbase64 = encode_base64("\000$user\000$pass"); $self->{sock} = new IO::Socket::INET ( PeerAddr=>$mail_server, PeerPort=>25, Proto=>'tcp', ); $sock = $self->{sock}; die"Socket could not be created.$!\n" unless $sock; $sock->autoflush(1); my $ack = <$sock>; warn "$ack"; my $ehlo="ehlo $local_server"; warn "$ehlo\n"; print $sock "$ehlo\n"; my $msg; $self->wait_for("250 HELP"); warn "auth tpe = $auth_type"; if ($auth_type eq "PLAIN") { my $login = "AUTH PLAIN $userpassbase64"; warn "$login\n"; print $sock "$login"; } elsif($auth_type eq "LOGIN") { my $login = "AUTH LOGIN\n"; warn "$login\n"; print $sock "$login"; $self->wait_for(334); my $base64user = encode_base64($user); warn "$base64user\n"; print $sock "$base64user"; $self->wait_for(334); my $base64pass = encode_base64($pass); warn "$base64pass\n"; print $sock "$base64pass"; } elsif($auth_type eq "CRAM-MD5") { my $login = "AUTH CRAM-MD5\n"; warn "$login\n"; print $sock "$login"; my $msg = $self->wait_for(334); my $ipad=chr(0x36) x 64; my $opad=chr(0x5c) x 64; chomp($msg); $msg=~s/^334 //; my $ts=decode_base64($msg);; my $digest=md5(("$pass" ^ "$opad").md5(("$pass" ^ "$ipad").$ts)); my $response=encode_base64("$user ".unpack("H*", $digest)); $response=~s/[\r\n]//gs; warn "$response"; print $sock "$response\n"; } $self->wait_for("235 Authentication succeeded"); my $mail_from = "mail from: <$from>"; warn "$mail_from\n"; print $sock "$mail_from\n"; $self->wait_for("250 OK"); my $rcpt_to = "rcpt to: <$to>"; warn "$rcpt_to\n"; print $sock "$rcpt_to\n"; $self->wait_for("250 Accepted"); my $data = "DATA"; warn "$data\n"; print $sock "$data\n"; $self->wait_for(354); my $data = "Subject: $subject\nFrom: $from\nTo: $to\n$message\n.\n"; warn "$data\n"; print $sock "$data\n"; $msg = <$sock>; warn "$msg"; close($sock); } sub wait_for { ($self, $FromAddress) = @_; my $msg; warn "waiting for $_[1]"; while ($msg !~ /^$_[1]/) { $msg = <$sock>; warn "$msg"; die "ERROR: Mail not sent" if ($msg =~/^5[0-9]{2}/); } return $msg; } 1;