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