File Coverage

blib/lib/Email/Stuffer.pm
Criterion Covered Total %
statement 179 191 93.7
branch 67 100 67.0
condition 13 21 61.9
subroutine 38 40 95.0
pod 19 20 95.0
total 316 372 84.9


line stmt bran cond sub pod time code
1 9     9   635470 use strict;
  9         98  
  9         275  
2 9     9   48 use warnings;
  9         17  
  9         574  
3             package Email::Stuffer;
4             # ABSTRACT: A more casual approach to creating and sending Email:: emails
5             $Email::Stuffer::VERSION = '0.018';
6 9     9   61 use Scalar::Util qw(blessed);
  9         17  
  9         793  
7              
8             #pod =head1 SYNOPSIS
9             #pod
10             #pod # Prepare the message
11             #pod my $body = <<'AMBUSH_READY';
12             #pod Dear Santa
13             #pod
14             #pod I have killed Bun Bun.
15             #pod
16             #pod Yes, I know what you are thinking... but it was actually a total accident.
17             #pod
18             #pod I was in a crowded line at a BayWatch signing, and I tripped, and stood on
19             #pod his head.
20             #pod
21             #pod I know. Oops! :/
22             #pod
23             #pod So anyways, I am willing to sell you the body for $1 million dollars.
24             #pod
25             #pod Be near the pinhole to the Dimension of Pain at midnight.
26             #pod
27             #pod Alias
28             #pod
29             #pod AMBUSH_READY
30             #pod
31             #pod # Create and send the email in one shot
32             #pod Email::Stuffer->from ('cpan@ali.as' )
33             #pod ->to ('santa@northpole.org' )
34             #pod ->bcc ('bunbun@sluggy.com' )
35             #pod ->text_body($body )
36             #pod ->attach_file('dead_bunbun_faked.gif' )
37             #pod ->send;
38             #pod
39             #pod =head1 DESCRIPTION
40             #pod
41             #pod B
42             #pod name and/or API changes>
43             #pod
44             #pod Email::Stuffer, as its name suggests, is a fairly casual module used
45             #pod to stuff things into an email and send them. It is a high-level module
46             #pod designed for ease of use when doing a very specific common task, but
47             #pod implemented on top of the light and tolerable Email:: modules.
48             #pod
49             #pod Email::Stuffer is typically used to build emails and send them in a single
50             #pod statement, as seen in the synopsis. And it is certain only for use when
51             #pod creating and sending emails. As such, it contains no email parsing
52             #pod capability, and little to no modification support.
53             #pod
54             #pod To re-iterate, this is very much a module for those "slap it together and
55             #pod fire it off" situations, but that still has enough grunt behind the scenes
56             #pod to do things properly.
57             #pod
58             #pod =head2 Default Transport
59             #pod
60             #pod Although it cannot be relied upon to work, the default behaviour is to
61             #pod use C to send mail, if you don't provide the mail send channel
62             #pod with either the C method, or as an argument to C.
63             #pod
64             #pod (Actually, the choice of default is delegated to
65             #pod L, which makes its own choices. But usually, it
66             #pod uses C.)
67             #pod
68             #pod =head2 Why use this?
69             #pod
70             #pod Why not just use L or L? After all, this just adds
71             #pod another layer of stuff around those. Wouldn't using them directly be better?
72             #pod
73             #pod Certainly, if you know EXACTLY what you are doing. The docs are clear enough,
74             #pod but you really do need to have an understanding of the structure of MIME
75             #pod emails. This structure is going to be different depending on whether you have
76             #pod text body, HTML, both, with or without an attachment etc.
77             #pod
78             #pod Then there's brevity... compare the following roughly equivalent code.
79             #pod
80             #pod First, the Email::Stuffer way.
81             #pod
82             #pod Email::Stuffer->to('Simon Cozens')
83             #pod ->from('Santa@northpole.org')
84             #pod ->text_body("You've been good this year. No coal for you.")
85             #pod ->attach_file('choochoo.gif')
86             #pod ->send;
87             #pod
88             #pod And now doing it directly with a knowledge of what your attachment is, and
89             #pod what the correct MIME structure is.
90             #pod
91             #pod use Email::MIME;
92             #pod use Email::Sender::Simple;
93             #pod use IO::All;
94             #pod
95             #pod Email::Sender::Simple->try_to_send(
96             #pod Email::MIME->create(
97             #pod header => [
98             #pod To => 'simon@somewhere.jp',
99             #pod From => 'santa@northpole.org',
100             #pod ],
101             #pod parts => [
102             #pod Email::MIME->create(
103             #pod body => "You've been a good boy this year. No coal for you."
104             #pod ),
105             #pod Email::MIME->create(
106             #pod body => io('choochoo.gif'),
107             #pod attributes => {
108             #pod filename => 'choochoo.gif',
109             #pod content_type => 'image/gif',
110             #pod },
111             #pod ),
112             #pod ],
113             #pod );
114             #pod );
115             #pod
116             #pod Again, if you know MIME well, and have the patience to manually code up
117             #pod the L structure, go do that, if you really want to.
118             #pod
119             #pod Email::Stuffer as the name suggests, solves one case and one case only:
120             #pod generate some stuff, and email it to somewhere, as conveniently as
121             #pod possible. DWIM, but do it as thinly as possible and use the solid
122             #pod Email:: modules underneath.
123             #pod
124             #pod =head1 COOKBOOK
125             #pod
126             #pod Here is another example (maybe plural later) of how you can use
127             #pod Email::Stuffer's brevity to your advantage.
128             #pod
129             #pod =head2 Custom Alerts
130             #pod
131             #pod package SMS::Alert;
132             #pod use base 'Email::Stuffer';
133             #pod
134             #pod sub new {
135             #pod shift()->SUPER::new(@_)
136             #pod ->from('monitor@my.website')
137             #pod # Of course, we could have pulled these from
138             #pod # $MyConfig->{support_tech} or something similar.
139             #pod ->to('0416181595@sms.gateway')
140             #pod ->transport('SMTP', { host => '123.123.123.123' });
141             #pod }
142             #pod
143             #pod Z<>
144             #pod
145             #pod package My::Code;
146             #pod
147             #pod unless ( $Server->restart ) {
148             #pod # Notify the admin on call that a server went down and failed
149             #pod # to restart.
150             #pod SMS::Alert->subject("Server $Server failed to restart cleanly")
151             #pod ->send;
152             #pod }
153             #pod
154             #pod =head1 METHODS
155             #pod
156             #pod As you can see from the synopsis, all methods that B the
157             #pod Email::Stuffer object returns the object, and thus most normal calls are
158             #pod chainable.
159             #pod
160             #pod However, please note that C, and the group of methods that do not
161             #pod change the Email::Stuffer object B return the object, and thus
162             #pod B chainable.
163             #pod
164             #pod =cut
165              
166 9     9   235 use 5.005;
  9         29  
167 9     9   53 use strict;
  9         25  
  9         257  
168 9     9   49 use Carp qw(croak);
  9         17  
  9         489  
169 9     9   69 use File::Basename ();
  9         16  
  9         318  
170 9     9   4974 use Params::Util 1.05 qw(_INSTANCE _INSTANCEDOES);
  9         45263  
  9         667  
171 9     9   5596 use Email::MIME 1.943 ();
  9         554355  
  9         282  
172 9     9   84 use Email::MIME::Creator ();
  9         18  
  9         178  
173 9     9   4353 use Email::Sender::Simple ();
  9         1080330  
  9         301  
174 9     9   86 use Module::Runtime qw(require_module);
  9         18  
  9         45  
175              
176             #####################################################################
177             # Constructor and Accessors
178              
179             #pod =method new
180             #pod
181             #pod Creates a new, empty, Email::Stuffer object.
182             #pod
183             #pod You can pass a hashref of properties to set, including:
184             #pod
185             #pod =for :list
186             #pod * to
187             #pod * from
188             #pod * cc
189             #pod * bcc
190             #pod * reply_to
191             #pod * subject
192             #pod * text_body
193             #pod * html_body
194             #pod * transport
195             #pod
196             #pod The to, cc, bcc, and reply_to headers properties may be provided as array
197             #pod references. The array's contents will be used as the list of arguments to the
198             #pod setter.
199             #pod
200             #pod =cut
201              
202             my %IS_INIT_ARG = map {; $_ => 1 } qw(
203             to from cc bcc reply_to subject text_body html_body transport
204             );
205              
206             my %IS_ARRAY_ARG = map {; $_ => 1 } qw(
207             to cc bcc reply_to
208             transport
209             );
210              
211             sub new {
212 12 50   12 1 979 Carp::croak("new method called on Email::Stuffer instance") if ref $_[0];
213              
214 12         43 my ($class, $arg) = @_;
215              
216 12         109 my $self = bless {
217             parts => [],
218             email => Email::MIME->create(
219             header => [],
220             parts => [],
221             ),
222             }, $class;
223              
224 12 100       37313 my @init_args = keys %{ $arg || {} };
  12         113  
225 12 50       63 if (my @bogus = grep {; ! $IS_INIT_ARG{$_} } @init_args) {
  2         7  
226 0         0 Carp::croak("illegal arguments to Email::Stuffer->new: @bogus");
227             }
228              
229 12         37 for my $init_arg (@init_args) {
230 2         7 my @args = $arg->{$init_arg};
231 2 50 66     15 if ($IS_ARRAY_ARG{$init_arg} && ref $args[0] && ref $args[0] eq 'ARRAY') {
      66        
232 1         2 @args = @{ $args[0] };
  1         4  
233             }
234              
235 2         9 $self->$init_arg(@args);
236             }
237              
238 12         50 $self;
239             }
240              
241             sub _self {
242 68     68   163 my $either = shift;
243 68 100       647 ref($either) ? $either : $either->new;
244             }
245              
246             #pod =method header_names
247             #pod
248             #pod Returns, as a list, all of the headers currently set for the Email
249             #pod For backwards compatibility, this method can also be called as B[headers].
250             #pod
251             #pod =cut
252              
253             sub header_names {
254 0     0 1 0 shift()->{email}->header_names;
255             }
256              
257             sub headers {
258 1     1 0 413 shift()->{email}->header_names; ## This is now header_names, headers is depreciated
259             }
260              
261             #pod =method parts
262             #pod
263             #pod Returns, as a list, the L parts for the Email
264             #pod
265             #pod =cut
266              
267             sub parts {
268 61     61 1 89 grep { defined $_ } @{shift()->{parts}};
  28         72  
  61         168  
269             }
270              
271             #####################################################################
272             # Header Methods
273              
274             #pod =method header $header => $value
275             #pod
276             #pod Sets a named header in the email. Multiple calls with the same $header
277             #pod will overwrite previous calls $value.
278             #pod
279             #pod =cut
280              
281             sub header {
282 3     3 1 1756 my $self = shift()->_self;
283 3 50       15 return unless @_;
284 3         26 $self->{email}->header_str_set(ucfirst shift, shift);
285 3         6111 return $self;
286             }
287              
288             #pod =method to @addresses
289             #pod
290             #pod Sets the To: header in the email
291             #pod
292             #pod =cut
293              
294             sub _assert_addr_list_ok {
295 27     27   75 my ($self, $header, $allow_empty, $list) = @_;
296              
297 27 50 66     133 Carp::croak("$header is a required field")
298             unless $allow_empty or @$list;
299              
300 27         64 for (@$list) {
301 34 50       94 Carp::croak("list of $header headers contains undefined values")
302             unless defined;
303              
304 34 100 66     543 Carp::croak("list of $header headers contains unblessed references")
305             if ref && ! blessed $_;
306             }
307             }
308              
309             sub to {
310 12     12 1 1678 my $self = shift()->_self;
311 12         67 $self->_assert_addr_list_ok(to => 0 => \@_);
312 11 100       114 $self->{email}->header_str_set(To => (@_ > 1 ? \@_ : @_));
313 11         8311 return $self;
314             }
315              
316             #pod =method from $address
317             #pod
318             #pod Sets the From: header in the email
319             #pod
320             #pod =cut
321              
322             sub from {
323 10     10 1 418824 my $self = shift()->_self;
324 10         60 $self->_assert_addr_list_ok(from => 0 => \@_);
325 10 50       39 Carp::croak("only one address is allowed in the from header") if @_ > 1;
326 10         79 $self->{email}->header_str_set(From => shift);
327 10         31193 return $self;
328             }
329              
330             #pod =method reply_to $address
331             #pod
332             #pod Sets the Reply-To: header in the email
333             #pod
334             #pod =cut
335              
336             sub reply_to {
337 1     1 1 607 my $self = shift()->_self;
338 1         6 $self->_assert_addr_list_ok('reply-to' => 0 => \@_);
339 1 50       5 Carp::croak("only one address is allowed in the reply-to header") if @_ > 1;
340 1         6 $self->{email}->header_str_set('Reply-To' => shift);
341 1         253 return $self;
342             }
343              
344             #pod =method cc @addresses
345             #pod
346             #pod Sets the Cc: header in the email
347             #pod
348             #pod =cut
349              
350             sub cc {
351 2     2 1 1325 my $self = shift()->_self;
352 2         10 $self->_assert_addr_list_ok(cc => 1 => \@_);
353 1 50       9 $self->{email}->header_str_set(Cc => (@_ > 1 ? \@_ : @_));
354 1         421 return $self;
355             }
356              
357             #pod =method bcc @addresses
358             #pod
359             #pod Sets the Bcc: header in the email
360             #pod
361             #pod =cut
362              
363             sub bcc {
364 2     2 1 1333 my $self = shift()->_self;
365 2         9 $self->_assert_addr_list_ok(bcc => 1 => \@_);
366 1 50       8 $self->{email}->header_str_set(Bcc => (@_ > 1 ? \@_ : @_));
367 1         389 return $self;
368             }
369              
370             #pod =method subject $text
371             #pod
372             #pod Sets the Subject: header in the email
373             #pod
374             #pod =cut
375              
376             sub subject {
377 10     10 1 813 my $self = shift()->_self;
378 10 50       40 Carp::croak("subject is a required field") unless defined $_[0];
379 10         52 $self->{email}->header_str_set(Subject => shift);
380 10         933 return $self;
381             }
382              
383             #####################################################################
384             # Body and Attachments
385              
386             #pod =method text_body $body [, $attribute => $value, ... ]
387             #pod
388             #pod Sets the text body of the email. Appropriate headers are set for you.
389             #pod You may override MIME attributes as needed. See the C
390             #pod parameter to L for the headers you can set.
391             #pod
392             #pod If C<$body> is undefined, this method will do nothing.
393             #pod
394             #pod Prior to Email::Stuffer version 0.015 text body was marked as flowed,
395             #pod which broke all pre-formated body text. Empty space at the beggining
396             #pod of the line was dropped and every new line character could be changed
397             #pod to one space (and vice versa). Version 0.015 (and later) does not set
398             #pod flowed format automatically anymore and so text body is really plain
399             #pod text. If you want to use old behavior of "advanced" flowed formatting,
400             #pod set flowed format manually by: C<< text_body($body, format => 'flowed') >>.
401             #pod
402             #pod =cut
403              
404             sub text_body {
405 7     7 1 29 my $self = shift()->_self;
406 7 50       45 my $body = defined $_[0] ? shift : return $self;
407 7         46 my %attr = (
408             # Defaults
409             content_type => 'text/plain',
410             charset => 'utf-8',
411             encoding => 'quoted-printable',
412             # Params overwrite them
413             @_,
414             );
415              
416             # Create the part in the text slot
417 7         46 $self->{parts}->[0] = Email::MIME->create(
418             attributes => \%attr,
419             body_str => $body,
420             );
421              
422 7         14239 $self;
423             }
424              
425             #pod =method html_body $body [, $header => $value, ... ]
426             #pod
427             #pod Sets the HTML body of the email. Appropriate headers are set for you.
428             #pod You may override MIME attributes as needed. See the C
429             #pod parameter to L for the headers you can set.
430             #pod
431             #pod If C<$body> is undefined, this method will do nothing.
432             #pod
433             #pod =cut
434              
435             sub html_body {
436 2     2 1 11 my $self = shift()->_self;
437 2 50       9 my $body = defined $_[0] ? shift : return $self;
438 2         12 my %attr = (
439             # Defaults
440             content_type => 'text/html',
441             charset => 'utf-8',
442             encoding => 'quoted-printable',
443             # Params overwrite them
444             @_,
445             );
446              
447             # Create the part in the HTML slot
448 2         10 $self->{parts}->[1] = Email::MIME->create(
449             attributes => \%attr,
450             body_str => $body,
451             );
452              
453 2         3271 $self;
454             }
455              
456             #pod =method attach $contents [, $attribute => $value, ... ]
457             #pod
458             #pod Adds an attachment to the email. The first argument is the file contents
459             #pod followed by (as for text_body and html_body) the list of headers to use.
460             #pod Email::Stuffer will I to guess the headers correctly, but you may wish
461             #pod to provide them anyway to be sure. Encoding is Base64 by default. See
462             #pod the C parameter to L for the headers you
463             #pod can set.
464             #pod
465             #pod =cut
466              
467             sub _detect_content_type {
468 11     11   30 my ($filename, $body) = @_;
469              
470 11 100       26 if (defined($filename)) {
471 6 50       31 if ($filename =~ /\.([a-zA-Z]{3,4})\z/) {
472             my $content_type = {
473             'gif' => 'image/gif',
474             'png' => 'image/png',
475             'jpg' => 'image/jpeg',
476             'jpeg' => 'image/jpeg',
477             'txt' => 'text/plain',
478             'htm' => 'text/html',
479             'html' => 'text/html',
480             'css' => 'text/css',
481             'csv' => 'text/csv',
482             'pdf' => 'application/pdf',
483             'wav' => 'audio/wav',
484 6         64 }->{lc($1)};
485 6 50       37 return $content_type if defined $content_type;
486             }
487             }
488 5 50       30 if ($body =~ /
489             \A(?:
490             (GIF8) # gif
491             | (\xff\xd8) # jpeg
492             | (\x89PNG) # png
493             | (%PDF-) # pdf
494             )
495             /x) {
496 5 100       17 return 'image/gif' if $1;
497 4 100       14 return 'image/jpeg' if $2;
498 3 100       16 return 'image/png' if $3;
499 1 50       11 return 'application/pdf' if $4;
500             }
501 0         0 return 'application/octet-stream';
502             }
503              
504             sub attach {
505 12     12 1 535 my $self = shift()->_self;
506 12 50       35 my $body = defined $_[0] ? shift : return undef;
507 12         80 my %attr = (
508             # Cheap defaults
509             encoding => 'base64',
510             # Params overwrite them
511             @_,
512             );
513              
514             # The more expensive defaults if needed
515 12 100       38 unless ( $attr{content_type} ) {
516 11         35 $attr{content_type} = _detect_content_type($attr{filename}, $body);
517             }
518              
519             ### MORE?
520              
521             # Determine the slot to put it at
522 12         27 my $slot = scalar @{$self->{parts}};
  12         27  
523 12 100       31 $slot = 3 if $slot < 3;
524              
525             # Create the part in the attachment slot
526 12         76 $self->{parts}->[$slot] = Email::MIME->create(
527             attributes => \%attr,
528             body => $body,
529             );
530              
531 12         17441 $self;
532             }
533              
534             #pod =method attach_file $file [, $attribute => $value, ... ]
535             #pod
536             #pod Attachs a file that already exists on the filesystem to the email.
537             #pod C will attempt to auto-detect the MIME type, and use the
538             #pod file's current name when attaching. See the C parameter to
539             #pod L for the headers you can set.
540             #pod
541             #pod =cut
542              
543             sub attach_file {
544 9     9 1 5587 my $self = shift;
545 9         13 my $body_arg = shift;
546 9         23 my $name = undef;
547 9         14 my $body = undef;
548              
549             # Support IO::All::File arguments
550 9 50 66     86 if ( Params::Util::_INSTANCE($body_arg, 'IO::All::File') ) {
    100          
551 0         0 $body_arg->binmode;
552 0         0 $name = $body_arg->name;
553 0         0 $body = $body_arg->all;
554              
555             # Support file names
556             } elsif ( defined $body_arg and Params::Util::_STRING($body_arg) ) {
557 8 100       392 croak "No such file '$body_arg'" unless -f $body_arg;
558 7         21 $name = $body_arg;
559 7         20 $body = _slurp( $body_arg );
560              
561             # That's it
562             } else {
563 1   33     7 my $type = ref($body_arg) || "<$body_arg>";
564 1         120 croak "Expected a file name or an IO::All::File derivative, got $type";
565             }
566              
567             # Clean the file name
568 7         403 $name = File::Basename::basename($name);
569              
570 7 50       28 croak("basename somehow returned undef") unless defined $name;
571              
572             # Now attach as normal
573 7         28 $self->attach( $body, name => $name, filename => $name, @_ );
574             }
575              
576             # Provide a simple _slurp implementation
577             sub _slurp {
578 8     8   701 my $file = shift;
579 8         39 local $/ = undef;
580              
581 8 100       484 open my $slurp, '<:raw', $file or croak("error opening $file: $!");
582 7         322 my $source = <$slurp>;
583 7 50       88 close( $slurp ) or croak "error after slurping $file: $!";
584 7         60 \$source;
585             }
586              
587             #pod =method transport
588             #pod
589             #pod $stuffer->transport( $moniker, @options )
590             #pod
591             #pod or
592             #pod
593             #pod $stuffer->transport( $transport_obj )
594             #pod
595             #pod The C method specifies the L transport that
596             #pod you want to use to send the email, and any options that need to be
597             #pod used to instantiate the transport. C<$moniker> is used as the transport
598             #pod name; if it starts with an equals sign (C<=>) then the text after the
599             #pod sign is used as the class. Otherwise, the text is prepended by
600             #pod C.
601             #pod
602             #pod Alternatively, you can pass a complete transport object (which must be
603             #pod an L object) and it will be used as is.
604             #pod
605             #pod =cut
606              
607             sub transport {
608 7     7 1 25 my $self = shift()->_self;
609              
610 7 50       37 if ( @_ ) {
611             # Change the transport
612 7 50       212 if ( _INSTANCEDOES($_[0], 'Email::Sender::Transport') ) {
613 7         475 $self->{transport} = shift;
614             } else {
615 0         0 my ($moniker, @arg) = @_;
616 0 0       0 my $class = $moniker =~ s/\A=//
617             ? $moniker
618             : "Email::Sender::Transport::$moniker";
619 0         0 require_module($class);
620 0         0 my $transport = $class->new(@arg);
621 0         0 $self->{transport} = $transport;
622             }
623             }
624              
625 7         35 $self;
626             }
627              
628             #####################################################################
629             # Output Methods
630              
631             #pod =method email
632             #pod
633             #pod Creates and returns the full L object for the email.
634             #pod
635             #pod =cut
636              
637             sub email {
638 61     61 1 12253 my $self = shift;
639 61         152 my @parts = $self->parts;
640              
641             ### Lyle Hopkins, code added to Fix single part, and multipart/alternative
642             ### problems
643 61 100       85 if (scalar(@{ $self->{parts} }) >= 3) {
  61 100       170  
644             ## multipart/mixed
645 3         16 $self->{email}->parts_set(\@parts);
646 58         145 } elsif (scalar(@{ $self->{parts} })) {
647             ## Check we actually have any parts
648 5 100 66     121 if ( _INSTANCE($parts[0], 'Email::MIME')
    50          
649             && _INSTANCE($parts[1], 'Email::MIME')
650             ) {
651             ## multipart/alternate
652 1         8 $self->{email}->header_set('Content-Type' => 'multipart/alternative');
653 1         89 $self->{email}->parts_set(\@parts);
654             } elsif (_INSTANCE($parts[0], 'Email::MIME')) {
655             ## As @parts is $self->parts without the blanks, we only need check
656             ## $parts[0]
657             ## single part text/plain
658 4         24 _transfer_headers($self->{email}, $parts[0]);
659 4         344 $self->{email} = $parts[0];
660             }
661             }
662              
663 61         21914 $self->{email};
664             }
665              
666             # Support coercion to an Email::MIME
667 0     0   0 sub __as_Email_MIME { shift()->email }
668              
669             # Quick any routine
670             sub _any (&@) {
671 20     20   37 my $f = shift;
672 20 50       45 return if ! @_;
673 20         42 for (@_) {
674 60 100       88 return 1 if $f->();
675             }
676 12         37 return 0;
677             }
678              
679             # header transfer from one object to another
680             sub _transfer_headers {
681             # $_[0] = from, $_[1] = to
682 4     4   26 my @headers_move = $_[0]->header_names;
683 4         200 my @headers_skip = $_[1]->header_names;
684 4         121 foreach my $header_name (@headers_move) {
685 20 100   60   2133 next if _any { $_ eq $header_name } @headers_skip;
  60         171  
686 12         53 my @values = $_[0]->header($header_name);
687 12         670 $_[1]->header_str_set( $header_name, @values );
688             }
689             }
690              
691             #pod =method as_string
692             #pod
693             #pod Returns the string form of the email. Identical to (and uses behind the
694             #pod scenes) Email::MIME-Eas_string.
695             #pod
696             #pod =cut
697              
698             sub as_string {
699 31     31 1 3794 shift()->email->as_string;
700             }
701              
702             #pod =method send
703             #pod
704             #pod $stuffer->send;
705             #pod
706             #pod or
707             #pod
708             #pod $stuffer->send({ to => [ $to_1, $to_2 ], from => $sender });
709             #pod
710             #pod Sends the email via L.
711             #pod L
712             #pod can be specified in a hash reference.
713             #pod
714             #pod On failure, returns false.
715             #pod
716             #pod =cut
717              
718             sub send {
719 5     5 1 13 my $self = shift;
720 5         9 my $arg = shift;
721 5 50       18 my $email = $self->email or return undef;
722              
723 5         16 my $transport = $self->{transport};
724              
725 5 50       57 Email::Sender::Simple->try_to_send(
    50          
726             $email,
727             {
728             ($transport ? (transport => $transport) : ()),
729             $arg ? %$arg : (),
730             },
731             );
732             }
733              
734             #pod =method send_or_die
735             #pod
736             #pod $stuffer->send_or_die;
737             #pod
738             #pod or
739             #pod
740             #pod $stuffer->send_or_die({ to => [ $to_1, $to_2 ], from => $sender });
741             #pod
742             #pod Sends the email via L.
743             #pod L
744             #pod can be specified in a hash reference.
745             #pod
746             #pod On failure, throws an exception.
747             #pod
748             #pod =cut
749              
750             sub send_or_die {
751 2     2 1 5 my $self = shift;
752 2         3 my $arg = shift;
753 2 50       8 my $email = $self->email or return undef;
754              
755 2         5 my $transport = $self->{transport};
756              
757 2 50       23 Email::Sender::Simple->send(
    50          
758             $email,
759             {
760             ($transport ? (transport => $transport) : ()),
761             $arg ? %$arg : (),
762             },
763             );
764             }
765              
766             1;
767              
768             #pod =head1 TO DO
769             #pod
770             #pod =for :list
771             #pod * Fix a number of bugs still likely to exist
772             #pod * Write more tests.
773             #pod * Add any additional small bit of automation that isn't too expensive
774             #pod
775             #pod =head1 SEE ALSO
776             #pod
777             #pod L, L, L
778             #pod
779             #pod =cut
780              
781             __END__