Fixing call to generate_part
[catagits/Catalyst-View-Email.git] / lib / Catalyst / View / Email.pm
1 package Catalyst::View::Email;
2
3 use warnings;
4 use strict;
5
6 use Class::C3;
7 use Carp;
8
9 use Email::Send;
10 use Email::MIME::Creator;
11
12 use base qw/ Catalyst::View /;
13
14 our $VERSION = '0.09999_01';
15
16 __PACKAGE__->mk_accessors(qw/ mailer /);
17
18 =head1 NAME
19
20 Catalyst::View::Email - Send Email from Catalyst
21
22 =head1 SYNOPSIS
23
24 This module simply sends out email from a stash key specified in the
25 configuration settings.
26
27 =head1 CONFIGURATION
28
29 Use the helper to create your View:
30     
31     $ script/myapp_create.pl view Email Email
32
33 In your app configuration (example in L<YAML>):
34
35     View::Email:
36         # Where to look in the stash for the email information.
37         # 'email' is the default, so you don't have to specify it.
38         stash_key: email
39         # Define the defaults for the mail
40         default:
41             # Defines the default content type (mime type).
42             # mandatory
43             content_type: text/plain
44             # Defines the default charset for every MIME part with the content
45             # type text.
46             # According to RFC2049 a MIME part without a charset should
47             # be treated as US-ASCII by the mail client.
48             # If the charset is not set it won't be set for all MIME parts
49             # without an overridden one.
50             # Default: none
51             charset: utf-8
52         # Setup how to send the email
53         # all those options are passed directly to Email::Send
54         sender:
55             mailer: SMTP
56             # mailer_args is passed directly into Email::Send 
57             mailer_args:
58                 Host:       smtp.example.com # defaults to localhost
59                 username:   username
60                 password:   password
61
62 =head2 NOTE ON SMTP
63
64 If you use SMTP and don't specify Host, it will default to localhost and
65 attempt delivery.  This often times means an email will sit in a queue
66 somewhere and not be delivered.
67
68 =cut
69
70 __PACKAGE__->config(
71     stash_key   => 'email',
72     default     => {
73         content_type    => 'text/html',
74     },
75 );
76
77 =head1 SENDING EMAIL
78
79 In your controller, simply forward to the view after populating the C<stash_key>
80
81     sub controller : Private {
82         my ( $self, $c ) = @_;
83         $c->stash->{email} = {
84             to      => q{catalyst@rocksyoursocks.com},
85             cc      => q{foo@bar.com},
86             bcc     => q{hidden@secret.com},
87             from    => q{no-reply@socksthatarerocked.com},
88             subject => qq{Your Subject Here},
89             body    => qq{Body Body Body}
90         };
91         $c->forward('View::Email');
92     }
93
94 Alternatively, you can use a more raw interface, and specify the headers as
95 an array reference.
96
97     $c->stash->{email} = {
98         header => [
99             To      => 'foo@bar.com',
100             Subject => 'Note the capitalization differences'
101         ],
102         body => qq{Ain't got no body, and nobody cares.},
103         # Or, send parts
104         parts => [
105             Email::MIME->create(
106                 attributes => {
107                     content_type => 'text/plain',
108                     disposition  => 'attachment',
109                     charset      => 'US-ASCII',
110                 },
111                 body => qq{Got a body, but didn't get ahead.}
112             )
113         ],
114     };
115
116 =head1 HANDLING FAILURES
117
118 If the email fails to send, the view will die (throw an exception).  After
119 your forward to the view, it is a good idea to check for errors:
120     
121     $c->forward('View::Email');
122     if ( scalar( @{ $c->error } ) ) {
123         $c->error(0); # Reset the error condition if you need to
124         $c->res->body('Oh noes!');
125     } else {
126         $c->res->body('Email sent A-OK! (At least as far as we can tell)');
127     }
128
129 =head1 USING TEMPLATES FOR EMAIL
130
131 Now, it's no fun to just send out email using plain strings.
132 Take a look at L<Catalyst::View::Email::Template> to see how you can use your
133 favourite template engine to render the mail body.
134
135
136 =cut
137
138 sub new {
139     my $self = shift->next::method(@_);
140
141     my ( $c, $arguments ) = @_;
142     
143     my $stash_key = $self->{stash_key};
144     croak "$self stash_key isn't defined!"
145         if ($stash_key eq '');
146
147     my $sender = Email::Send->new;
148
149     if ( my $mailer = $self->{sender}->{mailer} ) {
150         croak "$mailer is not supported, see Email::Send"
151             unless $sender->mailer_available($mailer);
152         $sender->mailer($mailer);
153     } else {
154         # Default case, run through the most likely options first.
155         for ( qw/SMTP Sendmail Qmail/ ) {
156             $sender->mailer($_) and last if $sender->mailer_available($_);
157         }
158     }
159
160     if ( my $args = $self->{sender}->{mailer_args} ) {
161         if ( ref $args eq 'HASH' ) {
162             $sender->mailer_args([ %$args ]);
163         }
164         elsif ( ref $args eq 'ARRAY' ) {
165             $sender->mailer_args($args);
166         } else {
167             croak "Invalid mailer_args specified, check pod for Email::Send!";
168         }
169     }
170
171     $self->mailer($sender);
172
173     return $self;
174 }
175
176 sub process {
177     my ( $self, $c ) = @_;
178
179     croak "Unable to send mail, bad mail configuration"
180         unless $self->mailer;
181
182     my $email  = $c->stash->{$self->{stash_key}};
183     croak "Can't send email without a valid email structure"
184         unless $email;
185     
186     if ( exists $self->{content_type} ) {
187         $email->{content_type} ||= $self->{content_type};
188     }
189
190     my $header  = $email->{header} || [];
191         push @$header, ('To' => delete $email->{to})
192             if $email->{to};
193         push @$header, ('Cc' => delete $email->{cc})
194             if $email->{cc};
195         push @$header, ('Bcc' => delete $email->{bcc})
196             if $email->{bcc};
197         push @$header, ('From' => delete $email->{from})
198             if $email->{from};
199         push @$header, ('Subject' => delete $email->{subject})
200             if $email->{subject};
201         push @$header, ('Content-type' => delete $email->{content_type})
202             if $email->{content_type};
203
204     my $parts = $email->{parts};
205     my $body  = $email->{body};
206    
207     unless ( $parts or $body ) {
208         croak "Can't send email without parts or body, check stash";
209     }
210
211     my %mime = ( header => $header );
212
213     if ( $parts and ref $parts eq 'ARRAY' ) {
214         $mime{parts} = $parts;
215     } else {
216         $mime{body} = $body;
217     }
218     
219     if ( $mime{attributes} and not $mime{attributes}->{charset} and
220          $self->{default}->{charset} )
221     {
222         $mime{attributes}->{charset} = $self->{default}->{charset};
223     }
224
225     my $message = $self->generate_part( $c, \%mime );
226
227     #my $message = Email::MIME->create(%mime);
228
229     if ( $message ) {
230         my $return = $self->mailer->send($message);
231         croak "$return" if !$return;
232     } else {
233         croak "Unable to create message";
234     }
235 }
236
237 sub setup_attributes {
238     my ( $self, $c, $attrs ) = @_;
239     
240     my $default_content_type    = $self->{default}->{content_type};
241     my $default_charset         = $self->{default}->{charset};
242
243     my $e_m_attrs = {};
244
245     if (exists $attrs->{content_type} && defined $attrs->{content_type} && $attrs->{content_type} ne '') {
246         $e_m_attrs->{content_type} = $attrs->{content_type};
247     }
248     elsif (defined $default_content_type && $default_content_type ne '') {
249         $e_m_attrs->{content_type} = $default_content_type;
250     }
251    
252     if (exists $attrs->{charset} && defined $attrs->{charset} && $attrs->{charset} ne '') {
253         $e_m_attrs->{charset} = $attrs->{charset};
254     }
255     elsif (defined $default_charset && $default_charset ne '') {
256         $e_m_attrs->{charset} = $default_charset;
257     }
258
259     return $e_m_attrs;
260 }
261
262 sub generate_part {
263     my ( $self, $c, $attr ) = @_;
264
265 $c->log->info("generate_part in Email");    
266     # setup the attributes (merge with defaults)
267     $attr->{attributes} = $self->setup_attributes($attr->{attributes});
268     return Email::MIME->create(%$attr);
269 }
270
271 =head1 SEE ALSO
272
273 =head2 L<Catalyst::View::Email::Template> - Send fancy template emails with Cat
274
275 =head2 L<Catalyst::Manual> - The Catalyst Manual
276
277 =head2 L<Catalyst::Manual::Cookbook> - The Catalyst Cookbook
278
279 =head1 AUTHORS
280
281 J. Shirley <jshirley@gmail.com>
282
283 =head1 CONTRIBUTORS
284
285 (Thanks!)
286
287 Matt S Trout
288
289 Daniel Westermann-Clark
290
291 Simon Elliott <cpan@browsing.co.uk>
292
293 Roman Filippov
294
295 Alexander Hartmaier <alex_hartmaier@hotmail.com>
296
297 =head1 LICENSE
298
299 This library is free software, you can redistribute it and/or modify it under
300 the same terms as Perl itself.
301
302 =cut
303
304 1;