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