bumped version
[catagits/Catalyst-View-Email.git] / lib / Catalyst / View / Email.pm
CommitLineData
529915ab 1package Catalyst::View::Email;
2
4e8cf755 3use Moose;
529915ab 4use Carp;
5
e512f6ca 6use Encode qw(encode decode);
2a6e60a4 7use Email::Sender::Simple qw/ sendmail /;
d8e2374d 8use Email::MIME::Creator;
4e8cf755 9extends 'Catalyst::View';
529915ab 10
8af1eb76 11our $VERSION = '0.34';
9ff9161d 12$VERSION = eval $VERSION;
d8e2374d 13
cbfdc762 14has 'mailer' => (
d8e2374d 15 is => 'rw',
16 isa => 'Str',
17 lazy => 1,
cbfdc762 18 default => sub { "sendmail" }
19);
20
21has '_mailer_obj' => (
22 is => 'rw',
08a6e227 23 does => 'Email::Sender::Transport',
cbfdc762 24 lazy => 1,
25 builder => '_build_mailer_obj',
d8e2374d 26);
529915ab 27
4e8cf755 28has 'stash_key' => (
29 is => 'rw',
d8e2374d 30 isa => 'Str',
31 lazy => 1,
4e8cf755 32 default => sub { "email" }
33);
34
35has 'default' => (
36 is => 'rw',
d8e2374d 37 isa => 'HashRef',
38 default => sub { { content_type => 'text/plain' } },
4e8cf755 39 lazy => 1,
40);
41
4e8cf755 42has 'sender' => (
43 is => 'rw',
d8e2374d 44 isa => 'HashRef',
45 lazy => 1,
cbfdc762 46 default => sub { { mailer => shift->mailer } }
4e8cf755 47);
48
49has 'content_type' => (
50 is => 'rw',
502b5606 51 isa => 'Str',
52 default => sub { shift->default->{content_type} },
53 lazy => 1,
4e8cf755 54);
529915ab 55
56=head1 NAME
57
58Catalyst::View::Email - Send Email from Catalyst
59
60=head1 SYNOPSIS
61
4a44bcd3 62This module sends out emails from a stash key specified in the
529915ab 63configuration settings.
64
65=head1 CONFIGURATION
66
4a44bcd3 67WARNING: since version 0.10 the configuration options slightly changed!
68
ea115f9b 69Use the helper to create your View:
70
71 $ script/myapp_create.pl view Email Email
72
e512f6ca 73In your app configuration:
74
75 __PACKAGE__->config(
76 'View::Email' => {
77 # Where to look in the stash for the email information.
78 # 'email' is the default, so you don't have to specify it.
79 stash_key => 'email',
80 # Define the defaults for the mail
81 default => {
82 # Defines the default content type (mime type). Mandatory
83 content_type => 'text/plain',
84 # Defines the default charset for every MIME part with the
85 # content type text.
86 # According to RFC2049 a MIME part without a charset should
87 # be treated as US-ASCII by the mail client.
88 # If the charset is not set it won't be set for all MIME parts
89 # without an overridden one.
90 # Default: none
91 charset => 'utf-8'
6cbcc613 92 },
e512f6ca 93 # Setup how to send the email
502b5606 94 # all those options are passed directly to Email::Sender::Simple
e512f6ca 95 sender => {
502b5606 96 # if mailer doesn't start with Email::Sender::Simple::Transport::,
cbfdc762 97 # then this is prepended.
6cbcc613 98 mailer => 'SMTP',
502b5606 99 # mailer_args is passed directly into Email::Sender::Simple
e512f6ca 100 mailer_args => {
2f883858 101 host => 'smtp.example.com', # defaults to localhost
39e6f202 102 sasl_username => 'sasl_username',
103 sasl_password => 'sasl_password',
e512f6ca 104 }
98e5068b 105 }
106 }
e512f6ca 107 );
229f9fdd 108
4a44bcd3 109=head1 NOTE ON SMTP
229f9fdd 110
cbfdc762 111If you use SMTP and don't specify host, it will default to localhost and
4a44bcd3 112attempt delivery. This often means an email will sit in a queue and
113not be delivered.
529915ab 114
115=cut
116
529915ab 117=head1 SENDING EMAIL
118
4a44bcd3 119Sending email is just filling the stash and forwarding to the view:
529915ab 120
121 sub controller : Private {
122 my ( $self, $c ) = @_;
4a44bcd3 123
529915ab 124 $c->stash->{email} = {
4a44bcd3 125 to => 'jshirley@gmail.com',
126 cc => 'abraxxa@cpan.org',
4a44bcd3 127 from => 'no-reply@foobar.com',
128 subject => 'I am a Catalyst generated email',
129 body => 'Body Body Body',
529915ab 130 };
4a44bcd3 131
132 $c->forward( $c->view('Email') );
529915ab 133 }
134
4a44bcd3 135Alternatively you can use a more raw interface and specify the headers as
136an array reference like it is passed to L<Email::MIME::Creator>.
137Note that you may also mix both syntaxes if you like ours better but need to
138specify additional header attributes.
139The attributes are appended to the header array reference without overwriting
140contained ones.
529915ab 141
142 $c->stash->{email} = {
143 header => [
4a44bcd3 144 To => 'jshirley@gmail.com',
145 Cc => 'abraxxa@cpan.org',
98e5068b 146 Bcc => join ',', qw/hidden@secret.com hidden2@foobar.com/,
4a44bcd3 147 From => 'no-reply@foobar.com',
148 Subject => 'Note the capitalization differences',
529915ab 149 ],
150 body => qq{Ain't got no body, and nobody cares.},
151 # Or, send parts
152 parts => [
153 Email::MIME->create(
154 attributes => {
155 content_type => 'text/plain',
156 disposition => 'attachment',
157 charset => 'US-ASCII',
158 },
4a44bcd3 159 body => qq{Got a body, but didn't get ahead.},
529915ab 160 )
161 ],
162 };
163
8b534249 164You can set the envelope sender and recipient as well:
165
166 $c->stash->{email} = {
167
168 envelope_from => 'envelope-from@example.com',
169 from => 'header-from@example.com',
170
171 envelope_to => [ 'foo@example.com', 'bar@example.com' ],
172 to => 'Undisclosed Recipients:;',
173
174 ...
175 };
176
2a175229 177=head1 HANDLING ERRORS
529915ab 178
4a44bcd3 179If the email fails to send, the view will die (throw an exception).
180After your forward to the view, it is a good idea to check for errors:
181
182 $c->forward( $c->view('Email') );
529915ab 183
529915ab 184 if ( scalar( @{ $c->error } ) ) {
185 $c->error(0); # Reset the error condition if you need to
4a44bcd3 186 $c->response->body('Oh noes!');
529915ab 187 } else {
4a44bcd3 188 $c->response->body('Email sent A-OK! (At least as far as we can tell)');
529915ab 189 }
190
ea115f9b 191=head1 USING TEMPLATES FOR EMAIL
529915ab 192
ea115f9b 193Now, it's no fun to just send out email using plain strings.
194Take a look at L<Catalyst::View::Email::Template> to see how you can use your
195favourite template engine to render the mail body.
529915ab 196
4a44bcd3 197=head1 METHODS
198
199=over 4
200
201=item new
202
502b5606 203Validates the base config and creates the L<Email::Sender::Simple> object for later use
4a44bcd3 204by process.
529915ab 205
206=cut
d8e2374d 207
4e8cf755 208sub BUILD {
209 my $self = shift;
529915ab 210
4e8cf755 211 my $stash_key = $self->stash_key;
d8e2374d 212 croak "$self stash_key isn't defined!"
213 if ( $stash_key eq '' );
529915ab 214
529915ab 215}
216
cbfdc762 217sub _build_mailer_obj {
502b5606 218 my ($self) = @_;
219 my $transport_class = ucfirst $self->sender->{mailer};
cbfdc762 220
cd6f4257 221 # borrowed from Email::Sender::Simple -- apeiron, 2010-01-26
502b5606 222 if ( $transport_class !~ /^Email::Sender::Transport::/ ) {
223 $transport_class = "Email::Sender::Transport::$transport_class";
224 }
cbfdc762 225
502b5606 226 Class::MOP::load_class($transport_class);
cbfdc762 227
502b5606 228 return $transport_class->new( $self->sender->{mailer_args} || {} );
cbfdc762 229}
230
4a44bcd3 231=item process($c)
11a0bf18 232
233The process method does the actual processing when the view is dispatched to.
234
502b5606 235This method sets up the email parts and hands off to L<Email::Sender::Simple> to handle
11a0bf18 236the actual email delivery.
237
238=cut
239
529915ab 240sub process {
241 my ( $self, $c ) = @_;
242
243 croak "Unable to send mail, bad mail configuration"
cbfdc762 244 unless $self->sender->{mailer};
529915ab 245
d8e2374d 246 my $email = $c->stash->{ $self->stash_key };
529915ab 247 croak "Can't send email without a valid email structure"
d8e2374d 248 unless $email;
249
250 # Default content type
251 if ( $self->content_type and not $email->{content_type} ) {
252 $email->{content_type} = $self->content_type;
253 }
254
255 my $header = $email->{header} || [];
256 push @$header, ( 'To' => delete $email->{to} )
257 if $email->{to};
258 push @$header, ( 'Cc' => delete $email->{cc} )
259 if $email->{cc};
d8e2374d 260 push @$header, ( 'From' => delete $email->{from} )
261 if $email->{from};
262 push @$header,
263 ( 'Subject' => Encode::encode( 'MIME-Header', delete $email->{subject} ) )
264 if $email->{subject};
265 push @$header, ( 'Content-type' => $email->{content_type} )
266 if $email->{content_type};
529915ab 267
268 my $parts = $email->{parts};
269 my $body = $email->{body};
d8e2374d 270
529915ab 271 unless ( $parts or $body ) {
272 croak "Can't send email without parts or body, check stash";
273 }
274
ab4326b4 275 my %mime = ( header => $header, attributes => {} );
529915ab 276
277 if ( $parts and ref $parts eq 'ARRAY' ) {
278 $mime{parts} = $parts;
d8e2374d 279 }
280 else {
529915ab 281 $mime{body} = $body;
282 }
ab4326b4 283
d8e2374d 284 $mime{attributes}->{content_type} = $email->{content_type}
285 if $email->{content_type};
286 if ( $mime{attributes}
287 and not $mime{attributes}->{charset}
288 and $self->{default}->{charset} )
289 {
290 $mime{attributes}->{charset} = $self->{default}->{charset};
291 }
292
beda8c31 293 $mime{attributes}->{encoding} = $email->{encoding}
294 if $email->{encoding};
295
d0e11256 296 my $message = $self->generate_message( $c, \%mime );
529915ab 297
d8e2374d 298 if ($message) {
8b534249 299 my $return = sendmail( $message,
300 {
301 exists $email->{envelope_from} ? ( from => $email->{envelope_from} ) : (),
302 exists $email->{envelope_to} ? ( to => $email->{envelope_to} ) : (),
303 transport => $self->_mailer_obj,
304 } );
d8e2374d 305
2a175229 306 # return is a Return::Value object, so this will stringify as the error
d8e2374d 307 # in the case of a failure.
95629d46 308 croak "$return" if !$return;
d8e2374d 309 }
310 else {
529915ab 311 croak "Unable to create message";
312 }
313}
314
4a44bcd3 315=item setup_attributes($c, $attr)
11a0bf18 316
4a44bcd3 317Merge attributes with the configured defaults. You can override this method to
11a0bf18 318return a structure to pass into L<generate_message> which subsequently
319passes the return value of this method to Email::MIME->create under the
320C<attributes> key.
321
322=cut
323
d8e2374d 324sub setup_attributes {
325 my ( $self, $c, $attrs ) = @_;
326
327 my $default_content_type = $self->default->{content_type};
beda8c31 328 my $default_charset = $self->default->{charset};
329 my $default_encoding = $self->default->{encoding};
d8e2374d 330
331 my $e_m_attrs = {};
332
333 if ( exists $attrs->{content_type}
334 && defined $attrs->{content_type}
335 && $attrs->{content_type} ne '' )
336 {
337 $c->log->debug( 'C::V::Email uses specified content_type '
338 . $attrs->{content_type}
339 . '.' )
340 if $c->debug;
341 $e_m_attrs->{content_type} = $attrs->{content_type};
342 }
343 elsif ( defined $default_content_type && $default_content_type ne '' ) {
344 $c->log->debug(
345 "C::V::Email uses default content_type $default_content_type.")
346 if $c->debug;
347 $e_m_attrs->{content_type} = $default_content_type;
348 }
349
350 if ( exists $attrs->{charset}
351 && defined $attrs->{charset}
352 && $attrs->{charset} ne '' )
353 {
354 $e_m_attrs->{charset} = $attrs->{charset};
355 }
356 elsif ( defined $default_charset && $default_charset ne '' ) {
357 $e_m_attrs->{charset} = $default_charset;
358 }
359
beda8c31 360 if ( exists $attrs->{encoding}
361 && defined $attrs->{encoding}
362 && $attrs->{encoding} ne '' )
363 {
364 $c->log->debug(
365 'C::V::Email uses specified encoding '
366 . $attrs->{encoding}
367 . '.' )
368 if $c->debug;
369 $e_m_attrs->{encoding} = $attrs->{encoding};
370 }
371 elsif ( defined $default_encoding && $default_encoding ne '' ) {
372 $c->log->debug(
373 "C::V::Email uses default encoding $default_encoding.")
374 if $c->debug;
375 $e_m_attrs->{encoding} = $default_encoding;
376 }
377
d8e2374d 378 return $e_m_attrs;
379}
380
4a44bcd3 381=item generate_message($c, $attr)
11a0bf18 382
383Generate a message part, which should be an L<Email::MIME> object and return it.
384
385Takes the attributes, merges with the defaults as necessary and returns a
386message object.
387
388=cut
389
d0e11256 390sub generate_message {
0c8469c1 391 my ( $self, $c, $attr ) = @_;
43090696 392
d8e2374d 393 # setup the attributes (merge with defaultis)
502b5606 394 $attr->{attributes} = $self->setup_attributes( $c, $attr->{attributes} );
395 Email::MIME->create( %$attr );
43090696 396}
397
4a44bcd3 398=back
399
cbfdc762 400
e512f6ca 401=head1 TROUBLESHOOTING
402
403As with most things computer related, things break. Email even more so.
404Typically any errors are going to come from using SMTP as your sending method,
405which means that if you are having trouble the first place to look is at
cd6f4257 406L<Email::Sender::Transport::SMTP>. This module is just a wrapper for L<Email::Sender::Simple>,
e512f6ca 407so if you get an error on sending, it is likely from there anyway.
408
409If you are using SMTP and have troubles sending, whether it is authentication
410or a very bland "Can't send" message, make sure that you have L<Net::SMTP> and,
411if applicable, L<Net::SMTP::SSL> installed.
412
413It is very simple to check that you can connect via L<Net::SMTP>, and if you
414do have sending errors the first thing to do is to write a simple script
415that attempts to connect. If it works, it is probably something in your
416configuration so double check there. If it doesn't, well, keep modifying
417the script and/or your mail server configuration until it does!
418
529915ab 419=head1 SEE ALSO
420
421=head2 L<Catalyst::View::Email::Template> - Send fancy template emails with Cat
422
423=head2 L<Catalyst::Manual> - The Catalyst Manual
424
425=head2 L<Catalyst::Manual::Cookbook> - The Catalyst Cookbook
426
427=head1 AUTHORS
428
429J. Shirley <jshirley@gmail.com>
430
4a44bcd3 431Alexander Hartmaier <abraxxa@cpan.org>
432
25650747 433=head1 CONTRIBUTORS
434
435(Thanks!)
436
94b4e4ff 437Matt S Trout
438
25650747 439Daniel Westermann-Clark
440
ea115f9b 441Simon Elliott <cpan@browsing.co.uk>
229f9fdd 442
95629d46 443Roman Filippov
444
b7b30250 445Lance Brown <lance@bearcircle.net>
446
6ca945f0 447Devin Austin <dhoss@cpan.org>
448
cbfdc762 449Chris Nehren <apeiron@cpan.org>
450
da1c5877 451=head1 COPYRIGHT
452
453Copyright (c) 2007 - 2009
454the Catalyst::View::Email L</AUTHORS> and L</CONTRIBUTORS>
455as listed above.
456
529915ab 457=head1 LICENSE
458
459This library is free software, you can redistribute it and/or modify it under
460the same terms as Perl itself.
461
462=cut
463
4641;