1 package Catalyst::View::Email::Template;
5 use Scalar::Util qw/ blessed /;
6 extends 'Catalyst::View::Email';
9 $VERSION = eval $VERSION;
12 Catalyst::View::Email::Template - Send Templated Email from Catalyst
16 Sends templated mail, based upon your default view. It captures the output
17 of the rendering path, slurps in based on mime-types and assembles a multi-part
18 email using L<Email::MIME::Creator> and sends it out.
22 WARNING: since version 0.10 the configuration options slightly changed!
24 Use the helper to create your view:
26 $ script/myapp_create.pl view Email::Template Email::Template
28 For basic configuration look at L<Catalyst::View::Email/CONFIGURATION>.
30 In your app configuration (example in L<YAML>):
32 View::Email::Template:
33 # Optional prefix to look somewhere under the existing configured
36 template_prefix: email
37 # Define the defaults for the mail
39 # Defines the default view used to render the templates.
40 # If none is specified neither here nor in the stash
41 # Catalysts default view is used.
42 # Warning: if you don't tell Catalyst explicit which of your views should
43 # be its default one, C::V::Email::Template may choose the wrong one!
48 Sending email works just like for L<Catalyst::View::Email> but by specifying
49 the template instead of the body and forwarding to your Email::Template view:
51 sub controller : Private {
52 my ( $self, $c ) = @_;
54 $c->stash->{email} = {
55 to => 'jshirley@gmail.com',
56 cc => 'abraxxa@cpan.org',
57 bcc => 'hidden@secret.com hidden2@foobar.com',
58 from => 'no-reply@foobar.com',
59 subject => 'I am a Catalyst generated email',
60 template => 'test.tt',
61 content_type => 'multipart/alternative'
64 $c->forward( $c->view('Email::Template') );
67 Alternatively if you want more control over your templates you can use the following idiom
68 to override the defaults. If charset and encoding given, the body become properly encoded.
72 template => 'email/test.html.tt',
73 content_type => 'text/html',
75 encoding => 'quoted-printable',
79 template => 'email/test.plain.mason',
80 content_type => 'text/plain',
82 encoding => 'quoted-printable',
89 =head1 HANDLING ERRORS
91 See L<Catalyst::View::Email/HANDLING ERRORS>.
95 # here the defaults of Catalyst::View::Email are extended by the additional
96 # ones Template.pm needs.
101 default => sub { "email" },
105 has 'template_prefix' => (
108 default => sub { '' },
118 content_type => 'text/html',
124 # This view hitches into your default view and will call the render function
125 # on the templates provided. This means that you have a layer of abstraction
126 # and you aren't required to modify your templates based on your desired engine
127 # (Template Toolkit or Mason, for example). As long as the view adequately
128 # supports ->render, all things are good. Mason, and others, are not good.
131 # The path here is to check configuration for the template root, and then
132 # proceed to call render on the subsequent templates and stuff each one
133 # into an Email::MIME container. The mime-type will be stupidly guessed with
134 # the subdir on the template.
137 # Set it up so if you have multiple parts, they're alternatives.
138 # This is on the top-level message, not the individual parts.
139 #multipart/alternative
142 my ( $self, $view ) = @_;
144 croak "C::V::Email::Template's configured view '$view' isn't an object!"
145 unless ( blessed($view) );
148 "C::V::Email::Template's configured view '$view' isn't an Catalyst::View!"
149 unless ( $view->isa('Catalyst::View') );
152 "C::V::Email::Template's configured view '$view' doesn't have a render method!"
153 unless ( $view->can('render') );
162 Generates a MIME part to include in the email. Since the email is template based
163 every template piece is a separate part that is included in the email.
168 my ( $self, $c, $attrs ) = @_;
170 my $template_prefix = $self->template_prefix;
171 my $default_view = $self->default->{view};
172 my $default_content_type = $self->default->{content_type};
173 my $default_charset = $self->default->{charset};
177 # use the view specified for the email part
178 if ( exists $attrs->{view}
179 && defined $attrs->{view}
180 && $attrs->{view} ne '' )
182 $view = $c->view( $attrs->{view} );
184 "C::V::Email::Template uses specified view $view for rendering.")
188 # if none specified use the configured default view
189 elsif ($default_view) {
190 $view = $c->view($default_view);
192 "C::V::Email::Template uses default view $view for rendering.")
196 # else fallback to Catalysts default view
200 "C::V::Email::Template uses Catalysts default view $view for rendering."
204 # validate the per template view
205 $self->_validate_view($view);
207 # prefix with template_prefix if configured
209 $template_prefix ne ''
210 ? join( '/', $template_prefix, $attrs->{template} )
211 : $attrs->{template};
213 # setup the attributes (merge with defaults)
214 my $e_m_attrs = $self->SUPER::setup_attributes( $c, $attrs );
216 # render the email part
217 my $output = $view->render(
221 content_type => $e_m_attrs->{content_type},
222 stash_key => $self->stash_key,
227 croak $output->can('as_string') ? $output->as_string : $output;
230 if ( exists $e_m_attrs->{encoding}
231 && defined $e_m_attrs->{encoding}
232 && exists $e_m_attrs->{charset}
233 && defined $e_m_attrs->{charset} ) {
235 return Email::MIME->create(
236 attributes => $e_m_attrs,
242 return Email::MIME->create(
243 attributes => $e_m_attrs,
251 The process method is called when the view is dispatched to. This creates the
252 multipart message and then sends the message contents off to
253 L<Catalyst::View::Email> for processing, which in turn hands off to
254 L<Email::Sender::Simple>.
258 around 'process' => sub {
259 my ( $orig, $self, $c, @args ) = @_;
260 my $stash_key = $self->stash_key;
261 return $self->$orig( $c, @args )
262 unless $c->stash->{$stash_key}->{template}
263 or $c->stash->{$stash_key}->{templates};
265 # in case of the simple api only one
268 # now find out if the single or multipart api was used
269 # prefer the multipart one
272 if ( $c->stash->{$stash_key}->{templates}
273 && ref $c->stash->{$stash_key}->{templates} eq 'ARRAY'
274 && ref $c->stash->{$stash_key}->{templates}[0] eq 'HASH' )
277 # loop through all parts of the mail
278 foreach my $part ( @{ $c->stash->{$stash_key}->{templates} } ) {
280 $self->generate_part(
283 view => $part->{view},
284 template => $part->{template},
285 content_type => $part->{content_type},
286 charset => $part->{charset},
287 encoding => $part->{encoding},
294 elsif ( $c->stash->{$stash_key}->{template} ) {
296 $self->generate_part( $c,
297 { template => $c->stash->{$stash_key}->{template}, } );
300 delete $c->stash->{$stash_key}->{body};
301 $c->stash->{$stash_key}->{parts} ||= [];
302 push @{ $c->stash->{$stash_key}->{parts} }, @parts;
304 return $self->$orig($c);
314 There needs to be a method to support attachments. What I am thinking is
315 something along these lines:
318 # Set the body to a file handle object, specify content_type and
319 # the file name. (name is what it is sent at, not the file)
320 { body => $fh, name => "foo.pdf", content_type => "application/pdf" },
321 # Or, specify a filename that is added, and hey, encoding!
322 { filename => "foo.gif", name => "foo.gif", content_type => "application/pdf", encoding => "quoted-printable" },
323 # Or, just a path to a file, and do some guesswork for the content type
324 "/path/to/somefile.pdf",
329 =head2 L<Catalyst::View::Email> - Send plain boring emails with Catalyst
331 =head2 L<Catalyst::Manual> - The Catalyst Manual
333 =head2 L<Catalyst::Manual::Cookbook> - The Catalyst Cookbook
337 J. Shirley <jshirley@gmail.com>
339 Simon Elliott <cpan@browsing.co.uk>
341 Alexander Hartmaier <abraxxa@cpan.org>
345 This library is free software, you can redistribute it and/or modify it under
346 the same terms as Perl itself.