File Coverage

blib/lib/Email/Stuffer.pm
Criterion Covered Total %
statement 173 185 93.5
branch 67 100 67.0
condition 13 21 61.9
subroutine 36 38 94.7
pod 19 20 95.0
total 308 364 84.6


line stmt bran cond sub pod time code
1 9     9   633687 use v5.12.0;
  9         130  
2 9     9   52 use warnings;
  9         16  
  9         412  
3             package Email::Stuffer 0.019;
4             # ABSTRACT: A more casual approach to creating and sending Email:: emails
5              
6 9     9   60 use Scalar::Util qw(blessed);
  9         29  
  9         756  
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   72 use Carp qw(croak);
  9         13  
  9         434  
167 9     9   59 use File::Basename ();
  9         17  
  9         299  
168 9     9   4753 use Params::Util 1.05 qw(_INSTANCE _INSTANCEDOES);
  9         60341  
  9         653  
169 9     9   5544 use Email::MIME 1.943 ();
  9         552728  
  9         285  
170 9     9   86 use Email::MIME::Creator ();
  9         21  
  9         147  
171 9     9   4260 use Email::Sender::Simple ();
  9         1052904  
  9         287  
172 9     9   89 use Module::Runtime qw(require_module);
  9         22  
  9         44  
173              
174             #####################################################################
175             # Constructor and Accessors
176              
177             #pod =method new
178             #pod
179             #pod Creates a new, empty, Email::Stuffer object.
180             #pod
181             #pod You can pass a hashref of properties to set, including:
182             #pod
183             #pod =for :list
184             #pod * to
185             #pod * from
186             #pod * cc
187             #pod * bcc
188             #pod * reply_to
189             #pod * subject
190             #pod * text_body
191             #pod * html_body
192             #pod * transport
193             #pod
194             #pod The to, cc, bcc, and reply_to headers properties may be provided as array
195             #pod references. The array's contents will be used as the list of arguments to the
196             #pod setter.
197             #pod
198             #pod =cut
199              
200             my %IS_INIT_ARG = map {; $_ => 1 } qw(
201             to from cc bcc reply_to subject text_body html_body transport
202             );
203              
204             my %IS_ARRAY_ARG = map {; $_ => 1 } qw(
205             to cc bcc reply_to
206             transport
207             );
208              
209             sub new {
210 12 50   12 1 1093 Carp::croak("new method called on Email::Stuffer instance") if ref $_[0];
211              
212 12         42 my ($class, $arg) = @_;
213              
214 12         153 my $self = bless {
215             parts => [],
216             email => Email::MIME->create(
217             header => [],
218             parts => [],
219             ),
220             }, $class;
221              
222 12 100       38048 my @init_args = keys %{ $arg || {} };
  12         108  
223 12 50       84 if (my @bogus = grep {; ! $IS_INIT_ARG{$_} } @init_args) {
  2         11  
224 0         0 Carp::croak("illegal arguments to Email::Stuffer->new: @bogus");
225             }
226              
227 12         41 for my $init_arg (@init_args) {
228 2         6 my @args = $arg->{$init_arg};
229 2 50 66     17 if ($IS_ARRAY_ARG{$init_arg} && ref $args[0] && ref $args[0] eq 'ARRAY') {
      66        
230 1         2 @args = @{ $args[0] };
  1         3  
231             }
232              
233 2         9 $self->$init_arg(@args);
234             }
235              
236 12         41 $self;
237             }
238              
239             sub _self {
240 68     68   140 my $either = shift;
241 68 100       294 ref($either) ? $either : $either->new;
242             }
243              
244             #pod =method header_names
245             #pod
246             #pod Returns, as a list, all of the headers currently set for the Email
247             #pod For backwards compatibility, this method can also be called as B[headers].
248             #pod
249             #pod =cut
250              
251             sub header_names {
252 0     0 1 0 shift()->{email}->header_names;
253             }
254              
255             sub headers {
256 1     1 0 596 shift()->{email}->header_names; ## This is now header_names, headers is depreciated
257             }
258              
259             #pod =method parts
260             #pod
261             #pod Returns, as a list, the L parts for the Email
262             #pod
263             #pod =cut
264              
265             sub parts {
266 61     61 1 90 grep { defined $_ } @{shift()->{parts}};
  28         67  
  61         162  
267             }
268              
269             #####################################################################
270             # Header Methods
271              
272             #pod =method header $header => $value
273             #pod
274             #pod Sets a named header in the email. Multiple calls with the same $header
275             #pod will overwrite previous calls $value.
276             #pod
277             #pod =cut
278              
279             sub header {
280 3     3 1 1670 my $self = shift()->_self;
281 3 50       12 return unless @_;
282 3         26 $self->{email}->header_str_set(ucfirst shift, shift);
283 3         3023 return $self;
284             }
285              
286             #pod =method to @addresses
287             #pod
288             #pod Sets the To: header in the email
289             #pod
290             #pod =cut
291              
292             sub _assert_addr_list_ok {
293 27     27   80 my ($self, $header, $allow_empty, $list) = @_;
294              
295 27 50 66     135 Carp::croak("$header is a required field")
296             unless $allow_empty or @$list;
297              
298 27         67 for (@$list) {
299 34 50       76 Carp::croak("list of $header headers contains undefined values")
300             unless defined;
301              
302 34 100 66     448 Carp::croak("list of $header headers contains unblessed references")
303             if ref && ! blessed $_;
304             }
305             }
306              
307             sub to {
308 12     12 1 1739 my $self = shift()->_self;
309 12         113 $self->_assert_addr_list_ok(to => 0 => \@_);
310 11 100       109 $self->{email}->header_str_set(To => (@_ > 1 ? \@_ : @_));
311 11         8039 return $self;
312             }
313              
314             #pod =method from $address
315             #pod
316             #pod Sets the From: header in the email
317             #pod
318             #pod =cut
319              
320             sub from {
321 10     10 1 410085 my $self = shift()->_self;
322 10         58 $self->_assert_addr_list_ok(from => 0 => \@_);
323 10 50       37 Carp::croak("only one address is allowed in the from header") if @_ > 1;
324 10         70 $self->{email}->header_str_set(From => shift);
325 10         13246 return $self;
326             }
327              
328             #pod =method reply_to $address
329             #pod
330             #pod Sets the Reply-To: header in the email
331             #pod
332             #pod =cut
333              
334             sub reply_to {
335 1     1 1 574 my $self = shift()->_self;
336 1         8 $self->_assert_addr_list_ok('reply-to' => 0 => \@_);
337 1 50       6 Carp::croak("only one address is allowed in the reply-to header") if @_ > 1;
338 1         5 $self->{email}->header_str_set('Reply-To' => shift);
339 1         261 return $self;
340             }
341              
342             #pod =method cc @addresses
343             #pod
344             #pod Sets the Cc: header in the email
345             #pod
346             #pod =cut
347              
348             sub cc {
349 2     2 1 1333 my $self = shift()->_self;
350 2         9 $self->_assert_addr_list_ok(cc => 1 => \@_);
351 1 50       16 $self->{email}->header_str_set(Cc => (@_ > 1 ? \@_ : @_));
352 1         394 return $self;
353             }
354              
355             #pod =method bcc @addresses
356             #pod
357             #pod Sets the Bcc: header in the email
358             #pod
359             #pod =cut
360              
361             sub bcc {
362 2     2 1 1221 my $self = shift()->_self;
363 2         11 $self->_assert_addr_list_ok(bcc => 1 => \@_);
364 1 50       8 $self->{email}->header_str_set(Bcc => (@_ > 1 ? \@_ : @_));
365 1         381 return $self;
366             }
367              
368             #pod =method subject $text
369             #pod
370             #pod Sets the Subject: header in the email
371             #pod
372             #pod =cut
373              
374             sub subject {
375 10     10 1 1142 my $self = shift()->_self;
376 10 50       42 Carp::croak("subject is a required field") unless defined $_[0];
377 10         49 $self->{email}->header_str_set(Subject => shift);
378 10         984 return $self;
379             }
380              
381             #####################################################################
382             # Body and Attachments
383              
384             #pod =method text_body $body [, $attributes => $value, ... ]
385             #pod
386             #pod Sets the text body of the email. Appropriate headers are set for you.
387             #pod You may override MIME attributes as needed. See the C
388             #pod parameter to L for the headers you can set.
389             #pod
390             #pod If C<$body> is undefined, this method will do nothing.
391             #pod
392             #pod Prior to Email::Stuffer version 0.015 text body was marked as flowed,
393             #pod which broke all pre-formated body text. Empty space at the beggining
394             #pod of the line was dropped and every new line character could be changed
395             #pod to one space (and vice versa). Version 0.015 (and later) does not set
396             #pod flowed format automatically anymore and so text body is really plain
397             #pod text. If you want to use old behavior of "advanced" flowed formatting,
398             #pod set flowed format manually by: C<< text_body($body, format => 'flowed') >>.
399             #pod
400             #pod =cut
401              
402             sub text_body {
403 7     7 1 22 my $self = shift()->_self;
404 7 50       34 my $body = defined $_[0] ? shift : return $self;
405 7         46 my %attr = (
406             # Defaults
407             content_type => 'text/plain',
408             charset => 'utf-8',
409             encoding => 'quoted-printable',
410             # Params overwrite them
411             @_,
412             );
413              
414             # Create the part in the text slot
415 7         44 $self->{parts}->[0] = Email::MIME->create(
416             attributes => \%attr,
417             body_str => $body,
418             );
419              
420 7         14151 $self;
421             }
422              
423             #pod =method html_body $body [, $header => $value, ... ]
424             #pod
425             #pod Sets the HTML body of the email. Appropriate headers are set for you.
426             #pod You may override MIME attributes as needed. See the C
427             #pod parameter to L for the headers you can set.
428             #pod
429             #pod If C<$body> is undefined, this method will do nothing.
430             #pod
431             #pod =cut
432              
433             sub html_body {
434 2     2 1 10 my $self = shift()->_self;
435 2 50       14 my $body = defined $_[0] ? shift : return $self;
436 2         15 my %attr = (
437             # Defaults
438             content_type => 'text/html',
439             charset => 'utf-8',
440             encoding => 'quoted-printable',
441             # Params overwrite them
442             @_,
443             );
444              
445             # Create the part in the HTML slot
446 2         10 $self->{parts}->[1] = Email::MIME->create(
447             attributes => \%attr,
448             body_str => $body,
449             );
450              
451 2         3481 $self;
452             }
453              
454             #pod =method attach $contents [, $attribute => $value, ... ]
455             #pod
456             #pod Adds an attachment to the email. The first argument is the file contents
457             #pod followed by (as for text_body and html_body) the list of headers to use.
458             #pod Email::Stuffer will I to guess the headers correctly, but you may wish
459             #pod to provide them anyway to be sure. Encoding is Base64 by default. See
460             #pod the C parameter to L for the headers you
461             #pod can set.
462             #pod
463             #pod =cut
464              
465             sub _detect_content_type {
466 11     11   35 my ($filename, $body) = @_;
467              
468 11 100       26 if (defined($filename)) {
469 6 50       31 if ($filename =~ /\.([a-zA-Z]{3,4})\z/) {
470             my $content_type = {
471             'gif' => 'image/gif',
472             'png' => 'image/png',
473             'jpg' => 'image/jpeg',
474             'jpeg' => 'image/jpeg',
475             'txt' => 'text/plain',
476             'htm' => 'text/html',
477             'html' => 'text/html',
478             'css' => 'text/css',
479             'csv' => 'text/csv',
480             'pdf' => 'application/pdf',
481             'wav' => 'audio/wav',
482 6         70 }->{lc($1)};
483 6 50       41 return $content_type if defined $content_type;
484             }
485             }
486 5 50       27 if ($body =~ /
487             \A(?:
488             (GIF8) # gif
489             | (\xff\xd8) # jpeg
490             | (\x89PNG) # png
491             | (%PDF-) # pdf
492             )
493             /x) {
494 5 100       17 return 'image/gif' if $1;
495 4 100       14 return 'image/jpeg' if $2;
496 3 100       45 return 'image/png' if $3;
497 1 50       8 return 'application/pdf' if $4;
498             }
499 0         0 return 'application/octet-stream';
500             }
501              
502             sub attach {
503 12     12 1 518 my $self = shift()->_self;
504 12 50       33 my $body = defined $_[0] ? shift : return undef;
505 12         49 my %attr = (
506             # Cheap defaults
507             encoding => 'base64',
508             # Params overwrite them
509             @_,
510             );
511              
512             # The more expensive defaults if needed
513 12 100       50 unless ( $attr{content_type} ) {
514 11         38 $attr{content_type} = _detect_content_type($attr{filename}, $body);
515             }
516              
517             ### MORE?
518              
519             # Determine the slot to put it at
520 12         22 my $slot = scalar @{$self->{parts}};
  12         27  
521 12 100       32 $slot = 3 if $slot < 3;
522              
523             # Create the part in the attachment slot
524 12         77 $self->{parts}->[$slot] = Email::MIME->create(
525             attributes => \%attr,
526             body => $body,
527             );
528              
529 12         18820 $self;
530             }
531              
532             #pod =method attach_file $file [, $attribute => $value, ... ]
533             #pod
534             #pod Attachs a file that already exists on the filesystem to the email.
535             #pod C will attempt to auto-detect the MIME type, and use the
536             #pod file's current name when attaching. See the C parameter to
537             #pod L for the headers you can set.
538             #pod
539             #pod =cut
540              
541             sub attach_file {
542 9     9 1 5594 my $self = shift;
543 9         17 my $body_arg = shift;
544 9         15 my $name = undef;
545 9         15 my $body = undef;
546              
547             # Support IO::All::File arguments
548 9 50 66     91 if ( Params::Util::_INSTANCE($body_arg, 'IO::All::File') ) {
    100          
549 0         0 $body_arg->binmode;
550 0         0 $name = $body_arg->name;
551 0         0 $body = $body_arg->all;
552              
553             # Support file names
554             } elsif ( defined $body_arg and Params::Util::_STRING($body_arg) ) {
555 8 100       319 croak "No such file '$body_arg'" unless -f $body_arg;
556 7         23 $name = $body_arg;
557 7         22 $body = _slurp( $body_arg );
558              
559             # That's it
560             } else {
561 1   33     5 my $type = ref($body_arg) || "<$body_arg>";
562 1         84 croak "Expected a file name or an IO::All::File derivative, got $type";
563             }
564              
565             # Clean the file name
566 7         306 $name = File::Basename::basename($name);
567              
568 7 50       26 croak("basename somehow returned undef") unless defined $name;
569              
570             # Now attach as normal
571 7         31 $self->attach( $body, name => $name, filename => $name, @_ );
572             }
573              
574             # Provide a simple _slurp implementation
575             sub _slurp {
576 8     8   691 my $file = shift;
577 8         39 local $/ = undef;
578              
579 8 100       449 open my $slurp, '<:raw', $file or croak("error opening $file: $!");
580 7         414 my $source = <$slurp>;
581 7 50       105 close( $slurp ) or croak "error after slurping $file: $!";
582 7         62 \$source;
583             }
584              
585             #pod =method transport
586             #pod
587             #pod $stuffer->transport( $moniker, @options )
588             #pod
589             #pod or
590             #pod
591             #pod $stuffer->transport( $transport_obj )
592             #pod
593             #pod The C method specifies the L transport that
594             #pod you want to use to send the email, and any options that need to be
595             #pod used to instantiate the transport. C<$moniker> is used as the transport
596             #pod name; if it starts with an equals sign (C<=>) then the text after the
597             #pod sign is used as the class. Otherwise, the text is prepended by
598             #pod C.
599             #pod
600             #pod Alternatively, you can pass a complete transport object (which must be
601             #pod an L object) and it will be used as is.
602             #pod
603             #pod =cut
604              
605             sub transport {
606 7     7 1 28 my $self = shift()->_self;
607              
608 7 50       35 if ( @_ ) {
609             # Change the transport
610 7 50       46 if ( _INSTANCEDOES($_[0], 'Email::Sender::Transport') ) {
611 7         339 $self->{transport} = shift;
612             } else {
613 0         0 my ($moniker, @arg) = @_;
614 0 0       0 my $class = $moniker =~ s/\A=//
615             ? $moniker
616             : "Email::Sender::Transport::$moniker";
617 0         0 require_module($class);
618 0         0 my $transport = $class->new(@arg);
619 0         0 $self->{transport} = $transport;
620             }
621             }
622              
623 7         34 $self;
624             }
625              
626             #####################################################################
627             # Output Methods
628              
629             #pod =method email
630             #pod
631             #pod Creates and returns the full L object for the email.
632             #pod
633             #pod =cut
634              
635             sub email {
636 61     61 1 12075 my $self = shift;
637 61         152 my @parts = $self->parts;
638              
639             ### Lyle Hopkins, code added to Fix single part, and multipart/alternative
640             ### problems
641 61 100       91 if (scalar(@{ $self->{parts} }) >= 3) {
  61 100       167  
642             ## multipart/mixed
643 3         19 $self->{email}->parts_set(\@parts);
644 58         154 } elsif (scalar(@{ $self->{parts} })) {
645             ## Check we actually have any parts
646 5 100 66     145 if ( _INSTANCE($parts[0], 'Email::MIME')
    50          
647             && _INSTANCE($parts[1], 'Email::MIME')
648             ) {
649             ## multipart/alternate
650 1         12 $self->{email}->header_set('Content-Type' => 'multipart/alternative');
651 1         70 $self->{email}->parts_set(\@parts);
652             } elsif (_INSTANCE($parts[0], 'Email::MIME')) {
653             ## As @parts is $self->parts without the blanks, we only need check
654             ## $parts[0]
655             ## single part text/plain
656 4         26 _transfer_headers($self->{email}, $parts[0]);
657 4         402 $self->{email} = $parts[0];
658             }
659             }
660              
661 61         24478 $self->{email};
662             }
663              
664             # Support coercion to an Email::MIME
665 0     0   0 sub __as_Email_MIME { shift()->email }
666              
667             # Quick any routine
668             sub _any (&@) {
669 20     20   38 my $f = shift;
670 20 50       52 return if ! @_;
671 20         38 for (@_) {
672 60 100       89 return 1 if $f->();
673             }
674 12         39 return 0;
675             }
676              
677             # header transfer from one object to another
678             sub _transfer_headers {
679             # $_[0] = from, $_[1] = to
680 4     4   27 my @headers_move = $_[0]->header_names;
681 4         216 my @headers_skip = $_[1]->header_names;
682 4         130 foreach my $header_name (@headers_move) {
683 20 100   60   2096 next if _any { $_ eq $header_name } @headers_skip;
  60         175  
684 12         65 my @values = $_[0]->header($header_name);
685 12         586 $_[1]->header_str_set( $header_name, @values );
686             }
687             }
688              
689             #pod =method as_string
690             #pod
691             #pod Returns the string form of the email. Identical to (and uses behind the
692             #pod scenes) Email::MIME-Eas_string.
693             #pod
694             #pod =cut
695              
696             sub as_string {
697 31     31 1 3749 shift()->email->as_string;
698             }
699              
700             #pod =method send
701             #pod
702             #pod $stuffer->send;
703             #pod
704             #pod or
705             #pod
706             #pod $stuffer->send({ to => [ $to_1, $to_2 ], from => $sender });
707             #pod
708             #pod Sends the email via L.
709             #pod L
710             #pod can be specified in a hash reference.
711             #pod
712             #pod On failure, returns false.
713             #pod
714             #pod =cut
715              
716             sub send {
717 5     5 1 13 my $self = shift;
718 5         11 my $arg = shift;
719 5 50       17 my $email = $self->email or return undef;
720              
721 5         17 my $transport = $self->{transport};
722              
723 5 50       69 Email::Sender::Simple->try_to_send(
    50          
724             $email,
725             {
726             ($transport ? (transport => $transport) : ()),
727             $arg ? %$arg : (),
728             },
729             );
730             }
731              
732             #pod =method send_or_die
733             #pod
734             #pod $stuffer->send_or_die;
735             #pod
736             #pod or
737             #pod
738             #pod $stuffer->send_or_die({ to => [ $to_1, $to_2 ], from => $sender });
739             #pod
740             #pod Sends the email via L.
741             #pod L
742             #pod can be specified in a hash reference.
743             #pod
744             #pod On failure, throws an exception.
745             #pod
746             #pod =cut
747              
748             sub send_or_die {
749 2     2 1 4 my $self = shift;
750 2         6 my $arg = shift;
751 2 50       10 my $email = $self->email or return undef;
752              
753 2         9 my $transport = $self->{transport};
754              
755 2 50       28 Email::Sender::Simple->send(
    50          
756             $email,
757             {
758             ($transport ? (transport => $transport) : ()),
759             $arg ? %$arg : (),
760             },
761             );
762             }
763              
764             1;
765              
766             #pod =head1 TO DO
767             #pod
768             #pod =for :list
769             #pod * Fix a number of bugs still likely to exist
770             #pod * Write more tests.
771             #pod * Add any additional small bit of automation that isn't too expensive
772             #pod
773             #pod =head1 SEE ALSO
774             #pod
775             #pod L, L, L
776             #pod
777             #pod =cut
778              
779             __END__