We love Moose.
We love email.
Let's put them together!
The idea:
I'm working on a website where email is going to be used extensively. Like most sites, I'll need registration confirmation, email updates to users, confirm password change, and future things like emailing photos in, etc.
I've used other modules for email and have never really been happy with them. I came upon Email::Stuff recently, and decided to give it a whack. However, I didn't want to have to set it up over and over everywhere it needed to be used. So this is where Moose came in.
Here we go!
The source listing:
package BoyosPlace::Email;
use Moose;
use Moose::Util::TypeConstraints;
use Email::Stuff;
use Email::Valid;
subtype 'Email',
as 'Str',
where { Email::Valid->address($_) eq $_ };
coerce 'Email',
from 'Str',
via { scalar Email::Valid->address($_) };
has 'subject' => ( is => 'rw', isa => "Str" );
has 'to' => ( is => 'rw', isa => "Email" );
has 'from' => ( is => 'rw', isa => "Email" );
has 'data' => ( is => 'rw', isa => "Str" );
has 'email' => ( is => 'ro', isa => "Email::Stuff",
default => sub {
my $self = shift;
Email::Stuff->from ( $self->from )
->to ( $self->to )
->subject ( $self->subject )
->text_body ( $self->data )
},
lazy =>1,
);
sub send {
my $self = shift;
my $rv = $self->email->send;
die $rv unless $rv;
}
no Moose;
__PACKAGE__->meta->make_immutable;
1;
Let's back up.
What I've done here is allowed the user to do something like
my $email = BoyosPlace::Email->new(%options)
The options (at this point) are "subject" of type Str(ing), "to" of type "Email", which is a subtype created as a Str type and coerced into an Email::Valid type so that email addresses passed are able to be type validated using Email::Valid. Same with the "from" option. The "data" attribute/option is simply a Str type, as it's mostly likely just going to contain text, for now. So there we have our attributes covered.
Finally, we create our email object through an attribute as type Email::Stuff. We set up the entire Email::Stuff object in this through default, and make sure it's set up via lazy, so it's only created upon being called.
The send method simply calls Email::Stuff's send method.
This is a pretty simple set up, but because I used Moose, I can add in additional Roles to take care of things like attachments, etc, messaging of different sorts. This code could be improved by making all the attributes should be 'ro' (read-only) and have writers, etc.
Email::Stuff is a neat and simple way to send email. Add Moose into the mix, and you get a lot of flexibility for free. For more information, you can check out the documentation, or visit #email on irc.perl.org.




I'm still pretty new to Moose, but I'm wondering why email isn't just a method on BoyosPlace::Email instead of an attribute. Does that make applying Moose roles easier?