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