Note: my patched version of 3.024 is now available as MIME::Lite 3.025 on CPAN, thanks Ricardo!
If you use SMTP to send email using MIME::Lite from your Perl program and use not the default SMTP port 25 but specify one as follows:
$msg->send('smtp','some.host', Port => 12345 );
the Port
setting is ignored if you're
using MIME::Lite version between 3.01_04 - 3.024
(inclusive). The culprit is not Net::SMTP which
checks the value of the Port
argument, and if true copies this value to
PeerPort
otherwise sets
PeerPort
to 'smtp(25)', but
MIME::Lite which copies argument name-value pairs
only if the argument name is in a list, a list
which misses Port
. This results in
the following error if port 25 is configured to
not accept connections (viz. blocked by your
firewall, blocked by your ISP, has no service
listening on port 25 on the server):
SMTP Failed to connect to mail server: Unknown error
because MIME::Lite by not passing the Port
argument and value makes Net::SMTP default to
smtp(25)
.
Adding a Debug argument with a non-zero value doesn't report anything because Net::SMTP can't even connect.
Edit 18th of August 2009: an
easier solution might be to specify the Host value
as host:port
. Since MIME::Lite uses
Net::SMTP which allows this value to "be a single
scalar, as defined for the PeerAddr
option in IO::Socket::INET" which is
<hostname>[:<port>]
In order to make MIME::Lite copy the non-default
port you just have to add Port
to the
list that specifies which agument name-value pairs
MIME::Lite should copy. This list is assigned to the
variable @_net_smpt_opts
:
my @_net_smtp_opts = qw( Hello LocalAddr LocalPort Timeout
ExactAddresses Debug );
at line 2829 for MIME::Lite 3.024. By adding Port
to this it's again possible to specify a non-default SMTP port:
my @_net_smtp_opts = qw( Hello LocalAddr LocalPort Timeout
Port ExactAddresses Debug );
If you don't want to modify Lite.pm
on your system you can copy the Lite.pm file to a directory
named MIME and modify it.
In order for your Perl program to load the modified
MIME::Lite module you have to make sure that the path
to the parent directory of the MIME directory
is added to the front of the @INC
array:
use lib '/full/path/to/parent/dir';
PERL5LIB
(or
if not defined PERLLIB
). If you
have more than one directory use the value
reported by perl -V:path_sep
to
separated paths. Note: this
does not work when running taint checks. In that
case use the previous or next option instead.
-I/full/path/to/parent/dir
option
to the perl
call, e.g.
perl -I/home/john/.perl-modules perlprogram.pl
See also: perldoc perlrun
.
Another option is to create a module that inherits
from MIME::Lite and redefines the
__opt
method. And since there are
always many ways in Perl, you could also redefine
this method by manipulating the symbol table of
MIME::Lite as follows:
{
no warnings 'redefine';
*MIME::Lite::__opts = sub {
my ( $args, @keys ) = @_;
join ( '', @keys )
eq 'HelloLocalAddrLocalPortTimeoutExactAddressesDebug'
and push @keys, 'Port';
return map {
exists $args->{$_} ? ( $_ => $args->{$_} ) : ()
} @keys;
};
}
Note the use of no warnings
'redefine';
- within an enclosing block to
limit its scope - to prevent a "Subroutine
MIME::Lite::__opts redefined at ... line ...."
warning.
Since __opts
is called with a list
of keys to copy the above code check if it's the
list that misses Port
and if so, adds
it
Note: make sure you check the
version of MIME::Lite before you redefine
__opts
.
After I had reported this bug I noticed that it had already been reported nearly 2 years ago: #21156: Not passing PORT parameter from smtp to Net::SMTP (Note to self: read the reported bugs first before reporting a duplicate). Anyway, since I can more than imagine that the current maintainer, Ricardo Signes, has been quite busy I emailed him if I could email a patch or use git; I had noticed that mime-lite is located at http://github.com/rjbs/mime-lite/.
Within a very short time I received a reply that either
way would be fine but a git remote to pull would
be preferred. After I had installed git
and git-core
and done a
git clone git://github.com/rjbs/mime-lite/ mime-lite-remote
I tried to find out, using "Pragmatic Version Control Using Git" by Travis Swicegood how to do the "remote to pull". Since I couldn't find an answer fast enough and also because I had the feeling that "remote to pull" involves the files I would modify to be available on the Internet somehow I decided to just generate a patches file.
So after modifying ./changes.pod
(entry for 3.025 including thanking myself) and
./lib/MIME/Lite.pm
(update of
$VERSION's value and addition of Port to
@_net_smtp_opts) I generated a patches file using:
git diff > ../patch.txt
which I emailed to Ricardo.
Note: there is a git
send-email
but which I am sure makes things
much easier if I take the time to set all SMTP
settings.
Shortly after I had emailed the file containing the MIME::Lite patches to Ricardo I received a very clear explanation of the "remote to pull" git part I didn't understand:
So I created a github free account, and did:
git clone git@github.com:john-bokma/mime-lite.git jb-mime-lite-remote
which failed with "Permission denied (publickey)." because I hadn't added a public SSH key during sign up. After I had created a public SSH key and added it to my profile, the aforementioned command succeeded, after it asked for my pass phrase.
Note: the clone URL was copied from the one given after "Your Clone URL:" at http://github.com/john-bokma/mime-lite/tree/master.
Next I copied the changed files I already had
over the cloned repository, commited both files,
and pushed the changes upstream using git
push
. I checked my fork at Github and hurray, my
changes were there. Then I realised that it
would be a good idea to have Port
listed in the documentation of
send_by_smtp
as well, so I added
"=item Port" to the POD section above
send_by_smtp
.
Satisfied with the changes I clicked the "pull request" button on my mime-lite page, and entered a note for Ricardo, to thank him for explaining how to do the pull request.
About an hour later I got an email from Ricardo stating "Merged, reviewed, released.". I checked CPAN and there it was MIME::Lite 3.025, the 3.024 version I patched.
In his email Ricardo also suggested to consider Email::Sender, which I certainly will do.
Special thanks to Ricardo "rjbs" Signes for taking the time to read and reply to my emails, teaching me how to use github to assist in updating MIME::Lite, and last but not least for maintaining MIME::Lite.