| 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__ |