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