Commit | Line | Data |
529915ab |
1 | package Catalyst::View::Email; |
2 | |
3 | use warnings; |
4 | use strict; |
5 | |
29840e4a |
6 | use Class::C3; |
529915ab |
7 | use Carp; |
8 | |
9 | use Email::Send; |
10 | use Email::MIME::Creator; |
11 | |
ea115f9b |
12 | use base qw/ Catalyst::View /; |
529915ab |
13 | |
d0e11256 |
14 | our $VERSION = '0.09999_02'; |
529915ab |
15 | |
ea115f9b |
16 | __PACKAGE__->mk_accessors(qw/ mailer /); |
529915ab |
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 | |
ea115f9b |
29 | Use the helper to create your View: |
30 | |
31 | $ script/myapp_create.pl view Email Email |
32 | |
529915ab |
33 | In your app configuration (example in L<YAML>): |
25650747 |
34 | |
529915ab |
35 | View::Email: |
ea115f9b |
36 | # Where to look in the stash for the email information. |
37 | # 'email' is the default, so you don't have to specify it. |
529915ab |
38 | stash_key: email |
ea115f9b |
39 | # Define the defaults for the mail |
40 | default: |
41 | # Defines the default content type (mime type). |
42 | # mandatory |
43 | content_type: text/plain |
43090696 |
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 |
ea115f9b |
52 | # Setup how to send the email |
53 | # all those options are passed directly to Email::Send |
529915ab |
54 | sender: |
06afcdbc |
55 | mailer: SMTP |
b3d2ac28 |
56 | # mailer_args is passed directly into Email::Send |
57 | mailer_args: |
229f9fdd |
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. |
529915ab |
67 | |
68 | =cut |
69 | |
70 | __PACKAGE__->config( |
06afcdbc |
71 | stash_key => 'email', |
72 | default => { |
73 | content_type => 'text/html', |
74 | }, |
529915ab |
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} = { |
b3d2ac28 |
84 | to => q{catalyst@rocksyoursocks.com}, |
ea115f9b |
85 | cc => q{foo@bar.com}, |
86 | bcc => q{hidden@secret.com}, |
b3d2ac28 |
87 | from => q{no-reply@socksthatarerocked.com}, |
529915ab |
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 | |
ea115f9b |
129 | =head1 USING TEMPLATES FOR EMAIL |
529915ab |
130 | |
ea115f9b |
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. |
529915ab |
134 | |
529915ab |
135 | |
136 | =cut |
137 | |
138 | sub new { |
25650747 |
139 | my $self = shift->next::method(@_); |
140 | |
141 | my ( $c, $arguments ) = @_; |
ea115f9b |
142 | |
143 | my $stash_key = $self->{stash_key}; |
144 | croak "$self stash_key isn't defined!" |
145 | if ($stash_key eq ''); |
529915ab |
146 | |
06afcdbc |
147 | my $sender = Email::Send->new; |
529915ab |
148 | |
06afcdbc |
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); |
529915ab |
153 | } else { |
154 | # Default case, run through the most likely options first. |
155 | for ( qw/SMTP Sendmail Qmail/ ) { |
06afcdbc |
156 | $sender->mailer($_) and last if $sender->mailer_available($_); |
529915ab |
157 | } |
158 | } |
159 | |
06afcdbc |
160 | if ( my $args = $self->{sender}->{mailer_args} ) { |
229f9fdd |
161 | if ( ref $args eq 'HASH' ) { |
06afcdbc |
162 | $sender->mailer_args([ %$args ]); |
229f9fdd |
163 | } |
164 | elsif ( ref $args eq 'ARRAY' ) { |
06afcdbc |
165 | $sender->mailer_args($args); |
229f9fdd |
166 | } else { |
167 | croak "Invalid mailer_args specified, check pod for Email::Send!"; |
168 | } |
529915ab |
169 | } |
170 | |
06afcdbc |
171 | $self->mailer($sender); |
529915ab |
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 | |
ea115f9b |
182 | my $email = $c->stash->{$self->{stash_key}}; |
529915ab |
183 | croak "Can't send email without a valid email structure" |
184 | unless $email; |
d0e11256 |
185 | |
ea115f9b |
186 | if ( exists $self->{content_type} ) { |
187 | $email->{content_type} ||= $self->{content_type}; |
529915ab |
188 | } |
189 | |
190 | my $header = $email->{header} || []; |
191 | push @$header, ('To' => delete $email->{to}) |
192 | if $email->{to}; |
ea115f9b |
193 | push @$header, ('Cc' => delete $email->{cc}) |
194 | if $email->{cc}; |
195 | push @$header, ('Bcc' => delete $email->{bcc}) |
196 | if $email->{bcc}; |
529915ab |
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 | } |
43090696 |
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 | |
d0e11256 |
225 | my $message = $self->generate_message( $c, \%mime ); |
529915ab |
226 | |
43090696 |
227 | #my $message = Email::MIME->create(%mime); |
529915ab |
228 | |
229 | if ( $message ) { |
95629d46 |
230 | my $return = $self->mailer->send($message); |
231 | croak "$return" if !$return; |
529915ab |
232 | } else { |
233 | croak "Unable to create message"; |
234 | } |
235 | } |
236 | |
43090696 |
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 '') { |
d0e11256 |
246 | $c->log->debug('C::V::Email uses specified content_type ' . $attrs->{content_type} . '.') if $c->debug; |
43090696 |
247 | $e_m_attrs->{content_type} = $attrs->{content_type}; |
248 | } |
249 | elsif (defined $default_content_type && $default_content_type ne '') { |
d0e11256 |
250 | $c->log->debug("C::V::Email uses default content_type $default_content_type.") if $c->debug; |
43090696 |
251 | $e_m_attrs->{content_type} = $default_content_type; |
252 | } |
253 | |
254 | if (exists $attrs->{charset} && defined $attrs->{charset} && $attrs->{charset} ne '') { |
255 | $e_m_attrs->{charset} = $attrs->{charset}; |
256 | } |
257 | elsif (defined $default_charset && $default_charset ne '') { |
258 | $e_m_attrs->{charset} = $default_charset; |
259 | } |
260 | |
261 | return $e_m_attrs; |
262 | } |
263 | |
d0e11256 |
264 | sub generate_message { |
0c8469c1 |
265 | my ( $self, $c, $attr ) = @_; |
43090696 |
266 | |
267 | # setup the attributes (merge with defaults) |
d0e11256 |
268 | $attr->{attributes} = $self->setup_attributes($c, $attr->{attributes}); |
43090696 |
269 | return Email::MIME->create(%$attr); |
270 | } |
271 | |
529915ab |
272 | =head1 SEE ALSO |
273 | |
274 | =head2 L<Catalyst::View::Email::Template> - Send fancy template emails with Cat |
275 | |
276 | =head2 L<Catalyst::Manual> - The Catalyst Manual |
277 | |
278 | =head2 L<Catalyst::Manual::Cookbook> - The Catalyst Cookbook |
279 | |
280 | =head1 AUTHORS |
281 | |
282 | J. Shirley <jshirley@gmail.com> |
283 | |
25650747 |
284 | =head1 CONTRIBUTORS |
285 | |
286 | (Thanks!) |
287 | |
94b4e4ff |
288 | Matt S Trout |
289 | |
25650747 |
290 | Daniel Westermann-Clark |
291 | |
ea115f9b |
292 | Simon Elliott <cpan@browsing.co.uk> |
229f9fdd |
293 | |
95629d46 |
294 | Roman Filippov |
295 | |
ea115f9b |
296 | Alexander Hartmaier <alex_hartmaier@hotmail.com> |
297 | |
529915ab |
298 | =head1 LICENSE |
299 | |
300 | This library is free software, you can redistribute it and/or modify it under |
301 | the same terms as Perl itself. |
302 | |
303 | =cut |
304 | |
305 | 1; |