Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lib/Email/Sender/Transport/SMTP.pm
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ The following attributes may be passed to the constructor:

=over 4

=item C<host>: the name of the host to connect to; defaults to C<localhost>
=item C<host>: the DNS name, IPv4 or IPv6 address of the host to connect to;
defaults to C<localhost>. Do not include a port number. Use the C<port>
option instead.

=item C<ssl>: if 'starttls', use STARTTLS; if 'ssl' (or 1), connect securely;
otherwise, no security
Expand All @@ -45,8 +47,10 @@ IO::Socket::SSL

sub BUILD {
my ($self) = @_;
Carp::croak("do not pass port number to SMTP transport in host, use port parameter")
if $self->host =~ /:/;
Carp::croak("Do not pass port number to SMTP transport in host, use port parameter")
if $self->host =~ /^\d+\.\d+\.\d+\.\d+:/ # IPv4 address
or $self->host =~ /^\[[\w:]{3,}\]:/ # IPv6 address
or $self->host =~ /^[\w\.]{3,}:/; # DNS name
}

has host => (is => 'ro', isa => Str, default => sub { 'localhost' });
Expand Down
45 changes: 44 additions & 1 deletion t/smtp-via-mock.t
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use strict;
use warnings;
use Test::More;
use Test::Exception;

BEGIN {
plan skip_all => 'Test::MockObject required to test SMTP transport by mocking'
Expand Down Expand Up @@ -32,7 +33,7 @@ BEGIN {
$mock_smtp->{failaddr}{'permfail@example.net'} = [ 519 => 'Permanent STHU' ];
}

plan tests => 95;
plan tests => 96;

use Email::Sender::Transport::SMTP;
use Email::Sender::Transport::SMTP::Persistent;
Expand Down Expand Up @@ -368,3 +369,45 @@ subtest "quoteaddr" => sub {
is($q->(qq{$local\@example.com}), $want, "correct behavior for $local");
}
};

subtest "portinaddr" => sub {
my @lives_tests = (
'1.1.1.1', 'IPv4 address',
'1::', 'IPv6 address 1 groups',
'1::8', 'IPv6 address 2 groups',
'1::ae:8', 'IPv6 address 3 groups',
'1::f45a:7:8', 'IPv6 address 4 groups',
'1::5:bd23:7:8', 'IPv6 address 5 groups',
'1::26fa:5:6:7:8', 'IPv6 address 6 groups',
'1::3:4:5:66ff:7:8', 'IPv6 address 7 groups',
'1:2:3:4:098a:6:7:8', 'IPv6 address 8 groups',
'server', 'Unqualified DNS name',
'corp.com', 'DNS zone',
'server.corp.com', 'Fully-qualified DNS name',
);
my @dies_tests = (
'1.1.1.1:125', 'IPv4 address with port',
'[::1]:125', 'IPv6 address shortest form with port',
'[1::]:125', 'IPv6 address 1 groups]:125',
'[1::8]:125', 'IPv6 address 2 groups]:125',
'[1::ae:8]:125', 'IPv6 address 3 groups]:125',
'[1::f45a:7:8]:125', 'IPv6 address 4 groups]:125',
'[1::5:bd23:7:8]:125', 'IPv6 address 5 groups]:125',
'[1::26fa:5:6:7:8]:125', 'IPv6 address 6 groups]:125',
'[1::3:4:5:66ff:7:8]:125', 'IPv6 address 7 groups]:125',
'[1:2:3:4:098a:6:7:8]:125', 'IPv6 address 8 groups]:125',
'server:125', 'Unqualified DNS name with port',
'corp.com:125', 'DNS zone with port',
'server.corp.com:125', 'Fully-qualified DNS name with port',
);

plan tests => (scalar(@lives_tests) + scalar(@dies_tests))/2;

while (my ($host, $test_name) = splice @lives_tests, 0, 2) {
lives_ok(sub {Email::Sender::Transport::SMTP->new({ host => $host })}, $test_name);
}

while (my ($host, $test_name) = splice @dies_tests, 0, 2) {
dies_ok(sub {Email::Sender::Transport::SMTP->new({ host => $host })}, $test_name);
}
};