Subject: | allow per-message args to mailer |
Date: | Tue, 6 Jun 2006 09:04:07 -0400 |
To: | bug-email-send [...] rt.cpan.org |
From: | Ricardo SIGNES <rjbs [...] cpan.org> |
(This is an RT-ified version of the email I'd sent Casey in 2006-02.)
One of the biggest barriers to writing sophisticated plugins to Email::Send is
the fact that one can't pass invocation args to the mailer. If I write an SMTP
mailer that can be told what envelope recipient and sender to use, I have to do
this:
my $rv = Email::Send->new({
mailer => 'NewSMTP',
mailer_args => [ $to, $from ],
})->send($message);
This is ugly. Worse, it reinforces the problem (solved by an earlier,
unapplied patch (now ticket 19732) that mailers are assumed to be nearly
stateless singletons. I can't create an SMTP mailer that can send many
messages through one host without disconnecting.
Using that previous patch, I could write a mailer that stays connected, and use
it as an object. Unfortunately, I can't actually pass any arguments to it!
my $sender = Email::Send->new({ mailer => NewSMTP });
$sender->send($message, @args);
In the above snippet, @args go to the message_modifier if it exists, and are
otherwise dropped on the floor.
Because the signature of the method basically consumes every possible case of
arguments that include "a message and something else," the solution for this
involves special-casing one circumstance. I think the sanest one is:
# third arg is optional:
$sender->send($message, \%more_mailer_arg, \%modifier_arg);
We can then assume (but verify) that the mailer args from the constructor were
also a hashref, and merge. So, we can specify some named mailer args in the
constructor and override or add more in the send call.
This lets the sender accept mailer arguments on each sending, so that we don't
need create a new mailer or sender for minor changes to the mailing options.
In combination with object (not class) mailers, this allows for
persistent-state mailers that can maintain connections state and send many
messages more efficiently. This could also be used for test (or other) sending
of mails to a database or to any resource with an overhead cost to establishing
and closing a connection.
I have attached a patch that implements this new calling style, documents it,
and lightly tests it.
I have also attached a tar file containing a very naive implementation of
NewSMTP. It is not persistent, but does accept and use envelope sender and
recipient. The test file works, but you'll want to edit it to use addresses
that will deliver to you, so you can see it in action.
I think this API change may be the last barrier to the use of Email::Send for
heavy work sending email.
--
rjbs
Message body not shown because it is not plain text.
Message body is not shown because sender requested not to inline it.