initself has asked for the wisdom of the Perl Monks concerning the following question:
Update: brian_d_foy has created a patch to Net::SMTP that solves my problem. Hopefully it will be applied to CPAN in the next few days. Thanks, brian!
I am attempting to use Email::Stuff to send a secure SMTP email through my GMail account. Here's the code:
#!/usr/bin/perl
use warnings;
use strict;
use Email::Stuff;
my $return = Email::Stuff->to('test@mikebaas.com')
->from('mike@mikebaas.com')
->subject('Test Subject')
->text_body('This is a test.')
->send('SMTP', Host => smtp.gmail.com:465',
ssl => 1,
username => mike@mikebaas.com',
password => 'x',
);
Simple enough, right?
The result I continue to see:
Couldn't connect to smtp.gmail.com:465 at testmail.pl line 15.
As far as I know, I have the parameters for Email::Send::SMTP (which is what Email::Stuff inevitably uses to send this message) correct. Plus, the docs for Email::Send::SMTP are clear that with the right parameters, a secure email can be sent:
Any arguments passed to send will be passed to Net::SMTP->new(), with some exceptions. username and password, if passed, are used to invoke Net::SMTP->auth() for SASL authentication support. ssl, if set to true, turns on SSL support by using Net::SMTP::SSL.
Can anyone see where I might have gone astray?
Re: Using Email::Stuff to send SMTP mail through GMail
by jasonk (Parson) on Sep 19, 2006 at 22:35 UTC
|
'smtp.gmail.com:465' is not a valid hostname. Since Net::SMTP is a subclass of IO::Socket::INET, you probably want Host => 'smtp.gmail.com', PeerPort => 465, instead.
We're not surrounded, we're in a target-rich environment! |
---|
| [reply] [d/l] |
|
->send('SMTP', Host => 'smtp.gmail.com',
PeerPort => 465,
ssl => 1,
username => 'mike@mikebaas.com',
password => 'x',
);
| [reply] [d/l] [select] |
|
my $objst = Email::Stuff
->to('tshinnic@io.com')
->from('tshinnic@gmail.com')
->subject('Test Subject')
->text_body('This is a test.');
# This forces Net::SMTP::SSL to be loaded
$objst->using( 'SMTP', ssl => 1 );
# Which allows us to do this ...
$IO::Socket::SSL::DEBUG = 1;
my $rc = $objst->send('SMTP',
ssl => 1,
Host => 'smtp.gmail.com',
PeerPort => 465,
username => 'tshinnic',
password => 'xxx',
Debug => 1,
);
which finally gets us an actual error message!
CA file certs/my-ca.pem not found, using CA path instead.
IO::Socket::INET configuration failederror:00000000:lib(0):func(0):rea
+son(0)
at C:/Perl587/site/lib/Email/Send/SMTP.pm line 37
which is of very little help to me, anyway...
After taking the same extraordinary measures, what error messages do you see? | [reply] [d/l] [select] |
|
|
|
|
|
Eail::Stuff seems to be something of a wrapper around a whole lot of otehr modules, there's no problemw ith that, so after your last post I thought, well, let's see what Net::SMTP::SSL does with this:
#!/usr/bin/perl
use warnings;
use strict;
use Net::SMTP::SSL;
my $smtp = Net::SMTP::SSL->new(
'smtp.gmail.com',
Port => 465,
Timeout => 30,
Debug => 1,
);
print $@;
produces:
Net::SMTP::SSL: Bad service ''
So I think the problem is deeper again, Net::SMTP::SSL is purely a thing wrapper around Net::SMTP to enable it to use IO::SOCKET::SSL instead of IO::SOCKET::INET.
I don't have time to try more now, but this might give you some more thngs to follow up.
jdtoronto | [reply] [d/l] [select] |
|
|
|
Re: Using Email::Stuff to send SMTP mail through GMail
by initself (Monk) on Sep 30, 2006 at 05:33 UTC
|
brian_d_foy helped me understand that issues with the way all the modules Email::Stuff is using talk to one another make it necessary to pass through LocalHost and LocalPort variables in order to send mail via GMail:
"The problem is the long chain of modules with slightly different interfaces. I haven't narrowed it down, but somebody isn't setting LocalAddr and LocalPort, so when you try to configure things, IO::Socket::configure fails because IO::Socket::_sock_info fails since nothing set those hash entries:"
($laddr,$lport,$proto) = _sock_info($arg->{LocalAddr},
$arg->{LocalPort},
$arg->{Proto})
or return _error($sock, $!, $@);
So my solution ended up looking like this:
#!/usr/bin/perl
use warnings;
use strict;
use Email::Stuff;
my $LocalHost = 'jasmines.mikebaas.org';
my $LocalPort = '2525';
my $RemoteHost = 'smtp.gmail.com';
my $RemotePort = '465';
my $objst = Email::Stuff
->to($ARGV[0])
->from($ARGV[1])
->subject($ARGV[2])
->text_body($ARGV[3])
;
$objst->send(
'SMTP',
ssl => 1,
Host => $RemoteHost,
Port => $RemotePort,
Proto => 'tcp',
username => $ARGV[4],
password => $ARGV[5],
Debug => 1,
LocalAddr => $LocalHost,
LocalPort => $LocalPort,
);
However, I cannot send emails one after the other in serial since the localport 2525 binds to 465 and doesn't let go. As far as I can see, there is no way to send a QUIT via Email::Stuff. If there were, I could create one connection per each email I wish to send via Gmail.
I've also tried sleeping in between each message but because that always seemed to produce random results. So I'm closer but not out of the woods yet. | [reply] [d/l] [select] |
|
Thanks to brian_d_foy, we've got the final solution: a patch to Net::SMTP. Hopefully this will be applied to CPAN in the next few days. Using this patch, you no longer have to declare a LocalPort or LocalAddr. Instead you set 'Reuse => 1'.
$objst->send(
'SMTP',
ssl => 1,
Host => $RemoteHost,
Port => $RemotePort,
Proto => 'tcp',
username => $username,
password => $password,
Debug => 1,
Reuse => 1,
);
Here's the patch:
# Patch to Net::SMTP
BEGIN {
use Net::SMTP;
no warnings 'redefine';
*Net::SMTP::new = sub
{
print "In my Net::SMTP::new...\n";
package Net::SMTP;
use Net::Config;
use Net::Cmd;
my $self = shift;
my $type = ref($self) || $self;
my ($host,%arg);
if (@_ % 2) {
$host = shift ;
%arg = @_;
} else {
%arg = @_;
$host=delete $arg{Host};
}
my $hosts = defined $host ? $host : $NetConfig{smtp_hosts};
my $obj;
my $h;
foreach $h (@{ref($hosts) ? $hosts : [ $hosts ]})
{
$obj = $type->SUPER::new(PeerAddr => ($host = $h),
PeerPort => $arg{Port} || 'smtp(25)',
$arg{LocalAddr} ? ( LocalAddr => $arg{LocalAddr} ) : (
+),
$arg{LocalPort} ? ( LocalPort => $arg{LocalPort} ) : (
+),
Proto => 'tcp',
Timeout => defined $arg{Timeout}
? $arg{Timeout}
: 120
);
last if $obj;
}
return undef
unless defined $obj;
$obj->autoflush(1);
$obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
unless ($obj->response() == CMD_OK)
{
$obj->close();
return undef;
}
${*$obj}{'net_smtp_exact_addr'} = $arg{ExactAddresses}; ${*$obj}{'ne
+t_smtp_host'} = $host;
(${*$obj}{'net_smtp_banner'}) = $obj->message;
(${*$obj}{'net_smtp_domain'}) = $obj->message =~ /\A\s*(\S+)/;
unless($obj->hello($arg{Hello} || ""))
{
$obj->close();
return undef;
}
$obj;
}
}
| [reply] [d/l] [select] |
Re: Using Email::Stuff to send SMTP mail through GMail
by initself (Monk) on Oct 01, 2006 at 02:04 UTC
|
There are limitations to using GMail for Domains for bulk mailing that I'd like everyone to be aware of:
- There is a 500 outbound message limit. You can only send 500 messages before receiving this warnings:
Net::SMTP::SSL=GLOB(0x8619eec)<<< 550 5.4.5 Daily sending quota exceeded. 36sm2931073nza
- I have found that when sending many messages in a row, GMail can get a little stubborn and randomly refuse to accept my credentials. I will be working on a solution that error checks a little more intelligently in the future.
| [reply] [d/l] |
|
|