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