summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfukachan <fukachan>2001-04-06 12:54:55 +0000
committerfukachan <fukachan>2001-04-06 12:54:55 +0000
commiteea2c34e5bebdaab143ffd7851c685fd9fa42454 (patch)
treec65265919b537ca5a062552f8bfc35ae2ebd8a05
parentd5acf8761f04aef6a5f1eb5f2c27c8675521b040 (diff)
downloadfml8-eea2c34e5bebdaab143ffd7851c685fd9fa42454.tar.gz
fml8-eea2c34e5bebdaab143ffd7851c685fd9fa42454.tar.bz2
fml8-eea2c34e5bebdaab143ffd7851c685fd9fa42454.zip
Initial revision
-rw-r--r--cpan/dist/MIME-Lite/COPYING248
-rw-r--r--cpan/dist/MIME-Lite/INSTALLING26
-rw-r--r--cpan/dist/MIME-Lite/MANIFEST35
-rwxr-xr-xcpan/dist/MIME-Lite/Makefile.PL20
-rw-r--r--cpan/dist/MIME-Lite/README1357
-rw-r--r--cpan/dist/MIME-Lite/README.system8
-rw-r--r--cpan/dist/MIME-Lite/docs/MIME/Lite.pm.html1976
-rw-r--r--cpan/dist/MIME-Lite/docs/MIME/icons/h1bullet.gifbin0 -> 421 bytes
-rw-r--r--cpan/dist/MIME-Lite/docs/MIME/icons/h2bullet.gifbin0 -> 345 bytes
-rw-r--r--cpan/dist/MIME-Lite/docs/MIME/icons/zeegee.gifbin0 -> 5269 bytes
-rw-r--r--cpan/dist/MIME-Lite/docs/icons/h1bullet.gifbin0 -> 421 bytes
-rw-r--r--cpan/dist/MIME-Lite/docs/icons/h2bullet.gifbin0 -> 345 bytes
-rw-r--r--cpan/dist/MIME-Lite/docs/icons/zeegee.gifbin0 -> 5269 bytes
-rw-r--r--cpan/dist/MIME-Lite/docs/index-menu.html27
-rw-r--r--cpan/dist/MIME-Lite/docs/index.html13
-rw-r--r--cpan/dist/MIME-Lite/docs/index.menu24
-rw-r--r--cpan/dist/MIME-Lite/docs/mime_fwd.html55
-rw-r--r--cpan/dist/MIME-Lite/docs/mime_gif.html56
-rw-r--r--cpan/dist/MIME-Lite/docs/mime_hack.html55
-rw-r--r--cpan/dist/MIME-Lite/docs/mime_longlines.html72
-rw-r--r--cpan/dist/MIME-Lite/docs/mime_postcard.html59
-rwxr-xr-xcpan/dist/MIME-Lite/examples/mime_fwd69
-rwxr-xr-xcpan/dist/MIME-Lite/examples/mime_gif93
-rwxr-xr-xcpan/dist/MIME-Lite/examples/mime_hack58
-rwxr-xr-xcpan/dist/MIME-Lite/examples/mime_longlines92
-rwxr-xr-xcpan/dist/MIME-Lite/examples/mime_postcard79
-rw-r--r--cpan/dist/MIME-Lite/lib/MIME/Lite.pm3227
-rw-r--r--cpan/dist/MIME-Lite/t/ExtUtils/TBone.pm534
-rw-r--r--cpan/dist/MIME-Lite/t/Utils.pm23
-rw-r--r--cpan/dist/MIME-Lite/t/addrs.t87
-rw-r--r--cpan/dist/MIME-Lite/t/data.t55
-rw-r--r--cpan/dist/MIME-Lite/t/head.t87
-rw-r--r--cpan/dist/MIME-Lite/t/verify.t39
-rw-r--r--cpan/dist/MIME-Lite/testin/README1
-rw-r--r--cpan/dist/MIME-Lite/testin/hello2
-rw-r--r--cpan/lib/MIME/Lite.pm3227
36 files changed, 11704 insertions, 0 deletions
diff --git a/cpan/dist/MIME-Lite/COPYING b/cpan/dist/MIME-Lite/COPYING
new file mode 100644
index 00000000..3c68f02b
--- /dev/null
+++ b/cpan/dist/MIME-Lite/COPYING
@@ -0,0 +1,248 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/cpan/dist/MIME-Lite/INSTALLING b/cpan/dist/MIME-Lite/INSTALLING
new file mode 100644
index 00000000..0e9c6e93
--- /dev/null
+++ b/cpan/dist/MIME-Lite/INSTALLING
@@ -0,0 +1,26 @@
+------------------------------------------------------------
+STANDARD INSTALLATION
+
+On most systems, just do this from the command line:
+
+ perl Makefile.PL
+ make test
+ make install
+
+Please note that you'll need permission to write to the
+standard installation directories; under Unix-like systems, this
+often means that you must be logged in as "root".
+
+If you're on a non-Unix platform, you might be using 'dmake'
+instead of 'make'.
+
+------------------------------------------------------------
+NON-STANDARD INSTALLATION
+
+To install to a non-standard place else (e.g., "/home/me/lib"),
+see the manual page for ExtUtils::MakeMaker, or try this:
+
+ perl Makefile.PL LIB=/home/me/lib
+ make test
+ make install
+
diff --git a/cpan/dist/MIME-Lite/MANIFEST b/cpan/dist/MIME-Lite/MANIFEST
new file mode 100644
index 00000000..44cd881b
--- /dev/null
+++ b/cpan/dist/MIME-Lite/MANIFEST
@@ -0,0 +1,35 @@
+COPYING
+INSTALLING
+MANIFEST
+Makefile.PL
+README
+README.system
+docs/MIME/Lite.pm.html
+docs/MIME/icons/h1bullet.gif
+docs/MIME/icons/h2bullet.gif
+docs/MIME/icons/zeegee.gif
+docs/icons/h1bullet.gif
+docs/icons/h2bullet.gif
+docs/icons/zeegee.gif
+docs/index-menu.html
+docs/index.html
+docs/index.menu
+docs/mime_fwd.html
+docs/mime_gif.html
+docs/mime_hack.html
+docs/mime_longlines.html
+docs/mime_postcard.html
+examples/mime_fwd
+examples/mime_gif
+examples/mime_hack
+examples/mime_longlines
+examples/mime_postcard
+lib/MIME/Lite.pm
+t/ExtUtils/TBone.pm
+t/Utils.pm
+t/addrs.t
+t/data.t
+t/head.t
+t/verify.t
+testin/README
+testin/hello
diff --git a/cpan/dist/MIME-Lite/Makefile.PL b/cpan/dist/MIME-Lite/Makefile.PL
new file mode 100755
index 00000000..447f1cb1
--- /dev/null
+++ b/cpan/dist/MIME-Lite/Makefile.PL
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+use ExtUtils::MakeMaker;
+
+#------------------------------------------------------------
+# Makefile:
+#------------------------------------------------------------
+
+# Write the Makefile:
+WriteMakefile(
+ NAME => 'MIME::Lite',
+ VERSION_FROM => "lib/MIME/Lite.pm",
+ DISTNAME => "MIME-Lite",
+ EXE_FILES => [@EXES],
+ 'dist' => {
+ PREOP => 'cvu_perl_preop -m MIME::Lite -f',
+ COMPRESS => 'gzip',
+ SUFFIX => 'gz',
+ }
+ );
+
diff --git a/cpan/dist/MIME-Lite/README b/cpan/dist/MIME-Lite/README
new file mode 100644
index 00000000..0f884797
--- /dev/null
+++ b/cpan/dist/MIME-Lite/README
@@ -0,0 +1,1357 @@
+NAME
+ MIME::Lite - low-calorie MIME generator
+
+SYNOPSIS
+ use MIME::Lite;
+
+ Create a single-part message:
+
+ ### Create a new single-part message, to send a GIF file:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'Helloooooo, nurse!',
+ Type =>'image/gif',
+ Encoding =>'base64',
+ Path =>'hellonurse.gif'
+ );
+
+ Create a multipart message (i.e., one with attachments):
+
+ ### Create a new multipart message:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'A message with 2 parts...',
+ Type =>'multipart/mixed'
+ );
+
+ ### Add parts (each "attach" has same arguments as "new"):
+ $msg->attach(Type =>'TEXT',
+ Data =>"Here's the GIF file you wanted"
+ );
+ $msg->attach(Type =>'image/gif',
+ Path =>'aaa000123.gif',
+ Filename =>'logo.gif',
+ Disposition => 'attachment'
+ );
+
+ Output a message:
+
+ ### Format as a string:
+ $str = $msg->as_string;
+
+ ### Print to a filehandle (say, a "sendmail" stream):
+ $msg->print(\*SENDMAIL);
+
+ Send a message:
+
+ ### Send in the "best" way (the default is to use "sendmail"):
+ $msg->send;
+
+DESCRIPTION
+ In the never-ending quest for great taste with fewer calories, we
+ proudly present: *MIME::Lite*.
+
+ MIME::Lite is intended as a simple, standalone module for generating
+ (not parsing!) MIME messages... specifically, it allows you to output a
+ simple, decent single- or multi-part message with text or binary
+ attachments. It does not require that you have the Mail:: or MIME::
+ modules installed.
+
+ You can specify each message part as either the literal data itself (in
+ a scalar or array), or as a string which can be given to open() to get a
+ readable filehandle (e.g., "<filename" or "somecommand|").
+
+ You don't need to worry about encoding your message data: this module
+ will do that for you. It handles the 5 standard MIME encodings.
+
+ If you need more sophisticated behavior, please get the MIME-tools
+ package instead. I will be more likely to add stuff to that toolkit over
+ this one.
+
+MORE EXAMPLES
+ Attach a GIF to a text message
+
+ This will create a multipart message exactly as above, but using the
+ "attach to singlepart" hack:
+
+ ### Create a new multipart message:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'A message with 2 parts...',
+ Type =>'TEXT',
+ Data =>"Here's the GIF file you wanted"
+ );
+
+ ### Attach a part:
+ $msg->attach(Type =>'image/gif',
+ Path =>'aaa000123.gif',
+ Filename =>'logo.gif'
+ );
+
+ Attach a pre-prepared part (allows fine-tuning):
+
+ $part = MIME::Lite->new(
+ Type =>'text/html',
+ Data =>'<H1>Hello</H1>',
+ );
+ $part->attr('content-type.charset' => 'UTF8');
+ $part->add('X-Comment' => 'A message for you');
+ $msg->attach($part);
+
+ Send an HTML document... with images included!
+
+ $msg = MIME::Lite->new(
+ To =>'you@yourhost.com',
+ Subject =>'HTML with in-line images!',
+ Type =>'multipart/related'
+ );
+ $msg->attach(Type => 'text/html',
+ Data => qq{ <body>
+ Here's <i>my</i> image:
+ <img src="cid:myimage.gif">
+ </body> }
+ );
+ $msg->attach(Type => 'image/gif',
+ Id => 'myimage.gif',
+ Path => '/path/to/somefile.gif',
+ );
+ $msg->send();
+
+ Output a message to a filehandle
+
+ ### Write it to a filehandle:
+ $msg->print(\*STDOUT);
+
+ ### Write just the header:
+ $msg->print_header(\*STDOUT);
+
+ ### Write just the encoded body:
+ $msg->print_body(\*STDOUT);
+
+ Get a message as a string
+
+ ### Get entire message as a string:
+ $str = $msg->as_string;
+
+ ### Get just the header:
+ $str = $msg->header_as_string;
+
+ ### Get just the encoded body:
+ $str = $msg->body_as_string;
+
+ Change how messages are sent
+
+ ### Do something like this in your 'main':
+ if ($I_DONT_HAVE_SENDMAIL) {
+ MIME::Lite->send('smtp', "smtp.myisp.net", Timeout=>60);
+ }
+
+ ### Now this will do the right thing:
+ $msg->send; ### will now use Net::SMTP as shown above
+
+FAQ
+ How do I prevent "Content" headers from showing up in my mail reader?
+
+ Apparently, some people are using mail readers which display the MIME
+ headers like "Content-disposition", and they want MIME::Lite not to
+ generate them "because they look ugly".
+
+ Sigh.
+
+ Y'know, kids, those headers aren't just there for cosmetic purposes.
+ They help ensure that the message is *understood* correctly by mail
+ readers. But okay, you asked for it, you got it... here's how you can
+ suppress the standard MIME headers. Before you send the message, do
+ this:
+
+ $msg->scrub;
+
+ You can scrub() any part of a multipart message independently; just be
+ aware that it works recursively. Before you scrub, note the rules that I
+ follow:
+
+ Content-type
+ You can safely scrub the "content-type" attribute if, and only if,
+ the part is of type "text/plain" with charset "us-ascii".
+
+ Content-transfer-encoding
+ You can safely scrub the "content-transfer-encoding" attribute if,
+ and only if, the part uses "7bit", "8bit", or "binary" encoding. You
+ are far better off doing this if your lines are under 1000
+ characters. Generally, that means you *can* scrub it for plain text,
+ and you can *not* scrub this for images, etc.
+
+ Content-disposition
+ You can safely scrub the "content-disposition" attribute if you
+ trust the mail reader to do the right thing when it decides whether
+ to show an attachment inline or as a link. Be aware that scrubbing
+ both the content-disposition and the content-type means that there
+ is no way to "recommend" a filename for the attachment!
+
+ Note: there are reports of brain-dead MUAs out there that do the
+ wrong thing if you *provide* the content-disposition. If your
+ attachments keep showing up inline or vice-versa, try scrubbing this
+ attribute.
+
+ Content-length
+ You can always scrub "content-length" safely.
+
+ How do I give my attachment a [different] recommended filename?
+
+ By using the Filename option (which is different from Path!):
+
+ $msg->attach(Type => "image/gif",
+ Path => "/here/is/the/real/file.GIF",
+ Filename => "logo.gif");
+
+ You should *not* put path information in the Filename.
+
+PUBLIC INTERFACE
+ Global configuration
+
+ To alter the way the entire module behaves, you have the following
+ methods/options:
+
+ MIME::Lite->header_order()
+ When used as a classmethod, this changes the default order in which
+ headers are output for *all* messages.
+
+ MIME::Lite->quiet()
+ This classmethod can be used to suppress/unsuppress all warnings
+ coming from this module.
+
+ MIME::Lite->send()
+ When used as a classmethod, this can be used to specify a different
+ default mechanism for sending message. The initial default is:
+
+ MIME::Lite->send("sendmail", "/usr/lib/sendmail -t -oi -oem");
+
+ However, you should consider the similar but smarter and taint-safe
+ variant:
+
+ MIME::Lite->send("sendmail");
+
+ Or, for non-Unix users:
+
+ MIME::Lite->send("smtp");
+
+ $MIME::Lite::PARANOID
+ If true, we won't attempt to use MIME::Base64/MIME::QuotedPrint,
+ even if they're available. Default is false.
+
+ $MIME::Lite::AUTO_ENCODE
+ If true, automatically choose the encoding from the content type.
+ Default is true.
+
+ $MIME::Lite::AUTO_CC
+ If true, automatically send to the Cc/Bcc addresses for
+ send_by_smtp(). Default is true.
+
+ $MIME::Lite::AUTO_VERIFY
+ If true, check paths to attachments right before printing, raising
+ an exception if any path is unreadable. Default is true.
+
+ Construction
+
+ new [PARAMHASH]
+ *Class method, constructor.* Create a new message object.
+
+ If any arguments are given, they are passed into `build()';
+ otherwise, just the empty object is created.
+
+ attach PART
+ attach PARAMHASH...
+ *Instance method.* Add a new part to this message, and return the
+ new part.
+
+ If you supply a single PART argument, it will be regarded as a
+ MIME::Lite object to be attached. Otherwise, this method assumes
+ that you are giving in the pairs of a PARAMHASH which will be sent
+ into `new()' to create the new part.
+
+ One of the possibly-quite-useful hacks thrown into this is the
+ "attach-to-singlepart" hack: if you attempt to attach a part (let's
+ call it "part 1") to a message that doesn't have a content-type of
+ "multipart" or "message", the following happens:
+
+ * A new part (call it "part 0") is made.
+
+ * The MIME attributes and data (but *not* the other headers) are cut
+ from the "self" message, and pasted into "part 0".
+
+ * The "self" is turned into a "multipart/mixed" message.
+
+ * The new "part 0" is added to the "self", and *then* "part 1" is
+ added.
+
+ One of the nice side-effects is that you can create a text message
+ and then add zero or more attachments to it, much in the same way
+ that a user agent like Netscape allows you to do.
+
+ build [PARAMHASH]
+ *Class/instance method, initializer.* Create (or initialize) a MIME
+ message object. Normally, you'll use the following keys in
+ PARAMHASH:
+
+ * Data, FH, or Path (either one of these, or none if multipart)
+ * Type (e.g., "image/jpeg")
+ * From, To, and Subject (if this is the "top level" of a message)
+
+ The PARAMHASH can contain the following keys:
+
+ (fieldname)
+ Any field you want placed in the message header, taken from the
+ standard list of header fields (you don't need to worry about
+ case):
+
+ Approved Encrypted Received Sender
+ Bcc From References Subject
+ Cc Keywords Reply-To To
+ Comments Message-ID Resent-* X-*
+ Content-* MIME-Version Return-Path
+ Date Organization
+
+ To give experienced users some veto power, these fields will be
+ set *after* the ones I set... so be careful: *don't set any MIME
+ fields* (like `Content-type') unless you know what you're doing!
+
+ To specify a fieldname that's *not* in the above list, even one
+ that's identical to an option below, just give it with a
+ trailing `":"', like `"My-field:"'. When in doubt, that *always*
+ signals a mail field (and it sort of looks like one too).
+
+ Data *Alternative to "Path" or "FH".* The actual message data. This may
+ be a scalar or a ref to an array of strings; if the latter, the
+ message consists of a simple concatenation of all the strings in
+ the array.
+
+ Datestamp
+ *Optional.* If given true (or omitted), we force the creation of
+ a `Date:' field stamped with the current date/time if this is a
+ top-level message. You may want this if using send_by_smtp(). If
+ you don't want this to be done, either provide your own Date or
+ explicitly set this to false.
+
+ Disposition
+ *Optional.* The content disposition, `"inline"' or
+ `"attachment"'. The default is `"inline"'.
+
+ Encoding
+ *Optional.* The content transfer encoding that should be used to
+ encode your data:
+
+ Use encoding: | If your message contains:
+ ------------------------------------------------------------
+ 7bit | Only 7-bit text, all lines <1000 characters
+ 8bit | 8-bit text, all lines <1000 characters
+ quoted-printable | 8-bit text or long lines (more reliable than "8bit")
+ base64 | Largely non-textual data: a GIF, a tar file, etc.
+
+ The default is taken from the Type; generally it is "binary" (no
+ encoding) for text/*, message/*, and multipart/*, and "base64"
+ for everything else. A value of `"binary"' is generally *not*
+ suitable for sending anything but ASCII text files with lines
+ under 1000 characters, so consider using one of the other values
+ instead.
+
+ In the case of "7bit"/"8bit", long lines are automatically
+ chopped to legal length; in the case of "7bit", all 8-bit
+ characters are automatically *removed*. This may not be what you
+ want, so pick your encoding well! For more info, see the section
+ on "A MIME PRIMER".
+
+ FH *Alternative to "Data" or "Path".* Filehandle containing the data,
+ opened for reading. See "ReadNow" also.
+
+ Filename
+ *Optional.* The name of the attachment. You can use this to
+ supply a recommended filename for the end-user who is saving the
+ attachment to disk. You only need this if the filename at the
+ end of the "Path" is inadequate, or if you're using "Data"
+ instead of "Path". You should *not* put path information in here
+ (e.g., no "/" or "\" or ":" characters should be used).
+
+ Id *Optional.* Same as setting "content-id".
+
+ Length *Optional.* Set the content length explicitly. Normally, this header
+ is automatically computed, but only under certain circumstances
+ (see the section on "Limitations").
+
+ Path *Alternative to "Data" or "FH".* Path to a file containing the
+ data... actually, it can be any open()able expression. If it
+ looks like a path, the last element will automatically be
+ treated as the filename. See "ReadNow" also.
+
+ ReadNow *Optional, for use with "Path".* If true, will open the path and
+ slurp the contents into core now. This is useful if the Path
+ points to a command and you don't want to run the command over
+ and over if outputting the message several times. Fatal
+ exception raised if the open fails.
+
+ Top *Optional.* If defined, indicates whether or not this is a "top-
+ level" MIME message. The parts of a multipart message are *not*
+ top-level. Default is true.
+
+ Type *Optional.* The MIME content type, or one of these special values
+ (case-sensitive):
+
+ "TEXT" means "text/plain"
+ "BINARY" means "application/octet-stream"
+
+ The default is `"TEXT"'.
+
+ A picture being worth 1000 words (which is of course 2000 bytes, so
+ it's probably more of an "icon" than a "picture", but I digress...),
+ here are some examples:
+
+ $msg = MIME::Lite->build(
+ From => 'yelling@inter.com',
+ To => 'stocking@fish.net',
+ Subject => "Hi there!",
+ Type => 'TEXT',
+ Encoding => '7bit',
+ Data => "Just a quick note to say hi!");
+
+ $msg = MIME::Lite->build(
+ From => 'dorothy@emerald-city.oz',
+ To => 'gesundheit@edu.edu.edu',
+ Subject => "A gif for U"
+ Type => 'image/gif',
+ Path => "/home/httpd/logo.gif");
+
+ $msg = MIME::Lite->build(
+ From => 'laughing@all.of.us',
+ To => 'scarlett@fiddle.dee.de',
+ Subject => "A gzipp'ed tar file",
+ Type => 'x-gzip',
+ Path => "gzip < /usr/inc/somefile.tar |",
+ ReadNow => 1,
+ Filename => "somefile.tgz");
+
+ To show you what's really going on, that last example could also
+ have been written:
+
+ $msg = new MIME::Lite;
+ $msg->build(Type => 'x-gzip',
+ Path => "gzip < /usr/inc/somefile.tar |",
+ ReadNow => 1,
+ Filename => "somefile.tgz");
+ $msg->add(From => "laughing@all.of.us");
+ $msg->add(To => "scarlett@fiddle.dee.de");
+ $msg->add(Subject => "A gzipp'ed tar file");
+
+ Setting/getting headers and attributes
+
+ add TAG,VALUE
+ *Instance method.* Add field TAG with the given VALUE to the end of
+ the header. The TAG will be converted to all-lowercase, and the
+ VALUE will be made "safe" (returns will be given a trailing space).
+
+ Beware: any MIME fields you "add" will override any MIME attributes
+ I have when it comes time to output those fields. Normally, you will
+ use this method to add *non-MIME* fields:
+
+ $msg->add("Subject" => "Hi there!");
+
+ Giving VALUE as an arrayref will cause all those values to be added.
+ This is only useful for special multiple-valued fields like
+ "Received":
+
+ $msg->add("Received" => ["here", "there", "everywhere"]
+
+ Giving VALUE as the empty string adds an invisible placeholder to
+ the header, which can be used to suppress the output of the
+ "Content-*" fields or the special "MIME-Version" field. When
+ suppressing fields, you should use replace() instead of add():
+
+ $msg->replace("Content-disposition" => "");
+
+ *Note:* add() is probably going to be more efficient than
+ `replace()', so you're better off using it for most applications if
+ you are certain that you don't need to delete() the field first.
+
+ *Note:* the name comes from Mail::Header.
+
+ attr ATTR,[VALUE]
+ *Instance method.* Set MIME attribute ATTR to the string VALUE. ATTR
+ is converted to all-lowercase. This method is normally used to
+ set/get MIME attributes:
+
+ $msg->attr("content-type" => "text/html");
+ $msg->attr("content-type.charset" => "US-ASCII");
+ $msg->attr("content-type.name" => "homepage.html");
+
+ This would cause the final output to look something like this:
+
+ Content-type: text/html; charset=US-ASCII; name="homepage.html"
+
+ Note that the special empty sub-field tag indicates the anonymous
+ first sub-field.
+
+ Giving VALUE as undefined will cause the contents of the named
+ subfield to be deleted.
+
+ Supplying no VALUE argument just returns the attribute's value:
+
+ $type = $msg->attr("content-type"); ### returns "text/html"
+ $name = $msg->attr("content-type.name"); ### returns "homepage.html"
+
+ delete TAG
+ *Instance method.* Delete field TAG with the given VALUE to the end
+ of the header. The TAG will be converted to all-lowercase.
+
+ $msg->delete("Subject");
+
+ *Note:* the name comes from Mail::Header.
+
+ field_order FIELD,...FIELD
+ *Class/instance method.* Change the order in which header fields are
+ output for this object:
+
+ $msg->field_order('from', 'to', 'content-type', 'subject');
+
+ When used as a class method, changes the default settings for all
+ objects:
+
+ MIME::Lite->field_order('from', 'to', 'content-type', 'subject');
+
+ Case does not matter: all field names will be coerced to lowercase.
+ In either case, supply the empty array to restore the default
+ ordering.
+
+ fields
+ *Instance method.* Return the full header for the object, as a ref
+ to an array of `[TAG, VALUE]' pairs, where each TAG is all-
+ lowercase. Note that any fields the user has explicitly set will
+ override the corresponding MIME fields that we would otherwise
+ generate. So, don't say...
+
+ $msg->set("Content-type" => "text/html; charset=US-ASCII");
+
+ unless you want the above value to override the "Content-type" MIME
+ field that we would normally generate.
+
+ *Note:* I called this "fields" because the header() method of
+ Mail::Header returns something different, but similar enough to be
+ confusing.
+
+ You can change the order of the fields: see the header_order entry
+ elsewhere in this document . You really shouldn't need to do this,
+ but some people have to deal with broken mailers.
+
+ filename [FILENAME]
+ *Instance method.* Set the filename which this data will be reported
+ as. This actually sets both "standard" attributes.
+
+ With no argument, returns the filename as dictated by the content-
+ disposition.
+
+ get TAG,[INDEX]
+ *Instance method.* Get the contents of field TAG, which might have
+ been set with set() or replace(). Returns the text of the field.
+
+ $ml->get('Subject', 0);
+
+ If the optional 0-based INDEX is given, then we return the INDEX'th
+ occurence of field TAG. Otherwise, we look at the context: In a
+ scalar context, only the first (0th) occurence of the field is
+ returned; in an array context, *all* occurences are returned.
+
+ *Warning:* this should only be used with non-MIME fields. Behavior
+ with MIME fields is TBD, and will raise an exception for now.
+
+ get_length
+ *Instance method.* Recompute the content length for the message *if
+ the process is trivial*, setting the "content-length" attribute as a
+ side-effect:
+
+ $msg->get_length;
+
+ Returns the length, or undefined if not set.
+
+ *Note:* the content length can be difficult to compute, since it
+ involves assembling the entire encoded body and taking the length of
+ it (which, in the case of multipart messages, means freezing all the
+ sub-parts, etc.).
+
+ This method only sets the content length to a defined value if the
+ message is a singlepart with `"binary"' encoding, *and* the body is
+ available either in-core or as a simple file. Otherwise, the content
+ length is set to the undefined value.
+
+ Since content-length is not a standard MIME field anyway (that's
+ right, kids: it's not in the MIME RFCs, it's an HTTP thing), this
+ seems pretty fair.
+
+ replace TAG,VALUE
+ *Instance method.* Delete all occurences of fields named TAG, and
+ add a new field with the given VALUE. TAG is converted to all-
+ lowercase.
+
+ Beware the special MIME fields (MIME-version, Content-*): if you
+ "replace" a MIME field, the replacement text will override the
+ *actual* MIME attributes when it comes time to output that field. So
+ normally you use attr() to change MIME fields and add()/replace() to
+ change *non-MIME* fields:
+
+ $msg->replace("Subject" => "Hi there!");
+
+ Giving VALUE as the *empty string* will effectively *prevent* that
+ field from being output. This is the correct way to suppress the
+ special MIME fields:
+
+ $msg->replace("Content-disposition" => "");
+
+ Giving VALUE as *undefined* will just cause all explicit values for
+ TAG to be deleted, without having any new values added.
+
+ *Note:* the name of this method comes from Mail::Header.
+
+ scrub
+ *Instance method.* This is Alpha code. If you use it, please let me
+ know how it goes. Recursively goes through the "parts" tree of this
+ message and tries to find MIME attributes that can be removed. With
+ an array argument, removes exactly those attributes; e.g.:
+
+ $msg->scrub(['content-disposition', 'content-length']);
+
+ Is the same as recursively doing:
+
+ $msg->replace('Content-disposition' => '');
+ $msg->replace('Content-length' => '');
+
+ Setting/getting message data
+
+ binmode [OVERRIDE]
+ *Instance method.* With no argument, returns whether or not it
+ thinks that the data (as given by the "Path" argument of `build()')
+ should be read using binmode() (for example, when `read_now()' is
+ invoked).
+
+ The default behavior is that any content type other than `text/*' or
+ `message/*' is binmode'd; this should in general work fine.
+
+ With a defined argument, this method sets an explicit "override"
+ value. An undefined argument unsets the override. The new current
+ value is returned.
+
+ data [DATA]
+ *Instance method.* Get/set the literal DATA of the message. The DATA
+ may be either a scalar, or a reference to an array of scalars (which
+ will simply be joined).
+
+ *Warning:* setting the data causes the "content-length" attribute to
+ be recomputed (possibly to nothing).
+
+ path [PATH]
+ Get/set the PATH to the message data.
+
+ *Warning:* setting the path recomputes any existing "content-length"
+ field, and re-sets the "filename" (to the last element of the path
+ if it looks like a simple path, and to nothing if not).
+
+ fh [FILEHANDLE]
+ Get/set the FILEHANDLE which contains the message data.
+
+ Takes a filehandle as an input and stores it in the object. This
+ routine is similar to path(); one important difference is that no
+ attempt is made to set the content length.
+
+ resetfh [FILEHANDLE]
+ Set the current position of the filehandle back to the beginning.
+ Only applies if you used "FH" in build() or attach() for this
+ message.
+
+ Returns false if unable to reset the filehandle (since not all
+ filehandles are seekable).
+
+ read_now
+ Forces data from the path/filehandle (as specified by `build()') to
+ be read into core immediately, just as though you had given it
+ literally with the `Data' keyword.
+
+ Note that the in-core data will always be used if available.
+
+ Be aware that everything is slurped into a giant scalar: you may not
+ want to use this if sending tar files! The benefit of *not* reading
+ in the data is that very large files can be handled by this module
+ if left on disk until the message is output via `print()' or
+ `print_body()'.
+
+ sign PARAMHASH
+ Sign the message. This forces the message to be read into core,
+ after which the signature is appended to it.
+
+ Data As in `build()': the literal signature data. Can be either a scalar
+ or a ref to an array of scalars.
+
+ Path As in `build()': the path to the file.
+
+ If no arguments are given, the default is:
+
+ Path => "$ENV{HOME}/.signature"
+
+ The content-length is recomputed.
+
+ verify_data
+ *Instance method.* Verify that all "paths" to attached data exist,
+ recursively. It might be a good idea for you to do this before a
+ print(), to prevent accidental partial output if a file might be
+ missing. Raises exception if any path is not readable.
+
+ Output
+
+ print [OUTHANDLE]
+ *Instance method.* Print the message to the given output handle, or
+ to the currently-selected filehandle if none was given.
+
+ All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+ any object that responds to a print() message.
+
+ print_body [OUTHANDLE]
+ *Instance method.* Print the body of a message to the given output
+ handle, or to the currently-selected filehandle if none was given.
+
+ All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+ any object that responds to a print() message.
+
+ Fatal exception raised if unable to open any of the input files, or
+ if a part contains no data, or if an unsupported encoding is
+ encountered.
+
+ print_header [OUTHANDLE]
+ *Instance method.* Print the header of the message to the given
+ output handle, or to the currently-selected filehandle if none was
+ given.
+
+ All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+ any object that responds to a print() message.
+
+ as_string
+ *Instance method.* Return the entire message as a string, with a
+ header and an encoded body.
+
+ body_as_string
+ *Instance method.* Return the encoded body as a string. This is the
+ portion after the header and the blank line.
+
+ *Note:* actually prepares the body by "printing" to a scalar. Proof
+ that you can hand the `print*()' methods any blessed object that
+ responds to a `print()' message.
+
+ header_as_string
+ *Instance method.* Return the header as a string.
+
+ Sending
+
+ send
+ send HOW, HOWARGS...
+ *Class/instance method.* This is the principal method for sending
+ mail, and for configuring how mail will be sent.
+
+ *As an instance method* (with no arguments), sends the message by
+ whatever means has been set up (the default is to use the Unix
+ "sendmail" program). Returns whatever the mail-handling routine
+ returns: this should be true on success, false/exception on error:
+
+ $msg = MIME::Lite->new(From=>...);
+ $msg->send || die "you DON'T have mail!";
+
+ *As a class method* (with a HOW argument and optional HOWARGS), sets
+ up how the instance method will work for all objects until further
+ notice It treats HOW as a facility name, with optional HOWARGS
+ handled by the facility (and returns the previous HOW and HOWARGS as
+ an array). There are three facilities:
+
+ "sendmail", ARGS...
+ Send a message by piping it into the "sendmail" command. Uses
+ the send_by_sendmail() method, giving it the ARGS. This usage
+ implements (and deprecates) the `sendmail()' method.
+
+ "smtp", [HOSTNAME]
+ Send a message by SMTP, using optional HOSTNAME as SMTP-sending
+ host. Uses the send_by_smtp() method.
+
+ "sub", \&SUBREF, ARGS...
+ Sends a message MSG by invoking the subroutine SUBREF of your
+ choosing, with MSG as the first argument, and ARGS following.
+
+ *For example:* let's say you're on an OS which lacks the usual Unix
+ "sendmail" facility, but you've installed something a lot like it,
+ and you need to configure your Perl script to use this
+ "sendmail.exe" program. Do this following in your script's setup:
+
+ MIME::Lite->send('sendmail', "d:\\programs\\sendmail.exe");
+
+ Then, whenever you need to send a message $msg, just say:
+
+ $msg->send;
+
+ That's it. Now, if you ever move your script to a Unix box, all you
+ need to do is change that line in the setup and you're done. All of
+ your $msg->send invocations will work as expected.
+
+ send_by_sendmail SENDMAILCMD
+ send_by_sendmail PARAM=>VALUE, ...
+ *Instance method.* Send message via an external "sendmail" program
+ (this will probably only work out-of-the-box on Unix systems).
+
+ Returns true on success, false or exception on error.
+
+ You can specify the program and all its arguments by giving a single
+ string, SENDMAILCMD. Nothing fancy is done; the message is simply
+ piped in.
+
+ However, if your needs are a little more advanced, you can specify
+ zero or more of the following PARAM/VALUE pairs; a Unix-style,
+ taint-safe "sendmail" command will be constructed for you:
+
+ Sendmail
+ Full path to the program to use. Default is "/usr/lib/sendmail".
+
+ BaseArgs
+ Ref to the basic array of arguments we start with. Default is
+ `["-t", "-oi", "-oem"]'.
+
+ SetSender
+ Unless this is *explicitly* given as false, we attempt to
+ automatically set the `-f' argument to the first address that
+ can be extracted from the "From:" field of the message (if there
+ is one).
+
+ *What is the -f, and why do we use it?* Suppose we did *not* use
+ `-f', and you gave an explicit "From:" field in your message: in
+ this case, the sendmail "envelope" would indicate the *real*
+ user your process was running under, as a way of preventing mail
+ forgery. Using the `-f' switch causes the sender to be set in
+ the envelope as well.
+
+ *So when would I NOT want to use it?* If sendmail doesn't regard
+ you as a "trusted" user, it will permit the `-f' but also add an
+ "X-Authentication-Warning" header to the message to indicate a
+ forged envelope. To avoid this, you can either (1) have
+ SetSender be false, or (2) make yourself a trusted user by
+ adding a `T' configuration command to your *sendmail.cf* file
+ (e.g.: `Teryq' if the script is running as user "eryq").
+
+ FromSender
+ If defined, this is identical to setting SetSender to true,
+ except that instead of looking at the "From:" field we use the
+ address given by this option. Thus:
+
+ FromSender => 'me@myhost.com'
+
+ send_by_smtp ARGS...
+ *Instance method.* Send message via SMTP, using Net::SMTP. The
+ optional ARGS are sent into Net::SMTP::new(): usually, these are
+
+ MAILHOST, OPTION=>VALUE, ...
+
+ Note that the list of recipients is taken from the "To", "Cc" and
+ "Bcc" fields.
+
+ Returns true on success, false or exception on error.
+
+ sendmail COMMAND...
+ *Class method, DEPRECATED.* Declare the sender to be "sendmail", and
+ set up the "sendmail" command. *You should use send() instead.*
+
+ Miscellaneous
+
+ quiet ONOFF
+ *Class method.* Suppress/unsuppress all warnings coming from this
+ module.
+
+ MIME::Lite->quiet(1); ### I know what I'm doing
+
+ I recommend that you include that comment as well. And while you
+ type it, say it out loud: if it doesn't feel right, then maybe you
+ should reconsider the whole line. `;-)'
+
+NOTES
+ Benign limitations
+
+ This is "lite", after all...
+
+ * There's no parsing. Get MIME-tools if you need to parse MIME messages.
+
+ * MIME::Lite messages are currently *not* interchangeable with either
+ Mail::Internet or MIME::Entity objects. This is a completely
+ separate module.
+
+ * A content-length field is only inserted if the encoding is binary, the
+ message is a singlepart, and all the document data is available at
+ `build()' time by virtue of residing in a simple path, or in-core.
+ Since content-length is not a standard MIME field anyway (that's
+ right, kids: it's not in the MIME RFCs, it's an HTTP thing), this
+ seems pretty fair.
+
+ * MIME::Lite alone cannot help you lose weight. You must supplement your
+ use of MIME::Lite with a healthy diet and exercise.
+
+ Cheap and easy mailing
+
+ I thought putting in a default "sendmail" invocation wasn't too bad an
+ idea, since a lot of Perlers are on UNIX systems. The out-of-the-box
+ configuration is:
+
+ MIME::Lite->send('sendmail', "/usr/lib/sendmail -t -oi -oem");
+
+ By the way, these arguments to sendmail are:
+
+ -t Scan message for To:, Cc:, Bcc:, etc.
+
+ -oi Do NOT treat a single "." on a line as a message terminator.
+ As in, "-oi vey, it truncated my message... why?!"
+
+ -oem On error, mail back the message (I assume to the
+ appropriate address, given in the header).
+ When mail returns, circle is complete. Jai Guru Deva -oem.
+
+ Note that these are the same arguments you get if you configure to use
+ the smarter, taint-safe mailing:
+
+ MIME::Lite->send('sendmail');
+
+ If you get "X-Authentication-Warning" headers from this, you can forgo
+ diddling with the envelope by instead specifying:
+
+ MIME::Lite->send('sendmail', SetSender=>0);
+
+ And, if you're not on a Unix system, or if you'd just rather send mail
+ some other way, there's always:
+
+ MIME::Lite->send('smtp', "smtp.myisp.net");
+
+ Or you can set up your own subroutine to call. In any case, check out
+ the send() method.
+
+WARNINGS
+ Good-vs-bad email addresses with send_by_smtp()
+
+ If using send_by_smtp(), be aware that you are forcing MIME::Lite to
+ extract email addresses out of a possible list provided in the `To:',
+ `Cc:', and `Bcc:' fields. This is tricky stuff, and as such only the
+ following sorts of addresses will work reliably:
+
+ username
+ full.name@some.host.com
+ "Name, Full" <full.name@some.host.com>
+
+ This last form is discouraged because SMTP must be able to get at the
+ *name* or *name@domain* portion.
+
+ Disclaimer: MIME::Lite was never intended to be a Mail User Agent, so
+ please don't expect a full implementation of RFC-822. Restrict yourself
+ to the common forms of Internet addresses described herein, and you
+ should be fine. If this is not feasible, then consider using MIME::Lite
+ to *prepare* your message only, and using Net::SMTP explicitly to *send*
+ your message.
+
+ Formatting of headers delayed until print()
+
+ This class treats a MIME header in the most abstract sense, as being a
+ collection of high-level attributes. The actual RFC-822-style header
+ fields are not constructed until it's time to actually print the darn
+ thing.
+
+ Encoding of data delayed until print()
+
+ When you specify message bodies (in build() or attach()) -- whether by
+ FH, Data, or Path -- be warned that we don't attempt to open files, read
+ filehandles, or encode the data until print() is invoked.
+
+ In the past, this created some confusion for users of sendmail who gave
+ the wrong path to an attachment body, since enough of the print() would
+ succeed to get the initial part of the message out. Nowadays,
+ $AUTO_VERIFY is used to spot-check the Paths given before the mail
+ facility is employed. A whisker slower, but tons safer.
+
+ Note that if you give a message body via FH, and try to print() a
+ message twice, the second print() will not do the right thing unless you
+ explicitly rewind the filehandle.
+
+ You can get past these difficulties by using the ReadNow option,
+ provided that you have enough memory to handle your messages.
+
+ MIME attributes are separate from header fields!
+
+ Important: the MIME attributes are stored and manipulated separately
+ from the message header fields; when it comes time to print the header
+ out, *any explicitly-given header fields override the ones that would be
+ created from the MIME attributes.* That means that this:
+
+ ### DANGER ### DANGER ### DANGER ### DANGER ### DANGER ###
+ $msg->add("Content-type", "text/html; charset=US-ASCII");
+
+ will set the exact `"Content-type"' field in the header I write,
+ *regardless of what the actual MIME attributes are.*
+
+ *This feature is for experienced users only,* as an escape hatch in case
+ the code that normally formats MIME header fields isn't doing what you
+ need. And, like any escape hatch, it's got an alarm on it: MIME::Lite
+ will warn you if you attempt to `set()' or `replace()' any MIME header
+ field. Use `attr()' instead.
+
+ Beware of lines consisting of a single dot
+
+ Julian Haight noted that MIME::Lite allows you to compose messages with
+ lines in the body consisting of a single ".". This is true: it should be
+ completely harmless so long as "sendmail" is used with the -oi option
+ (see the section on "Cheap and easy mailing").
+
+ However, I don't know if using Net::SMTP to transfer such a message is
+ equally safe. Feedback is welcomed.
+
+ My perspective: I don't want to magically diddle with a user's message
+ unless absolutely positively necessary. Some users may want to send
+ files with "." alone on a line; my well-meaning tinkering could
+ seriously harm them.
+
+ Infinite loops may mean tainted data!
+
+ Stefan Sautter noticed a bug in 2.106 where a m//gc match was failing
+ due to tainted data, leading to an infinite loop inside MIME::Lite.
+
+ I am attempting to correct for this, but be advised that my fix will
+ silently untaint the data (given the context in which the problem
+ occurs, this should be benign: I've labelled the source code with
+ UNTAINT comments for the curious).
+
+ So: don't depend on taint-checking to save you from outputting tainted
+ data in a message.
+
+A MIME PRIMER
+ Content types
+
+ The "Type" parameter of `build()' is a *content type*. This is the
+ actual type of data you are sending. Generally this is a string of the
+ form `"majortype/minortype"'.
+
+ Here are the major MIME types. A more-comprehensive listing may be found
+ in RFC-2046.
+
+ application
+ Data which does not fit in any of the other categories, particularly
+ data to be processed by some type of application program.
+ `application/octet-stream', `application/gzip',
+ `application/postscript'...
+
+ audio
+ Audio data. `audio/basic'...
+
+ image
+ Graphics data. `image/gif', `image/jpeg'...
+
+ message
+ A message, usually another mail or MIME message. `message/rfc822'...
+
+ multipart
+ A message containing other messages. `multipart/mixed',
+ `multipart/alternative'...
+
+ text
+ Textual data, meant for humans to read. `text/plain', `text/html'...
+
+ video
+ Video or video+audio data. `video/mpeg'...
+
+ Content transfer encodings
+
+ The "Encoding" parameter of `build()'. This is how the message body is
+ packaged up for safe transit.
+
+ Here are the 5 major MIME encodings. A more-comprehensive listing may be
+ found in RFC-2045.
+
+ 7bit
+ Basically, no *real* encoding is done. However, this label
+ guarantees that no 8-bit characters are present, and that lines do
+ not exceed 1000 characters in length.
+
+ 8bit
+ Basically, no *real* encoding is done. The message might contain 8-
+ bit characters, but this encoding guarantees that lines do not
+ exceed 1000 characters in length.
+
+ binary
+ No encoding is done at all. Message might contain 8-bit characters,
+ and lines might be longer than 1000 characters long.
+
+ The most liberal, and the least likely to get through mail gateways.
+ Use sparingly, or (better yet) not at all.
+
+ base64
+ Like "uuencode", but very well-defined. This is how you should send
+ essentially binary information (tar files, GIFs, JPEGs, etc.).
+
+ quoted-printable
+ Useful for encoding messages which are textual in nature, yet which
+ contain non-ASCII characters (e.g., Latin-1, Latin-2, or any other
+ 8-bit alphabet).
+
+VERSION
+ $Id: Lite.pm,v 2.108 2001/03/30 06:16:54 eryq Exp $
+
+CHANGE LOG
+ Version 2.108
+ New `field_order()' allows you to set the header order, both on a
+ per-message basis, and package-wide. *Thanks to Thomas Stromberg for
+ suggesting this.*
+
+ Added code to try and divine "sendmail" path more intelligently.
+ *Thanks to Slaven Rezic for the suggestion.*
+
+ Version 2.107 (2001/03/27)
+ Fixed serious bug where tainted data with quoted-printable encoding
+ was causing infinite loops. The "fix" untaints the data in question,
+ which is not optimal, but it's probably benign in this case. *Thanks
+ to Stefan Sautter for tracking this nasty little beast down.*
+ *Thanks to Larry Geralds for a related patch.*
+
+ "Doctor, O doctor:
+ it's painful when I do *this* --"
+ "Simple: don't *do* that."
+
+ Fixed bugs where a non-local `$_' was being modified... again! Will
+ I never learn? *Thanks to Maarten Koskamp for reporting this.*
+
+ Dollar-underscore
+ can poison distant waters;
+ 'local' must it be.
+
+ Fixed buglet in `add()' where all value references were being
+ treated as arrayrefs, instead of as possibly-self-stringifying
+ object refs. Now you can send in an object ref as the 2nd argument.
+ *Thanks to dLux for the bug report.*
+
+ That ref is a string?
+ Operator overload
+ has ruined my day.
+
+ Added "Approved" as an acceptable header field for `new()', as per
+ RFC1036. *Thanks to Thomax for the suggestion regarding MIME-tools.*
+
+ Small improvements to docs to make different uses of attach() and
+ various arguments clearer. *Thanks to Sven Rassman and Roland Walter
+ for the suggestions.*
+
+ Version 2.106 (2000/11/21)
+ Added Alpha version of scrub() to make it easy for people to
+ suppress the printing of unwanted MIME attributes (like Content-
+ length). *Thanks to the many people who asked for this.*
+
+ Headers with empty-strings for their values are no longer printed.
+ This seems sensible, and helps us implement scrub().
+
+ Version 2.105 (2000/10/14)
+ The regression-test failure was identified, and it was my fault.
+ Apparently some of the \-quoting in my "autoloaded" code was making
+ Perl 5.6 unhappy. For this nesting-related idiocy, a nesting kaiku.
+ *Thanks to Scott Schwartz for identifying the problem.*
+
+ In a pattern, my
+ backslash-s dwells peacefully,
+ unambiguous --
+
+ but I embed it
+ in a double-quoted string
+ doubling the backslash --
+
+ interpolating
+ that same double-quoted string
+ in other patterns --
+
+ and, worlds within worlds,
+ I single-quote the function
+ to autoload it --
+
+ changing the meaning
+ of the backslash and the 's';
+ and Five-Point-Six growls.
+
+ Version 2.104 (2000/09/28)
+ Now attempts to load and use Mail::Address for parsing email
+ addresses *before* falling back to our own method. *Thanks to
+ numerous people for suggesting this.*
+
+ Parsing addresses
+ is too damn hard. One last hope:
+ Let Graham Barr do it!
+
+ For the curious, the version of Mail::Address appears as the "A"
+ number in the X-Mailer:
+
+ X-Mailer: MIME::Lite 2.104 (A1.15; B2.09; Q2.03)
+
+ Added FromSender option to send_by_sendmail(). *Thanks to Bill
+ Moseley for suggesting this feature.*
+
+ Version 2.101 (2000/06/06)
+ Major revision to print_body() and body_as_string() so that "body"
+ really means "the part after the header", which is what most people
+ would want in this context. This is not how it was used 1.x, where
+ "body" only meant "the body of a simple singlepart". Hopefully, this
+ change will solve many problems and create very few ones.
+
+ Added support for attaching a part to a "message/rfc822", treating
+ the "message" type as a multipart-like container.
+
+ Now takes care not to include "Bcc:" in header when using
+ send_by_smtp, as a safety precaution against qmail's behavior.
+ *Thanks to Tatsuhiko Miyagawa for identifying this problem.*
+
+ Improved efficiency of many stringifying operations by using string-
+ arrays which are joined, instead of doing multiple appends to a
+ scalar.
+
+ Cleaned up the "examples" directory.
+
+ Version 1.147 (2000/06/02)
+ Fixed buglet where lack of Cc:/Bcc: was causing extract_addrs to
+ emit "undefined variable" warnings. Also, lack of a "To:" field now
+ causes a croak. *Thanks to David Mitchell for the bug report and
+ suggested patch.*
+
+ Version 1.146 (2000/05/18)
+ Fixed bug in parsing of addresses; please read the WARNINGS section
+ which describes recommended address formats for "To:", "Cc:", etc.
+ Also added automatic inclusion of a UT "Date:" at top level unless
+ explicitly told not to. *Thanks to Andy Jacobs for the bug report
+ and the suggestion.*
+
+ Version 1.145 (2000/05/06)
+ Fixed bug in encode_7bit(): a lingering `/e' modifier was removed.
+ *Thanks to Michael A. Chase for the patch.*
+
+ Version 1.142 (2000/05/02)
+ Added new, taint-safe invocation of "sendmail", one which also sets
+ up the `-f' option. Unfortunately, I couldn't make this automatic:
+ the change could have broken a lot of code out there which used
+ send_by_sendmail() with unusual "sendmail" variants. So you'll have
+ to configure "send" to use the new mechanism:
+
+ MIME::Lite->send('sendmail'); ### no args!
+
+ *Thanks to Jeremy Howard for suggesting these features.*
+
+ Version 1.140 (2000/04/27)
+ Fixed bug in support for "To", "Cc", and "Bcc" in send_by_smtp():
+ multiple (comma-separated) addresses should now work fine. We try
+ real hard to extract addresses from the flat text strings. *Thanks
+ to John Mason for motivating this change.*
+
+ Added automatic verification that attached data files exist, done
+ immediately before the "send" action is invoked. To turn this off,
+ set $MIME::Lite::AUTO_VERIFY to false.
+
+ Version 1.137 (2000/03/22)
+ Added support for "Cc" and "Bcc" in send_by_smtp(). To turn this
+ off, set $MIME::Lite::AUTO_CC to false. *Thanks to Lucas Maneos for
+ the patch, and tons of others for the suggestion.*
+
+ Chooses a better default content-transfer-encoding if the content-
+ type is "image/*", "audio/*", etc. To turn this off, set
+ $MIME::Lite::AUTO_ENCODE to false. *Thanks to many folks for the
+ suggestion.*
+
+ Fixed bug in QP-encoding where a non-local `$_' was being modified.
+ *Thanks to Jochen Stenzel for finding this very obscure bug!*
+
+ Removed references to `$`', `$'', and `$&' (bad variables which slow
+ things down).
+
+ Added an example of how to send HTML files with enclosed in-line
+ images, per popular demand.
+
+ Version 1.133 (1999/04/17)
+ Fixed bug in "Data" handling: arrayrefs were not being handled
+ properly.
+
+ Version 1.130 (1998/12/14)
+ Added much larger and more-flexible send() facility. *Thanks to
+ Andrew McRae (and Optimation New Zealand Ltd) for the Net::SMTP
+ interface. Additional thanks to the many folks who requested this
+ feature.*
+
+ Added get() method for extracting basic attributes.
+
+ New... "t" tests!
+
+ Version 1.124 (1998/11/13)
+ Folded in filehandle (FH) support in build/attach. *Thanks to Miko
+ O'Sullivan for the code.*
+
+ Version 1.122 (1998/01/19)
+ MIME::Base64 and MIME::QuotedPrint are used if available.
+
+ The 7bit encoding no longer does "escapes"; it merely strips 8-bit
+ characters.
+
+ Version 1.121 (1997/04/08)
+ Filename attribute is now no longer ignored by build(). *Thanks to
+ Ian Smith for finding and patching this bug.*
+
+ Version 1.120 (1997/03/29)
+ Efficiency hack to speed up MIME::Lite::IO_Scalar. *Thanks to David
+ Aspinwall for the patch.*
+
+ Version 1.116 (1997/03/19)
+ Small bug in our private copy of encode_base64() was patched.
+ *Thanks to Andreas Koenig for pointing this out.*
+
+ New, prettier way of specifying mail message headers in `build()'.
+
+ New quiet method to turn off warnings.
+
+ Changed "stringify" methods to more-standard "as_string" methods.
+
+ Version 1.112 (1997/03/06)
+ Added `read_now()', and `binmode()' method for our non-Unix-using
+ brethren: file data is now read using binmode() if appropriate.
+ *Thanks to Xiangzhou Wang for pointing out this bug.*
+
+ Version 1.110 (1997/03/06)
+ Fixed bug in opening the data filehandle.
+
+ Version 1.102 (1997/03/01)
+ Initial release.
+
+ Version 1.101 (1997/03/01)
+ Baseline code.
+
+TERMS AND CONDITIONS
+ Copyright (c) 1997 by Eryq. Copyright (c) 1998 by ZeeGee Software Inc.
+ All rights reserved. This program is free software; you can redistribute
+ it and/or modify it under the same terms as Perl itself.
+
+ This software comes with NO WARRANTY of any kind. See the COPYING file
+ in the distribution for details.
+
+NUTRITIONAL INFORMATION
+ For some reason, the US FDA says that this is now required by law on any
+ products that bear the name "Lite"...
+
+ MIME::Lite |
+ ------------------------------------------------------------
+ Serving size: | 1 module
+ Servings per container: | 1
+ Calories: | 0
+ Fat: | 0g
+ Saturated Fat: | 0g
+
+ Warning: for consumption by hardware only! May produce indigestion in
+ humans if taken internally.
+
+AUTHOR
+ Eryq (eryq@zeegee.com). President, ZeeGee Software Inc.
+ (http://www.zeegee.com).
+
+ Created: 11 December 1996. Ho ho ho.
+
diff --git a/cpan/dist/MIME-Lite/README.system b/cpan/dist/MIME-Lite/README.system
new file mode 100644
index 00000000..ad1fc97c
--- /dev/null
+++ b/cpan/dist/MIME-Lite/README.system
@@ -0,0 +1,8 @@
+DEVELOPMENT SYSTEM:
+Linux eryq 2.0.34 #1 Fri May 8 16:05:57 EDT 1998 i586 unknown
+
+DEVELOPMENT PERL:
+This is perl, version 5.005_56 built for i586-linux
+
+DEVELOPMENT DATE:
+Fri Mar 30 01:17:47 EST 2001
diff --git a/cpan/dist/MIME-Lite/docs/MIME/Lite.pm.html b/cpan/dist/MIME-Lite/docs/MIME/Lite.pm.html
new file mode 100644
index 00000000..8c13907e
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/MIME/Lite.pm.html
@@ -0,0 +1,1976 @@
+<HTML>
+<HEAD>
+ <TITLE>MIME::Lite</TITLE>
+</HEAD>
+<BODY
+ bgcolor="#FFFFFF" link="#CC3366" vlink="#993366" alink="#FF6666">
+<FONT FACE="sans-serif" SIZE=-1><A HREF="http://www.zeegee.com" TARGET="_top"><IMG SRC="icons/zeegee.gif" ALT="ZeeGee Software" ALIGN="RIGHT" BORDER="0"></A><A NAME="__TOP__"><H1>MIME::Lite</H1>
+</A><UL>
+<LI> <A HREF="#NAME">NAME</A>
+<LI> <A HREF="#SYNOPSIS">SYNOPSIS</A>
+<LI> <A HREF="#DESCRIPTION">DESCRIPTION</A>
+<LI> <A HREF="#MORE_EXAMPLES">MORE EXAMPLES</A>
+<UL>
+<LI> <A HREF="#Attach_a_GIF_to_a_text_message">Attach a GIF to a text message</A>
+<LI> <A HREF="#Attach_a_pre-prepared_part_allows_fine-tuning">Attach a pre-prepared part (allows fine-tuning):</A>
+<LI> <A HREF="#Send_an_HTML_document_with_images_included">Send an HTML document... with images included!</A>
+<LI> <A HREF="#Output_a_message_to_a_filehandle">Output a message to a filehandle</A>
+<LI> <A HREF="#Get_a_message_as_a_string">Get a message as a string</A>
+<LI> <A HREF="#Change_how_messages_are_sent">Change how messages are sent</A>
+</UL>
+<LI> <A HREF="#FAQ">FAQ</A>
+<UL>
+<LI> <A HREF="#How_do_I_prevent_Content_headers_from_showing_up_in_my_mail_reader">How do I prevent &quot;Content&quot; headers from showing up in my mail reader?</A>
+<LI> <A HREF="#How_do_I_give_my_attachment_a_different_recommended_filename">How do I give my attachment a [different] recommended filename?</A>
+</UL>
+<LI> <A HREF="#PUBLIC_INTERFACE">PUBLIC INTERFACE</A>
+<UL>
+<LI> <A HREF="#Global_configuration">Global configuration</A>
+<LI> <A HREF="#Construction">Construction</A>
+<LI> <A HREF="#Setting_getting_headers_and_attributes">Setting/getting headers and attributes</A>
+<LI> <A HREF="#Setting_getting_message_data">Setting/getting message data</A>
+<LI> <A HREF="#Output">Output</A>
+<LI> <A HREF="#Sending">Sending</A>
+<LI> <A HREF="#Miscellaneous">Miscellaneous</A>
+</UL>
+<LI> <A HREF="#NOTES">NOTES</A>
+<UL>
+<LI> <A HREF="#Benign_limitations">Benign limitations</A>
+<LI> <A HREF="#Cheap_and_easy_mailing">Cheap and easy mailing</A>
+</UL>
+<LI> <A HREF="#WARNINGS">WARNINGS</A>
+<UL>
+<LI> <A HREF="#Good-vs-bad_email_addresses_with_send_by_smtp">Good-vs-bad email addresses with send_by_smtp()</A>
+<LI> <A HREF="#Formatting_of_headers_delayed_until_print">Formatting of headers delayed until print()</A>
+<LI> <A HREF="#Encoding_of_data_delayed_until_print">Encoding of data delayed until print()</A>
+<LI> <A HREF="#MIME_attributes_are_separate_from_header_fields">MIME attributes are separate from header fields!</A>
+<LI> <A HREF="#Beware_of_lines_consisting_of_a_single_dot">Beware of lines consisting of a single dot</A>
+<LI> <A HREF="#Infinite_loops_may_mean_tainted_data">Infinite loops may mean tainted data!</A>
+</UL>
+<LI> <A HREF="#A_MIME_PRIMER">A MIME PRIMER</A>
+<UL>
+<LI> <A HREF="#Content_types">Content types</A>
+<LI> <A HREF="#Content_transfer_encodings">Content transfer encodings</A>
+</UL>
+<LI> <A HREF="#VERSION">VERSION</A>
+<LI> <A HREF="#CHANGE_LOG">CHANGE LOG</A>
+<LI> <A HREF="#TERMS_AND_CONDITIONS">TERMS AND CONDITIONS</A>
+<LI> <A HREF="#NUTRITIONAL_INFORMATION">NUTRITIONAL INFORMATION</A>
+<LI> <A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+</A>
+
+<P><HR>
+<A NAME="NAME"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NAME</H2></A>
+
+
+<P>MIME::Lite - low-calorie MIME generator
+
+
+
+<P><HR>
+<A NAME="SYNOPSIS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> SYNOPSIS</H2></A>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ use MIME::Lite;
+
+Create a single-part message:
+</PRE></FONT>
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Create a new single-part message, to send a GIF file:
+ $msg = MIME::Lite-&gt;new(
+ From =&gt;'me@myhost.com',
+ To =&gt;'you@yourhost.com',
+ Cc =&gt;'some@other.com, some@more.com',
+ Subject =&gt;'Helloooooo, nurse!',
+ Type =&gt;'image/gif',
+ Encoding =&gt;'base64',
+ Path =&gt;'hellonurse.gif'
+ );
+</PRE></FONT>
+
+<P>Create a multipart message (i.e., one with attachments):
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Create a new multipart message:
+ $msg = MIME::Lite-&gt;new(
+ From =&gt;'me@myhost.com',
+ To =&gt;'you@yourhost.com',
+ Cc =&gt;'some@other.com, some@more.com',
+ Subject =&gt;'A message with 2 parts...',
+ Type =&gt;'multipart/mixed'
+ );
+
+ ### Add parts (each &quot;attach&quot; has same arguments as &quot;new&quot;):
+ $msg-&gt;attach(Type =&gt;'TEXT',
+ Data =&gt;&quot;Here's the GIF file you wanted&quot;
+ );
+ $msg-&gt;attach(Type =&gt;'image/gif',
+ Path =&gt;'aaa000123.gif',
+ Filename =&gt;'logo.gif',
+ Disposition =&gt; 'attachment'
+ );
+</PRE></FONT>
+
+<P>Output a message:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Format as a string:
+ $str = $msg-&gt;as_string;
+
+ ### Print to a filehandle (say, a &quot;sendmail&quot; stream):
+ $msg-&gt;print(\*SENDMAIL);
+</PRE></FONT>
+
+<P>Send a message:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Send in the &quot;best&quot; way (the default is to use &quot;sendmail&quot;):
+ $msg-&gt;send;
+
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="DESCRIPTION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> DESCRIPTION</H2></A>
+
+
+<P>In the never-ending quest for great taste with fewer calories,
+we proudly present: <I>MIME::Lite</I>.
+
+
+<P>MIME::Lite is intended as a simple, standalone module for generating
+(not parsing!) MIME messages... specifically, it allows you to
+output a simple, decent single- or multi-part message with text or binary
+attachments. It does not require that you have the Mail:: or MIME::
+modules installed.
+
+
+<P>You can specify each message part as either the literal data itself (in
+a scalar or array), or as a string which can be given to open() to get
+a readable filehandle (e.g., &quot;&lt;filename&quot; or &quot;somecommand|&quot;).
+
+
+<P>You don't need to worry about encoding your message data:
+this module will do that for you. It handles the 5 standard MIME encodings.
+
+
+<P>If you need more sophisticated behavior, please get the MIME-tools
+package instead. I will be more likely to add stuff to that toolkit
+over this one.
+
+
+
+<P><HR>
+<A NAME="MORE_EXAMPLES"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> MORE EXAMPLES</H2></A>
+
+
+
+<P><HR>
+<A NAME="Attach_a_GIF_to_a_text_message"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Attach a GIF to a text message</H3></A>
+
+
+<P>This will create a multipart message exactly as above, but using the
+&quot;attach to singlepart&quot; hack:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Create a new multipart message:
+ $msg = MIME::Lite-&gt;new(
+ From =&gt;'me@myhost.com',
+ To =&gt;'you@yourhost.com',
+ Cc =&gt;'some@other.com, some@more.com',
+ Subject =&gt;'A message with 2 parts...',
+ Type =&gt;'TEXT',
+ Data =&gt;&quot;Here's the GIF file you wanted&quot;
+ );
+
+ ### Attach a part:
+ $msg-&gt;attach(Type =&gt;'image/gif',
+ Path =&gt;'aaa000123.gif',
+ Filename =&gt;'logo.gif'
+ );
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="Attach_a_pre-prepared_part_allows_fine-tuning"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Attach a pre-prepared part (allows fine-tuning):</H3></A>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $part = MIME::Lite-&gt;new(
+ Type =&gt;'text/html',
+ Data =&gt;'&lt;H1&gt;Hello&lt;/H1&gt;',
+ );
+ $part-&gt;attr('content-type.charset' =&gt; 'UTF8');
+ $part-&gt;add('X-Comment' =&gt; 'A message for you');
+ $msg-&gt;attach($part);
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="Send_an_HTML_document_with_images_included"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Send an HTML document... with images included!</H3></A>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg = MIME::Lite-&gt;new(
+ To =&gt;'you@yourhost.com',
+ Subject =&gt;'HTML with in-line images!',
+ Type =&gt;'multipart/related'
+ );
+ $msg-&gt;attach(Type =&gt; 'text/html',
+ Data =&gt; qq{ &lt;body&gt;
+ Here's &lt;i&gt;my&lt;/i&gt; image:
+ &lt;img src=&quot;cid:myimage.gif&quot;&gt;
+ &lt;/body&gt; }
+ );
+ $msg-&gt;attach(Type =&gt; 'image/gif',
+ Id =&gt; 'myimage.gif',
+ Path =&gt; '/path/to/somefile.gif',
+ );
+ $msg-&gt;send();
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="Output_a_message_to_a_filehandle"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Output a message to a filehandle</H3></A>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Write it to a filehandle:
+ $msg-&gt;print(\*STDOUT);
+
+ ### Write just the header:
+ $msg-&gt;print_header(\*STDOUT);
+
+ ### Write just the encoded body:
+ $msg-&gt;print_body(\*STDOUT);
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="Get_a_message_as_a_string"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Get a message as a string</H3></A>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Get entire message as a string:
+ $str = $msg-&gt;as_string;
+
+ ### Get just the header:
+ $str = $msg-&gt;header_as_string;
+
+ ### Get just the encoded body:
+ $str = $msg-&gt;body_as_string;
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="Change_how_messages_are_sent"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Change how messages are sent</H3></A>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### Do something like this in your 'main':
+ if ($I_DONT_HAVE_SENDMAIL) {
+ MIME::Lite-&gt;send('smtp', &quot;smtp.myisp.net&quot;, Timeout=&gt;60);
+ }
+
+ ### Now this will do the right thing:
+ $msg-&gt;send; ### will now use Net::SMTP as shown above
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="FAQ"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> FAQ</H2></A>
+
+
+
+<P><HR>
+<A NAME="How_do_I_prevent_Content_headers_from_showing_up_in_my_mail_reader"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> How do I prevent &quot;Content&quot; headers from showing up in my mail reader?</H3></A>
+
+
+<P>Apparently, some people are using mail readers which display the MIME
+headers like &quot;Content-disposition&quot;, and they want MIME::Lite not
+to generate them &quot;because they look ugly&quot;.
+
+
+<P>Sigh.
+
+
+<P>Y'know, kids, those headers aren't just there for cosmetic purposes.
+They help ensure that the message is <I>understood</I> correctly by mail
+readers. But okay, you asked for it, you got it...
+here's how you can suppress the standard MIME headers.
+Before you send the message, do this:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;scrub;
+</PRE></FONT>
+
+<P>You can scrub() any part of a multipart message independently;
+just be aware that it works recursively. Before you scrub,
+note the rules that I follow:
+
+
+
+<DL>
+<P><DT><B><A NAME="item:Content-type">Content-type</A></B></DT>
+<DD>
+You can safely scrub the &quot;content-type&quot; attribute if, and only if,
+the part is of type &quot;text/plain&quot; with charset &quot;us-ascii&quot;.
+
+<P><DT><B><A NAME="item:Content-transfer-encoding">Content-transfer-encoding</A></B></DT>
+<DD>
+You can safely scrub the &quot;content-transfer-encoding&quot; attribute
+if, and only if, the part uses &quot;7bit&quot;, &quot;8bit&quot;, or &quot;binary&quot; encoding.
+You are far better off doing this if your lines are under 1000
+characters. Generally, that means you <I>can</I> scrub it for plain
+text, and you can <I>not</I> scrub this for images, etc.
+
+<P><DT><B><A NAME="item:Content-disposition">Content-disposition</A></B></DT>
+<DD>
+You can safely scrub the &quot;content-disposition&quot; attribute
+if you trust the mail reader to do the right thing when it decides
+whether to show an attachment inline or as a link. Be aware
+that scrubbing both the content-disposition and the content-type
+means that there is no way to &quot;recommend&quot; a filename for the attachment!
+
+
+<P><B>Note:</B> there are reports of brain-dead MUAs out there that
+do the wrong thing if you <I>provide</I> the content-disposition.
+If your attachments keep showing up inline or vice-versa,
+try scrubbing this attribute.
+
+<P><DT><B><A NAME="item:Content-length">Content-length</A></B></DT>
+<DD>
+You can always scrub &quot;content-length&quot; safely.
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="How_do_I_give_my_attachment_a_different_recommended_filename"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> How do I give my attachment a [different] recommended filename?</H3></A>
+
+
+<P>By using the Filename option (which is different from Path!):
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;attach(Type =&gt; &quot;image/gif&quot;,
+ Path =&gt; &quot;/here/is/the/real/file.GIF&quot;,
+ Filename =&gt; &quot;logo.gif&quot;);
+</PRE></FONT>
+
+<P>You should <I>not</I> put path information in the Filename.
+
+
+
+<P><HR>
+<A NAME="PUBLIC_INTERFACE"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> PUBLIC INTERFACE</H2></A>
+
+
+
+<P><HR>
+<A NAME="Global_configuration"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Global configuration</H3></A>
+
+
+<P>To alter the way the entire module behaves, you have the following
+methods/options:
+
+
+
+<DL>
+<P><DT><B><A NAME="item:MIME_Lite-_header_order">MIME::Lite-&gt;header_order()</A></B></DT>
+<DD>
+When used as a <A HREF="#item:send">classmethod</A>, this changes the default
+order in which headers are output for <I>all</I> messages.
+
+<P><DT><B><A NAME="item:MIME_Lite-_quiet">MIME::Lite-&gt;quiet()</A></B></DT>
+<DD>
+This <A HREF="#item:quiet">classmethod</A> can be used to suppress/unsuppress
+all warnings coming from this module.
+
+<P><DT><B><A NAME="item:MIME_Lite-_send">MIME::Lite-&gt;send()</A></B></DT>
+<DD>
+When used as a <A HREF="#item:send">classmethod</A>, this can be used to specify
+a different default mechanism for sending message.
+The initial default is:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send(&quot;sendmail&quot;, &quot;/usr/lib/sendmail -t -oi -oem&quot;);
+</PRE></FONT>
+
+<P>However, you should consider the similar but smarter and taint-safe variant:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send(&quot;sendmail&quot;);
+</PRE></FONT>
+
+<P>Or, for non-Unix users:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send(&quot;smtp&quot;);
+</PRE></FONT>
+<P><DT><B><A NAME="item:MIME_Lite_PARANOID">$MIME::Lite::PARANOID</A></B></DT>
+<DD>
+If true, we won't attempt to use MIME::Base64/MIME::QuotedPrint, even
+if they're available.
+Default is <B>false</B>.
+
+<P><DT><B><A NAME="item:MIME_Lite_AUTO_ENCODE">$MIME::Lite::AUTO_ENCODE</A></B></DT>
+<DD>
+If true, automatically choose the encoding from the content type.
+Default is <B>true</B>.
+
+<P><DT><B><A NAME="item:MIME_Lite_AUTO_CC">$MIME::Lite::AUTO_CC</A></B></DT>
+<DD>
+If true, automatically send to the Cc/Bcc addresses for send_by_smtp().
+Default is <B>true</B>.
+
+<P><DT><B><A NAME="item:MIME_Lite_AUTO_VERIFY">$MIME::Lite::AUTO_VERIFY</A></B></DT>
+<DD>
+If true, check paths to attachments right before printing, raising an exception
+if any path is unreadable.
+Default is <B>true</B>.
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="Construction"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Construction</H3></A>
+
+
+
+<DL>
+<P><DT><B><A NAME="item:new">new [PARAMHASH]</A></B></DT>
+<DD>
+<I>Class method, constructor.</I>
+Create a new message object.
+
+
+<P>If any arguments are given, they are passed into <CODE>build()</CODE>; otherwise,
+just the empty object is created.
+
+<P><DT><B><A NAME="item:attach">attach PART</A></B></DT>
+<DD>
+<P><DT><B><A NAME="item:attach">attach PARAMHASH...</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Add a new part to this message, and return the new part.
+
+
+<P>If you supply a single PART argument, it will be regarded
+as a MIME::Lite object to be attached. Otherwise, this
+method assumes that you are giving in the pairs of a PARAMHASH
+which will be sent into <CODE>new()</CODE> to create the new part.
+
+
+<P>One of the possibly-quite-useful hacks thrown into this is the
+&quot;attach-to-singlepart&quot; hack: if you attempt to attach a part (let's
+call it &quot;part 1&quot;) to a message that doesn't have a content-type
+of &quot;multipart&quot; or &quot;message&quot;, the following happens:
+
+
+
+<UL>
+<P><LI>
+<P>A new part (call it &quot;part 0&quot;) is made.
+
+<P><LI>
+<P>The MIME attributes and data (but <I>not</I> the other headers)
+are cut from the &quot;self&quot; message, and pasted into &quot;part 0&quot;.
+
+<P><LI>
+<P>The &quot;self&quot; is turned into a &quot;multipart/mixed&quot; message.
+
+<P><LI>
+<P>The new &quot;part 0&quot; is added to the &quot;self&quot;, and <I>then</I> &quot;part 1&quot; is added.
+
+</UL>
+
+
+<P>One of the nice side-effects is that you can create a text message
+and then add zero or more attachments to it, much in the same way
+that a user agent like Netscape allows you to do.
+
+<P><DT><B><A NAME="item:build">build [PARAMHASH]</A></B></DT>
+<DD>
+<I>Class/instance method, initializer.</I>
+Create (or initialize) a MIME message object.
+Normally, you'll use the following keys in PARAMHASH:
+
+<P><UL><LI> Data, FH, or Path (either one of these, or none if multipart)<LI> Type (e.g., &quot;image/jpeg&quot;)<LI> From, To, and Subject (if this is the &quot;top level&quot; of a message)</UL>
+<P>The PARAMHASH can contain the following keys:
+
+
+
+<DL>
+<P><DT><B><A NAME="item:fieldname">(fieldname)</A></B></DT>
+<DD>
+Any field you want placed in the message header, taken from the
+standard list of header fields (you don't need to worry about case):
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ Approved Encrypted Received Sender
+ Bcc From References Subject
+ Cc Keywords Reply-To To
+ Comments Message-ID Resent-* X-*
+ Content-* MIME-Version Return-Path
+ Date Organization
+</PRE></FONT>
+
+<P>To give experienced users some veto power, these fields will be set
+<I>after</I> the ones I set... so be careful: <I>don't set any MIME fields</I>
+(like <CODE>Content-type</CODE>) unless you know what you're doing!
+
+
+<P>To specify a fieldname that's <I>not</I> in the above list, even one that's
+identical to an option below, just give it with a trailing <CODE>&quot;:&quot;</CODE>,
+like <CODE>&quot;My-field:&quot;</CODE>. When in doubt, that <I>always</I> signals a mail
+field (and it sort of looks like one too).
+
+<P><DT><B><A NAME="item:Data">Data</A></B></DT>
+<DD>
+<I>Alternative to &quot;Path&quot; or &quot;FH&quot;.</I>
+The actual message data. This may be a scalar or a ref to an array of
+strings; if the latter, the message consists of a simple concatenation
+of all the strings in the array.
+
+<P><DT><B><A NAME="item:Datestamp">Datestamp</A></B></DT>
+<DD>
+<I>Optional.</I>
+If given true (or omitted), we force the creation of a <CODE>Date:</CODE> field
+stamped with the current date/time if this is a top-level message.
+You may want this if using <A HREF="#item:send_by_smtp">send_by_smtp()</A>.
+If you don't want this to be done, either provide your own Date
+or explicitly set this to false.
+
+<P><DT><B><A NAME="item:Disposition">Disposition</A></B></DT>
+<DD>
+<I>Optional.</I>
+The content disposition, <CODE>&quot;inline&quot;</CODE> or <CODE>&quot;attachment&quot;</CODE>.
+The default is <CODE>&quot;inline&quot;</CODE>.
+
+<P><DT><B><A NAME="item:Encoding">Encoding</A></B></DT>
+<DD>
+<I>Optional.</I>
+The content transfer encoding that should be used to encode your data:
+
+<P><TABLE CELLPADDING=4 CELLSPACING=0 BORDER=1 ALIGN=CENTER BGCOLOR=#EEEEEE><TR><TH BGCOLOR=#AA0055 ALIGN=LEFT><FONT SIZE=2 COLOR=#FFFFFF FACE="sans-serif">Use encoding:&nbsp;</FONT></TH BGCOLOR=#AA0055><TH BGCOLOR=#AA0055 ALIGN=LEFT><FONT SIZE=2 COLOR=#FFFFFF FACE="sans-serif">If your message contains:&nbsp;</FONT></TH BGCOLOR=#AA0055></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">7bit</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">Only 7-bit text, all lines &lt;1000 characters</FONT></TD></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">8bit</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">8-bit text, all lines &lt;1000 characters</FONT></TD></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">quoted-printable</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">8-bit text or long lines (more reliable than &quot;8bit&quot;)</FONT></TD></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">base64</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">Largely non-textual data: a GIF, a tar file, etc.</FONT></TD></TR></TABLE>
+<P>The default is taken from the Type; generally it is &quot;binary&quot; (no
+encoding) for text/*, message/*, and multipart/*, and &quot;base64&quot; for
+everything else. A value of <CODE>&quot;binary&quot;</CODE> is generally <I>not</I> suitable
+for sending anything but ASCII text files with lines under 1000
+characters, so consider using one of the other values instead.
+
+
+<P>In the case of &quot;7bit&quot;/&quot;8bit&quot;, long lines are automatically chopped to
+legal length; in the case of &quot;7bit&quot;, all 8-bit characters are
+automatically <I>removed</I>. This may not be what you want, so pick your
+encoding well! For more info, see <A HREF="#A_MIME_PRIMER">A MIME PRIMER</A>.
+
+<P><DT><B><A NAME="item:FH">FH</A></B></DT>
+<DD>
+<I>Alternative to &quot;Data&quot; or &quot;Path&quot;.</I>
+Filehandle containing the data, opened for reading.
+See &quot;ReadNow&quot; also.
+
+<P><DT><B><A NAME="item:Filename">Filename</A></B></DT>
+<DD>
+<I>Optional.</I>
+The name of the attachment. You can use this to supply a
+recommended filename for the end-user who is saving the attachment
+to disk. You only need this if the filename at the end of the
+&quot;Path&quot; is inadequate, or if you're using &quot;Data&quot; instead of &quot;Path&quot;.
+You should <I>not</I> put path information in here (e.g., no &quot;/&quot;
+or &quot;\&quot; or &quot;:&quot; characters should be used).
+
+<P><DT><B><A NAME="item:Id">Id</A></B></DT>
+<DD>
+<I>Optional.</I>
+Same as setting &quot;content-id&quot;.
+
+<P><DT><B><A NAME="item:Length">Length</A></B></DT>
+<DD>
+<I>Optional.</I>
+Set the content length explicitly. Normally, this header is automatically
+computed, but only under certain circumstances (see <A HREF="#Limitations">Limitations</A>).
+
+<P><DT><B><A NAME="item:Path">Path</A></B></DT>
+<DD>
+<I>Alternative to &quot;Data&quot; or &quot;FH&quot;.</I>
+Path to a file containing the data... actually, it can be any open()able
+expression. If it looks like a path, the last element will automatically
+be treated as the filename.
+See &quot;ReadNow&quot; also.
+
+<P><DT><B><A NAME="item:ReadNow">ReadNow</A></B></DT>
+<DD>
+<I>Optional, for use with &quot;Path&quot;.</I>
+If true, will open the path and slurp the contents into core now.
+This is useful if the Path points to a command and you don't want
+to run the command over and over if outputting the message several
+times. <B>Fatal exception</B> raised if the open fails.
+
+<P><DT><B><A NAME="item:Top">Top</A></B></DT>
+<DD>
+<I>Optional.</I>
+If defined, indicates whether or not this is a &quot;top-level&quot; MIME message.
+The parts of a multipart message are <I>not</I> top-level.
+Default is true.
+
+<P><DT><B><A NAME="item:Type">Type</A></B></DT>
+<DD>
+<I>Optional.</I>
+The MIME content type, or one of these special values (case-sensitive):
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ &quot;TEXT&quot; means &quot;text/plain&quot;
+ &quot;BINARY&quot; means &quot;application/octet-stream&quot;
+</PRE></FONT>
+
+<P>The default is <CODE>&quot;TEXT&quot;</CODE>.
+
+</DL>
+
+
+<P>A picture being worth 1000 words (which
+is of course 2000 bytes, so it's probably more of an &quot;icon&quot; than a &quot;picture&quot;,
+but I digress...), here are some examples:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg = MIME::Lite-&gt;build(
+ From =&gt; 'yelling@inter.com',
+ To =&gt; 'stocking@fish.net',
+ Subject =&gt; &quot;Hi there!&quot;,
+ Type =&gt; 'TEXT',
+ Encoding =&gt; '7bit',
+ Data =&gt; &quot;Just a quick note to say hi!&quot;);
+
+ $msg = MIME::Lite-&gt;build(
+ From =&gt; 'dorothy@emerald-city.oz',
+ To =&gt; 'gesundheit@edu.edu.edu',
+ Subject =&gt; &quot;A gif for U&quot;
+ Type =&gt; 'image/gif',
+ Path =&gt; &quot;/home/httpd/logo.gif&quot;);
+
+ $msg = MIME::Lite-&gt;build(
+ From =&gt; 'laughing@all.of.us',
+ To =&gt; 'scarlett@fiddle.dee.de',
+ Subject =&gt; &quot;A gzipp'ed tar file&quot;,
+ Type =&gt; 'x-gzip',
+ Path =&gt; &quot;gzip &lt; /usr/inc/somefile.tar |&quot;,
+ ReadNow =&gt; 1,
+ Filename =&gt; &quot;somefile.tgz&quot;);
+</PRE></FONT>
+
+<P>To show you what's really going on, that last example could also
+have been written:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg = new MIME::Lite;
+ $msg-&gt;build(Type =&gt; 'x-gzip',
+ Path =&gt; &quot;gzip &lt; /usr/inc/somefile.tar |&quot;,
+ ReadNow =&gt; 1,
+ Filename =&gt; &quot;somefile.tgz&quot;);
+ $msg-&gt;add(From =&gt; &quot;laughing@all.of.us&quot;);
+ $msg-&gt;add(To =&gt; &quot;scarlett@fiddle.dee.de&quot;);
+ $msg-&gt;add(Subject =&gt; &quot;A gzipp'ed tar file&quot;);
+</PRE></FONT>
+</DL>
+
+
+
+<P><HR>
+<A NAME="Setting_getting_headers_and_attributes"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Setting/getting headers and attributes</H3></A>
+
+
+
+<DL>
+<P><DT><B><A NAME="item:add">add TAG,VALUE</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Add field TAG with the given VALUE to the end of the header.
+The TAG will be converted to all-lowercase, and the VALUE
+will be made &quot;safe&quot; (returns will be given a trailing space).
+
+
+<P><B>Beware:</B> any MIME fields you &quot;add&quot; will override any MIME
+attributes I have when it comes time to output those fields.
+Normally, you will use this method to add <I>non-MIME</I> fields:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;add(&quot;Subject&quot; =&gt; &quot;Hi there!&quot;);
+</PRE></FONT>
+
+<P>Giving VALUE as an arrayref will cause all those values to be added.
+This is only useful for special multiple-valued fields like &quot;Received&quot;:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;add(&quot;Received&quot; =&gt; [&quot;here&quot;, &quot;there&quot;, &quot;everywhere&quot;]
+</PRE></FONT>
+
+<P>Giving VALUE as the empty string adds an invisible placeholder
+to the header, which can be used to suppress the output of
+the &quot;Content-*&quot; fields or the special &quot;MIME-Version&quot; field.
+When suppressing fields, you should use replace() instead of add():
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;replace(&quot;Content-disposition&quot; =&gt; &quot;&quot;);
+</PRE></FONT>
+
+<P><I>Note:</I> add() is probably going to be more efficient than <CODE>replace()</CODE>,
+so you're better off using it for most applications if you are
+certain that you don't need to delete() the field first.
+
+
+<P><I>Note:</I> the name comes from Mail::Header.
+
+<P><DT><B><A NAME="item:attr">attr ATTR,[VALUE]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Set MIME attribute ATTR to the string VALUE.
+ATTR is converted to all-lowercase.
+This method is normally used to set/get MIME attributes:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;attr(&quot;content-type&quot; =&gt; &quot;text/html&quot;);
+ $msg-&gt;attr(&quot;content-type.charset&quot; =&gt; &quot;US-ASCII&quot;);
+ $msg-&gt;attr(&quot;content-type.name&quot; =&gt; &quot;homepage.html&quot;);
+</PRE></FONT>
+
+<P>This would cause the final output to look something like this:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ Content-type: text/html; charset=US-ASCII; name=&quot;homepage.html&quot;
+</PRE></FONT>
+
+<P>Note that the special empty sub-field tag indicates the anonymous
+first sub-field.
+
+
+<P>Giving VALUE as undefined will cause the contents of the named
+subfield to be deleted.
+
+
+<P>Supplying no VALUE argument just returns the attribute's value:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $type = $msg-&gt;attr(&quot;content-type&quot;); ### returns &quot;text/html&quot;
+ $name = $msg-&gt;attr(&quot;content-type.name&quot;); ### returns &quot;homepage.html&quot;
+</PRE></FONT>
+<P><DT><B><A NAME="item:delete">delete TAG</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Delete field TAG with the given VALUE to the end of the header.
+The TAG will be converted to all-lowercase.
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;delete(&quot;Subject&quot;);
+</PRE></FONT>
+
+<P><I>Note:</I> the name comes from Mail::Header.
+
+<P><DT><B><A NAME="item:field_order">field_order FIELD,...FIELD</A></B></DT>
+<DD>
+<I>Class/instance method.</I>
+Change the order in which header fields are output for this object:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;field_order('from', 'to', 'content-type', 'subject');
+</PRE></FONT>
+
+<P>When used as a class method, changes the default settings for
+all objects:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;field_order('from', 'to', 'content-type', 'subject');
+</PRE></FONT>
+
+<P>Case does not matter: all field names will be coerced to lowercase.
+In either case, supply the empty array to restore the default ordering.
+
+<P><DT><B><A NAME="item:fields">fields</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Return the full header for the object, as a ref to an array
+of <CODE>[TAG, VALUE]</CODE> pairs, where each TAG is all-lowercase.
+Note that any fields the user has explicitly set will override the
+corresponding MIME fields that we would otherwise generate.
+So, don't say...
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;set(&quot;Content-type&quot; =&gt; &quot;text/html; charset=US-ASCII&quot;);
+</PRE></FONT>
+
+<P>unless you want the above value to override the &quot;Content-type&quot;
+MIME field that we would normally generate.
+
+
+<P><I>Note:</I> I called this &quot;fields&quot; because the header() method of
+Mail::Header returns something different, but similar enough to
+be confusing.
+
+
+<P>You can change the order of the fields: see <A HREF="#item:header_order">header_order</A>.
+You really shouldn't need to do this, but some people have to
+deal with broken mailers.
+
+<P><DT><B><A NAME="item:filename">filename [FILENAME]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Set the filename which this data will be reported as.
+This actually sets both &quot;standard&quot; attributes.
+
+
+<P>With no argument, returns the filename as dictated by the
+content-disposition.
+
+<P><DT><B><A NAME="item:get">get TAG,[INDEX]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Get the contents of field TAG, which might have been set
+with set() or replace(). Returns the text of the field.
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $ml-&gt;get('Subject', 0);
+</PRE></FONT>
+
+<P>If the optional 0-based INDEX is given, then we return the INDEX'th
+occurence of field TAG. Otherwise, we look at the context:
+In a scalar context, only the first (0th) occurence of the
+field is returned; in an array context, <I>all</I> occurences are returned.
+
+
+<P><I>Warning:</I> this should only be used with non-MIME fields.
+Behavior with MIME fields is TBD, and will raise an exception for now.
+
+<P><DT><B><A NAME="item:get_length">get_length</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Recompute the content length for the message <I>if the process is trivial</I>,
+setting the &quot;content-length&quot; attribute as a side-effect:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;get_length;
+</PRE></FONT>
+
+<P>Returns the length, or undefined if not set.
+
+
+<P><I>Note:</I> the content length can be difficult to compute, since it
+involves assembling the entire encoded body and taking the length
+of it (which, in the case of multipart messages, means freezing
+all the sub-parts, etc.).
+
+
+<P>This method only sets the content length to a defined value if the
+message is a singlepart with <CODE>&quot;binary&quot;</CODE> encoding, <I>and</I> the body is
+available either in-core or as a simple file. Otherwise, the content
+length is set to the undefined value.
+
+
+<P>Since content-length is not a standard MIME field anyway (that's right, kids:
+it's not in the MIME RFCs, it's an HTTP thing), this seems pretty fair.
+
+<P><DT><B><A NAME="item:replace">replace TAG,VALUE</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Delete all occurences of fields named TAG, and add a new
+field with the given VALUE. TAG is converted to all-lowercase.
+
+
+<P><B>Beware</B> the special MIME fields (MIME-version, Content-*):
+if you &quot;replace&quot; a MIME field, the replacement text will override
+the <I>actual</I> MIME attributes when it comes time to output that field.
+So normally you use attr() to change MIME fields and add()/replace() to
+change <I>non-MIME</I> fields:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;replace(&quot;Subject&quot; =&gt; &quot;Hi there!&quot;);
+</PRE></FONT>
+
+<P>Giving VALUE as the <I>empty string</I> will effectively <I>prevent</I> that
+field from being output. This is the correct way to suppress
+the special MIME fields:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;replace(&quot;Content-disposition&quot; =&gt; &quot;&quot;);
+</PRE></FONT>
+
+<P>Giving VALUE as <I>undefined</I> will just cause all explicit values
+for TAG to be deleted, without having any new values added.
+
+
+<P><I>Note:</I> the name of this method comes from Mail::Header.
+
+<P><DT><B><A NAME="item:scrub">scrub</A></B></DT>
+<DD>
+<I>Instance method.</I>
+<B>This is Alpha code. If you use it, please let me know how it goes.</B>
+Recursively goes through the &quot;parts&quot; tree of this message and tries
+to find MIME attributes that can be removed.
+With an array argument, removes exactly those attributes; e.g.:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;scrub(['content-disposition', 'content-length']);
+</PRE></FONT>
+
+<P>Is the same as recursively doing:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;replace('Content-disposition' =&gt; '');
+ $msg-&gt;replace('Content-length' =&gt; '');
+</PRE></FONT>
+</DL>
+
+
+
+<P><HR>
+<A NAME="Setting_getting_message_data"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Setting/getting message data</H3></A>
+
+
+
+<DL>
+<P><DT><B><A NAME="item:binmode">binmode [OVERRIDE]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+With no argument, returns whether or not it thinks that the data
+(as given by the &quot;Path&quot; argument of <CODE>build()</CODE>) should be read using
+binmode() (for example, when <CODE>read_now()</CODE> is invoked).
+
+
+<P>The default behavior is that any content type other than
+<CODE>text/*</CODE> or <CODE>message/*</CODE> is binmode'd; this should in general work fine.
+
+
+<P>With a defined argument, this method sets an explicit &quot;override&quot;
+value. An undefined argument unsets the override.
+The new current value is returned.
+
+<P><DT><B><A NAME="item:data">data [DATA]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Get/set the literal DATA of the message. The DATA may be
+either a scalar, or a reference to an array of scalars (which
+will simply be joined).
+
+
+<P><I>Warning:</I> setting the data causes the &quot;content-length&quot; attribute
+to be recomputed (possibly to nothing).
+
+<P><DT><B><A NAME="item:path">path [PATH]</A></B></DT>
+<DD>
+Get/set the PATH to the message data.
+
+
+<P><I>Warning:</I> setting the path recomputes any existing &quot;content-length&quot; field,
+and re-sets the &quot;filename&quot; (to the last element of the path if it
+looks like a simple path, and to nothing if not).
+
+<P><DT><B><A NAME="item:fh">fh [FILEHANDLE]</A></B></DT>
+<DD>
+Get/set the FILEHANDLE which contains the message data.
+
+
+<P>Takes a filehandle as an input and stores it in the object.
+This routine is similar to path(); one important difference is that
+no attempt is made to set the content length.
+
+<P><DT><B><A NAME="item:resetfh">resetfh [FILEHANDLE]</A></B></DT>
+<DD>
+Set the current position of the filehandle back to the beginning.
+Only applies if you used &quot;FH&quot; in build() or attach() for this message.
+
+
+<P>Returns false if unable to reset the filehandle (since not all filehandles
+are seekable).
+
+<P><DT><B><A NAME="item:read_now">read_now</A></B></DT>
+<DD>
+Forces data from the path/filehandle (as specified by <CODE>build()</CODE>)
+to be read into core immediately, just as though you had given it
+literally with the <CODE>Data</CODE> keyword.
+
+
+<P>Note that the in-core data will always be used if available.
+
+
+<P>Be aware that everything is slurped into a giant scalar: you may not want
+to use this if sending tar files! The benefit of <I>not</I> reading in the data
+is that very large files can be handled by this module if left on disk
+until the message is output via <CODE>print()</CODE> or <CODE>print_body()</CODE>.
+
+<P><DT><B><A NAME="item:sign">sign PARAMHASH</A></B></DT>
+<DD>
+Sign the message. This forces the message to be read into core,
+after which the signature is appended to it.
+
+
+
+<DL>
+<P><DT><B><A NAME="item:Data">Data</A></B></DT>
+<DD>
+As in <CODE>build()</CODE>: the literal signature data.
+Can be either a scalar or a ref to an array of scalars.
+
+<P><DT><B><A NAME="item:Path">Path</A></B></DT>
+<DD>
+As in <CODE>build()</CODE>: the path to the file.
+
+</DL>
+
+
+<P>If no arguments are given, the default is:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ Path =&gt; &quot;$ENV{HOME}/.signature&quot;
+</PRE></FONT>
+
+<P>The content-length is recomputed.
+
+<P><DT><B><A NAME="item:verify_data">verify_data</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Verify that all &quot;paths&quot; to attached data exist, recursively.
+It might be a good idea for you to do this before a print(), to
+prevent accidental partial output if a file might be missing.
+Raises exception if any path is not readable.
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="Output"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Output</H3></A>
+
+
+
+<DL>
+<P><DT><B><A NAME="item:print">print [OUTHANDLE]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Print the message to the given output handle, or to the currently-selected
+filehandle if none was given.
+
+
+<P>All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+<P><DT><B><A NAME="item:print_body">print_body [OUTHANDLE]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Print the body of a message to the given output handle, or to
+the currently-selected filehandle if none was given.
+
+
+<P>All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+
+<P><B>Fatal exception</B> raised if unable to open any of the input files,
+or if a part contains no data, or if an unsupported encoding is
+encountered.
+
+<P><DT><B><A NAME="item:print_header">print_header [OUTHANDLE]</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Print the header of the message to the given output handle,
+or to the currently-selected filehandle if none was given.
+
+
+<P>All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+<P><DT><B><A NAME="item:as_string">as_string</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Return the entire message as a string, with a header and an encoded body.
+
+<P><DT><B><A NAME="item:body_as_string">body_as_string</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Return the encoded body as a string.
+This is the portion after the header and the blank line.
+
+
+<P><I>Note:</I> actually prepares the body by &quot;printing&quot; to a scalar.
+Proof that you can hand the <CODE>print*()</CODE> methods any blessed object
+that responds to a <CODE>print()</CODE> message.
+
+<P><DT><B><A NAME="item:header_as_string">header_as_string</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Return the header as a string.
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="Sending"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Sending</H3></A>
+
+
+
+<DL>
+<P><DT><B><A NAME="item:send">send</A></B></DT>
+<DD>
+<P><DT><B><A NAME="item:send">send HOW, HOWARGS...</A></B></DT>
+<DD>
+<I>Class/instance method.</I>
+This is the principal method for sending mail, and for configuring
+how mail will be sent.
+
+
+<P><I>As an instance method</I> (with no arguments), sends the message by whatever
+means has been set up (the default is to use the Unix &quot;sendmail&quot; program).
+Returns whatever the mail-handling routine returns: this should be true
+on success, false/exception on error:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg = MIME::Lite-&gt;new(From=&gt;...);
+ $msg-&gt;send || die &quot;you DON'T have mail!&quot;;
+</PRE></FONT>
+
+<P><I>As a class method</I> (with a HOW argument and optional HOWARGS), sets up
+how the instance method will work for all objects until further notice
+It treats HOW as a facility name, with optional HOWARGS handled by
+the facility (and returns the previous HOW and HOWARGS as an array).
+There are three facilities:
+
+
+
+<DL>
+<P><DT><B><A NAME="item:sendmail_ARGS">&quot;sendmail&quot;, ARGS...</A></B></DT>
+<DD>
+Send a message by piping it into the &quot;sendmail&quot; command.
+Uses the <A HREF="#item:send_by_sendmail">send_by_sendmail()</A> method, giving it the ARGS.
+This usage implements (and deprecates) the <CODE>sendmail()</CODE> method.
+
+<P><DT><B><A NAME="item:smtp_HOSTNAME">&quot;smtp&quot;, [HOSTNAME]</A></B></DT>
+<DD>
+Send a message by SMTP, using optional HOSTNAME as SMTP-sending host.
+Uses the <A HREF="#item:send_by_smtp">send_by_smtp()</A> method.
+
+<P><DT><B><A NAME="item:sub_SUBREF_ARGS">&quot;sub&quot;, \&amp;SUBREF, ARGS...</A></B></DT>
+<DD>
+Sends a message MSG by invoking the subroutine SUBREF of your choosing,
+with MSG as the first argument, and ARGS following.
+
+</DL>
+
+
+<P><I>For example:</I> let's say you're on an OS which lacks the usual Unix
+&quot;sendmail&quot; facility, but you've installed something a lot like it, and
+you need to configure your Perl script to use this &quot;sendmail.exe&quot; program.
+Do this following in your script's setup:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send('sendmail', &quot;d:\\programs\\sendmail.exe&quot;);
+</PRE></FONT>
+
+<P>Then, whenever you need to send a message $msg, just say:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ $msg-&gt;send;
+</PRE></FONT>
+
+<P>That's it. Now, if you ever move your script to a Unix box, all you
+need to do is change that line in the setup and you're done.
+All of your $msg-&gt;send invocations will work as expected.
+
+<P><DT><B><A NAME="item:send_by_sendmail">send_by_sendmail SENDMAILCMD</A></B></DT>
+<DD>
+<P><DT><B><A NAME="item:send_by_sendmail">send_by_sendmail PARAM=&gt;VALUE, ...</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Send message via an external &quot;sendmail&quot; program
+(this will probably only work out-of-the-box on Unix systems).
+
+
+<P>Returns true on success, false or exception on error.
+
+
+<P>You can specify the program and all its arguments by giving a single
+string, SENDMAILCMD. Nothing fancy is done; the message is simply
+piped in.
+
+
+<P>However, if your needs are a little more advanced, you can specify
+zero or more of the following PARAM/VALUE pairs; a Unix-style,
+taint-safe &quot;sendmail&quot; command will be constructed for you:
+
+
+
+<DL>
+<P><DT><B><A NAME="item:Sendmail">Sendmail</A></B></DT>
+<DD>
+Full path to the program to use.
+Default is &quot;/usr/lib/sendmail&quot;.
+
+<P><DT><B><A NAME="item:BaseArgs">BaseArgs</A></B></DT>
+<DD>
+Ref to the basic array of arguments we start with.
+Default is <CODE>[&quot;-t&quot;, &quot;-oi&quot;, &quot;-oem&quot;]</CODE>.
+
+<P><DT><B><A NAME="item:SetSender">SetSender</A></B></DT>
+<DD>
+Unless this is <I>explicitly</I> given as false, we attempt to automatically
+set the <CODE>-f</CODE> argument to the first address that can be extracted from
+the &quot;From:&quot; field of the message (if there is one).
+
+
+<P><I>What is the -f, and why do we use it?</I>
+Suppose we did <I>not</I> use <CODE>-f</CODE>, and you gave an explicit &quot;From:&quot;
+field in your message: in this case, the sendmail &quot;envelope&quot; would
+indicate the <I>real</I> user your process was running under, as a way
+of preventing mail forgery. Using the <CODE>-f</CODE> switch causes the sender
+to be set in the envelope as well.
+
+
+<P><I>So when would I NOT want to use it?</I>
+If sendmail doesn't regard you as a &quot;trusted&quot; user, it will permit
+the <CODE>-f</CODE> but also add an &quot;X-Authentication-Warning&quot; header to the message
+to indicate a forged envelope. To avoid this, you can either
+(1) have SetSender be false, or
+(2) make yourself a trusted user by adding a <CODE>T</CODE> configuration
+ command to your <I>sendmail.cf</I> file
+ (e.g.: <CODE>Teryq</CODE> if the script is running as user &quot;eryq&quot;).
+
+<P><DT><B><A NAME="item:FromSender">FromSender</A></B></DT>
+<DD>
+If defined, this is identical to setting SetSender to true,
+except that instead of looking at the &quot;From:&quot; field we use
+the address given by this option.
+Thus:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ FromSender =&gt; 'me@myhost.com'
+</PRE></FONT>
+</DL>
+
+<P><DT><B><A NAME="item:send_by_smtp">send_by_smtp ARGS...</A></B></DT>
+<DD>
+<I>Instance method.</I>
+Send message via SMTP, using Net::SMTP.
+The optional ARGS are sent into Net::SMTP::new(): usually, these are
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MAILHOST, OPTION=&gt;VALUE, ...
+</PRE></FONT>
+
+<P>Note that the list of recipients is taken from the
+&quot;To&quot;, &quot;Cc&quot; and &quot;Bcc&quot; fields.
+
+
+<P>Returns true on success, false or exception on error.
+
+<P><DT><B><A NAME="item:sendmail">sendmail COMMAND...</A></B></DT>
+<DD>
+<I>Class method, DEPRECATED.</I>
+Declare the sender to be &quot;sendmail&quot;, and set up the &quot;sendmail&quot; command.
+<I>You should use send() instead.</I>
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="Miscellaneous"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Miscellaneous</H3></A>
+
+
+
+<DL>
+<P><DT><B><A NAME="item:quiet">quiet ONOFF</A></B></DT>
+<DD>
+<I>Class method.</I>
+Suppress/unsuppress all warnings coming from this module.
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;quiet(1); ### I know what I'm doing
+</PRE></FONT>
+
+<P>I recommend that you include that comment as well. And while
+you type it, say it out loud: if it doesn't feel right, then maybe
+you should reconsider the whole line. <CODE>;-)</CODE>
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="NOTES"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NOTES</H2></A>
+
+
+
+<P><HR>
+<A NAME="Benign_limitations"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Benign limitations</H3></A>
+
+
+<P>This is &quot;lite&quot;, after all...
+
+
+
+<UL>
+<P><LI>
+<P>There's no parsing. Get MIME-tools if you need to parse MIME messages.
+
+<P><LI>
+<P>MIME::Lite messages are currently <I>not</I> interchangeable with
+either Mail::Internet or MIME::Entity objects. This is a completely
+separate module.
+
+<P><LI>
+<P>A content-length field is only inserted if the encoding is binary,
+the message is a singlepart, and all the document data is available
+at <CODE>build()</CODE> time by virtue of residing in a simple path, or in-core.
+Since content-length is not a standard MIME field anyway (that's right, kids:
+it's not in the MIME RFCs, it's an HTTP thing), this seems pretty fair.
+
+<P><LI>
+<P>MIME::Lite alone cannot help you lose weight. You must supplement
+your use of MIME::Lite with a healthy diet and exercise.
+
+</UL>
+
+
+
+<P><HR>
+<A NAME="Cheap_and_easy_mailing"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Cheap and easy mailing</H3></A>
+
+
+<P>I thought putting in a default &quot;sendmail&quot; invocation wasn't too bad an
+idea, since a lot of Perlers are on UNIX systems.
+The out-of-the-box configuration is:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send('sendmail', &quot;/usr/lib/sendmail -t -oi -oem&quot;);
+</PRE></FONT>
+
+<P>By the way, these arguments to sendmail are:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ -t Scan message for To:, Cc:, Bcc:, etc.
+
+ -oi Do NOT treat a single &quot;.&quot; on a line as a message terminator.
+ As in, &quot;-oi vey, it truncated my message... why?!&quot;
+
+ -oem On error, mail back the message (I assume to the
+ appropriate address, given in the header).
+ When mail returns, circle is complete. Jai Guru Deva -oem.
+</PRE></FONT>
+
+<P>Note that these are the same arguments you get if you configure to use
+the smarter, taint-safe mailing:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send('sendmail');
+</PRE></FONT>
+
+<P>If you get &quot;X-Authentication-Warning&quot; headers from this, you can forgo
+diddling with the envelope by instead specifying:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send('sendmail', SetSender=&gt;0);
+</PRE></FONT>
+
+<P>And, if you're not on a Unix system, or if you'd just rather send mail
+some other way, there's always:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send('smtp', &quot;smtp.myisp.net&quot;);
+</PRE></FONT>
+
+<P>Or you can set up your own subroutine to call.
+In any case, check out the <A HREF="#item:send">send()</A> method.
+
+
+
+<P><HR>
+<A NAME="WARNINGS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> WARNINGS</H2></A>
+
+
+
+<P><HR>
+<A NAME="Good-vs-bad_email_addresses_with_send_by_smtp"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Good-vs-bad email addresses with send_by_smtp()</H3></A>
+
+
+<P>If using <A HREF="#item:send_by_smtp">send_by_smtp()</A>, be aware that you are
+forcing MIME::Lite to extract email addresses out of a possible list
+provided in the <CODE>To:</CODE>, <CODE>Cc:</CODE>, and <CODE>Bcc:</CODE> fields. This is tricky
+stuff, and as such only the following sorts of addresses will work
+reliably:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ username
+ full.name@some.host.com
+ &quot;Name, Full&quot; &lt;full.name@some.host.com&gt;
+</PRE></FONT>
+
+<P>This last form is discouraged because SMTP must be able to get
+at the <I>name</I> or <I>name@domain</I> portion.
+
+
+<P><B>Disclaimer:</B>
+MIME::Lite was never intended to be a Mail User Agent, so please
+don't expect a full implementation of RFC-822. Restrict yourself to
+the common forms of Internet addresses described herein, and you should
+be fine. If this is not feasible, then consider using MIME::Lite
+to <I>prepare</I> your message only, and using Net::SMTP explicitly to
+<I>send</I> your message.
+
+
+
+<P><HR>
+<A NAME="Formatting_of_headers_delayed_until_print"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Formatting of headers delayed until print()</H3></A>
+
+
+<P>This class treats a MIME header in the most abstract sense,
+as being a collection of high-level attributes. The actual
+RFC-822-style header fields are not constructed until it's time
+to actually print the darn thing.
+
+
+
+<P><HR>
+<A NAME="Encoding_of_data_delayed_until_print"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Encoding of data delayed until print()</H3></A>
+
+
+<P>When you specify message bodies
+(in <A HREF="#item:build">build()</A> or <A HREF="#item:attach">attach()</A>) --
+whether by <B>FH</B>, <B>Data</B>, or <B>Path</B> -- be warned that we don't
+attempt to open files, read filehandles, or encode the data until
+<A HREF="#item:print">print()</A> is invoked.
+
+
+<P>In the past, this created some confusion for users of sendmail
+who gave the wrong path to an attachment body, since enough of
+the print() would succeed to get the initial part of the message out.
+Nowadays, $AUTO_VERIFY is used to spot-check the Paths given before
+the mail facility is employed. A whisker slower, but tons safer.
+
+
+<P>Note that if you give a message body via FH, and try to print()
+a message twice, the second print() will not do the right thing
+unless you explicitly rewind the filehandle.
+
+
+<P>You can get past these difficulties by using the <B>ReadNow</B> option,
+provided that you have enough memory to handle your messages.
+
+
+
+<P><HR>
+<A NAME="MIME_attributes_are_separate_from_header_fields"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> MIME attributes are separate from header fields!</H3></A>
+
+
+<P><B>Important:</B> the MIME attributes are stored and manipulated separately
+from the message header fields; when it comes time to print the
+header out, <I>any explicitly-given header fields override the ones that
+would be created from the MIME attributes.</I> That means that this:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ ### DANGER ### DANGER ### DANGER ### DANGER ### DANGER ###
+ $msg-&gt;add(&quot;Content-type&quot;, &quot;text/html; charset=US-ASCII&quot;);
+</PRE></FONT>
+
+<P>will set the exact <CODE>&quot;Content-type&quot;</CODE> field in the header I write,
+<I>regardless of what the actual MIME attributes are.</I>
+
+
+<P><I>This feature is for experienced users only,</I> as an escape hatch in case
+the code that normally formats MIME header fields isn't doing what
+you need. And, like any escape hatch, it's got an alarm on it:
+MIME::Lite will warn you if you attempt to <CODE>set()</CODE> or <CODE>replace()</CODE>
+any MIME header field. Use <CODE>attr()</CODE> instead.
+
+
+
+<P><HR>
+<A NAME="Beware_of_lines_consisting_of_a_single_dot"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Beware of lines consisting of a single dot</H3></A>
+
+
+<P>Julian Haight noted that MIME::Lite allows you to compose messages
+with lines in the body consisting of a single &quot;.&quot;.
+This is true: it should be completely harmless so long as &quot;sendmail&quot;
+is used with the -oi option (see <A HREF="#Cheap_and_easy_mailing">Cheap and easy mailing</A>).
+
+
+<P>However, I don't know if using Net::SMTP to transfer such a message
+is equally safe. Feedback is welcomed.
+
+
+<P>My perspective: I don't want to magically diddle with a user's
+message unless absolutely positively necessary.
+Some users may want to send files with &quot;.&quot; alone on a line;
+my well-meaning tinkering could seriously harm them.
+
+
+
+<P><HR>
+<A NAME="Infinite_loops_may_mean_tainted_data"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Infinite loops may mean tainted data!</H3></A>
+
+
+<P>Stefan Sautter noticed a bug in 2.106 where a m//gc match was
+failing due to tainted data, leading to an infinite loop inside
+MIME::Lite.
+
+
+<P>I am attempting to correct for this, but be advised that my fix will
+silently untaint the data (given the context in which the problem
+occurs, this should be benign: I've labelled the source code with
+UNTAINT comments for the curious).
+
+
+<P>So: don't depend on taint-checking to save you from outputting
+tainted data in a message.
+
+
+
+<P><HR>
+<A NAME="A_MIME_PRIMER"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> A MIME PRIMER</H2></A>
+
+
+
+<P><HR>
+<A NAME="Content_types"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Content types</H3></A>
+
+
+<P>The &quot;Type&quot; parameter of <CODE>build()</CODE> is a <I>content type</I>.
+This is the actual type of data you are sending.
+Generally this is a string of the form <CODE>&quot;majortype/minortype&quot;</CODE>.
+
+
+<P>Here are the major MIME types.
+A more-comprehensive listing may be found in RFC-2046.
+
+
+
+<DL>
+<P><DT><B><A NAME="item:application">application</A></B></DT>
+<DD>
+Data which does not fit in any of the other categories, particularly
+data to be processed by some type of application program.
+<CODE>application/octet-stream</CODE>, <CODE>application/gzip</CODE>, <CODE>application/postscript</CODE>...
+
+<P><DT><B><A NAME="item:audio">audio</A></B></DT>
+<DD>
+Audio data.
+<CODE>audio/basic</CODE>...
+
+<P><DT><B><A NAME="item:image">image</A></B></DT>
+<DD>
+Graphics data.
+<CODE>image/gif</CODE>, <CODE>image/jpeg</CODE>...
+
+<P><DT><B><A NAME="item:message">message</A></B></DT>
+<DD>
+A message, usually another mail or MIME message.
+<CODE>message/rfc822</CODE>...
+
+<P><DT><B><A NAME="item:multipart">multipart</A></B></DT>
+<DD>
+A message containing other messages.
+<CODE>multipart/mixed</CODE>, <CODE>multipart/alternative</CODE>...
+
+<P><DT><B><A NAME="item:text">text</A></B></DT>
+<DD>
+Textual data, meant for humans to read.
+<CODE>text/plain</CODE>, <CODE>text/html</CODE>...
+
+<P><DT><B><A NAME="item:video">video</A></B></DT>
+<DD>
+Video or video+audio data.
+<CODE>video/mpeg</CODE>...
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="Content_transfer_encodings"><H3><A HREF="#__TOP__"><IMG SRC="icons/h2bullet.gif" ALT="Top" BORDER="0"></A> Content transfer encodings</H3></A>
+
+
+<P>The &quot;Encoding&quot; parameter of <CODE>build()</CODE>.
+This is how the message body is packaged up for safe transit.
+
+
+<P>Here are the 5 major MIME encodings.
+A more-comprehensive listing may be found in RFC-2045.
+
+
+
+<DL>
+<P><DT><B><A NAME="item:7bit">7bit</A></B></DT>
+<DD>
+Basically, no <I>real</I> encoding is done. However, this label guarantees that no
+8-bit characters are present, and that lines do not exceed 1000 characters
+in length.
+
+<P><DT><B><A NAME="item:8bit">8bit</A></B></DT>
+<DD>
+Basically, no <I>real</I> encoding is done. The message might contain 8-bit
+characters, but this encoding guarantees that lines do not exceed 1000
+characters in length.
+
+<P><DT><B><A NAME="item:binary">binary</A></B></DT>
+<DD>
+No encoding is done at all. Message might contain 8-bit characters,
+and lines might be longer than 1000 characters long.
+
+
+<P>The most liberal, and the least likely to get through mail gateways.
+Use sparingly, or (better yet) not at all.
+
+<P><DT><B><A NAME="item:base64">base64</A></B></DT>
+<DD>
+Like &quot;uuencode&quot;, but very well-defined. This is how you should send
+essentially binary information (tar files, GIFs, JPEGs, etc.).
+
+<P><DT><B><A NAME="item:quoted-printable">quoted-printable</A></B></DT>
+<DD>
+Useful for encoding messages which are textual in nature, yet which contain
+non-ASCII characters (e.g., Latin-1, Latin-2, or any other 8-bit alphabet).
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="VERSION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> VERSION</H2></A>
+
+
+<P>$Id: Lite.pm,v 2.108 2001/03/30 06:16:54 eryq Exp $
+
+
+
+<P><HR>
+<A NAME="CHANGE_LOG"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> CHANGE LOG</H2></A>
+
+
+
+<DL>
+<P><DT><B><A NAME="item:Version">Version 2.108</A></B></DT>
+<DD>
+New <CODE>field_order()</CODE> allows you to set the header order, both on a
+per-message basis, and package-wide.
+<I>Thanks to Thomas Stromberg for suggesting this.</I>
+
+
+<P>Added code to try and divine &quot;sendmail&quot; path more intelligently.
+<I>Thanks to Slaven Rezic for the suggestion.</I>
+
+<P><DT><B><A NAME="item:Version">Version 2.107 (2001/03/27)</A></B></DT>
+<DD>
+Fixed serious bug where tainted data with quoted-printable encoding
+was causing infinite loops. The &quot;fix&quot; untaints the data in question,
+which is not optimal, but it's probably benign in this case.
+<I>Thanks to Stefan Sautter for tracking this nasty little beast down.</I>
+<I>Thanks to Larry Geralds for a related patch.</I>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ &quot;Doctor, O doctor:
+ it's painful when I do *this* --&quot;
+ &quot;Simple: don't *do* that.&quot;
+</PRE></FONT>
+
+<P>Fixed bugs where a non-local <CODE>$_</CODE> was being modified... again!
+Will I never learn?
+<I>Thanks to Maarten Koskamp for reporting this.</I>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ Dollar-underscore
+ can poison distant waters;
+ 'local' must it be.
+</PRE></FONT>
+
+<P>Fixed buglet in <CODE>add()</CODE> where all value references were being treated
+as arrayrefs, instead of as possibly-self-stringifying object refs.
+Now you can send in an object ref as the 2nd argument.
+<I>Thanks to dLux for the bug report.</I>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ That ref is a string?
+ Operator overload
+ has ruined my day.
+</PRE></FONT>
+
+<P>Added &quot;Approved&quot; as an acceptable header field for <CODE>new()</CODE>, as per RFC1036.
+<I>Thanks to Thomax for the suggestion regarding MIME-tools.</I>
+
+
+<P>Small improvements to docs to make different uses of attach()
+and various arguments clearer.
+<I>Thanks to Sven Rassman and Roland Walter for the suggestions.</I>
+
+<P><DT><B><A NAME="item:Version">Version 2.106 (2000/11/21)</A></B></DT>
+<DD>
+Added Alpha version of scrub() to make it easy for people to suppress
+the printing of unwanted MIME attributes (like Content-length).
+<I>Thanks to the many people who asked for this.</I>
+
+
+<P>Headers with empty-strings for their values are no longer
+printed. This seems sensible, and helps us implement scrub().
+
+<P><DT><B><A NAME="item:Version">Version 2.105 (2000/10/14)</A></B></DT>
+<DD>
+The regression-test failure was identified, and it was my fault.
+Apparently some of the \-quoting in my &quot;autoloaded&quot; code was
+making Perl 5.6 unhappy. For this nesting-related idiocy,
+a nesting kaiku.
+<I>Thanks to Scott Schwartz for identifying the problem.</I>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ In a pattern, my
+ backslash-s dwells peacefully,
+ unambiguous --
+
+ but I embed it
+ in a double-quoted string
+ doubling the backslash --
+
+ interpolating
+ that same double-quoted string
+ in other patterns --
+
+ and, worlds within worlds,
+ I single-quote the function
+ to autoload it --
+
+ changing the meaning
+ of the backslash and the 's';
+ and Five-Point-Six growls.
+</PRE></FONT>
+<P><DT><B><A NAME="item:Version">Version 2.104 (2000/09/28)</A></B></DT>
+<DD>
+Now attempts to load and use Mail::Address for parsing email
+addresses <I>before</I> falling back to our own method.
+<I>Thanks to numerous people for suggesting this.</I>
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ Parsing addresses
+ is too damn hard. One last hope:
+ Let Graham Barr do it!
+</PRE></FONT>
+
+<P>For the curious, the version of Mail::Address appears
+as the &quot;A&quot; number in the X-Mailer:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ X-Mailer: MIME::Lite 2.104 (A1.15; B2.09; Q2.03)
+</PRE></FONT>
+
+<P>Added <B>FromSender</B> option to send_by_sendmail().
+<I>Thanks to Bill Moseley for suggesting this feature.</I>
+
+<P><DT><B><A NAME="item:Version">Version 2.101 (2000/06/06)</A></B></DT>
+<DD>
+Major revision to print_body() and body_as_string() so that
+&quot;body&quot; really means &quot;the part after the header&quot;, which is what most
+people would want in this context. This is <B>not</B> how it was used
+1.x, where &quot;body&quot; only meant &quot;the body of a simple singlepart&quot;.
+Hopefully, this change will solve many problems and create very few ones.
+
+
+<P>Added support for attaching a part to a &quot;message/rfc822&quot;, treating
+the &quot;message&quot; type as a multipart-like container.
+
+
+<P>Now takes care not to include &quot;Bcc:&quot; in header when using send_by_smtp,
+as a safety precaution against qmail's behavior.
+<I>Thanks to Tatsuhiko Miyagawa for identifying this problem.</I>
+
+
+<P>Improved efficiency of many stringifying operations by using
+string-arrays which are joined, instead of doing multiple appends
+to a scalar.
+
+
+<P>Cleaned up the &quot;examples&quot; directory.
+
+<P><DT><B><A NAME="item:Version">Version 1.147 (2000/06/02)</A></B></DT>
+<DD>
+Fixed buglet where lack of Cc:/Bcc: was causing extract_addrs
+to emit &quot;undefined variable&quot; warnings. Also, lack of a &quot;To:&quot; field
+now causes a croak.
+<I>Thanks to David Mitchell for the bug report and suggested patch.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.146 (2000/05/18)</A></B></DT>
+<DD>
+Fixed bug in parsing of addresses; please read the WARNINGS section
+which describes recommended address formats for &quot;To:&quot;, &quot;Cc:&quot;, etc.
+Also added automatic inclusion of a UT &quot;Date:&quot; at top level unless
+explicitly told not to.
+<I>Thanks to Andy Jacobs for the bug report and the suggestion.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.145 (2000/05/06)</A></B></DT>
+<DD>
+Fixed bug in encode_7bit(): a lingering <CODE>/e</CODE> modifier was removed.
+<I>Thanks to Michael A. Chase for the patch.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.142 (2000/05/02)</A></B></DT>
+<DD>
+Added new, taint-safe invocation of &quot;sendmail&quot;, one which also
+sets up the <CODE>-f</CODE> option. Unfortunately, I couldn't make this automatic:
+the change could have broken a lot of code out there which used
+send_by_sendmail() with unusual &quot;sendmail&quot; variants.
+So you'll have to configure &quot;send&quot; to use the new mechanism:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ MIME::Lite-&gt;send('sendmail'); ### no args!
+</PRE></FONT>
+
+<P><I>Thanks to Jeremy Howard for suggesting these features.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.140 (2000/04/27)</A></B></DT>
+<DD>
+Fixed bug in support for &quot;To&quot;, &quot;Cc&quot;, and &quot;Bcc&quot; in send_by_smtp():
+multiple (comma-separated) addresses should now work fine.
+We try real hard to extract addresses from the flat text strings.
+<I>Thanks to John Mason for motivating this change.</I>
+
+
+<P>Added automatic verification that attached data files exist,
+done immediately before the &quot;send&quot; action is invoked.
+To turn this off, set $MIME::Lite::AUTO_VERIFY to false.
+
+<P><DT><B><A NAME="item:Version">Version 1.137 (2000/03/22)</A></B></DT>
+<DD>
+Added support for &quot;Cc&quot; and &quot;Bcc&quot; in send_by_smtp().
+To turn this off, set $MIME::Lite::AUTO_CC to false.
+<I>Thanks to Lucas Maneos for the patch, and tons of others for
+the suggestion.</I>
+
+
+<P>Chooses a better default content-transfer-encoding if the content-type
+is &quot;image/*&quot;, &quot;audio/*&quot;, etc.
+To turn this off, set $MIME::Lite::AUTO_ENCODE to false.
+<I>Thanks to many folks for the suggestion.</I>
+
+
+<P>Fixed bug in QP-encoding where a non-local <CODE>$_</CODE> was being modified.
+<I>Thanks to Jochen Stenzel for finding this very obscure bug!</I>
+
+
+<P>Removed references to <CODE>$`</CODE>, <CODE>$'</CODE>, and <CODE>$&amp;</CODE> (bad variables
+which slow things down).
+
+
+<P>Added an example of how to send HTML files with enclosed in-line
+images, per popular demand.
+
+<P><DT><B><A NAME="item:Version">Version 1.133 (1999/04/17)</A></B></DT>
+<DD>
+Fixed bug in &quot;Data&quot; handling: arrayrefs were not being handled
+properly.
+
+<P><DT><B><A NAME="item:Version">Version 1.130 (1998/12/14)</A></B></DT>
+<DD>
+Added much larger and more-flexible send() facility.
+<I>Thanks to Andrew McRae (and Optimation New Zealand Ltd)
+for the Net::SMTP interface. Additional thanks to the many folks
+who requested this feature.</I>
+
+
+<P>Added get() method for extracting basic attributes.
+
+
+<P>New... &quot;t&quot; tests!
+
+<P><DT><B><A NAME="item:Version">Version 1.124 (1998/11/13)</A></B></DT>
+<DD>
+Folded in filehandle (FH) support in build/attach.
+<I>Thanks to Miko O'Sullivan for the code.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.122 (1998/01/19)</A></B></DT>
+<DD>
+MIME::Base64 and MIME::QuotedPrint are used if available.
+
+
+<P>The 7bit encoding no longer does &quot;escapes&quot;; it merely strips 8-bit characters.
+
+<P><DT><B><A NAME="item:Version">Version 1.121 (1997/04/08)</A></B></DT>
+<DD>
+Filename attribute is now no longer ignored by build().
+<I>Thanks to Ian Smith for finding and patching this bug.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.120 (1997/03/29)</A></B></DT>
+<DD>
+Efficiency hack to speed up MIME::Lite::IO_Scalar.
+<I>Thanks to David Aspinwall for the patch.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.116 (1997/03/19)</A></B></DT>
+<DD>
+Small bug in our private copy of encode_base64() was patched.
+<I>Thanks to Andreas Koenig for pointing this out.</I>
+
+
+<P>New, prettier way of specifying mail message headers in <CODE>build()</CODE>.
+
+
+<P>New quiet method to turn off warnings.
+
+
+<P>Changed &quot;stringify&quot; methods to more-standard &quot;as_string&quot; methods.
+
+<P><DT><B><A NAME="item:Version">Version 1.112 (1997/03/06)</A></B></DT>
+<DD>
+Added <CODE>read_now()</CODE>, and <CODE>binmode()</CODE> method for our non-Unix-using brethren:
+file data is now read using binmode() if appropriate.
+<I>Thanks to Xiangzhou Wang for pointing out this bug.</I>
+
+<P><DT><B><A NAME="item:Version">Version 1.110 (1997/03/06)</A></B></DT>
+<DD>
+Fixed bug in opening the data filehandle.
+
+<P><DT><B><A NAME="item:Version">Version 1.102 (1997/03/01)</A></B></DT>
+<DD>
+Initial release.
+
+<P><DT><B><A NAME="item:Version">Version 1.101 (1997/03/01)</A></B></DT>
+<DD>
+Baseline code.
+
+</DL>
+
+
+
+<P><HR>
+<A NAME="TERMS_AND_CONDITIONS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> TERMS AND CONDITIONS</H2></A>
+
+
+<P>Copyright (c) 1997 by Eryq.
+Copyright (c) 1998 by ZeeGee Software Inc.
+All rights reserved. This program is free software; you can redistribute
+it and/or modify it under the same terms as Perl itself.
+
+
+<P>This software comes with <B>NO WARRANTY</B> of any kind.
+See the COPYING file in the distribution for details.
+
+
+
+<P><HR>
+<A NAME="NUTRITIONAL_INFORMATION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NUTRITIONAL INFORMATION</H2></A>
+
+
+<P>For some reason, the US FDA says that this is now required by law
+on any products that bear the name &quot;Lite&quot;...
+
+<P><TABLE CELLPADDING=4 CELLSPACING=0 BORDER=1 ALIGN=CENTER BGCOLOR=#EEEEEE><TR><TH BGCOLOR=#AA0055 ALIGN=LEFT><FONT SIZE=2 COLOR=#FFFFFF FACE="sans-serif">MIME::Lite&nbsp;</FONT></TH BGCOLOR=#AA0055><TH BGCOLOR=#AA0055 ALIGN=LEFT><FONT SIZE=2 COLOR=#FFFFFF FACE="sans-serif">&nbsp;</FONT></TH BGCOLOR=#AA0055></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">Serving size:</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">1 module</FONT></TD></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">Servings per container:</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">1</FONT></TD></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">Calories:</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">0</FONT></TD></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">Fat:</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">0g</FONT></TD></TR><TR><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">Saturated Fat:</FONT></TD><TD ALIGN=LEFT><FONT SIZE=2 COLOR=#000000 FACE="sans-serif">0g</FONT></TD></TR></TABLE>
+<P>Warning: for consumption by hardware only! May produce
+indigestion in humans if taken internally.
+
+
+
+<P><HR>
+<A NAME="AUTHOR"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> AUTHOR</H2></A>
+
+
+<P>Eryq (<I><FILE><A HREF="mailto:eryq@zeegee.com">eryq@zeegee.com</A></FILE></I>).
+President, ZeeGee Software Inc. (<I><FILE><A HREF="http://www.zeegee.com">http://www.zeegee.com</A></FILE></I>).
+
+
+<P>Created: 11 December 1996. Ho ho ho.
+
+<P><HR>
+<ADDRESS><FONT SIZE=-1>
+Generated Fri Mar 30 01:17:20 2001 by cvu_pod2html
+</FONT></ADDRESS>
+</FONT></BODY>
+</HTML>
diff --git a/cpan/dist/MIME-Lite/docs/MIME/icons/h1bullet.gif b/cpan/dist/MIME-Lite/docs/MIME/icons/h1bullet.gif
new file mode 100644
index 00000000..86986436
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/MIME/icons/h1bullet.gif
Binary files differ
diff --git a/cpan/dist/MIME-Lite/docs/MIME/icons/h2bullet.gif b/cpan/dist/MIME-Lite/docs/MIME/icons/h2bullet.gif
new file mode 100644
index 00000000..d26510cd
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/MIME/icons/h2bullet.gif
Binary files differ
diff --git a/cpan/dist/MIME-Lite/docs/MIME/icons/zeegee.gif b/cpan/dist/MIME-Lite/docs/MIME/icons/zeegee.gif
new file mode 100644
index 00000000..f6001a5f
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/MIME/icons/zeegee.gif
Binary files differ
diff --git a/cpan/dist/MIME-Lite/docs/icons/h1bullet.gif b/cpan/dist/MIME-Lite/docs/icons/h1bullet.gif
new file mode 100644
index 00000000..86986436
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/icons/h1bullet.gif
Binary files differ
diff --git a/cpan/dist/MIME-Lite/docs/icons/h2bullet.gif b/cpan/dist/MIME-Lite/docs/icons/h2bullet.gif
new file mode 100644
index 00000000..d26510cd
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/icons/h2bullet.gif
Binary files differ
diff --git a/cpan/dist/MIME-Lite/docs/icons/zeegee.gif b/cpan/dist/MIME-Lite/docs/icons/zeegee.gif
new file mode 100644
index 00000000..f6001a5f
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/icons/zeegee.gif
Binary files differ
diff --git a/cpan/dist/MIME-Lite/docs/index-menu.html b/cpan/dist/MIME-Lite/docs/index-menu.html
new file mode 100644
index 00000000..b8b68308
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/index-menu.html
@@ -0,0 +1,27 @@
+<HTML>
+<HEAD>
+<TITLE>perlmod</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" LINK="#CC3366" ALINK="#FF6666" VLINK="#993366">
+<FONT FACE="sans-serif"><TABLE>
+
+<TR VALIGN="TOP"><TH ALIGN="LEFT"><FONT FACE="sans-serif"><B>Overview</B></FONT></TH>
+<TR VALIGN="TOP"><TD><A HREF="MIME/Lite.pm.html" TARGET="perlmod.content"><FONT SIZE="-1" FACE="sans-serif">MIME::Lite</FONT></A></TD></TR>
+</TABLE>
+<HR>
+<TABLE>
+
+<TR VALIGN="TOP"><TH ALIGN="LEFT"><FONT FACE="sans-serif"><B>Examples</B></FONT></TH>
+<TR VALIGN="TOP"><TD><A HREF="mime_fwd.html" TARGET="perlmod.content"><FONT SIZE="-1" FACE="sans-serif">mime_fwd</FONT></A></TD></TR>
+
+<TR VALIGN="TOP"><TD><A HREF="mime_gif.html" TARGET="perlmod.content"><FONT SIZE="-1" FACE="sans-serif">mime_gif</FONT></A></TD></TR>
+
+<TR VALIGN="TOP"><TD><A HREF="mime_hack.html" TARGET="perlmod.content"><FONT SIZE="-1" FACE="sans-serif">mime_hack</FONT></A></TD></TR>
+
+<TR VALIGN="TOP"><TD><A HREF="mime_longlines.html" TARGET="perlmod.content"><FONT SIZE="-1" FACE="sans-serif">mime_longlines</FONT></A></TD></TR>
+
+<TR VALIGN="TOP"><TD><A HREF="mime_postcard.html" TARGET="perlmod.content"><FONT SIZE="-1" FACE="sans-serif">mime_postcard</FONT></A></TD></TR>
+</TABLE>
+<HR>
+</FONT></BODY>
+</HTML>
diff --git a/cpan/dist/MIME-Lite/docs/index.html b/cpan/dist/MIME-Lite/docs/index.html
new file mode 100644
index 00000000..d825be82
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/index.html
@@ -0,0 +1,13 @@
+<HEAD>
+<TITLE>perlmod</TITLE>
+</HEAD>
+<FRAMESET COLS="20%,*" BORDER=1 FRAMEBORDER=1 FRAMESPACING=10>
+ <FRAME NAME="perlmod.menu" SRC="index-menu.html">
+ <FRAME NAME="perlmod.content" SRC="MIME/Lite.pm.html">
+</FRAMESET>
+
+<NOFRAMES>
+ <BODY>
+ Go <A HREF="menu.html">here</A>
+ </BODY>
+</NOFRAMES>
diff --git a/cpan/dist/MIME-Lite/docs/index.menu b/cpan/dist/MIME-Lite/docs/index.menu
new file mode 100644
index 00000000..66830c98
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/index.menu
@@ -0,0 +1,24 @@
+MENU perlmod
+
+SECTION Overview
+
+ITEM MIME::Lite
+HREF MIME/Lite.pm.html
+
+SECTION Examples
+
+ITEM mime_fwd
+HREF mime_fwd.html
+
+ITEM mime_gif
+HREF mime_gif.html
+
+ITEM mime_hack
+HREF mime_hack.html
+
+ITEM mime_longlines
+HREF mime_longlines.html
+
+ITEM mime_postcard
+HREF mime_postcard.html
+
diff --git a/cpan/dist/MIME-Lite/docs/mime_fwd.html b/cpan/dist/MIME-Lite/docs/mime_fwd.html
new file mode 100644
index 00000000..923bd707
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/mime_fwd.html
@@ -0,0 +1,55 @@
+<HTML>
+<HEAD>
+ <TITLE>mime_fwd</TITLE>
+</HEAD>
+<BODY
+ bgcolor="#FFFFFF" link="#CC3366" vlink="#993366" alink="#FF6666">
+<FONT FACE="sans-serif" SIZE=-1><A HREF="http://www.zeegee.com" TARGET="_top"><IMG SRC="icons/zeegee.gif" ALT="ZeeGee Software" ALIGN="RIGHT" BORDER="0"></A><A NAME="__TOP__"><H1>mime_fwd</H1>
+</A><UL>
+<LI> <A HREF="#NAME">NAME</A>
+<LI> <A HREF="#SYNOPSIS">SYNOPSIS</A>
+<LI> <A HREF="#DESCRIPTION">DESCRIPTION</A>
+<LI> <A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+</A>
+
+<P><HR>
+<A NAME="NAME"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NAME</H2></A>
+
+
+<P>mime_fwd - test the ability to embed messages
+
+
+
+<P><HR>
+<A NAME="SYNOPSIS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> SYNOPSIS</H2></A>
+
+
+<P>Usage:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ mime_fwd
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="DESCRIPTION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> DESCRIPTION</H2></A>
+
+
+<P>Create a simple message, then wrap it in a &quot;forward&quot; and
+then a &quot;reply&quot;.
+
+
+
+<P><HR>
+<A NAME="AUTHOR"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> AUTHOR</H2></A>
+
+
+<P>Eryq, eryq@zeegee.com
+
+<P><HR>
+<ADDRESS><FONT SIZE=-1>
+Generated Fri Mar 30 01:17:33 2001 by cvu_pod2html
+</FONT></ADDRESS>
+</FONT></BODY>
+</HTML>
diff --git a/cpan/dist/MIME-Lite/docs/mime_gif.html b/cpan/dist/MIME-Lite/docs/mime_gif.html
new file mode 100644
index 00000000..e078b1dc
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/mime_gif.html
@@ -0,0 +1,56 @@
+<HTML>
+<HEAD>
+ <TITLE>mime_gif</TITLE>
+</HEAD>
+<BODY
+ bgcolor="#FFFFFF" link="#CC3366" vlink="#993366" alink="#FF6666">
+<FONT FACE="sans-serif" SIZE=-1><A HREF="http://www.zeegee.com" TARGET="_top"><IMG SRC="icons/zeegee.gif" ALT="ZeeGee Software" ALIGN="RIGHT" BORDER="0"></A><A NAME="__TOP__"><H1>mime_gif</H1>
+</A><UL>
+<LI> <A HREF="#NAME">NAME</A>
+<LI> <A HREF="#SYNOPSIS">SYNOPSIS</A>
+<LI> <A HREF="#DESCRIPTION">DESCRIPTION</A>
+<LI> <A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+</A>
+
+<P><HR>
+<A NAME="NAME"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NAME</H2></A>
+
+
+<P>mime_gif - encode a single gif by reading data different ways
+
+
+
+<P><HR>
+<A NAME="SYNOPSIS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> SYNOPSIS</H2></A>
+
+
+<P>Usage:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ mime_gif /path/to/some.gif
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="DESCRIPTION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> DESCRIPTION</H2></A>
+
+
+<P>Encode a multipart message where each part contains the same GIF
+file, but where the GIF file has been read-in in different ways.
+The subject line of each part will tell you how the GIF was read.
+
+
+
+<P><HR>
+<A NAME="AUTHOR"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> AUTHOR</H2></A>
+
+
+<P>Eryq, eryq@zeegee.com
+
+<P><HR>
+<ADDRESS><FONT SIZE=-1>
+Generated Fri Mar 30 01:17:36 2001 by cvu_pod2html
+</FONT></ADDRESS>
+</FONT></BODY>
+</HTML>
diff --git a/cpan/dist/MIME-Lite/docs/mime_hack.html b/cpan/dist/MIME-Lite/docs/mime_hack.html
new file mode 100644
index 00000000..41bd7ce1
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/mime_hack.html
@@ -0,0 +1,55 @@
+<HTML>
+<HEAD>
+ <TITLE>mime_hack</TITLE>
+</HEAD>
+<BODY
+ bgcolor="#FFFFFF" link="#CC3366" vlink="#993366" alink="#FF6666">
+<FONT FACE="sans-serif" SIZE=-1><A HREF="http://www.zeegee.com" TARGET="_top"><IMG SRC="icons/zeegee.gif" ALT="ZeeGee Software" ALIGN="RIGHT" BORDER="0"></A><A NAME="__TOP__"><H1>mime_hack</H1>
+</A><UL>
+<LI> <A HREF="#NAME">NAME</A>
+<LI> <A HREF="#SYNOPSIS">SYNOPSIS</A>
+<LI> <A HREF="#DESCRIPTION">DESCRIPTION</A>
+<LI> <A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+</A>
+
+<P><HR>
+<A NAME="NAME"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NAME</H2></A>
+
+
+<P>mime_hack - test the &quot;attach to singlepart&quot; hack
+
+
+
+<P><HR>
+<A NAME="SYNOPSIS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> SYNOPSIS</H2></A>
+
+
+<P>Usage:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ mime_hack /path/to/some.gif
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="DESCRIPTION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> DESCRIPTION</H2></A>
+
+
+<P>Encode a multipart message by starting with a text message,
+and attaching a GIF file to it.
+
+
+
+<P><HR>
+<A NAME="AUTHOR"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> AUTHOR</H2></A>
+
+
+<P>Eryq, eryq@zeegee.com
+
+<P><HR>
+<ADDRESS><FONT SIZE=-1>
+Generated Fri Mar 30 01:17:39 2001 by cvu_pod2html
+</FONT></ADDRESS>
+</FONT></BODY>
+</HTML>
diff --git a/cpan/dist/MIME-Lite/docs/mime_longlines.html b/cpan/dist/MIME-Lite/docs/mime_longlines.html
new file mode 100644
index 00000000..da87b792
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/mime_longlines.html
@@ -0,0 +1,72 @@
+<HTML>
+<HEAD>
+ <TITLE>mime_longlines</TITLE>
+</HEAD>
+<BODY
+ bgcolor="#FFFFFF" link="#CC3366" vlink="#993366" alink="#FF6666">
+<FONT FACE="sans-serif" SIZE=-1><A HREF="http://www.zeegee.com" TARGET="_top"><IMG SRC="icons/zeegee.gif" ALT="ZeeGee Software" ALIGN="RIGHT" BORDER="0"></A><A NAME="__TOP__"><H1>mime_longlines</H1>
+</A><UL>
+<LI> <A HREF="#NAME">NAME</A>
+<LI> <A HREF="#SYNOPSIS">SYNOPSIS</A>
+<LI> <A HREF="#DESCRIPTION">DESCRIPTION</A>
+<LI> <A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+</A>
+
+<P><HR>
+<A NAME="NAME"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NAME</H2></A>
+
+
+<P>mime_longlines - generate a test message with long lines
+
+
+
+<P><HR>
+<A NAME="SYNOPSIS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> SYNOPSIS</H2></A>
+
+
+<P>Usage:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ mime_longlines [-s]
+</PRE></FONT>
+
+<P>Options:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ -s Stringify message first, and print the *string* to STDOUT.
+</PRE></FONT>
+
+
+<P><HR>
+<A NAME="DESCRIPTION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> DESCRIPTION</H2></A>
+
+
+<P>Assemble and print (to the standard output) a multipart message
+with 5 attachments, for the purpose of &quot;eyeballing&quot; how well the
+encoders are working.
+
+
+<P>Each attachments holds the same data -- some 8-bit text, and a long
+line consisting of 1000 &quot;a&quot;s followed by a few &quot;b&quot;s) -- but each
+has a different encoding (the &quot;Content-transfer-encoding&quot; field
+will tell you which is which).
+
+
+<P>All of the encodings (except for the first one, &quot;binary&quot;) should
+break the long line before the b's.
+
+
+
+<P><HR>
+<A NAME="AUTHOR"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> AUTHOR</H2></A>
+
+
+<P>Eryq, eryq@zeegee.com
+
+<P><HR>
+<ADDRESS><FONT SIZE=-1>
+Generated Fri Mar 30 01:17:41 2001 by cvu_pod2html
+</FONT></ADDRESS>
+</FONT></BODY>
+</HTML>
diff --git a/cpan/dist/MIME-Lite/docs/mime_postcard.html b/cpan/dist/MIME-Lite/docs/mime_postcard.html
new file mode 100644
index 00000000..cd406f44
--- /dev/null
+++ b/cpan/dist/MIME-Lite/docs/mime_postcard.html
@@ -0,0 +1,59 @@
+<HTML>
+<HEAD>
+ <TITLE>mime_postcard</TITLE>
+</HEAD>
+<BODY
+ bgcolor="#FFFFFF" link="#CC3366" vlink="#993366" alink="#FF6666">
+<FONT FACE="sans-serif" SIZE=-1><A HREF="http://www.zeegee.com" TARGET="_top"><IMG SRC="icons/zeegee.gif" ALT="ZeeGee Software" ALIGN="RIGHT" BORDER="0"></A><A NAME="__TOP__"><H1>mime_postcard</H1>
+</A><UL>
+<LI> <A HREF="#NAME">NAME</A>
+<LI> <A HREF="#SYNOPSIS">SYNOPSIS</A>
+<LI> <A HREF="#DESCRIPTION">DESCRIPTION</A>
+<LI> <A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+</A>
+
+<P><HR>
+<A NAME="NAME"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> NAME</H2></A>
+
+
+<P>mime_postcard - output a multipart/alternative message
+
+
+
+<P><HR>
+<A NAME="SYNOPSIS"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> SYNOPSIS</H2></A>
+
+
+<P>Usage:
+
+<FONT SIZE=3 FACE="courier"><PRE>
+ mime_postcard /path/to/some/graphic.jpg to@addr.com
+</PRE></FONT>
+
+<P>You can point it at a .gif file as well.
+The special address &quot;-&quot; just causes the message to go to STDOUT.
+
+
+
+<P><HR>
+<A NAME="DESCRIPTION"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> DESCRIPTION</H2></A>
+
+
+<P>This send a mesasge both as HTML and plain text.
+I use &quot;Data&quot;; you would probably use &quot;Path&quot;.
+
+
+
+<P><HR>
+<A NAME="AUTHOR"><H2><A HREF="#__TOP__"><IMG SRC="icons/h1bullet.gif" ALT="Top" BORDER="0"></A> AUTHOR</H2></A>
+
+
+<P>Eryq, eryq@zeegee.com
+
+<P><HR>
+<ADDRESS><FONT SIZE=-1>
+Generated Fri Mar 30 01:17:44 2001 by cvu_pod2html
+</FONT></ADDRESS>
+</FONT></BODY>
+</HTML>
diff --git a/cpan/dist/MIME-Lite/examples/mime_fwd b/cpan/dist/MIME-Lite/examples/mime_fwd
new file mode 100755
index 00000000..388d38d7
--- /dev/null
+++ b/cpan/dist/MIME-Lite/examples/mime_fwd
@@ -0,0 +1,69 @@
+#!/usr/bin/perl -w
+
+
+=head1 NAME
+
+mime_fwd - test the ability to embed messages
+
+
+=head1 SYNOPSIS
+
+Usage:
+
+ mime_fwd
+
+
+=head1 DESCRIPTION
+
+Create a simple message, then wrap it in a "forward" and
+then a "reply".
+
+
+=head1 AUTHOR
+
+Eryq, eryq@zeegee.com
+
+=cut
+
+use strict;
+use MIME::Lite;
+use Getopt::Std;
+
+#------------------------------
+# main
+#------------------------------
+sub main {
+ my %opts;
+ my $subj = "hello world";
+
+ ### Create a message:
+ my $msg = MIME::Lite->new(From => 'user0',
+ To => 'user1',
+ Subject => $subj,
+ Type => 'TEXT',
+ Data => ["This is the original message.\n",
+ "Let's see if we can embed it!\n"]);
+
+ ### Forward it:
+ my $fwd = MIME::Lite->new(From => 'user1',
+ To => 'user2',
+ Subject => ("Fwd: ".$msg->get('subject')),
+ Type => 'message/rfc822');
+ $fwd->attach($msg);
+
+ ### Reply:
+ my $re = MIME::Lite->new(From => 'user2',
+ To => 'user0',
+ Bcc => 'archives',
+ Subject => ("Re: ".$fwd->get('subject')),
+ Type => 'message/rfc822');
+ $re->attach($fwd);
+
+ ### Output!
+ $re->print;
+}
+exit (&main ? 0 : -1);
+
+__END__
+
+
diff --git a/cpan/dist/MIME-Lite/examples/mime_gif b/cpan/dist/MIME-Lite/examples/mime_gif
new file mode 100755
index 00000000..de4ea76c
--- /dev/null
+++ b/cpan/dist/MIME-Lite/examples/mime_gif
@@ -0,0 +1,93 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+mime_gif - encode a single gif by reading data different ways
+
+
+=head1 SYNOPSIS
+
+Usage:
+
+ mime_gif /path/to/some.gif
+
+
+=head1 DESCRIPTION
+
+Encode a multipart message where each part contains the same GIF
+file, but where the GIF file has been read-in in different ways.
+The subject line of each part will tell you how the GIF was read.
+
+
+=head1 AUTHOR
+
+Eryq, eryq@zeegee.com
+
+=cut
+
+use strict;
+use MIME::Lite;
+use Getopt::Std;
+
+#------------------------------
+# main
+#------------------------------
+sub main {
+ my %opts;
+
+ ### Get options:
+ getopts('', \%opts) or die "usage error\n";
+ my $gifpath = $ARGV[0] || die "missing path to GIF\n";
+
+ ### Create message:
+ my $msg = MIME::Lite->new(To => 'me@somewhere.com',
+ Subject => 'GIF test',
+ Type => 'multipart/mixed');
+
+ ### Read data:
+ open IN, "<$gifpath" or die "open $gifpath: $!\n";
+ binmode IN;
+ my @data;
+ local $_ = '';
+ while (read(IN, $_, 1024)) {
+ push @data, $_;
+ }
+ close IN;
+
+ ### Direct path:
+ if (1) {
+ my $path = $gifpath;
+ $msg->attach(Subject => "Read path directly",
+ Path => $path,
+ Type => 'image/gif');
+ }
+
+ ### Cat (Unix only):
+ if (1) {
+ my $path = "cat $gifpath |";
+ $msg->attach(Subject => "Cat path to pipe, and read that",
+ Path => $path,
+ Type => 'image/gif');
+ }
+
+ ### Array:
+ if (1) {
+ $msg->attach(Subject => "Read data as array",
+ Data => \@data,
+ Type => 'image/gif');
+ }
+
+ ### String:
+ if (1) {
+ $msg->attach(Subject => "Read data as string",
+ Data => join('', @data),
+ Type => 'image/gif');
+ }
+
+ ### Output:
+ $msg->print(\*STDOUT);
+}
+exit(&main ? 0 : -1);
+1;
+__END__
+
diff --git a/cpan/dist/MIME-Lite/examples/mime_hack b/cpan/dist/MIME-Lite/examples/mime_hack
new file mode 100755
index 00000000..74aa82fb
--- /dev/null
+++ b/cpan/dist/MIME-Lite/examples/mime_hack
@@ -0,0 +1,58 @@
+#!/usr/bin/perl -w
+
+
+=head1 NAME
+
+mime_hack - test the "attach to singlepart" hack
+
+
+=head1 SYNOPSIS
+
+Usage:
+
+ mime_hack /path/to/some.gif
+
+
+=head1 DESCRIPTION
+
+Encode a multipart message by starting with a text message,
+and attaching a GIF file to it.
+
+
+=head1 AUTHOR
+
+Eryq, eryq@zeegee.com
+
+=cut
+
+use strict;
+use MIME::Lite;
+use Getopt::Std;
+
+#------------------------------
+# main
+#------------------------------
+sub main {
+ my %opts;
+ my $gif = $ARGV[0] || die "usage error: missing GIF path\n";
+
+ ### Create a new multipart message:
+ my $msg = MIME::Lite->new(From => 'me@myhost.com',
+ To => 'you@yourhost.com',
+ Subject =>'Test the "attach to singlepart" hack',
+ Type => 'TEXT',
+ Data => ["This is a simple text message... ",
+ "can we attach a file to it?\n"]);
+
+ ### Attach a part:
+ $msg->attach(Type => 'image/gif',
+ Path => $gif);
+
+ ### Output!
+ $msg->print;
+}
+exit (&main ? 0 : -1);
+
+__END__
+
+
diff --git a/cpan/dist/MIME-Lite/examples/mime_longlines b/cpan/dist/MIME-Lite/examples/mime_longlines
new file mode 100755
index 00000000..1d95ade9
--- /dev/null
+++ b/cpan/dist/MIME-Lite/examples/mime_longlines
@@ -0,0 +1,92 @@
+#!/usr/bin/perl -w
+
+
+=head1 NAME
+
+mime_longlines - generate a test message with long lines
+
+
+=head1 SYNOPSIS
+
+Usage:
+
+ mime_longlines [-s]
+
+Options:
+
+ -s Stringify message first, and print the *string* to STDOUT.
+
+
+=head1 DESCRIPTION
+
+Assemble and print (to the standard output) a multipart message
+with 5 attachments, for the purpose of "eyeballing" how well the
+encoders are working.
+
+Each attachments holds the same data -- some 8-bit text, and a long
+line consisting of 1000 "a"s followed by a few "b"s) -- but each
+has a different encoding (the "Content-transfer-encoding" field
+will tell you which is which).
+
+All of the encodings (except for the first one, "binary") should
+break the long line before the b's.
+
+
+=head1 AUTHOR
+
+Eryq, eryq@zeegee.com
+
+=cut
+
+use strict;
+use MIME::Lite;
+use Getopt::Std;
+
+### Set up a long message:
+my $DATA = <<EOF;
+Here's a line with some 8-bit characters... the "7bit" encoding should
+strip them out:
+
+ \xABFran\xE7ois M\xFCller\xBB.
+
+The line below is REALLY long. It contains 1000 a's, followed by some b's.
+All of the encodings (except binary) should break the line before the b's:
+
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbb
+
+EOF
+
+#------------------------------
+# main
+#------------------------------
+sub main {
+ my %opts;
+
+ ### Get options:
+ getopts('s', \%opts) or die "usage error\n";
+
+ ### Create a new multipart message:
+ my $msg = new MIME::Lite
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'The Magnificent Five (encodings, that is)',
+ Type =>'multipart/mixed';
+
+ ### Add parts:
+ foreach my $enc (qw(binary 8bit 7bit quoted-printable base64)) {
+ $msg->attach(Type => 'TEXT',
+ Data => $DATA,
+ Encoding => $enc);
+ }
+
+ ### Print:
+ if ($opts{'s'}) { print $msg->stringify }
+ else { $msg->print(\*STDOUT) }
+ 1;
+}
+exit (&main ? 0 : -1);
+1;
+
+__END__
+
diff --git a/cpan/dist/MIME-Lite/examples/mime_postcard b/cpan/dist/MIME-Lite/examples/mime_postcard
new file mode 100755
index 00000000..19271717
--- /dev/null
+++ b/cpan/dist/MIME-Lite/examples/mime_postcard
@@ -0,0 +1,79 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+mime_postcard - output a multipart/alternative message
+
+
+=head1 SYNOPSIS
+
+Usage:
+
+ mime_postcard /path/to/some/graphic.jpg to@addr.com
+
+You can point it at a .gif file as well.
+The special address "-" just causes the message to go to STDOUT.
+
+
+=head1 DESCRIPTION
+
+This send a mesasge both as HTML and plain text.
+I use "Data"; you would probably use "Path".
+
+
+=head1 AUTHOR
+
+Eryq, eryq@zeegee.com
+
+
+=cut
+
+use MIME::Lite 1.137;
+use strict;
+$SIG{__DIE__} = sub { die "mime_postcard: $_[0]\n" };
+
+### Get graphic:
+my $graphic = shift @ARGV || die "usage error: missing path to graphic\n";
+(-r $graphic) or die "$graphic unreadable\n";
+my $graphic_type;
+if ($graphic =~ /\.gif$/i) { $graphic_type = "image/gif" }
+elsif ($graphic =~ /\.jpe?g$/i) { $graphic_type = "image/jpeg" }
+elsif ($graphic =~ /\.png$/i) { $graphic_type = "image/png" }
+else { die "unknown type for: $graphic\n"; }
+my $gid = "my-graphic";
+
+### Get destination:
+my $dest = shift @ARGV || die "missing destination\n";
+
+### The top-level message:
+my $msg = MIME::Lite->new(To => $dest,
+ Subject => 'A postcard for you',
+ Type => 'multipart/alternative');
+
+
+### Alternative #1 is the plain text:
+my $plain = $msg->attach(Type => 'text/plain',
+ Data => ["Having a wonderful time... \n",
+ "wish you were looking at HTML \n",
+ "instead of this boring text!\n"]);
+
+### Alternative #2 is the HTML-with-content:
+my $fancy = $msg->attach(Type => 'multipart/related');
+$fancy->attach(Type => 'text/html',
+ Data => [qq< <H1>Hey there!</H1> \n>,
+ qq< Having a <I>wonderful</I> time... take a look!\n >,
+ qq< <BR><IMG SRC="cid:$gid" ALT="Snapshot"> <HR> >]);
+$fancy->attach(Type => $graphic_type,
+ Path => $graphic,
+ Id => $gid);
+
+
+if ($dest eq '-') {
+ $msg->print;
+}
+else {
+ $msg->send;
+}
+
+
+
diff --git a/cpan/dist/MIME-Lite/lib/MIME/Lite.pm b/cpan/dist/MIME-Lite/lib/MIME/Lite.pm
new file mode 100644
index 00000000..ad8ac3cf
--- /dev/null
+++ b/cpan/dist/MIME-Lite/lib/MIME/Lite.pm
@@ -0,0 +1,3227 @@
+package MIME::Lite;
+
+
+=head1 NAME
+
+MIME::Lite - low-calorie MIME generator
+
+
+=head1 SYNOPSIS
+
+ use MIME::Lite;
+
+Create a single-part message:
+
+ ### Create a new single-part message, to send a GIF file:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'Helloooooo, nurse!',
+ Type =>'image/gif',
+ Encoding =>'base64',
+ Path =>'hellonurse.gif'
+ );
+
+Create a multipart message (i.e., one with attachments):
+
+ ### Create a new multipart message:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'A message with 2 parts...',
+ Type =>'multipart/mixed'
+ );
+
+ ### Add parts (each "attach" has same arguments as "new"):
+ $msg->attach(Type =>'TEXT',
+ Data =>"Here's the GIF file you wanted"
+ );
+ $msg->attach(Type =>'image/gif',
+ Path =>'aaa000123.gif',
+ Filename =>'logo.gif',
+ Disposition => 'attachment'
+ );
+
+Output a message:
+
+ ### Format as a string:
+ $str = $msg->as_string;
+
+ ### Print to a filehandle (say, a "sendmail" stream):
+ $msg->print(\*SENDMAIL);
+
+
+Send a message:
+
+ ### Send in the "best" way (the default is to use "sendmail"):
+ $msg->send;
+
+
+
+=head1 DESCRIPTION
+
+In the never-ending quest for great taste with fewer calories,
+we proudly present: I<MIME::Lite>.
+
+MIME::Lite is intended as a simple, standalone module for generating
+(not parsing!) MIME messages... specifically, it allows you to
+output a simple, decent single- or multi-part message with text or binary
+attachments. It does not require that you have the Mail:: or MIME::
+modules installed.
+
+You can specify each message part as either the literal data itself (in
+a scalar or array), or as a string which can be given to open() to get
+a readable filehandle (e.g., "<filename" or "somecommand|").
+
+You don't need to worry about encoding your message data:
+this module will do that for you. It handles the 5 standard MIME encodings.
+
+If you need more sophisticated behavior, please get the MIME-tools
+package instead. I will be more likely to add stuff to that toolkit
+over this one.
+
+
+=head1 MORE EXAMPLES
+
+=head2 Attach a GIF to a text message
+
+This will create a multipart message exactly as above, but using the
+"attach to singlepart" hack:
+
+ ### Create a new multipart message:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'A message with 2 parts...',
+ Type =>'TEXT',
+ Data =>"Here's the GIF file you wanted"
+ );
+
+ ### Attach a part:
+ $msg->attach(Type =>'image/gif',
+ Path =>'aaa000123.gif',
+ Filename =>'logo.gif'
+ );
+
+
+=head2 Attach a pre-prepared part (allows fine-tuning):
+
+ $part = MIME::Lite->new(
+ Type =>'text/html',
+ Data =>'<H1>Hello</H1>',
+ );
+ $part->attr('content-type.charset' => 'UTF8');
+ $part->add('X-Comment' => 'A message for you');
+ $msg->attach($part);
+
+
+=head2 Send an HTML document... with images included!
+
+ $msg = MIME::Lite->new(
+ To =>'you@yourhost.com',
+ Subject =>'HTML with in-line images!',
+ Type =>'multipart/related'
+ );
+ $msg->attach(Type => 'text/html',
+ Data => qq{ <body>
+ Here's <i>my</i> image:
+ <img src="cid:myimage.gif">
+ </body> }
+ );
+ $msg->attach(Type => 'image/gif',
+ Id => 'myimage.gif',
+ Path => '/path/to/somefile.gif',
+ );
+ $msg->send();
+
+
+=head2 Output a message to a filehandle
+
+ ### Write it to a filehandle:
+ $msg->print(\*STDOUT);
+
+ ### Write just the header:
+ $msg->print_header(\*STDOUT);
+
+ ### Write just the encoded body:
+ $msg->print_body(\*STDOUT);
+
+
+=head2 Get a message as a string
+
+ ### Get entire message as a string:
+ $str = $msg->as_string;
+
+ ### Get just the header:
+ $str = $msg->header_as_string;
+
+ ### Get just the encoded body:
+ $str = $msg->body_as_string;
+
+
+=head2 Change how messages are sent
+
+ ### Do something like this in your 'main':
+ if ($I_DONT_HAVE_SENDMAIL) {
+ MIME::Lite->send('smtp', "smtp.myisp.net", Timeout=>60);
+ }
+
+ ### Now this will do the right thing:
+ $msg->send; ### will now use Net::SMTP as shown above
+
+
+
+
+
+
+=head1 FAQ
+
+
+=head2 How do I prevent "Content" headers from showing up in my mail reader?
+
+Apparently, some people are using mail readers which display the MIME
+headers like "Content-disposition", and they want MIME::Lite not
+to generate them "because they look ugly".
+
+Sigh.
+
+Y'know, kids, those headers aren't just there for cosmetic purposes.
+They help ensure that the message is I<understood> correctly by mail
+readers. But okay, you asked for it, you got it...
+here's how you can suppress the standard MIME headers.
+Before you send the message, do this:
+
+ $msg->scrub;
+
+You can scrub() any part of a multipart message independently;
+just be aware that it works recursively. Before you scrub,
+note the rules that I follow:
+
+=over 4
+
+=item Content-type
+
+You can safely scrub the "content-type" attribute if, and only if,
+the part is of type "text/plain" with charset "us-ascii".
+
+=item Content-transfer-encoding
+
+You can safely scrub the "content-transfer-encoding" attribute
+if, and only if, the part uses "7bit", "8bit", or "binary" encoding.
+You are far better off doing this if your lines are under 1000
+characters. Generally, that means you I<can> scrub it for plain
+text, and you can I<not> scrub this for images, etc.
+
+=item Content-disposition
+
+You can safely scrub the "content-disposition" attribute
+if you trust the mail reader to do the right thing when it decides
+whether to show an attachment inline or as a link. Be aware
+that scrubbing both the content-disposition and the content-type
+means that there is no way to "recommend" a filename for the attachment!
+
+B<Note:> there are reports of brain-dead MUAs out there that
+do the wrong thing if you I<provide> the content-disposition.
+If your attachments keep showing up inline or vice-versa,
+try scrubbing this attribute.
+
+=item Content-length
+
+You can always scrub "content-length" safely.
+
+=back
+
+
+=head2 How do I give my attachment a [different] recommended filename?
+
+By using the Filename option (which is different from Path!):
+
+ $msg->attach(Type => "image/gif",
+ Path => "/here/is/the/real/file.GIF",
+ Filename => "logo.gif");
+
+You should I<not> put path information in the Filename.
+
+
+
+=head1 PUBLIC INTERFACE
+
+=head2 Global configuration
+
+To alter the way the entire module behaves, you have the following
+methods/options:
+
+=over 4
+
+
+=item MIME::Lite->header_order()
+
+When used as a L<classmethod|/send>, this changes the default
+order in which headers are output for I<all> messages.
+
+
+=item MIME::Lite->quiet()
+
+This L<classmethod|/quiet> can be used to suppress/unsuppress
+all warnings coming from this module.
+
+
+=item MIME::Lite->send()
+
+When used as a L<classmethod|/send>, this can be used to specify
+a different default mechanism for sending message.
+The initial default is:
+
+ MIME::Lite->send("sendmail", "/usr/lib/sendmail -t -oi -oem");
+
+However, you should consider the similar but smarter and taint-safe variant:
+
+ MIME::Lite->send("sendmail");
+
+Or, for non-Unix users:
+
+ MIME::Lite->send("smtp");
+
+
+=item $MIME::Lite::PARANOID
+
+If true, we won't attempt to use MIME::Base64/MIME::QuotedPrint, even
+if they're available.
+Default is B<false>.
+
+
+=item $MIME::Lite::AUTO_ENCODE
+
+If true, automatically choose the encoding from the content type.
+Default is B<true>.
+
+
+=item $MIME::Lite::AUTO_CC
+
+If true, automatically send to the Cc/Bcc addresses for send_by_smtp().
+Default is B<true>.
+
+
+=item $MIME::Lite::AUTO_VERIFY
+
+If true, check paths to attachments right before printing, raising an exception
+if any path is unreadable.
+Default is B<true>.
+
+=back
+
+=cut
+
+require 5.004; ### for /c modifier in m/\G.../gc modifier
+
+use Carp;
+use FileHandle;
+
+use strict;
+use vars qw(
+ $AUTO_CC
+ $AUTO_ENCODE
+ $AUTO_VERIFY
+ $PARANOID
+ $QUIET
+ $VANILLA
+ $VERSION
+ );
+
+
+
+#==============================
+#==============================
+#
+# GLOBALS, EXTERNAL/CONFIGURATION...
+
+### The package version, both in 1.23 style *and* usable by MakeMaker:
+$VERSION = substr q$Revision: 2.108 $, 10;
+
+### Don't warn me about dangerous activities:
+$QUIET = undef;
+
+### Set this true if you don't want to use MIME::Base64/MIME::QuotedPrint:
+$PARANOID = 0;
+
+### Unsupported (for tester use): don't qualify boundary with time/pid:
+$VANILLA = 0;
+
+### Automatically choose encoding from content type:
+$AUTO_ENCODE = 1;
+
+### Automatically interpret CC/BCC for SMTP:
+$AUTO_CC = 1;
+
+### Check paths right before printing:
+$AUTO_VERIFY = 1;
+
+
+#==============================
+#==============================
+#
+# GLOBALS, INTERNAL...
+
+### Find sendmail:
+my $SENDMAIL = "/usr/lib/sendmail";
+(-x $SENDMAIL) or ($SENDMAIL = "/usr/sbin/sendmail");
+(-x $SENDMAIL) or ($SENDMAIL = "sendmail");
+
+### Our sending facilities:
+my $Sender = "sendmail";
+my %SenderArgs = (
+ "sendmail" => ["$SENDMAIL -t -oi -oem"],
+ "smtp" => [],
+ "sub" => [],
+);
+
+### Boundary counter:
+my $BCount = 0;
+
+### Known Mail/MIME fields... these, plus some general forms like
+### "x-*", are recognized by build():
+my %KnownField = map {$_=>1}
+qw(
+ bcc cc comments date encrypted
+ from keywords message-id mime-version organization
+ received references reply-to return-path sender
+ subject to
+
+ approved
+ );
+
+### What external packages do we use for encoding?
+my @Uses;
+
+### Header order:
+my @FieldOrder;
+
+
+#==============================
+#==============================
+#
+# PRIVATE UTILITY FUNCTIONS...
+
+#------------------------------
+#
+# fold STRING
+#
+# Make STRING safe as a field value. Remove leading/trailing whitespace,
+# and make sure newlines are represented as newline+space
+
+sub fold {
+ my $str = shift;
+ $str =~ s/^\s*|\s*$//g; ### trim
+ $str =~ s/\n/\n /g;
+ $str;
+}
+
+#------------------------------
+#
+# gen_boundary
+#
+# Generate a new boundary to use.
+# The unsupported $VANILLA is for test purposes only.
+
+sub gen_boundary {
+ return ("_----------=_".($VANILLA ? '' : int(time).$$).$BCount++);
+}
+
+#------------------------------
+#
+# known_field FIELDNAME
+#
+# Is this a recognized Mail/MIME field?
+
+sub known_field {
+ my $field = lc(shift);
+ $KnownField{$field} or ($field =~ m{^(content|resent|x)-.});
+}
+
+#------------------------------
+#
+# is_mime_field FIELDNAME
+#
+# Is this a field I manage?
+
+sub is_mime_field {
+ $_[0] =~ /^(mime\-|content\-)/i;
+}
+
+#------------------------------
+#
+# extract_addrs STRING
+#
+# Split STRING into an array of email addresses: somewhat of a KLUDGE.
+#
+# Unless paranoid, we try to load the real code before supplying our own.
+
+my $ATOM = '[^ \000-\037()<>@,;:\134"\056\133\135]+';
+my $QSTR = '".*?"';
+my $WORD = '(?:' . $QSTR . '|' . $ATOM . ')';
+my $DOMAIN = '(?:' . $ATOM . '(?:' . '\\.' . $ATOM . ')*' . ')';
+my $LOCALPART = '(?:' . $WORD . '(?:' . '\\.' . $WORD . ')*' . ')';
+my $ADDR = '(?:' . $LOCALPART . '@' . $DOMAIN . ')';
+my $PHRASE = '(?:' . $WORD . ')+';
+my $SEP = "(?:^\\s*|\\s*,\\s*)"; ### before elems in a list
+
+sub my_extract_addrs {
+ my $str = shift;
+ my @addrs;
+ $str =~ s/\s/ /g; ### collapse whitespace
+
+ pos($str) = 0;
+ while ($str !~ m{\G\s*\Z}gco) {
+ ### print STDERR "TACKLING: ".substr($str, pos($str))."\n";
+ if ($str =~ m{\G$SEP$PHRASE\s*<\s*($ADDR)\s*>}gco) {push @addrs,$1}
+ elsif ($str =~ m{\G$SEP($ADDR)}gco) {push @addrs,$1}
+ elsif ($str =~ m{\G$SEP($ATOM)}gco) {push @addrs,$1}
+ else {
+ my $problem = substr($str, pos($str));
+ die "can't extract address at <$problem> in <$str>\n";
+ }
+ }
+ return @addrs;
+}
+
+if (eval "require Mail::Address") {
+ push @Uses, "A$Mail::Address::VERSION";
+ eval q{
+ sub extract_addrs {
+ return map { $_->format } Mail::Address->parse($_[0]);
+ }
+ }; ### q
+}
+else {
+ eval q{
+ sub extract_addrs {
+ return my_extract_addrs(@_);
+ }
+ }; ### q
+} ### if
+
+
+
+#==============================
+#==============================
+#
+# PRIVATE ENCODING FUNCTIONS...
+
+#------------------------------
+#
+# encode_base64 STRING
+#
+# Encode the given string using BASE64.
+# Unless paranoid, we try to load the real code before supplying our own.
+
+if (!$PARANOID and eval "require MIME::Base64") {
+ import MIME::Base64 qw(encode_base64);
+ push @Uses, "B$MIME::Base64::VERSION";
+}
+else {
+ eval q{
+sub encode_base64 {
+ my $res = "";
+ my $eol = "\n";
+
+ pos($_[0]) = 0; ### thanks, Andreas!
+ while ($_[0] =~ /(.{1,45})/gs) {
+ $res .= substr(pack('u', $1), 1);
+ chop($res);
+ }
+ $res =~ tr|` -_|AA-Za-z0-9+/|;
+
+ ### Fix padding at the end:
+ my $padding = (3 - length($_[0]) % 3) % 3;
+ $res =~ s/.{$padding}$/'=' x $padding/e if $padding;
+
+ ### Break encoded string into lines of no more than 76 characters each:
+ $res =~ s/(.{1,76})/$1$eol/g if (length $eol);
+ return $res;
+} ### sub
+ } ### q
+} ### if
+
+#------------------------------
+#
+# encode_qp STRING
+#
+# Encode the given string, LINE BY LINE, using QUOTED-PRINTABLE.
+# Stolen from MIME::QuotedPrint by Gisle Aas, with a slight bug fix: we
+# break lines earlier. Notice that this seems not to work unless
+# encoding line by line.
+#
+# Unless paranoid, we try to load the real code before supplying our own.
+
+if (!$PARANOID and eval "require MIME::QuotedPrint") {
+ import MIME::QuotedPrint qw(encode_qp);
+ push @Uses, "Q$MIME::QuotedPrint::VERSION";
+}
+else {
+ eval q{
+sub encode_qp {
+ my $res = shift;
+ local($_);
+ $res =~ s/([^ \t\n!-<>-~])/sprintf("=%02X", ord($1))/eg; ### rule #2,#3
+ $res =~ s/([ \t]+)$/
+ join('', map { sprintf("=%02X", ord($_)) }
+ split('', $1)
+ )/egm; ### rule #3 (encode whitespace at eol)
+
+ ### rule #5 (lines shorter than 76 chars, but can't break =XX escapes:
+ my $brokenlines = "";
+ $brokenlines .= "$1=\n" while $res =~ s/^(.{70}([^=]{2})?)//; ### 70 was 74
+ $brokenlines =~ s/=\n$// unless length $res;
+ "$brokenlines$res";
+} ### sub
+ } ### q
+} ### if
+
+
+#------------------------------
+#
+# encode_8bit STRING
+#
+# Encode the given string using 8BIT.
+# This breaks long lines into shorter ones.
+
+sub encode_8bit {
+ my $str = shift;
+ $str =~ s/^(.{990})/$1\n/mg;
+ $str;
+}
+
+#------------------------------
+#
+# encode_7bit STRING
+#
+# Encode the given string using 7BIT.
+# This NO LONGER protects people through encoding.
+
+sub encode_7bit {
+ my $str = shift;
+ $str =~ s/[\x80-\xFF]//g;
+ $str =~ s/^(.{990})/$1\n/mg;
+ $str;
+}
+
+#==============================
+#==============================
+
+=head2 Construction
+
+=over 4
+
+=cut
+
+
+#------------------------------
+
+=item new [PARAMHASH]
+
+I<Class method, constructor.>
+Create a new message object.
+
+If any arguments are given, they are passed into C<build()>; otherwise,
+just the empty object is created.
+
+=cut
+
+sub new {
+ my $class = shift;
+
+ ### Create basic object:
+ my $self = {
+ Attrs => {}, ### MIME attributes
+ Header => [], ### explicit message headers
+ Parts => [], ### array of parts
+ };
+ bless $self, $class;
+
+ ### Build, if needed:
+ return (@_ ? $self->build(@_) : $self);
+}
+
+
+#------------------------------
+
+=item attach PART
+
+=item attach PARAMHASH...
+
+I<Instance method.>
+Add a new part to this message, and return the new part.
+
+If you supply a single PART argument, it will be regarded
+as a MIME::Lite object to be attached. Otherwise, this
+method assumes that you are giving in the pairs of a PARAMHASH
+which will be sent into C<new()> to create the new part.
+
+One of the possibly-quite-useful hacks thrown into this is the
+"attach-to-singlepart" hack: if you attempt to attach a part (let's
+call it "part 1") to a message that doesn't have a content-type
+of "multipart" or "message", the following happens:
+
+=over 4
+
+=item *
+
+A new part (call it "part 0") is made.
+
+=item *
+
+The MIME attributes and data (but I<not> the other headers)
+are cut from the "self" message, and pasted into "part 0".
+
+=item *
+
+The "self" is turned into a "multipart/mixed" message.
+
+=item *
+
+The new "part 0" is added to the "self", and I<then> "part 1" is added.
+
+=back
+
+One of the nice side-effects is that you can create a text message
+and then add zero or more attachments to it, much in the same way
+that a user agent like Netscape allows you to do.
+
+=cut
+
+sub attach {
+ my $self = shift;
+
+ ### Create new part, if necessary:
+ my $part1 = ((@_ == 1) ? shift : ref($self)->new(Top=>0, @_));
+
+ ### Do the "attach-to-singlepart" hack:
+ if ($self->attr('content-type') !~ m{^(multipart|message)/}i) {
+
+ ### Create part zero:
+ my $part0 = ref($self)->new;
+
+ ### Cut MIME stuff from self, and paste into part zero:
+ foreach (qw(Attrs Data Path FH)) {
+ $part0->{$_} = $self->{$_}; delete($self->{$_});
+ }
+ $part0->top_level(0); ### clear top-level attributes
+
+ ### Make self a top-level multipart:
+ $self->{Attrs} ||= {}; ### reset
+ $self->attr('content-type' => 'multipart/mixed');
+ $self->attr('content-type.boundary' => gen_boundary());
+ $self->attr('content-transfer-encoding' => '7bit');
+ $self->top_level(1); ### activate top-level attributes
+
+ ### Add part 0:
+ push @{$self->{Parts}}, $part0;
+ }
+
+ ### Add the new part:
+ push @{$self->{Parts}}, $part1;
+ $part1;
+}
+
+#------------------------------
+
+=item build [PARAMHASH]
+
+I<Class/instance method, initializer.>
+Create (or initialize) a MIME message object.
+Normally, you'll use the following keys in PARAMHASH:
+
+ * Data, FH, or Path (either one of these, or none if multipart)
+ * Type (e.g., "image/jpeg")
+ * From, To, and Subject (if this is the "top level" of a message)
+
+The PARAMHASH can contain the following keys:
+
+=over 4
+
+=item (fieldname)
+
+Any field you want placed in the message header, taken from the
+standard list of header fields (you don't need to worry about case):
+
+ Approved Encrypted Received Sender
+ Bcc From References Subject
+ Cc Keywords Reply-To To
+ Comments Message-ID Resent-* X-*
+ Content-* MIME-Version Return-Path
+ Date Organization
+
+To give experienced users some veto power, these fields will be set
+I<after> the ones I set... so be careful: I<don't set any MIME fields>
+(like C<Content-type>) unless you know what you're doing!
+
+To specify a fieldname that's I<not> in the above list, even one that's
+identical to an option below, just give it with a trailing C<":">,
+like C<"My-field:">. When in doubt, that I<always> signals a mail
+field (and it sort of looks like one too).
+
+=item Data
+
+I<Alternative to "Path" or "FH".>
+The actual message data. This may be a scalar or a ref to an array of
+strings; if the latter, the message consists of a simple concatenation
+of all the strings in the array.
+
+=item Datestamp
+
+I<Optional.>
+If given true (or omitted), we force the creation of a C<Date:> field
+stamped with the current date/time if this is a top-level message.
+You may want this if using L<send_by_smtp()|/send_by_smtp>.
+If you don't want this to be done, either provide your own Date
+or explicitly set this to false.
+
+=item Disposition
+
+I<Optional.>
+The content disposition, C<"inline"> or C<"attachment">.
+The default is C<"inline">.
+
+=item Encoding
+
+I<Optional.>
+The content transfer encoding that should be used to encode your data:
+
+ Use encoding: | If your message contains:
+ ------------------------------------------------------------
+ 7bit | Only 7-bit text, all lines <1000 characters
+ 8bit | 8-bit text, all lines <1000 characters
+ quoted-printable | 8-bit text or long lines (more reliable than "8bit")
+ base64 | Largely non-textual data: a GIF, a tar file, etc.
+
+The default is taken from the Type; generally it is "binary" (no
+encoding) for text/*, message/*, and multipart/*, and "base64" for
+everything else. A value of C<"binary"> is generally I<not> suitable
+for sending anything but ASCII text files with lines under 1000
+characters, so consider using one of the other values instead.
+
+In the case of "7bit"/"8bit", long lines are automatically chopped to
+legal length; in the case of "7bit", all 8-bit characters are
+automatically I<removed>. This may not be what you want, so pick your
+encoding well! For more info, see L<"A MIME PRIMER">.
+
+=item FH
+
+I<Alternative to "Data" or "Path".>
+Filehandle containing the data, opened for reading.
+See "ReadNow" also.
+
+=item Filename
+
+I<Optional.>
+The name of the attachment. You can use this to supply a
+recommended filename for the end-user who is saving the attachment
+to disk. You only need this if the filename at the end of the
+"Path" is inadequate, or if you're using "Data" instead of "Path".
+You should I<not> put path information in here (e.g., no "/"
+or "\" or ":" characters should be used).
+
+=item Id
+
+I<Optional.>
+Same as setting "content-id".
+
+=item Length
+
+I<Optional.>
+Set the content length explicitly. Normally, this header is automatically
+computed, but only under certain circumstances (see L<"Limitations">).
+
+=item Path
+
+I<Alternative to "Data" or "FH".>
+Path to a file containing the data... actually, it can be any open()able
+expression. If it looks like a path, the last element will automatically
+be treated as the filename.
+See "ReadNow" also.
+
+=item ReadNow
+
+I<Optional, for use with "Path".>
+If true, will open the path and slurp the contents into core now.
+This is useful if the Path points to a command and you don't want
+to run the command over and over if outputting the message several
+times. B<Fatal exception> raised if the open fails.
+
+=item Top
+
+I<Optional.>
+If defined, indicates whether or not this is a "top-level" MIME message.
+The parts of a multipart message are I<not> top-level.
+Default is true.
+
+=item Type
+
+I<Optional.>
+The MIME content type, or one of these special values (case-sensitive):
+
+ "TEXT" means "text/plain"
+ "BINARY" means "application/octet-stream"
+
+The default is C<"TEXT">.
+
+=back
+
+A picture being worth 1000 words (which
+is of course 2000 bytes, so it's probably more of an "icon" than a "picture",
+but I digress...), here are some examples:
+
+ $msg = MIME::Lite->build(
+ From => 'yelling@inter.com',
+ To => 'stocking@fish.net',
+ Subject => "Hi there!",
+ Type => 'TEXT',
+ Encoding => '7bit',
+ Data => "Just a quick note to say hi!");
+
+ $msg = MIME::Lite->build(
+ From => 'dorothy@emerald-city.oz',
+ To => 'gesundheit@edu.edu.edu',
+ Subject => "A gif for U"
+ Type => 'image/gif',
+ Path => "/home/httpd/logo.gif");
+
+ $msg = MIME::Lite->build(
+ From => 'laughing@all.of.us',
+ To => 'scarlett@fiddle.dee.de',
+ Subject => "A gzipp'ed tar file",
+ Type => 'x-gzip',
+ Path => "gzip < /usr/inc/somefile.tar |",
+ ReadNow => 1,
+ Filename => "somefile.tgz");
+
+To show you what's really going on, that last example could also
+have been written:
+
+ $msg = new MIME::Lite;
+ $msg->build(Type => 'x-gzip',
+ Path => "gzip < /usr/inc/somefile.tar |",
+ ReadNow => 1,
+ Filename => "somefile.tgz");
+ $msg->add(From => "laughing@all.of.us");
+ $msg->add(To => "scarlett@fiddle.dee.de");
+ $msg->add(Subject => "A gzipp'ed tar file");
+
+=cut
+
+sub build {
+ my $self = shift;
+ my %params = @_;
+ my @params = @_;
+ my $key;
+
+ ### Miko's note: reorganized to check for exactly one of Data, Path, or FH
+ (defined($params{Data})+defined($params{Path})+defined($params{FH}) <= 1)
+ or croak "supply exactly zero or one of (Data|Path|FH).\n";
+
+ ### Create new instance, if necessary:
+ ref($self) or $self = $self->new;
+
+
+ ### CONTENT-TYPE....
+ ###
+
+ ### Get content-type:
+ my $type = ($params{Type} || 'TEXT');
+ ($type eq 'TEXT') and $type = 'text/plain';
+ ($type eq 'BINARY') and $type = 'application/octet-stream';
+ $type = lc($type);
+ $self->attr('content-type' => $type);
+
+ ### Get some basic attributes from the content type:
+ my $is_multipart = ($type =~ m{^(multipart)/}i);
+
+ ### Add in the multipart boundary:
+ if ($is_multipart) {
+ my $boundary = gen_boundary();
+ $self->attr('content-type.boundary' => $boundary);
+ }
+
+
+ ### CONTENT-ID...
+ ###
+ $self->attr('content-id' => $params{Id}) if defined($params{Id});
+
+
+ ### DATA OR PATH...
+ ### Note that we must do this *after* we get the content type,
+ ### in case read_now() is invoked, since it needs the binmode().
+
+ ### Get data, as...
+ ### ...either literal data:
+ if (defined($params{Data})) {
+ $self->data($params{Data});
+ }
+ ### ...or a path to data:
+ elsif (defined($params{Path})) {
+ $self->path($params{Path}); ### also sets filename
+ $self->read_now if $params{ReadNow};
+ }
+ ### ...or a filehandle to data:
+ ### Miko's note: this part works much like the path routine just above,
+ elsif (defined($params{FH})) {
+ $self->fh($params{FH});
+ $self->read_now if $params{ReadNow}; ### implement later
+ }
+
+
+ ### FILENAME... (added by Ian Smith <ian@safeway.dircon.co.uk> on 8/4/97)
+ ### Need this to make sure the filename is added. The Filename
+ ### attribute is ignored, otherwise.
+ if (defined($params{Filename})) {
+ $self->filename($params{Filename});
+ }
+
+
+ ### CONTENT-TRANSFER-ENCODING...
+ ###
+
+ ### Get it:
+ my $enc = ($params{Encoding} ||
+ ($AUTO_ENCODE and $self->suggest_encoding($type)) ||
+ 'binary');
+ $self->attr('content-transfer-encoding' => lc($enc));
+
+ ### Sanity check:
+ if ($type =~ m{^(multipart|message)/}) {
+ ($enc =~ m{^(7bit|8bit|binary)\Z}) or
+ croak "illegal MIME: can't have encoding $enc with type $type\n";
+ }
+
+ ### CONTENT-DISPOSITION...
+ ### Default is inline for single, none for multis:
+ ###
+ my $disp = ($params{Disposition} or ($is_multipart ? undef : 'inline'));
+ $self->attr('content-disposition' => $disp);
+
+ ### CONTENT-LENGTH...
+ ###
+ my $length;
+ if (exists($params{Length})) { ### given by caller:
+ $self->attr('content-length' => $params{Length});
+ }
+ else { ### compute it ourselves
+ $self->get_length;
+ }
+
+ ### Init the top-level fields:
+ my $is_top = defined($params{Top}) ? $params{Top} : 1;
+ $self->top_level($is_top);
+
+ ### Datestamp if desired:
+ my $ds_wanted = $params{Datestamp};
+ my $ds_defaulted = ($is_top and !exists($params{Datestamp}));
+ if (($ds_wanted or $ds_defaulted) and !exists($params{Date})) {
+ my ($u_wdy, $u_mon, $u_mdy, $u_time, $u_y4) =
+ split /\s+/, gmtime().""; ### should be non-locale-dependent
+ my $date = "$u_wdy, $u_mdy $u_mon $u_y4 $u_time UT";
+ $self->add("date", $date);
+ }
+
+ ### Set message headers:
+ my @paramz = @params;
+ my $field;
+ while (@paramz) {
+ my ($tag, $value) = (shift(@paramz), shift(@paramz));
+
+ ### Get tag, if a tag:
+ if ($tag =~ /^-(.*)/) { ### old style, backwards-compatibility
+ $field = lc($1);
+ }
+ elsif ($tag =~ /^(.*):$/) { ### new style
+ $field = lc($1);
+ }
+ elsif (known_field($field = lc($tag))) { ### known field
+ ### no-op
+ }
+ else { ### not a field:
+ next;
+ }
+
+ ### Add it:
+ $self->add($field, $value);
+ }
+
+ ### Done!
+ $self;
+}
+
+=back
+
+=cut
+
+
+#==============================
+#==============================
+
+=head2 Setting/getting headers and attributes
+
+=over 4
+
+=cut
+
+#------------------------------
+#
+# top_level ONOFF
+#
+# Set/unset the top-level attributes and headers.
+# This affects "MIME-Version" and "X-Mailer".
+
+sub top_level {
+ my ($self, $onoff) = @_;
+ if ($onoff) {
+ $self->attr('MIME-Version' => '1.0');
+ my $uses = (@Uses ? ("(" . join("; ", @Uses) . ")") : '');
+ $self->replace('X-Mailer' => "MIME::Lite $VERSION $uses")
+ unless $VANILLA;
+ }
+ else {
+ $self->attr('MIME-Version' => undef);
+ $self->delete('X-Mailer');
+ }
+}
+
+#------------------------------
+
+=item add TAG,VALUE
+
+I<Instance method.>
+Add field TAG with the given VALUE to the end of the header.
+The TAG will be converted to all-lowercase, and the VALUE
+will be made "safe" (returns will be given a trailing space).
+
+B<Beware:> any MIME fields you "add" will override any MIME
+attributes I have when it comes time to output those fields.
+Normally, you will use this method to add I<non-MIME> fields:
+
+ $msg->add("Subject" => "Hi there!");
+
+Giving VALUE as an arrayref will cause all those values to be added.
+This is only useful for special multiple-valued fields like "Received":
+
+ $msg->add("Received" => ["here", "there", "everywhere"]
+
+Giving VALUE as the empty string adds an invisible placeholder
+to the header, which can be used to suppress the output of
+the "Content-*" fields or the special "MIME-Version" field.
+When suppressing fields, you should use replace() instead of add():
+
+ $msg->replace("Content-disposition" => "");
+
+I<Note:> add() is probably going to be more efficient than C<replace()>,
+so you're better off using it for most applications if you are
+certain that you don't need to delete() the field first.
+
+I<Note:> the name comes from Mail::Header.
+
+=cut
+
+sub add {
+ my $self = shift;
+ my $tag = lc(shift);
+ my $value = shift;
+
+ ### If a dangerous option, warn them:
+ carp "Explicitly setting a MIME header field ($tag) is dangerous:\n".
+ "use the attr() method instead.\n"
+ if (is_mime_field($tag) && !$QUIET);
+
+ ### Get array of clean values:
+ my @vals = ((ref($value) and (ref($value) eq 'ARRAY'))
+ ? @{$value}
+ : ($value.''));
+ map { s/\n/\n /g } @vals;
+
+ ### Add them:
+ foreach (@vals) {
+ push @{$self->{Header}}, [$tag, $_];
+ }
+}
+
+#------------------------------
+
+=item attr ATTR,[VALUE]
+
+I<Instance method.>
+Set MIME attribute ATTR to the string VALUE.
+ATTR is converted to all-lowercase.
+This method is normally used to set/get MIME attributes:
+
+ $msg->attr("content-type" => "text/html");
+ $msg->attr("content-type.charset" => "US-ASCII");
+ $msg->attr("content-type.name" => "homepage.html");
+
+This would cause the final output to look something like this:
+
+ Content-type: text/html; charset=US-ASCII; name="homepage.html"
+
+Note that the special empty sub-field tag indicates the anonymous
+first sub-field.
+
+Giving VALUE as undefined will cause the contents of the named
+subfield to be deleted.
+
+Supplying no VALUE argument just returns the attribute's value:
+
+ $type = $msg->attr("content-type"); ### returns "text/html"
+ $name = $msg->attr("content-type.name"); ### returns "homepage.html"
+
+=cut
+
+sub attr {
+ my ($self, $attr, $value) = @_;
+ $attr = lc($attr);
+
+ ### Break attribute name up:
+ my ($tag, $subtag) = split /\./, $attr;
+ defined($subtag) or $subtag = '';
+
+ ### Set or get?
+ if (@_ > 2) { ### set:
+ $self->{Attrs}{$tag} ||= {}; ### force hash
+ delete $self->{Attrs}{$tag}{$subtag}; ### delete first
+ if (defined($value)) { ### set...
+ $value =~ s/[\r\n]//g; ### make clean
+ $self->{Attrs}{$tag}{$subtag} = $value;
+ }
+ }
+
+ ### Return current value:
+ $self->{Attrs}{$tag}{$subtag};
+}
+
+sub _safe_attr {
+ my ($self, $attr) = @_;
+ my $v = $self->attr($attr);
+ defined($v) ? $v : '';
+}
+
+#------------------------------
+
+=item delete TAG
+
+I<Instance method.>
+Delete field TAG with the given VALUE to the end of the header.
+The TAG will be converted to all-lowercase.
+
+ $msg->delete("Subject");
+
+I<Note:> the name comes from Mail::Header.
+
+=cut
+
+sub delete {
+ my $self = shift;
+ my $tag = lc(shift);
+
+ ### Delete from the header:
+ my $hdr = [];
+ my $field;
+ foreach $field (@{$self->{Header}}) {
+ push @$hdr, $field if ($field->[0] ne $tag);
+ }
+ $self->{Header} = $hdr;
+ $self;
+}
+
+
+#------------------------------
+
+=item field_order FIELD,...FIELD
+
+I<Class/instance method.>
+Change the order in which header fields are output for this object:
+
+ $msg->field_order('from', 'to', 'content-type', 'subject');
+
+When used as a class method, changes the default settings for
+all objects:
+
+ MIME::Lite->field_order('from', 'to', 'content-type', 'subject');
+
+Case does not matter: all field names will be coerced to lowercase.
+In either case, supply the empty array to restore the default ordering.
+
+=cut
+
+sub field_order {
+ my $self = shift;
+ if (ref($self)) { $self->{FieldOrder} = [ map { lc($_) } @_ ] }
+ else { @FieldOrder = map { lc($_) } @_ }
+}
+
+#------------------------------
+
+=item fields
+
+I<Instance method.>
+Return the full header for the object, as a ref to an array
+of C<[TAG, VALUE]> pairs, where each TAG is all-lowercase.
+Note that any fields the user has explicitly set will override the
+corresponding MIME fields that we would otherwise generate.
+So, don't say...
+
+ $msg->set("Content-type" => "text/html; charset=US-ASCII");
+
+unless you want the above value to override the "Content-type"
+MIME field that we would normally generate.
+
+I<Note:> I called this "fields" because the header() method of
+Mail::Header returns something different, but similar enough to
+be confusing.
+
+You can change the order of the fields: see L</header_order>.
+You really shouldn't need to do this, but some people have to
+deal with broken mailers.
+
+=cut
+
+sub fields {
+ my $self = shift;
+ my @fields;
+
+ ### Get a lookup-hash of all *explicitly-given* fields:
+ my %explicit = map { $_->[0] => 1 } @{$self->{Header}};
+
+ ### Start with any MIME attributes not given explicitly:
+ my $tag;
+ foreach $tag (sort keys %{$self->{Attrs}}) {
+
+ ### Skip if explicit:
+ next if ($explicit{$tag});
+
+ ### Skip if no subtags:
+ my @subtags = keys %{$self->{Attrs}{$tag}};
+ @subtags or next;
+
+ ### Create string:
+ my $value;
+ defined($value = $self->{Attrs}{$tag}{''}) or next; ### need default
+ foreach (sort @subtags) {
+ next if ($_ eq '');
+ $value .= qq{; $_="$self->{Attrs}{$tag}{$_}"};
+ }
+
+ ### Add to running fields;
+ push @fields, [$tag, $value];
+ }
+
+ ### Add remaining fields (note that we duplicate the array for safety):
+ foreach (@{$self->{Header}}) {
+ push @fields, [@{$_}];
+ }
+
+ ### Final step:
+ ### If a suggested ordering was given, we "sort" by that ordering.
+ ### The idea is that we give each field a numeric rank, which is
+ ### (1000 * order(field)) + origposition.
+ my @order = @{$self->{FieldOrder} || []}; ### object-specific
+ @order or @order = @FieldOrder; ### no? maybe generic
+ if (@order) { ### either?
+
+ ### Create hash mapping field names to 1-based rank:
+ my %rank = map {$order[$_] => (1+$_)} (0..$#order);
+
+ ### Create parallel array to @fields, called @ranked.
+ ### It contains fields tagged with numbers like 2003, where the
+ ### 3 is the original 0-based position, and 2000 indicates that
+ ### we wanted ths type of field to go second.
+ my @ranked = map {
+ [
+ ($_ + 1000*($rank{lc($fields[$_][0])} || (2+$#order))),
+ $fields[$_]
+ ]
+ } (0..$#fields);
+ # foreach (@ranked) {
+ # print STDERR "RANKED: $_->[0] $_->[1][0] $_->[1][1]\n";
+ # }
+
+ ### That was half the Schwartzian transform. Here's the rest:
+ @fields = map { $_->[1] }
+ sort { $a->[0] <=> $b->[0] }
+ @ranked;
+ }
+
+ ### Done!
+ return \@fields;
+}
+
+
+#------------------------------
+
+=item filename [FILENAME]
+
+I<Instance method.>
+Set the filename which this data will be reported as.
+This actually sets both "standard" attributes.
+
+With no argument, returns the filename as dictated by the
+content-disposition.
+
+=cut
+
+sub filename {
+ my ($self, $filename) = @_;
+ if (@_ > 1) {
+ $self->attr('content-type.name' => $filename);
+ $self->attr('content-disposition.filename' => $filename);
+ }
+ $self->attr('content-disposition.filename');
+}
+
+#------------------------------
+
+=item get TAG,[INDEX]
+
+I<Instance method.>
+Get the contents of field TAG, which might have been set
+with set() or replace(). Returns the text of the field.
+
+ $ml->get('Subject', 0);
+
+If the optional 0-based INDEX is given, then we return the INDEX'th
+occurence of field TAG. Otherwise, we look at the context:
+In a scalar context, only the first (0th) occurence of the
+field is returned; in an array context, I<all> occurences are returned.
+
+I<Warning:> this should only be used with non-MIME fields.
+Behavior with MIME fields is TBD, and will raise an exception for now.
+
+=cut
+
+sub get {
+ my ($self, $tag, $index) = @_;
+ $tag = lc($tag);
+ croak "get: can't be used with MIME fields\n" if is_mime_field($tag);
+
+ my @all = map { ($_->[0] eq $tag) ? $_->[1] : ()} @{$self->{Header}};
+ (defined($index) ? $all[$index] : (wantarray ? @all : $all[0]));
+}
+
+#------------------------------
+
+=item get_length
+
+I<Instance method.>
+Recompute the content length for the message I<if the process is trivial>,
+setting the "content-length" attribute as a side-effect:
+
+ $msg->get_length;
+
+Returns the length, or undefined if not set.
+
+I<Note:> the content length can be difficult to compute, since it
+involves assembling the entire encoded body and taking the length
+of it (which, in the case of multipart messages, means freezing
+all the sub-parts, etc.).
+
+This method only sets the content length to a defined value if the
+message is a singlepart with C<"binary"> encoding, I<and> the body is
+available either in-core or as a simple file. Otherwise, the content
+length is set to the undefined value.
+
+Since content-length is not a standard MIME field anyway (that's right, kids:
+it's not in the MIME RFCs, it's an HTTP thing), this seems pretty fair.
+
+=cut
+
+#----
+# Miko's note: I wasn't quite sure how to handle this, so I waited to hear
+# what you think. Given that the content-length isn't always required,
+# and given the performance cost of calculating it from a file handle,
+# I thought it might make more sense to add some some sort of computelength
+# property. If computelength is false, then the length simply isn't
+# computed. What do you think?
+#
+# Eryq's reply: I agree; for now, we can silently leave out the content-type.
+
+sub get_length {
+ my $self = shift;
+
+ my $is_multipart = ($self->attr('content-type') =~ m{^multipart/}i);
+ my $enc = lc($self->attr('content-transfer-encoding') || 'binary');
+ my $length;
+ if (!$is_multipart && ($enc eq "binary")){ ### might figure it out cheap:
+ if (defined($self->{Data})) { ### it's in core
+ $length = length($self->{Data});
+ }
+ elsif (defined($self->{FH})) { ### it's in a filehandle
+ ### no-op: it's expensive, so don't bother
+ }
+ elsif (defined($self->{Path})) { ### it's a simple file!
+ $length = (-s $self->{Path}) if (-e $self->{Path});
+ }
+ }
+ $self->attr('content-length' => $length);
+ return $length;
+}
+
+#------------------------------
+
+=item replace TAG,VALUE
+
+I<Instance method.>
+Delete all occurences of fields named TAG, and add a new
+field with the given VALUE. TAG is converted to all-lowercase.
+
+B<Beware> the special MIME fields (MIME-version, Content-*):
+if you "replace" a MIME field, the replacement text will override
+the I<actual> MIME attributes when it comes time to output that field.
+So normally you use attr() to change MIME fields and add()/replace() to
+change I<non-MIME> fields:
+
+ $msg->replace("Subject" => "Hi there!");
+
+Giving VALUE as the I<empty string> will effectively I<prevent> that
+field from being output. This is the correct way to suppress
+the special MIME fields:
+
+ $msg->replace("Content-disposition" => "");
+
+Giving VALUE as I<undefined> will just cause all explicit values
+for TAG to be deleted, without having any new values added.
+
+I<Note:> the name of this method comes from Mail::Header.
+
+=cut
+
+sub replace {
+ my ($self, $tag, $value) = @_;
+ $self->delete($tag);
+ $self->add($tag, $value) if defined($value);
+}
+
+
+#------------------------------
+
+=item scrub
+
+I<Instance method.>
+B<This is Alpha code. If you use it, please let me know how it goes.>
+Recursively goes through the "parts" tree of this message and tries
+to find MIME attributes that can be removed.
+With an array argument, removes exactly those attributes; e.g.:
+
+ $msg->scrub(['content-disposition', 'content-length']);
+
+Is the same as recursively doing:
+
+ $msg->replace('Content-disposition' => '');
+ $msg->replace('Content-length' => '');
+
+=cut
+
+sub scrub {
+ my ($self, @a) = @_;
+ my ($expl) = @a;
+ local $QUIET = 1;
+
+ ### Scrub me:
+ if (!@a) { ### guess
+
+ ### Scrub length always:
+ $self->replace('content-length', '');
+
+ ### Scrub disposition if no filename, or if content-type has same info:
+ if (!$self->_safe_attr('content-disposition.filename') ||
+ $self->_safe_attr('content-type.name')) {
+ $self->replace('content-disposition', '');
+ }
+
+ ### Scrub encoding if effectively unencoded:
+ if ($self->_safe_attr('content-transfer-encoding') =~
+ /^(7bit|8bit|binary)$/i) {
+ $self->replace('content-transfer-encoding', '');
+ }
+
+ ### Scrub charset if US-ASCII:
+ if ($self->_safe_attr('content-type.charset') =~ /^(us-ascii)/i) {
+ $self->attr('content-type.charset' => undef);
+ }
+
+ ### TBD: this is not really right for message/digest:
+ if ((keys %{$self->{Attrs}{'content-type'}} == 1) and
+ ($self->_safe_attr('content-type') eq 'text/plain')) {
+ $self->replace('content-type', '');
+ }
+ }
+ elsif ($expl and (ref($expl) eq 'ARRAY')) {
+ foreach (@{$expl}) { $self->replace($_, ''); }
+ }
+
+ ### Scrub my kids:
+ foreach (@{$self->{Parts}}) { $_->scrub(@a); }
+}
+
+=back
+
+=cut
+
+
+#==============================
+#==============================
+
+=head2 Setting/getting message data
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item binmode [OVERRIDE]
+
+I<Instance method.>
+With no argument, returns whether or not it thinks that the data
+(as given by the "Path" argument of C<build()>) should be read using
+binmode() (for example, when C<read_now()> is invoked).
+
+The default behavior is that any content type other than
+C<text/*> or C<message/*> is binmode'd; this should in general work fine.
+
+With a defined argument, this method sets an explicit "override"
+value. An undefined argument unsets the override.
+The new current value is returned.
+
+=cut
+
+sub binmode {
+ my $self = shift;
+ $self->{Binmode} = shift if (@_); ### argument? set override
+ return (defined($self->{Binmode})
+ ? $self->{Binmode}
+ : ($self->attr("content-type") !~ m{^(text|message)/}i));
+}
+
+#------------------------------
+
+=item data [DATA]
+
+I<Instance method.>
+Get/set the literal DATA of the message. The DATA may be
+either a scalar, or a reference to an array of scalars (which
+will simply be joined).
+
+I<Warning:> setting the data causes the "content-length" attribute
+to be recomputed (possibly to nothing).
+
+=cut
+
+sub data {
+ my $self = shift;
+ if (@_) {
+ $self->{Data} = ((ref($_[0]) eq 'ARRAY') ? join('', @{$_[0]}) : $_[0]);
+ $self->get_length;
+ }
+ $self->{Data};
+}
+
+
+#------------------------------
+
+=item path [PATH]
+
+Get/set the PATH to the message data.
+
+I<Warning:> setting the path recomputes any existing "content-length" field,
+and re-sets the "filename" (to the last element of the path if it
+looks like a simple path, and to nothing if not).
+
+=cut
+
+sub path {
+ my $self = shift;
+ if (@_) {
+
+ ### Set the path, and invalidate the content length:
+ $self->{Path} = shift;
+
+ ### Re-set filename, extracting it from path if possible:
+ my $filename;
+ if ($self->{Path} and ($self->{Path} !~ /\|$/)) { ### non-shell path:
+ ($filename = $self->{Path}) =~ s/^<//;
+ ($filename) = ($filename =~ m{([^\/]+)\Z});
+ }
+ $self->filename($filename);
+
+ ### Reset the length:
+ $self->get_length;
+ }
+ $self->{Path};
+}
+
+#------------------------------
+
+=item fh [FILEHANDLE]
+
+Get/set the FILEHANDLE which contains the message data.
+
+Takes a filehandle as an input and stores it in the object.
+This routine is similar to path(); one important difference is that
+no attempt is made to set the content length.
+
+=cut
+
+sub fh {
+ my $self = shift;
+ $self->{FH} = shift if @_;
+ $self->{FH};
+}
+
+#------------------------------
+
+=item resetfh [FILEHANDLE]
+
+Set the current position of the filehandle back to the beginning.
+Only applies if you used "FH" in build() or attach() for this message.
+
+Returns false if unable to reset the filehandle (since not all filehandles
+are seekable).
+
+=cut
+
+#----
+# Miko's note: With the Data and Path, the same data could theoretically
+# be reused. However, file handles need to be reset to be reused,
+# so I added this routine.
+#
+# Eryq reply: beware... not all filehandles are seekable (think about STDIN)!
+
+sub resetfh {
+ my $self = shift;
+ seek($self->{FH},0,0);
+}
+
+#------------------------------
+
+=item read_now
+
+Forces data from the path/filehandle (as specified by C<build()>)
+to be read into core immediately, just as though you had given it
+literally with the C<Data> keyword.
+
+Note that the in-core data will always be used if available.
+
+Be aware that everything is slurped into a giant scalar: you may not want
+to use this if sending tar files! The benefit of I<not> reading in the data
+is that very large files can be handled by this module if left on disk
+until the message is output via C<print()> or C<print_body()>.
+
+=cut
+
+sub read_now {
+ my $self = shift;
+ local $/ = undef;
+
+ if ($self->{FH}) { ### data from a filehandle:
+ my $chunk;
+ my @chunks;
+ CORE::binmode($self->{FH}) if $self->binmode;
+ while (read($self->{FH}, $chunk, 1024)) {
+ push @chunks, $chunk;
+ }
+ $self->{Data} = join '', @chunks;
+ }
+ elsif ($self->{Path}) { ### data from a path:
+ open SLURP, $self->{Path} or croak "open $self->{Path}: $!\n";
+ CORE::binmode(SLURP) if $self->binmode;
+ $self->{Data} = <SLURP>; ### sssssssssssssslurp...
+ close SLURP; ### ...aaaaaaaaahhh!
+ }
+}
+
+#------------------------------
+
+=item sign PARAMHASH
+
+Sign the message. This forces the message to be read into core,
+after which the signature is appended to it.
+
+=over 4
+
+=item Data
+
+As in C<build()>: the literal signature data.
+Can be either a scalar or a ref to an array of scalars.
+
+=item Path
+
+As in C<build()>: the path to the file.
+
+=back
+
+If no arguments are given, the default is:
+
+ Path => "$ENV{HOME}/.signature"
+
+The content-length is recomputed.
+
+=cut
+
+sub sign {
+ my $self = shift;
+ my %params = @_;
+
+ ### Default:
+ @_ or $params{Path} = "$ENV{HOME}/.signature";
+
+ ### Force message in-core:
+ defined($self->{Data}) or $self->read_now;
+
+ ### Load signature:
+ my $sig;
+ if (!defined($sig = $params{Data})) { ### not given explicitly:
+ local $/ = undef;
+ open SIG, $params{Path} or croak "open sig $params{Path}: $!\n";
+ $sig = <SIG>; ### sssssssssssssslurp...
+ close SIG; ### ...aaaaaaaaahhh!
+ }
+ $sig = join('',@$sig) if (ref($sig) and (ref($sig) eq 'ARRAY'));
+
+ ### Append, following Internet conventions:
+ $self->{Data} .= "\n-- \n$sig";
+
+ ### Re-compute length:
+ $self->get_length;
+ 1;
+}
+
+#------------------------------
+#
+# =item suggest_encoding CONTENTTYPE
+#
+# I<Class/instance method.>
+# Based on the CONTENTTYPE, return a good suggested encoding.
+# C<text> and C<message> types have their bodies scanned line-by-line
+# for 8-bit characters and long lines; lack of either means that the
+# message is 7bit-ok. Other types are chosen independent of their body:
+#
+# Major type: 7bit ok? Suggested encoding:
+# ------------------------------------------------------------
+# text yes 7bit
+# no quoted-printable
+# unknown binary
+#
+# message yes 7bit
+# no binary
+# unknown binary
+#
+# multipart n/a binary (in case some parts are not ok)
+#
+# (other) n/a base64
+#
+#=cut
+
+sub suggest_encoding {
+ my ($self, $ctype) = @_;
+
+ my ($type) = split '/', lc($ctype);
+ if (($type eq 'text') || ($type eq 'message')) { ### scan message body
+ return 'binary';
+ }
+ else {
+ return ($type eq 'multipart') ? 'binary' : 'base64';
+ }
+}
+
+#------------------------------
+
+=item verify_data
+
+I<Instance method.>
+Verify that all "paths" to attached data exist, recursively.
+It might be a good idea for you to do this before a print(), to
+prevent accidental partial output if a file might be missing.
+Raises exception if any path is not readable.
+
+=cut
+
+sub verify_data {
+ my $self = shift;
+
+ ### Verify self:
+ my $path = $self->{Path};
+ if ($path and ($path !~ /\|$/)) { ### non-shell path:
+ $path =~ s/^<//;
+ (-r $path) or die "$path: not readable\n";
+ }
+
+ ### Verify parts:
+ foreach my $part (@{$self->{Parts}}) { $part->verify_data }
+ 1;
+}
+
+=back
+
+=cut
+
+
+#==============================
+#==============================
+
+=head2 Output
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item print [OUTHANDLE]
+
+I<Instance method.>
+Print the message to the given output handle, or to the currently-selected
+filehandle if none was given.
+
+All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+=cut
+
+sub print {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Output head, separator, and body:
+ $out->print($self->header_as_string, "\n");
+ $self->print_body($out);
+}
+
+#------------------------------
+#
+# print_for_smtp
+#
+# Instance method, private.
+# Print, but filter out the topmost "Bcc" field.
+# This is because qmail apparently doesn't do this for us!
+#
+sub print_for_smtp {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Create a safe head:
+ my @fields = grep { $_->[0] ne 'bcc' } @{$self->fields};
+ my $header = $self->fields_as_string(\@fields);
+
+ ### Output head, separator, and body:
+ $out->print($header, "\n");
+ $self->print_body($out);
+}
+
+#------------------------------
+
+=item print_body [OUTHANDLE]
+
+I<Instance method.>
+Print the body of a message to the given output handle, or to
+the currently-selected filehandle if none was given.
+
+All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+B<Fatal exception> raised if unable to open any of the input files,
+or if a part contains no data, or if an unsupported encoding is
+encountered.
+
+=cut
+
+sub print_body {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Output either the body or the parts.
+ ### Notice that we key off of the content-type! We expect fewer
+ ### accidents that way, since the syntax will always match the MIME type.
+ my $type = $self->attr('content-type');
+ if ($type =~ m{^multipart/}i) {
+ my $boundary = $self->attr('content-type.boundary');
+
+ ### Preamble:
+ $out->print("This is a multi-part message in MIME format.\n");
+
+ ### Parts:
+ my $part;
+ foreach $part (@{$self->{Parts}}) {
+ $out->print("\n--$boundary\n");
+ $part->print($out);
+ }
+
+ ### Epilogue:
+ $out->print("\n--$boundary--\n\n");
+ }
+ elsif ($type =~ m{^message/}) {
+ my @parts = @{$self->{Parts}};
+
+ ### It's a toss-up; try both data and parts:
+ if (@parts == 0) { $self->print_simple_body($out) }
+ elsif (@parts == 1) { $parts[0]->print($out) }
+ else { croak "can't handle message with >1 part\n"; }
+ }
+ else {
+ $self->print_simple_body($out);
+ }
+ 1;
+}
+
+#------------------------------
+#
+# print_simple_body [OUTHANDLE]
+#
+# I<Instance method, private.>
+# Print the body of a simple singlepart message to the given
+# output handle, or to the currently-selected filehandle if none
+# was given.
+#
+# Note that if you want to print "the portion after
+# the header", you don't want this method: you want
+# L<print_body()|/print_body>.
+#
+# All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+# any object that responds to a print() message.
+#
+# B<Fatal exception> raised if unable to open any of the input files,
+# or if a part contains no data, or if an unsupported encoding is
+# encountered.
+#
+sub print_simple_body {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Get content-transfer-encoding:
+ my $encoding = uc($self->attr('content-transfer-encoding'));
+
+ ### Notice that we don't just attempt to slurp the data in from a file:
+ ### by processing files piecemeal, we still enable ourselves to prepare
+ ### very large MIME messages...
+
+ ### Is the data in-core? If so, blit it out...
+ if (defined($self->{Data})) {
+ DATA:
+ { local $_ = $encoding;
+
+ /^BINARY$/ and do {
+ $out->print($self->{Data});
+ last DATA;
+ };
+ /^8BIT$/ and do {
+ $out->print(encode_8bit($self->{Data}));
+ last DATA;
+ };
+ /^7BIT$/ and do {
+ $out->print(encode_7bit($self->{Data}));
+ last DATA;
+ };
+ /^QUOTED-PRINTABLE$/ and do {
+ ### UNTAINT since m//mg on tainted data loops forever:
+ my ($untainted) = ($self->{Data} =~ m/\A(.*)\Z/s);
+
+ ### Encode it line by line:
+ while ($untainted =~ m{^(.*[\r\n]*)}mg) {
+ $out->print(encode_qp($1)); ### have to do it line by line...
+ }
+ last DATA;
+ };
+ /^BASE64/ and do {
+ $out->print(encode_base64($self->{Data}));
+ last DATA;
+ };
+ croak "unsupported encoding: `$_'\n";
+ }
+ }
+
+ ### Else, is the data in a file? If so, output piecemeal...
+ ### Miko's note: this routine pretty much works the same with a path
+ ### or a filehandle. the only difference in behaviour is that it does
+ ### not attempt to open anything if it already has a filehandle
+ elsif (defined($self->{Path}) || defined($self->{FH})) {
+ no strict 'refs'; ### in case FH is not an object
+ my $DATA;
+
+ ### Open file if necessary:
+ if (defined($self->{Path})) {
+ $DATA = new FileHandle || croak "can't get new filehandle\n";
+ $DATA->open("$self->{Path}") or croak "open $self->{Path}: $!\n";
+ }
+ else {
+ $DATA=$self->{FH};
+ }
+ CORE::binmode($DATA) if $self->binmode;
+
+ ### Encode piece by piece:
+ PATH:
+ { local $_ = $encoding;
+
+ /^BINARY$/ and do {
+ $out->print($_) while read($DATA, $_, 2048);
+ last PATH;
+ };
+ /^8BIT$/ and do {
+ $out->print(encode_8bit($_)) while (<$DATA>);
+ last PATH;
+ };
+ /^7BIT$/ and do {
+ $out->print(encode_7bit($_)) while (<$DATA>);
+ last PATH;
+ };
+ /^QUOTED-PRINTABLE$/ and do {
+ $out->print(encode_qp($_)) while (<$DATA>);
+ last PATH;
+ };
+ /^BASE64$/ and do {
+ $out->print(encode_base64($_)) while (read($DATA, $_, 45));
+ last PATH;
+ };
+ croak "unsupported encoding: `$_'\n";
+ }
+
+ ### Close file:
+ close $DATA if defined($self->{Path});
+ }
+
+ else {
+ croak "no data in this part\n";
+ }
+ 1;
+}
+
+#------------------------------
+
+=item print_header [OUTHANDLE]
+
+I<Instance method.>
+Print the header of the message to the given output handle,
+or to the currently-selected filehandle if none was given.
+
+All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+=cut
+
+sub print_header {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Output the header:
+ $out->print($self->header_as_string);
+ 1;
+}
+
+#------------------------------
+
+=item as_string
+
+I<Instance method.>
+Return the entire message as a string, with a header and an encoded body.
+
+=cut
+
+sub as_string {
+ my $self = shift;
+ my @buf;
+ my $io = (wrap MIME::Lite::IO_ScalarArray \@buf);
+ $self->print($io);
+ join '', @buf;
+}
+*stringify = \&as_string; ### backwards compatibility
+
+#------------------------------
+
+=item body_as_string
+
+I<Instance method.>
+Return the encoded body as a string.
+This is the portion after the header and the blank line.
+
+I<Note:> actually prepares the body by "printing" to a scalar.
+Proof that you can hand the C<print*()> methods any blessed object
+that responds to a C<print()> message.
+
+=cut
+
+sub body_as_string {
+ my $self = shift;
+ my @buf;
+ my $io = (wrap MIME::Lite::IO_ScalarArray \@buf);
+ $self->print_body($io);
+ join '', @buf;
+}
+*stringify_body = \&body_as_string; ### backwards compatibility
+
+#------------------------------
+#
+# fields_as_string FIELDS
+#
+# PRIVATE! Return a stringified version of the given header
+# fields, where FIELDS is an arrayref like that returned by fields().
+#
+sub fields_as_string {
+ my ($self, $fields) = @_;
+ my @lines;
+ foreach (@$fields) {
+ my ($tag, $value) = @$_;
+ next if ($value eq ''); ### skip empties
+ $tag =~ s/\b([a-z])/uc($1)/ge; ### make pretty
+ $tag =~ s/^mime-/MIME-/ig; ### even prettier
+ push @lines, "$tag: $value\n";
+ }
+ join '', @lines;
+}
+
+#------------------------------
+
+=item header_as_string
+
+I<Instance method.>
+Return the header as a string.
+
+=cut
+
+sub header_as_string {
+ my $self = shift;
+ $self->fields_as_string($self->fields);
+}
+*stringify_header = \&header_as_string; ### backwards compatibility
+
+=back
+
+=cut
+
+
+
+#==============================
+#==============================
+
+=head2 Sending
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item send
+
+=item send HOW, HOWARGS...
+
+I<Class/instance method.>
+This is the principal method for sending mail, and for configuring
+how mail will be sent.
+
+I<As an instance method> (with no arguments), sends the message by whatever
+means has been set up (the default is to use the Unix "sendmail" program).
+Returns whatever the mail-handling routine returns: this should be true
+on success, false/exception on error:
+
+ $msg = MIME::Lite->new(From=>...);
+ $msg->send || die "you DON'T have mail!";
+
+I<As a class method> (with a HOW argument and optional HOWARGS), sets up
+how the instance method will work for all objects until further notice
+It treats HOW as a facility name, with optional HOWARGS handled by
+the facility (and returns the previous HOW and HOWARGS as an array).
+There are three facilities:
+
+=over 4
+
+=item "sendmail", ARGS...
+
+Send a message by piping it into the "sendmail" command.
+Uses the L<send_by_sendmail()|/send_by_sendmail> method, giving it the ARGS.
+This usage implements (and deprecates) the C<sendmail()> method.
+
+=item "smtp", [HOSTNAME]
+
+Send a message by SMTP, using optional HOSTNAME as SMTP-sending host.
+Uses the L<send_by_smtp()|/send_by_smtp> method.
+
+=item "sub", \&SUBREF, ARGS...
+
+Sends a message MSG by invoking the subroutine SUBREF of your choosing,
+with MSG as the first argument, and ARGS following.
+
+=back
+
+I<For example:> let's say you're on an OS which lacks the usual Unix
+"sendmail" facility, but you've installed something a lot like it, and
+you need to configure your Perl script to use this "sendmail.exe" program.
+Do this following in your script's setup:
+
+ MIME::Lite->send('sendmail', "d:\\programs\\sendmail.exe");
+
+Then, whenever you need to send a message $msg, just say:
+
+ $msg->send;
+
+That's it. Now, if you ever move your script to a Unix box, all you
+need to do is change that line in the setup and you're done.
+All of your $msg-E<gt>send invocations will work as expected.
+
+=cut
+
+sub send {
+ my $self = shift;
+
+ if (ref($self)) { ### instance method:
+ my $method = "send_by_$Sender";
+ my @args = @{$SenderArgs{$Sender} || []};
+ $self->verify_data if $AUTO_VERIFY; ### prevents missing parts!
+ return $self->$method(@args);
+ }
+ else { ### class method:
+ my @old = ($Sender, @{$SenderArgs{$Sender}});
+ $Sender = shift;
+ $SenderArgs{$Sender} = [@_]; ### remaining args
+ return @old;
+ }
+}
+
+#------------------------------
+
+=item send_by_sendmail SENDMAILCMD
+
+=item send_by_sendmail PARAM=>VALUE, ...
+
+I<Instance method.>
+Send message via an external "sendmail" program
+(this will probably only work out-of-the-box on Unix systems).
+
+Returns true on success, false or exception on error.
+
+You can specify the program and all its arguments by giving a single
+string, SENDMAILCMD. Nothing fancy is done; the message is simply
+piped in.
+
+However, if your needs are a little more advanced, you can specify
+zero or more of the following PARAM/VALUE pairs; a Unix-style,
+taint-safe "sendmail" command will be constructed for you:
+
+=over 4
+
+=item Sendmail
+
+Full path to the program to use.
+Default is "/usr/lib/sendmail".
+
+=item BaseArgs
+
+Ref to the basic array of arguments we start with.
+Default is C<["-t", "-oi", "-oem"]>.
+
+=item SetSender
+
+Unless this is I<explicitly> given as false, we attempt to automatically
+set the C<-f> argument to the first address that can be extracted from
+the "From:" field of the message (if there is one).
+
+I<What is the -f, and why do we use it?>
+Suppose we did I<not> use C<-f>, and you gave an explicit "From:"
+field in your message: in this case, the sendmail "envelope" would
+indicate the I<real> user your process was running under, as a way
+of preventing mail forgery. Using the C<-f> switch causes the sender
+to be set in the envelope as well.
+
+I<So when would I NOT want to use it?>
+If sendmail doesn't regard you as a "trusted" user, it will permit
+the C<-f> but also add an "X-Authentication-Warning" header to the message
+to indicate a forged envelope. To avoid this, you can either
+(1) have SetSender be false, or
+(2) make yourself a trusted user by adding a C<T> configuration
+ command to your I<sendmail.cf> file
+ (e.g.: C<Teryq> if the script is running as user "eryq").
+
+=item FromSender
+
+If defined, this is identical to setting SetSender to true,
+except that instead of looking at the "From:" field we use
+the address given by this option.
+Thus:
+
+ FromSender => 'me@myhost.com'
+
+=back
+
+=cut
+
+sub send_by_sendmail {
+ my $self = shift;
+
+ if (@_ == 1) { ### Use the given command...
+ my $sendmailcmd = shift @_;
+
+ ### Do it:
+ open SENDMAIL, "|$sendmailcmd" or croak "open |$sendmailcmd: $!\n";
+ $self->print(\*SENDMAIL);
+ close SENDMAIL;
+ return (($? >> 8) ? undef : 1);
+ }
+ else { ### Build the command...
+ my %p = @_;
+ $p{Sendmail} ||= "/usr/lib/sendmail";
+
+ ### Start with the command and basic args:
+ my @cmd = ($p{Sendmail}, @{$p{BaseArgs} || ['-t', '-oi', '-oem']});
+
+ ### See if we are forcibly setting the sender:
+ $p{SetSender} = 1 if defined($p{FromSender});
+
+ ### Add the -f argument, unless we're explicitly told NOT to:
+ unless (exists($p{SetSender}) and !$p{SetSender}) {
+ my $from = $p{FromSender} || ($self->get('From'))[0];
+ if ($from) {
+ my ($from_addr) = extract_addrs($from);
+ push @cmd, "-f$from_addr" if $from_addr;
+ }
+ }
+
+ ### Open the command in a taint-safe fashion:
+ my $pid = open SENDMAIL, "|-";
+ defined($pid) or die "open of pipe failed: $!\n";
+ if (!$pid) { ### child
+ exec(@cmd) or die "can't exec $p{Sendmail}: $!\n";
+ ### NOTREACHED
+ }
+ else { ### parent
+ $self->print(\*SENDMAIL);
+ close SENDMAIL || die "error closing $p{Sendmail}: $! (exit $?)\n";
+ return 1;
+ }
+ }
+}
+
+#------------------------------
+
+=item send_by_smtp ARGS...
+
+I<Instance method.>
+Send message via SMTP, using Net::SMTP.
+The optional ARGS are sent into Net::SMTP::new(): usually, these are
+
+ MAILHOST, OPTION=>VALUE, ...
+
+Note that the list of recipients is taken from the
+"To", "Cc" and "Bcc" fields.
+
+Returns true on success, false or exception on error.
+
+=cut
+
+### Provided by Andrew McRae. Version 0.2 anm 09Sep97
+### Copyright 1997 Optimation New Zealand Ltd.
+### May be modified/redistributed under the same terms as Perl.
+#
+sub send_by_smtp {
+ my ($self, @args) = @_;
+
+ ### We need the "From:" and "To:" headers to pass to the SMTP mailer:
+ my $hdr = $self->fields();
+ my $from = $self->get('From');
+ my $to = $self->get('To');
+
+ ### Sanity check:
+ defined($to) or croak "send_by_smtp: missing 'To:' address\n";
+
+ ### Get the destinations as a simple array of addresses:
+ my @to_all = extract_addrs($to);
+ if ($AUTO_CC) {
+ foreach my $field (qw(Cc Bcc)) {
+ my $value = $self->get($field);
+ push @to_all, extract_addrs($value) if defined($value);
+ }
+ }
+
+ ### Create SMTP client:
+ require Net::SMTP;
+ my $smtp = MIME::Lite::SMTP->new(@args)
+ or croak "Failed to connect to mail server: $!\n";
+ $smtp->mail($from)
+ or croak "SMTP MAIL command failed: $!\n";
+ $smtp->to(@to_all)
+ or croak "SMTP RCPT command failed: $!\n";
+ $smtp->data()
+ or croak "SMTP DATA command failed: $!\n";
+
+ ### MIME::Lite can print() to anything with a print() method:
+ $self->print_for_smtp($smtp);
+ $smtp->dataend();
+ $smtp->quit;
+ 1;
+}
+
+#------------------------------
+#
+# send_by_sub [\&SUBREF, [ARGS...]]
+#
+# I<Instance method, private.>
+# Send the message via an anonymous subroutine.
+#
+sub send_by_sub {
+ my ($self, $subref, @args) = @_;
+ &$subref($self, @args);
+}
+
+#------------------------------
+
+=item sendmail COMMAND...
+
+I<Class method, DEPRECATED.>
+Declare the sender to be "sendmail", and set up the "sendmail" command.
+I<You should use send() instead.>
+
+=cut
+
+sub sendmail {
+ my $self = shift;
+ $self->send('sendmail', join(' ', @_));
+}
+
+=back
+
+=cut
+
+
+
+#==============================
+#==============================
+
+=head2 Miscellaneous
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item quiet ONOFF
+
+I<Class method.>
+Suppress/unsuppress all warnings coming from this module.
+
+ MIME::Lite->quiet(1); ### I know what I'm doing
+
+I recommend that you include that comment as well. And while
+you type it, say it out loud: if it doesn't feel right, then maybe
+you should reconsider the whole line. C<;-)>
+
+=cut
+
+sub quiet {
+ my $class = shift;
+ $QUIET = shift if @_;
+ $QUIET;
+}
+
+=back
+
+=cut
+
+
+
+#============================================================
+
+package MIME::Lite::SMTP;
+
+#============================================================
+# This class just adds a print() method to Net::SMTP.
+# Notice that we don't use/require it until it's needed!
+
+use strict;
+use vars qw( @ISA );
+@ISA = qw(Net::SMTP);
+
+sub print { shift->datasend(@_) }
+
+
+
+#============================================================
+
+package MIME::Lite::IO_Handle;
+
+#============================================================
+
+### Wrap a non-object filehandle inside a blessed, printable interface:
+### Does nothing if the given $fh is already a blessed object.
+sub wrap {
+ my ($class, $fh) = @_;
+ no strict 'refs';
+
+ ### Get default, if necessary:
+ $fh or $fh = select; ### no filehandle means selected one
+ ref($fh) or $fh = \*$fh; ### scalar becomes a globref
+
+ ### Stop right away if already a printable object:
+ return $fh if (ref($fh) and (ref($fh) ne 'GLOB'));
+
+ ### Get and return a printable interface:
+ bless \$fh, $class; ### wrap it in a printable interface
+}
+
+### Print:
+sub print {
+ my $self = shift;
+ print {$$self} @_;
+}
+
+
+#============================================================
+
+package MIME::Lite::IO_Scalar;
+
+#============================================================
+
+### Wrap a scalar inside a blessed, printable interface:
+sub wrap {
+ my ($class, $scalarref) = @_;
+ defined($scalarref) or $scalarref = \"";
+ bless $scalarref, $class;
+}
+
+### Print:
+sub print {
+ my $self = shift;
+ $$self .= join('', @_);
+ 1;
+}
+
+
+#============================================================
+
+package MIME::Lite::IO_ScalarArray;
+
+#============================================================
+
+### Wrap an array inside a blessed, printable interface:
+sub wrap {
+ my ($class, $arrayref) = @_;
+ defined($arrayref) or $arrayref = [];
+ bless $arrayref, $class;
+}
+
+### Print:
+sub print {
+ my $self = shift;
+ push @$self, @_;
+ 1;
+}
+
+1;
+__END__
+
+
+#============================================================
+
+=head1 NOTES
+
+
+=head2 Benign limitations
+
+This is "lite", after all...
+
+=over 4
+
+=item *
+
+There's no parsing. Get MIME-tools if you need to parse MIME messages.
+
+=item *
+
+MIME::Lite messages are currently I<not> interchangeable with
+either Mail::Internet or MIME::Entity objects. This is a completely
+separate module.
+
+=item *
+
+A content-length field is only inserted if the encoding is binary,
+the message is a singlepart, and all the document data is available
+at C<build()> time by virtue of residing in a simple path, or in-core.
+Since content-length is not a standard MIME field anyway (that's right, kids:
+it's not in the MIME RFCs, it's an HTTP thing), this seems pretty fair.
+
+=item *
+
+MIME::Lite alone cannot help you lose weight. You must supplement
+your use of MIME::Lite with a healthy diet and exercise.
+
+=back
+
+
+=head2 Cheap and easy mailing
+
+I thought putting in a default "sendmail" invocation wasn't too bad an
+idea, since a lot of Perlers are on UNIX systems.
+The out-of-the-box configuration is:
+
+ MIME::Lite->send('sendmail', "/usr/lib/sendmail -t -oi -oem");
+
+By the way, these arguments to sendmail are:
+
+ -t Scan message for To:, Cc:, Bcc:, etc.
+
+ -oi Do NOT treat a single "." on a line as a message terminator.
+ As in, "-oi vey, it truncated my message... why?!"
+
+ -oem On error, mail back the message (I assume to the
+ appropriate address, given in the header).
+ When mail returns, circle is complete. Jai Guru Deva -oem.
+
+Note that these are the same arguments you get if you configure to use
+the smarter, taint-safe mailing:
+
+ MIME::Lite->send('sendmail');
+
+If you get "X-Authentication-Warning" headers from this, you can forgo
+diddling with the envelope by instead specifying:
+
+ MIME::Lite->send('sendmail', SetSender=>0);
+
+And, if you're not on a Unix system, or if you'd just rather send mail
+some other way, there's always:
+
+ MIME::Lite->send('smtp', "smtp.myisp.net");
+
+Or you can set up your own subroutine to call.
+In any case, check out the L<send()|/send> method.
+
+
+
+=head1 WARNINGS
+
+=head2 Good-vs-bad email addresses with send_by_smtp()
+
+If using L<send_by_smtp()|/send_by_smtp>, be aware that you are
+forcing MIME::Lite to extract email addresses out of a possible list
+provided in the C<To:>, C<Cc:>, and C<Bcc:> fields. This is tricky
+stuff, and as such only the following sorts of addresses will work
+reliably:
+
+ username
+ full.name@some.host.com
+ "Name, Full" <full.name@some.host.com>
+
+This last form is discouraged because SMTP must be able to get
+at the I<name> or I<name@domain> portion.
+
+B<Disclaimer:>
+MIME::Lite was never intended to be a Mail User Agent, so please
+don't expect a full implementation of RFC-822. Restrict yourself to
+the common forms of Internet addresses described herein, and you should
+be fine. If this is not feasible, then consider using MIME::Lite
+to I<prepare> your message only, and using Net::SMTP explicitly to
+I<send> your message.
+
+
+=head2 Formatting of headers delayed until print()
+
+This class treats a MIME header in the most abstract sense,
+as being a collection of high-level attributes. The actual
+RFC-822-style header fields are not constructed until it's time
+to actually print the darn thing.
+
+
+=head2 Encoding of data delayed until print()
+
+When you specify message bodies
+(in L<build()|/build> or L<attach()|/attach>) --
+whether by B<FH>, B<Data>, or B<Path> -- be warned that we don't
+attempt to open files, read filehandles, or encode the data until
+L<print()|/print> is invoked.
+
+In the past, this created some confusion for users of sendmail
+who gave the wrong path to an attachment body, since enough of
+the print() would succeed to get the initial part of the message out.
+Nowadays, $AUTO_VERIFY is used to spot-check the Paths given before
+the mail facility is employed. A whisker slower, but tons safer.
+
+Note that if you give a message body via FH, and try to print()
+a message twice, the second print() will not do the right thing
+unless you explicitly rewind the filehandle.
+
+You can get past these difficulties by using the B<ReadNow> option,
+provided that you have enough memory to handle your messages.
+
+
+=head2 MIME attributes are separate from header fields!
+
+B<Important:> the MIME attributes are stored and manipulated separately
+from the message header fields; when it comes time to print the
+header out, I<any explicitly-given header fields override the ones that
+would be created from the MIME attributes.> That means that this:
+
+ ### DANGER ### DANGER ### DANGER ### DANGER ### DANGER ###
+ $msg->add("Content-type", "text/html; charset=US-ASCII");
+
+will set the exact C<"Content-type"> field in the header I write,
+I<regardless of what the actual MIME attributes are.>
+
+I<This feature is for experienced users only,> as an escape hatch in case
+the code that normally formats MIME header fields isn't doing what
+you need. And, like any escape hatch, it's got an alarm on it:
+MIME::Lite will warn you if you attempt to C<set()> or C<replace()>
+any MIME header field. Use C<attr()> instead.
+
+
+=head2 Beware of lines consisting of a single dot
+
+Julian Haight noted that MIME::Lite allows you to compose messages
+with lines in the body consisting of a single ".".
+This is true: it should be completely harmless so long as "sendmail"
+is used with the -oi option (see L<"Cheap and easy mailing">).
+
+However, I don't know if using Net::SMTP to transfer such a message
+is equally safe. Feedback is welcomed.
+
+My perspective: I don't want to magically diddle with a user's
+message unless absolutely positively necessary.
+Some users may want to send files with "." alone on a line;
+my well-meaning tinkering could seriously harm them.
+
+
+=head2 Infinite loops may mean tainted data!
+
+Stefan Sautter noticed a bug in 2.106 where a m//gc match was
+failing due to tainted data, leading to an infinite loop inside
+MIME::Lite.
+
+I am attempting to correct for this, but be advised that my fix will
+silently untaint the data (given the context in which the problem
+occurs, this should be benign: I've labelled the source code with
+UNTAINT comments for the curious).
+
+So: don't depend on taint-checking to save you from outputting
+tainted data in a message.
+
+
+=head1 A MIME PRIMER
+
+=head2 Content types
+
+The "Type" parameter of C<build()> is a I<content type>.
+This is the actual type of data you are sending.
+Generally this is a string of the form C<"majortype/minortype">.
+
+Here are the major MIME types.
+A more-comprehensive listing may be found in RFC-2046.
+
+=over 4
+
+=item application
+
+Data which does not fit in any of the other categories, particularly
+data to be processed by some type of application program.
+C<application/octet-stream>, C<application/gzip>, C<application/postscript>...
+
+=item audio
+
+Audio data.
+C<audio/basic>...
+
+=item image
+
+Graphics data.
+C<image/gif>, C<image/jpeg>...
+
+=item message
+
+A message, usually another mail or MIME message.
+C<message/rfc822>...
+
+=item multipart
+
+A message containing other messages.
+C<multipart/mixed>, C<multipart/alternative>...
+
+=item text
+
+Textual data, meant for humans to read.
+C<text/plain>, C<text/html>...
+
+=item video
+
+Video or video+audio data.
+C<video/mpeg>...
+
+=back
+
+
+=head2 Content transfer encodings
+
+The "Encoding" parameter of C<build()>.
+This is how the message body is packaged up for safe transit.
+
+Here are the 5 major MIME encodings.
+A more-comprehensive listing may be found in RFC-2045.
+
+=over 4
+
+=item 7bit
+
+Basically, no I<real> encoding is done. However, this label guarantees that no
+8-bit characters are present, and that lines do not exceed 1000 characters
+in length.
+
+=item 8bit
+
+Basically, no I<real> encoding is done. The message might contain 8-bit
+characters, but this encoding guarantees that lines do not exceed 1000
+characters in length.
+
+=item binary
+
+No encoding is done at all. Message might contain 8-bit characters,
+and lines might be longer than 1000 characters long.
+
+The most liberal, and the least likely to get through mail gateways.
+Use sparingly, or (better yet) not at all.
+
+=item base64
+
+Like "uuencode", but very well-defined. This is how you should send
+essentially binary information (tar files, GIFs, JPEGs, etc.).
+
+=item quoted-printable
+
+Useful for encoding messages which are textual in nature, yet which contain
+non-ASCII characters (e.g., Latin-1, Latin-2, or any other 8-bit alphabet).
+
+=back
+
+
+
+=head1 VERSION
+
+$Id: Lite.pm,v 2.108 2001/03/30 06:16:54 eryq Exp $
+
+
+=head1 CHANGE LOG
+
+=over 4
+
+
+=item Version 2.108
+
+New C<field_order()> allows you to set the header order, both on a
+per-message basis, and package-wide.
+I<Thanks to Thomas Stromberg for suggesting this.>
+
+Added code to try and divine "sendmail" path more intelligently.
+I<Thanks to Slaven Rezic for the suggestion.>
+
+
+=item Version 2.107 (2001/03/27)
+
+Fixed serious bug where tainted data with quoted-printable encoding
+was causing infinite loops. The "fix" untaints the data in question,
+which is not optimal, but it's probably benign in this case.
+I<Thanks to Stefan Sautter for tracking this nasty little beast down.>
+I<Thanks to Larry Geralds for a related patch.>
+
+ "Doctor, O doctor:
+ it's painful when I do *this* --"
+ "Simple: don't *do* that."
+
+Fixed bugs where a non-local C<$_> was being modified... again!
+Will I never learn?
+I<Thanks to Maarten Koskamp for reporting this.>
+
+ Dollar-underscore
+ can poison distant waters;
+ 'local' must it be.
+
+Fixed buglet in C<add()> where all value references were being treated
+as arrayrefs, instead of as possibly-self-stringifying object refs.
+Now you can send in an object ref as the 2nd argument.
+I<Thanks to dLux for the bug report.>
+
+ That ref is a string?
+ Operator overload
+ has ruined my day.
+
+Added "Approved" as an acceptable header field for C<new()>, as per RFC1036.
+I<Thanks to Thomax for the suggestion regarding MIME-tools.>
+
+Small improvements to docs to make different uses of attach()
+and various arguments clearer.
+I<Thanks to Sven Rassman and Roland Walter for the suggestions.>
+
+
+=item Version 2.106 (2000/11/21)
+
+Added Alpha version of scrub() to make it easy for people to suppress
+the printing of unwanted MIME attributes (like Content-length).
+I<Thanks to the many people who asked for this.>
+
+Headers with empty-strings for their values are no longer
+printed. This seems sensible, and helps us implement scrub().
+
+
+=item Version 2.105 (2000/10/14)
+
+The regression-test failure was identified, and it was my fault.
+Apparently some of the \-quoting in my "autoloaded" code was
+making Perl 5.6 unhappy. For this nesting-related idiocy,
+a nesting kaiku.
+I<Thanks to Scott Schwartz for identifying the problem.>
+
+ In a pattern, my
+ backslash-s dwells peacefully,
+ unambiguous --
+
+ but I embed it
+ in a double-quoted string
+ doubling the backslash --
+
+ interpolating
+ that same double-quoted string
+ in other patterns --
+
+ and, worlds within worlds,
+ I single-quote the function
+ to autoload it --
+
+ changing the meaning
+ of the backslash and the 's';
+ and Five-Point-Six growls.
+
+
+=item Version 2.104 (2000/09/28)
+
+Now attempts to load and use Mail::Address for parsing email
+addresses I<before> falling back to our own method.
+I<Thanks to numerous people for suggesting this.>
+
+ Parsing addresses
+ is too damn hard. One last hope:
+ Let Graham Barr do it!
+
+For the curious, the version of Mail::Address appears
+as the "A" number in the X-Mailer:
+
+ X-Mailer: MIME::Lite 2.104 (A1.15; B2.09; Q2.03)
+
+Added B<FromSender> option to send_by_sendmail().
+I<Thanks to Bill Moseley for suggesting this feature.>
+
+
+=item Version 2.101 (2000/06/06)
+
+Major revision to print_body() and body_as_string() so that
+"body" really means "the part after the header", which is what most
+people would want in this context. This is B<not> how it was used
+1.x, where "body" only meant "the body of a simple singlepart".
+Hopefully, this change will solve many problems and create very few ones.
+
+Added support for attaching a part to a "message/rfc822", treating
+the "message" type as a multipart-like container.
+
+Now takes care not to include "Bcc:" in header when using send_by_smtp,
+as a safety precaution against qmail's behavior.
+I<Thanks to Tatsuhiko Miyagawa for identifying this problem.>
+
+Improved efficiency of many stringifying operations by using
+string-arrays which are joined, instead of doing multiple appends
+to a scalar.
+
+Cleaned up the "examples" directory.
+
+
+=item Version 1.147 (2000/06/02)
+
+Fixed buglet where lack of Cc:/Bcc: was causing extract_addrs
+to emit "undefined variable" warnings. Also, lack of a "To:" field
+now causes a croak.
+I<Thanks to David Mitchell for the bug report and suggested patch.>
+
+
+=item Version 1.146 (2000/05/18)
+
+Fixed bug in parsing of addresses; please read the WARNINGS section
+which describes recommended address formats for "To:", "Cc:", etc.
+Also added automatic inclusion of a UT "Date:" at top level unless
+explicitly told not to.
+I<Thanks to Andy Jacobs for the bug report and the suggestion.>
+
+=item Version 1.145 (2000/05/06)
+
+Fixed bug in encode_7bit(): a lingering C</e> modifier was removed.
+I<Thanks to Michael A. Chase for the patch.>
+
+
+=item Version 1.142 (2000/05/02)
+
+Added new, taint-safe invocation of "sendmail", one which also
+sets up the C<-f> option. Unfortunately, I couldn't make this automatic:
+the change could have broken a lot of code out there which used
+send_by_sendmail() with unusual "sendmail" variants.
+So you'll have to configure "send" to use the new mechanism:
+
+ MIME::Lite->send('sendmail'); ### no args!
+
+I<Thanks to Jeremy Howard for suggesting these features.>
+
+
+=item Version 1.140 (2000/04/27)
+
+Fixed bug in support for "To", "Cc", and "Bcc" in send_by_smtp():
+multiple (comma-separated) addresses should now work fine.
+We try real hard to extract addresses from the flat text strings.
+I<Thanks to John Mason for motivating this change.>
+
+Added automatic verification that attached data files exist,
+done immediately before the "send" action is invoked.
+To turn this off, set $MIME::Lite::AUTO_VERIFY to false.
+
+=item Version 1.137 (2000/03/22)
+
+Added support for "Cc" and "Bcc" in send_by_smtp().
+To turn this off, set $MIME::Lite::AUTO_CC to false.
+I<Thanks to Lucas Maneos for the patch, and tons of others for
+the suggestion.>
+
+Chooses a better default content-transfer-encoding if the content-type
+is "image/*", "audio/*", etc.
+To turn this off, set $MIME::Lite::AUTO_ENCODE to false.
+I<Thanks to many folks for the suggestion.>
+
+Fixed bug in QP-encoding where a non-local C<$_> was being modified.
+I<Thanks to Jochen Stenzel for finding this very obscure bug!>
+
+Removed references to C<$`>, C<$'>, and C<$&> (bad variables
+which slow things down).
+
+Added an example of how to send HTML files with enclosed in-line
+images, per popular demand.
+
+
+=item Version 1.133 (1999/04/17)
+
+Fixed bug in "Data" handling: arrayrefs were not being handled
+properly.
+
+
+=item Version 1.130 (1998/12/14)
+
+Added much larger and more-flexible send() facility.
+I<Thanks to Andrew McRae (and Optimation New Zealand Ltd)
+for the Net::SMTP interface. Additional thanks to the many folks
+who requested this feature.>
+
+Added get() method for extracting basic attributes.
+
+New... "t" tests!
+
+
+=item Version 1.124 (1998/11/13)
+
+Folded in filehandle (FH) support in build/attach.
+I<Thanks to Miko O'Sullivan for the code.>
+
+
+=item Version 1.122 (1998/01/19)
+
+MIME::Base64 and MIME::QuotedPrint are used if available.
+
+The 7bit encoding no longer does "escapes"; it merely strips 8-bit characters.
+
+
+=item Version 1.121 (1997/04/08)
+
+Filename attribute is now no longer ignored by build().
+I<Thanks to Ian Smith for finding and patching this bug.>
+
+
+=item Version 1.120 (1997/03/29)
+
+Efficiency hack to speed up MIME::Lite::IO_Scalar.
+I<Thanks to David Aspinwall for the patch.>
+
+
+=item Version 1.116 (1997/03/19)
+
+Small bug in our private copy of encode_base64() was patched.
+I<Thanks to Andreas Koenig for pointing this out.>
+
+New, prettier way of specifying mail message headers in C<build()>.
+
+New quiet method to turn off warnings.
+
+Changed "stringify" methods to more-standard "as_string" methods.
+
+
+=item Version 1.112 (1997/03/06)
+
+Added C<read_now()>, and C<binmode()> method for our non-Unix-using brethren:
+file data is now read using binmode() if appropriate.
+I<Thanks to Xiangzhou Wang for pointing out this bug.>
+
+
+=item Version 1.110 (1997/03/06)
+
+Fixed bug in opening the data filehandle.
+
+
+=item Version 1.102 (1997/03/01)
+
+Initial release.
+
+
+=item Version 1.101 (1997/03/01)
+
+Baseline code.
+
+=back
+
+
+=head1 TERMS AND CONDITIONS
+
+Copyright (c) 1997 by Eryq.
+Copyright (c) 1998 by ZeeGee Software Inc.
+All rights reserved. This program is free software; you can redistribute
+it and/or modify it under the same terms as Perl itself.
+
+This software comes with B<NO WARRANTY> of any kind.
+See the COPYING file in the distribution for details.
+
+
+=head1 NUTRITIONAL INFORMATION
+
+For some reason, the US FDA says that this is now required by law
+on any products that bear the name "Lite"...
+
+ MIME::Lite |
+ ------------------------------------------------------------
+ Serving size: | 1 module
+ Servings per container: | 1
+ Calories: | 0
+ Fat: | 0g
+ Saturated Fat: | 0g
+
+Warning: for consumption by hardware only! May produce
+indigestion in humans if taken internally.
+
+
+=head1 AUTHOR
+
+Eryq (F<eryq@zeegee.com>).
+President, ZeeGee Software Inc. (F<http://www.zeegee.com>).
+
+Created: 11 December 1996. Ho ho ho.
+
+=cut
+
diff --git a/cpan/dist/MIME-Lite/t/ExtUtils/TBone.pm b/cpan/dist/MIME-Lite/t/ExtUtils/TBone.pm
new file mode 100644
index 00000000..88dbe29c
--- /dev/null
+++ b/cpan/dist/MIME-Lite/t/ExtUtils/TBone.pm
@@ -0,0 +1,534 @@
+package ExtUtils::TBone;
+
+
+=head1 NAME
+
+ExtUtils::TBone - a "skeleton" for writing "t/*.t" test files.
+
+
+=head1 SYNOPSIS
+
+Include a copy of this module in your t directory (as t/ExtUtils/TBone.pm),
+and then write your t/*.t files like this:
+
+ use lib "./t"; # to pick up a ExtUtils::TBone
+ use ExtUtils::TBone;
+
+ # Make a tester... here are 3 different alternatives:
+ my $T = typical ExtUtils::TBone; # standard log
+ my $T = new ExtUtils::TBone; # no log
+ my $T = new ExtUtils::TBone "testout/Foo.tlog"; # explicit log
+
+ # Begin testing, and expect 3 tests in all:
+ $T->begin(3); # expect 3 tests
+ $T->msg("Something for the log file"); # message for the log
+
+ # Run some tests:
+ $T->ok($this); # test 1: no real info logged
+ $T->ok($that, # test 2: logs a comment
+ "Is that ok, or isn't it?");
+ $T->ok(($this eq $that), # test 3: logs comment + vars
+ "Do they match?",
+ This => $this,
+ That => $that);
+
+ # That last one could have also been written...
+ $T->ok_eq($this, $that); # does 'eq' and logs operands
+ $T->ok_eqnum($this, $that); # does '==' and logs operands
+
+ # End testing:
+ $T->end;
+
+
+=head1 DESCRIPTION
+
+This module is intended for folks who release CPAN modules with
+"t/*.t" tests. It makes it easy for you to output syntactically
+correct test-output while at the same time logging all test
+activity to a log file. Hopefully, bug reports which include
+the contents of this file will be easier for you to investigate.
+
+
+=head1 LOG FILE
+
+A typical log file output by this module looks like this:
+
+ 1..3
+
+ ** A message logged with msg().
+ ** Another one.
+ 1: My first test, using test(): how'd I do?
+ 1: ok 1
+
+ ** Yet another message.
+ 2: My second test, using test_eq()...
+ 2: A: The first string
+ 2: B: The second string
+ 2: not ok 2
+
+ 3: My third test.
+ 3: ok 3
+
+ END
+
+Each test() is logged with the test name and results, and
+the test-number prefixes each line.
+This allows you to scan a large file easily with "grep" (or, ahem, "perl").
+A blank line follows each test's record, for clarity.
+
+
+=head1 PUBLIC INTERFACE
+
+=cut
+
+# Globals:
+use strict;
+use vars qw($VERSION);
+use FileHandle;
+use File::Basename;
+
+# The package version, both in 1.23 style *and* usable by MakeMaker:
+$VERSION = substr q$Revision: 1.117 $, 10;
+
+
+
+#------------------------------
+
+=head2 Construction
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item new [ARGS...]
+
+I<Class method, constructor.>
+Create a new tester. Any arguments are sent to log_open().
+
+=cut
+
+sub new {
+ my $self = bless {
+ OUT =>\*STDOUT,
+ Begin=>0,
+ End =>0,
+ Count=>0,
+ }, shift;
+ $self->log_open(@_) if @_;
+ $self;
+}
+
+#------------------------------
+
+=item typical
+
+I<Class method, constructor.>
+Create a typical tester. Use this instead of new() for most applicaitons.
+The directory "testout" is created for you automatically, to hold
+the output log file.
+
+=cut
+
+sub typical {
+ my $class = shift;
+ my ($tfile) = basename $0;
+ unless (-d "testout") {
+ mkdir "testout", 0755
+ or die "Couldn't create a 'testout' subdirectory: $!\n";
+ ### warn "$class: created 'testout' directory\n";
+ }
+ $class->new($class->catfile('.', 'testout', "${tfile}log"));
+}
+
+#------------------------------
+# DESTROY
+#------------------------------
+# Class method, destructor.
+# Automatically closes the log.
+#
+sub DESTROY {
+ $_[0]->log_close;
+}
+
+
+#------------------------------
+
+=back
+
+=head2 Doing tests
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item begin NUMTESTS
+
+I<Instance method.>
+Start testing.
+
+=cut
+
+sub begin {
+ my ($self, $n) = @_;
+ return if $self->{Begin}++;
+ $self->l_print("1..$n\n\n");
+ print {$self->{OUT}} "1..$n\n";
+}
+
+#------------------------------
+
+=item end
+
+I<Instance method.>
+End testing.
+
+=cut
+
+sub end {
+ my ($self) = @_;
+ return if $self->{End}++;
+ $self->l_print("END\n");
+ print {$self->{OUT}} "END\n";
+}
+
+#------------------------------
+
+=item ok BOOL, [TESTNAME], [PARAMHASH...]
+
+I<Instance method.>
+Do a test, and log some information connected with it.
+Use it like this:
+
+ $T->ok(-e $dotforward);
+
+Or better yet, like this:
+
+ $T->ok((-e $dotforward),
+ "Does the user have a .forward file?");
+
+Or even better, like this:
+
+ $T->ok((-e $dotforward),
+ "Does the user have a .forward file?",
+ User => $ENV{USER},
+ Path => $dotforward,
+ Fwd => $ENV{FWD});
+
+That last one, if it were test #3, would be logged as:
+
+ 3: Does the user have a .forward file?
+ 3: User: "alice"
+ 3: Path: "/home/alice/.forward"
+ 3: Fwd: undef
+ 3: ok
+
+You get the idea. Note that defined quantities are logged with delimiters
+and with all nongraphical characters suitably escaped, so you can see
+evidence of unexpected whitespace and other badnasties.
+Had "Fwd" been the string "this\nand\nthat", you'd have seen:
+
+ 3: Fwd: "this\nand\nthat"
+
+And unblessed array refs like ["this", "and", "that"] are
+treated as multiple values:
+
+ 3: Fwd: "this"
+ 3: Fwd: "and"
+ 3: Fwd: "that"
+
+=cut
+
+sub ok {
+ my ($self, $ok, $test, @ps) = @_;
+ ++($self->{Count}); # next test
+
+ # Report to harness:
+ my $status = ($ok ? "ok " : "not ok ") . $self->{Count};
+ print {$self->{OUT}} $status, "\n";
+
+ # Log:
+ $self->ln_print($test, "\n") if $test;
+ while (@ps) {
+ my ($k, $v) = (shift @ps, shift @ps);
+ my @vs = ((ref($v) and (ref($v) eq 'ARRAY'))? @$v : ($v));
+ foreach (@vs) {
+ if (!defined($_)) { # value not defined: output keyword
+ $self->ln_print(qq{ $k: undef\n});
+ }
+ else { # value defined: output quoted, encoded form
+ s{([\n\t\x00-\x1F\x7F-\xFF\\\"])}
+ {'\\'.sprintf("%02X",ord($1)) }exg;
+ s{\\0A}{\\n}g;
+ $self->ln_print(qq{ $k: "$_"\n});
+ }
+ }
+ }
+ $self->ln_print($status, "\n");
+ $self->l_print("\n");
+ 1;
+}
+
+
+#------------------------------
+
+=item ok_eq ASTRING, BSTRING, [TESTNAME], [PARAMHASH...]
+
+I<Instance method.>
+Convenience front end to ok(): test whether C<ASTRING eq BSTRING>, and
+logs the operands as 'A' and 'B'.
+
+=cut
+
+sub ok_eq {
+ my ($self, $this, $that, $test, @ps) = @_;
+ $self->ok(($this eq $that),
+ ($test || "(Is 'A' string-equal to 'B'?)"),
+ A => $this,
+ B => $that,
+ @ps);
+}
+
+
+#------------------------------
+
+=item ok_eqnum ANUM, BNUM, [TESTNAME], [PARAMHASH...]
+
+I<Instance method.>
+Convenience front end to ok(): test whether C<ANUM == BNUM>, and
+logs the operands as 'A' and 'B'.
+
+=cut
+
+sub ok_eqnum {
+ my ($self, $this, $that, $test, @ps) = @_;
+ $self->ok(($this == $that),
+ ($test || "(Is 'A' numerically-equal to 'B'?)"),
+ A => $this,
+ B => $that,
+ @ps);
+}
+
+#------------------------------
+
+=back
+
+=head2 Logging messages
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item log_open PATH
+
+I<Instance method.>
+Open a log file for messages to be output to. This is invoked
+for you automatically by C<new(PATH)> and C<typical()>.
+
+=cut
+
+sub log_open {
+ my ($self, $path) = @_;
+ $self->{LogPath} = $path;
+ $self->{LOG} = FileHandle->new(">$path") || die "open $path: $!";
+ $self;
+}
+
+#------------------------------
+
+=item log_close
+
+I<Instance method.>
+Close the log file and stop logging.
+You shouldn't need to invoke this directly; the destructor does it.
+
+=cut
+
+sub log_close {
+ my $self = shift;
+ close(delete $self->{LOG}) if $self->{LOG};
+}
+
+#------------------------------
+
+=item log MESSAGE...
+
+I<Instance method.>
+Log a message to the log file. No alterations are made on the
+text of the message. See msg() for an alternative.
+
+=cut
+
+sub log {
+ my $self = shift;
+ print {$self->{LOG}} @_ if $self->{LOG};
+}
+
+#------------------------------
+
+=item msg MESSAGE...
+
+I<Instance method.>
+Log a message to the log file. Lines are prefixed with "** " for clarity,
+and a terminating newline is forced.
+
+=cut
+
+sub msg {
+ my $self = shift;
+ my $text = join '', @_;
+ chomp $text;
+ $text =~ s{^}{** }gm;
+ $self->l_print($text, "\n");
+}
+
+#------------------------------
+#
+# l_print MESSAGE...
+#
+# Instance method, private.
+# Print to the log file if there is one.
+#
+sub l_print {
+ my $self = shift;
+ print { $self->{LOG} } @_ if $self->{LOG};
+}
+
+#------------------------------
+#
+# ln_print MESSAGE...
+#
+# Instance method, private.
+# Print to the log file, prefixed by message number.
+#
+sub ln_print {
+ my $self = shift;
+ foreach (split /\n/, join('', @_)) {
+ $self->l_print("$self->{Count}: $_\n");
+ }
+}
+
+#------------------------------
+
+=back
+
+=head2 Utilities
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item catdir DIR, ..., DIR
+
+I<Class/instance method.>
+Concatenate several directories into a path ending in a directory.
+Lightweight version of the one in the (very new) File::Spec.
+
+Paths are assumed to be absolute.
+To signify a relative path, the first DIR must be ".",
+which is processed specially.
+
+On Mac, the path I<does> end in a ':'.
+On Unix, the path I<does not> end in a '/'.
+
+=cut
+
+sub catdir {
+ my $self = shift;
+ my $relative = shift @_ if ($_[0] eq '.');
+ if ($^O eq 'Mac') {
+ return ($relative ? ':' : '') . (join ':', @_) . ':';
+ }
+ else {
+ return ($relative ? './' : '/') . join '/', @_;
+ }
+}
+
+#------------------------------
+
+=item catfile DIR, ..., DIR, FILE
+
+I<Class/instance method.>
+Like catdir(), but last element is assumed to be a file.
+Note that, at a minimum, you must supply at least a single DIR.
+
+=cut
+
+sub catfile {
+ my $self = shift;
+ my $file = pop;
+ if ($^O eq 'Mac') {
+ return $self->catdir(@_) . $file;
+ }
+ else {
+ return $self->catdir(@_) . "/$file";
+ }
+}
+
+#------------------------------
+
+=back
+
+
+=head1 CHANGE LOG
+
+B<Current version:>
+$Id: TBone.pm,v 1.117 2000/08/16 05:08:09 eryq Exp $
+
+=over 4
+
+=item Version 1.116
+
+Cosmetic improvements only.
+
+
+=item Version 1.112
+
+Added lightweight catdir() and catfile() (a la File::Spec)
+to enhance portability to Mac environment.
+
+
+=item Version 1.111
+
+Now uses File::Basename to create "typical" logfile name,
+for portability.
+
+
+=item Version 1.110
+
+Fixed bug in constructor that surfaced if no log was being used.
+
+=back
+
+Created: Friday-the-13th of February, 1998.
+
+
+=head1 AUTHOR
+
+Eryq (F<eryq@zeegee.com>).
+President, ZeeGee Software Inc. (F<http://www.zeegee.com>)
+
+=cut
+
+#------------------------------
+
+1;
+__END__
+
+my $T = new ExtUtils::TBone "testout/foo.tlog";
+$T->begin(3);
+$T->msg("before 1\nor 2");
+$T->ok(1, "one");
+$T->ok(2, "Two");
+$T->ok(3, "Three", Roman=>'III', Arabic=>[3, '03'], Misc=>"3\nor 3");
+$T->end;
+
+1;
+
diff --git a/cpan/dist/MIME-Lite/t/Utils.pm b/cpan/dist/MIME-Lite/t/Utils.pm
new file mode 100644
index 00000000..5d14e9d4
--- /dev/null
+++ b/cpan/dist/MIME-Lite/t/Utils.pm
@@ -0,0 +1,23 @@
+package Utils;
+
+@ISA = qw(Exporter);
+@EXPORT = qw(slurp spew cmp);
+
+sub slurp {
+ my $path = shift;
+ open IN, "<$path"; my $data = join('',<IN>); close IN; $data;
+}
+
+sub spew {
+ my ($path, $data) = @_;
+ open OUT, ">$path"; print OUT $data; close OUT;
+}
+
+sub cmp {
+ my ($a, $b) = @_;
+ $a =~ s/\r//g;
+ $b =~ s/\r//g;
+ return ($a eq $b);
+}
+
+1;
diff --git a/cpan/dist/MIME-Lite/t/addrs.t b/cpan/dist/MIME-Lite/t/addrs.t
new file mode 100644
index 00000000..d5758fa6
--- /dev/null
+++ b/cpan/dist/MIME-Lite/t/addrs.t
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+use lib "lib", "t";
+use MIME::Lite;
+use ExtUtils::TBone;
+use Utils;
+
+# Make a tester... here are 3 different alternatives:
+my $T = typical ExtUtils::TBone; # standard log
+$MIME::Lite::VANILLA = 1;
+$MIME::Lite::PARANOID = 1;
+
+# Pairs:
+my @pairs =
+ (
+ [' me@myhost.com ',
+ 1,
+ '<me@myhost.com>'],
+
+ [' mylogin ',
+ 1,
+ '<mylogin>'],
+
+ [' "Me, Jr." < me@myhost.com > ',
+ 1,
+ '<me@myhost.com>'],
+
+ [' Me <me@myhost.com>',
+ 1,
+ '<me@myhost.com>'],
+
+ ['"Me, Jr." <me@myhost.com>',
+ 1,
+ '<me@myhost.com>'],
+
+ ['"Me@somewhere.com, Jr." <me@myhost.com>',
+ 1,
+ '<me@myhost.com>'],
+
+ ['me@myhost.com,you@yourhost.com',
+ 2,
+ '<me@myhost.com> <you@yourhost.com>'],
+
+ ['"Me" <me@myhost.com>, "You"<you@yourhost.com>',
+ 2,
+ '<me@myhost.com> <you@yourhost.com>'],
+
+ ['"Me" <me@myhost.com>, you@yourhost.com, "And also" <she@herhost.com>',
+ 3,
+ '<me@myhost.com> <you@yourhost.com> <she@herhost.com>'],
+
+ ['"Me" <me@myhost.com>, mylogin ,yourlogin , She <she@herhost.com>',
+ 4,
+ '<me@myhost.com> <mylogin> <yourlogin> <she@herhost.com>']
+ );
+
+
+# Abort?
+if (eval "require Mail::Address") {
+ $T->begin(1);
+ $T->ok(1, "we have and trust Mail::Address");
+ $T->end;
+ exit 0;
+}
+
+# Begin testing:
+$T->begin(2 * @pairs);
+
+# New:
+foreach my $pair (@pairs) {
+ my ($to, $count, $result) = @$pair;
+ my @addrs = MIME::Lite::extract_addrs($to);
+
+ $T->ok_eqnum(int(@addrs), $count,
+ "compare count",
+ In => $to);
+ $T->ok_eq(join(' ', map {"<$_>"} @addrs),
+ $result,
+ "compare result",
+ In => $to);
+}
+
+$T->end;
+
+
+
+
+
diff --git a/cpan/dist/MIME-Lite/t/data.t b/cpan/dist/MIME-Lite/t/data.t
new file mode 100644
index 00000000..e3e5ef71
--- /dev/null
+++ b/cpan/dist/MIME-Lite/t/data.t
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+use lib "lib", "t";
+use MIME::Lite;
+use ExtUtils::TBone;
+use Utils;
+
+# Make a tester... here are 3 different alternatives:
+my $T = typical ExtUtils::TBone; # standard log
+$MIME::Lite::VANILLA = 1;
+$MIME::Lite::PARANOID = 1;
+
+# Begin testing:
+$T->begin(4);
+
+my ($me, $str);
+
+#------------------------------
+$me = MIME::Lite->build(Type => 'text/plain',
+ Data => "Hello\nWorld\n");
+$str = $me->as_string;
+$T->ok(($str =~ m{Hello\nWorld\n}),
+ $from,
+ "Data string");
+
+#------------------------------
+$me = MIME::Lite->build(Type => 'text/plain',
+ Data => ["Hel", "lo\n", "World\n"]);
+$str = $me->as_string;
+$T->ok(($str =~ m{Hello\nWorld\n}),
+ $from,
+ "Data array 1");
+
+#------------------------------
+$me = MIME::Lite->build(Type => 'text/plain',
+ Data => ["Hel", "lo", "\n", "", "World", "", "","\n"]);
+$str = $me->as_string;
+$T->ok(($str =~ m{Hello\nWorld\n}),
+ $from,
+ "Data array 2");
+
+#------------------------------
+$me = MIME::Lite->build(Type => 'text/plain',
+ Path => "./testin/hello");
+$str = $me->as_string;
+$T->ok(($str =~ m{Hello\nWorld\n}),
+ $from,
+ "Data file");
+
+
+$T->end;
+
+
+
+
+
diff --git a/cpan/dist/MIME-Lite/t/head.t b/cpan/dist/MIME-Lite/t/head.t
new file mode 100644
index 00000000..a6680fb0
--- /dev/null
+++ b/cpan/dist/MIME-Lite/t/head.t
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+use lib "lib", "t";
+use MIME::Lite;
+use ExtUtils::TBone;
+use Utils;
+
+# Make a tester... here are 3 different alternatives:
+my $T = typical ExtUtils::TBone; # standard log
+$MIME::Lite::VANILLA = 1;
+$MIME::Lite::PARANOID = 1;
+
+# Begin testing:
+$T->begin(14);
+
+# New:
+my $from = 'me@myhost.com';
+my $me = MIME::Lite->build(From => $from,
+ To => 'you@yourhost.com',
+ Subject => 'Me!',
+ Type => 'text/plain',
+ Data => "Hello!\n");
+
+# Test "get" [4 tests]:
+$T->ok_eq(scalar($me->get('From')),
+ $from,
+ "get: simple get of 'From'");
+$T->ok_eq($me->get('From',0),
+ $from,
+ "get: indexed get(0) of 'From' gets first");
+$T->ok_eq($me->get('From',-1),
+ $from,
+ "get: indexed get(-1) of 'From' gets first");
+$T->ok_eq($me->get('FROM',0),
+ $from,
+ "get: indexed get(0) of 'FROM' gets From");
+
+# Test "add": add one, then two [6 tests]:
+$me->add('Received', 'sined');
+$me->add('Received', ['seeled', 'delivered']);
+$T->ok_eq(scalar($me->get('Received')),
+ 'sined',
+ "add: scalar context get of 'Received'");
+$T->ok_eq($me->get('Received',0),
+ 'sined',
+ "add: scalar context get(0) of 'Received'");
+$T->ok_eq($me->get('Received',1),
+ 'seeled',
+ "add: scalar context get(1) of 'Received'");
+$T->ok_eq($me->get('Received',2),
+ 'delivered',
+ "add: scalar context get(2) of 'Received'");
+$T->ok_eq($me->get('Received',-1),
+ 'delivered',
+ "add: scalar context get(-1) of 'Received'");
+$T->ok_eq(($me->get('Received'))[1],
+ 'seeled',
+ "add: array context get of 'Received', indexed to 1'th elem");
+
+# Test "delete" [1 test]:
+$me->delete('RECEIVED');
+$T->ok(!defined($me->get('Received')),
+ "delete: deletion of RECEIVED worked");
+
+# Test "replace" [1 test]:
+$me->replace('subject', "Hellooooo, nurse!");
+$T->ok_eq($me->get('SUBJECT'),
+ "Hellooooo, nurse!",
+ "replace: replace of SUBJECT worked");
+
+# Test "attr" [2 tests]:
+$me->attr('content-type.charset', 'US-ASCII');
+$T->ok_eq($me->attr('content-type.charset'),
+ 'US-ASCII',
+ "attr: replace of charset worked");
+#
+my ($ct) = map {($_->[0] eq 'content-type') ? $_->[1] : ()} @{$me->fields};
+$T->ok_eq($ct,
+ 'text/plain; charset="US-ASCII"',
+ "attr: replace of charset worked on whole line");
+
+
+$T->end;
+
+
+
+
+
diff --git a/cpan/dist/MIME-Lite/t/verify.t b/cpan/dist/MIME-Lite/t/verify.t
new file mode 100644
index 00000000..bb254239
--- /dev/null
+++ b/cpan/dist/MIME-Lite/t/verify.t
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+use lib "lib", "t";
+use MIME::Lite;
+use ExtUtils::TBone;
+use Utils;
+
+# Make a tester... here are 3 different alternatives:
+my $T = typical ExtUtils::TBone; # standard log
+$MIME::Lite::VANILLA = 1;
+$MIME::Lite::PARANOID = 1;
+
+# Begin testing:
+$T->begin(2);
+
+my $msg;
+
+$msg = MIME::Lite->new(From=>"me", To=>"you");
+$msg->attach(Path => "boguscmd |");
+$msg->attach(Data => "Hello");
+$msg->attach(Path => "<path.to.missing.file");
+eval { $msg->verify_data };
+$T->ok($@ =~ /path\.to\.missing\.file/,
+ "Did we detect a missing file?",
+ Error => $@);
+
+$msg = MIME::Lite->new(From=>"me", To=>"you");
+$msg->attach(Data => "Hello");
+eval { $msg->verify_data };
+$T->ok(!$@,
+ "Did we detect NO missing file?",
+ Error => $@);
+
+
+$T->end;
+
+
+
+
+
diff --git a/cpan/dist/MIME-Lite/testin/README b/cpan/dist/MIME-Lite/testin/README
new file mode 100644
index 00000000..84a5b0e7
--- /dev/null
+++ b/cpan/dist/MIME-Lite/testin/README
@@ -0,0 +1 @@
+Test input directory
diff --git a/cpan/dist/MIME-Lite/testin/hello b/cpan/dist/MIME-Lite/testin/hello
new file mode 100644
index 00000000..f9264f7f
--- /dev/null
+++ b/cpan/dist/MIME-Lite/testin/hello
@@ -0,0 +1,2 @@
+Hello
+World
diff --git a/cpan/lib/MIME/Lite.pm b/cpan/lib/MIME/Lite.pm
new file mode 100644
index 00000000..ad8ac3cf
--- /dev/null
+++ b/cpan/lib/MIME/Lite.pm
@@ -0,0 +1,3227 @@
+package MIME::Lite;
+
+
+=head1 NAME
+
+MIME::Lite - low-calorie MIME generator
+
+
+=head1 SYNOPSIS
+
+ use MIME::Lite;
+
+Create a single-part message:
+
+ ### Create a new single-part message, to send a GIF file:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'Helloooooo, nurse!',
+ Type =>'image/gif',
+ Encoding =>'base64',
+ Path =>'hellonurse.gif'
+ );
+
+Create a multipart message (i.e., one with attachments):
+
+ ### Create a new multipart message:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'A message with 2 parts...',
+ Type =>'multipart/mixed'
+ );
+
+ ### Add parts (each "attach" has same arguments as "new"):
+ $msg->attach(Type =>'TEXT',
+ Data =>"Here's the GIF file you wanted"
+ );
+ $msg->attach(Type =>'image/gif',
+ Path =>'aaa000123.gif',
+ Filename =>'logo.gif',
+ Disposition => 'attachment'
+ );
+
+Output a message:
+
+ ### Format as a string:
+ $str = $msg->as_string;
+
+ ### Print to a filehandle (say, a "sendmail" stream):
+ $msg->print(\*SENDMAIL);
+
+
+Send a message:
+
+ ### Send in the "best" way (the default is to use "sendmail"):
+ $msg->send;
+
+
+
+=head1 DESCRIPTION
+
+In the never-ending quest for great taste with fewer calories,
+we proudly present: I<MIME::Lite>.
+
+MIME::Lite is intended as a simple, standalone module for generating
+(not parsing!) MIME messages... specifically, it allows you to
+output a simple, decent single- or multi-part message with text or binary
+attachments. It does not require that you have the Mail:: or MIME::
+modules installed.
+
+You can specify each message part as either the literal data itself (in
+a scalar or array), or as a string which can be given to open() to get
+a readable filehandle (e.g., "<filename" or "somecommand|").
+
+You don't need to worry about encoding your message data:
+this module will do that for you. It handles the 5 standard MIME encodings.
+
+If you need more sophisticated behavior, please get the MIME-tools
+package instead. I will be more likely to add stuff to that toolkit
+over this one.
+
+
+=head1 MORE EXAMPLES
+
+=head2 Attach a GIF to a text message
+
+This will create a multipart message exactly as above, but using the
+"attach to singlepart" hack:
+
+ ### Create a new multipart message:
+ $msg = MIME::Lite->new(
+ From =>'me@myhost.com',
+ To =>'you@yourhost.com',
+ Cc =>'some@other.com, some@more.com',
+ Subject =>'A message with 2 parts...',
+ Type =>'TEXT',
+ Data =>"Here's the GIF file you wanted"
+ );
+
+ ### Attach a part:
+ $msg->attach(Type =>'image/gif',
+ Path =>'aaa000123.gif',
+ Filename =>'logo.gif'
+ );
+
+
+=head2 Attach a pre-prepared part (allows fine-tuning):
+
+ $part = MIME::Lite->new(
+ Type =>'text/html',
+ Data =>'<H1>Hello</H1>',
+ );
+ $part->attr('content-type.charset' => 'UTF8');
+ $part->add('X-Comment' => 'A message for you');
+ $msg->attach($part);
+
+
+=head2 Send an HTML document... with images included!
+
+ $msg = MIME::Lite->new(
+ To =>'you@yourhost.com',
+ Subject =>'HTML with in-line images!',
+ Type =>'multipart/related'
+ );
+ $msg->attach(Type => 'text/html',
+ Data => qq{ <body>
+ Here's <i>my</i> image:
+ <img src="cid:myimage.gif">
+ </body> }
+ );
+ $msg->attach(Type => 'image/gif',
+ Id => 'myimage.gif',
+ Path => '/path/to/somefile.gif',
+ );
+ $msg->send();
+
+
+=head2 Output a message to a filehandle
+
+ ### Write it to a filehandle:
+ $msg->print(\*STDOUT);
+
+ ### Write just the header:
+ $msg->print_header(\*STDOUT);
+
+ ### Write just the encoded body:
+ $msg->print_body(\*STDOUT);
+
+
+=head2 Get a message as a string
+
+ ### Get entire message as a string:
+ $str = $msg->as_string;
+
+ ### Get just the header:
+ $str = $msg->header_as_string;
+
+ ### Get just the encoded body:
+ $str = $msg->body_as_string;
+
+
+=head2 Change how messages are sent
+
+ ### Do something like this in your 'main':
+ if ($I_DONT_HAVE_SENDMAIL) {
+ MIME::Lite->send('smtp', "smtp.myisp.net", Timeout=>60);
+ }
+
+ ### Now this will do the right thing:
+ $msg->send; ### will now use Net::SMTP as shown above
+
+
+
+
+
+
+=head1 FAQ
+
+
+=head2 How do I prevent "Content" headers from showing up in my mail reader?
+
+Apparently, some people are using mail readers which display the MIME
+headers like "Content-disposition", and they want MIME::Lite not
+to generate them "because they look ugly".
+
+Sigh.
+
+Y'know, kids, those headers aren't just there for cosmetic purposes.
+They help ensure that the message is I<understood> correctly by mail
+readers. But okay, you asked for it, you got it...
+here's how you can suppress the standard MIME headers.
+Before you send the message, do this:
+
+ $msg->scrub;
+
+You can scrub() any part of a multipart message independently;
+just be aware that it works recursively. Before you scrub,
+note the rules that I follow:
+
+=over 4
+
+=item Content-type
+
+You can safely scrub the "content-type" attribute if, and only if,
+the part is of type "text/plain" with charset "us-ascii".
+
+=item Content-transfer-encoding
+
+You can safely scrub the "content-transfer-encoding" attribute
+if, and only if, the part uses "7bit", "8bit", or "binary" encoding.
+You are far better off doing this if your lines are under 1000
+characters. Generally, that means you I<can> scrub it for plain
+text, and you can I<not> scrub this for images, etc.
+
+=item Content-disposition
+
+You can safely scrub the "content-disposition" attribute
+if you trust the mail reader to do the right thing when it decides
+whether to show an attachment inline or as a link. Be aware
+that scrubbing both the content-disposition and the content-type
+means that there is no way to "recommend" a filename for the attachment!
+
+B<Note:> there are reports of brain-dead MUAs out there that
+do the wrong thing if you I<provide> the content-disposition.
+If your attachments keep showing up inline or vice-versa,
+try scrubbing this attribute.
+
+=item Content-length
+
+You can always scrub "content-length" safely.
+
+=back
+
+
+=head2 How do I give my attachment a [different] recommended filename?
+
+By using the Filename option (which is different from Path!):
+
+ $msg->attach(Type => "image/gif",
+ Path => "/here/is/the/real/file.GIF",
+ Filename => "logo.gif");
+
+You should I<not> put path information in the Filename.
+
+
+
+=head1 PUBLIC INTERFACE
+
+=head2 Global configuration
+
+To alter the way the entire module behaves, you have the following
+methods/options:
+
+=over 4
+
+
+=item MIME::Lite->header_order()
+
+When used as a L<classmethod|/send>, this changes the default
+order in which headers are output for I<all> messages.
+
+
+=item MIME::Lite->quiet()
+
+This L<classmethod|/quiet> can be used to suppress/unsuppress
+all warnings coming from this module.
+
+
+=item MIME::Lite->send()
+
+When used as a L<classmethod|/send>, this can be used to specify
+a different default mechanism for sending message.
+The initial default is:
+
+ MIME::Lite->send("sendmail", "/usr/lib/sendmail -t -oi -oem");
+
+However, you should consider the similar but smarter and taint-safe variant:
+
+ MIME::Lite->send("sendmail");
+
+Or, for non-Unix users:
+
+ MIME::Lite->send("smtp");
+
+
+=item $MIME::Lite::PARANOID
+
+If true, we won't attempt to use MIME::Base64/MIME::QuotedPrint, even
+if they're available.
+Default is B<false>.
+
+
+=item $MIME::Lite::AUTO_ENCODE
+
+If true, automatically choose the encoding from the content type.
+Default is B<true>.
+
+
+=item $MIME::Lite::AUTO_CC
+
+If true, automatically send to the Cc/Bcc addresses for send_by_smtp().
+Default is B<true>.
+
+
+=item $MIME::Lite::AUTO_VERIFY
+
+If true, check paths to attachments right before printing, raising an exception
+if any path is unreadable.
+Default is B<true>.
+
+=back
+
+=cut
+
+require 5.004; ### for /c modifier in m/\G.../gc modifier
+
+use Carp;
+use FileHandle;
+
+use strict;
+use vars qw(
+ $AUTO_CC
+ $AUTO_ENCODE
+ $AUTO_VERIFY
+ $PARANOID
+ $QUIET
+ $VANILLA
+ $VERSION
+ );
+
+
+
+#==============================
+#==============================
+#
+# GLOBALS, EXTERNAL/CONFIGURATION...
+
+### The package version, both in 1.23 style *and* usable by MakeMaker:
+$VERSION = substr q$Revision: 2.108 $, 10;
+
+### Don't warn me about dangerous activities:
+$QUIET = undef;
+
+### Set this true if you don't want to use MIME::Base64/MIME::QuotedPrint:
+$PARANOID = 0;
+
+### Unsupported (for tester use): don't qualify boundary with time/pid:
+$VANILLA = 0;
+
+### Automatically choose encoding from content type:
+$AUTO_ENCODE = 1;
+
+### Automatically interpret CC/BCC for SMTP:
+$AUTO_CC = 1;
+
+### Check paths right before printing:
+$AUTO_VERIFY = 1;
+
+
+#==============================
+#==============================
+#
+# GLOBALS, INTERNAL...
+
+### Find sendmail:
+my $SENDMAIL = "/usr/lib/sendmail";
+(-x $SENDMAIL) or ($SENDMAIL = "/usr/sbin/sendmail");
+(-x $SENDMAIL) or ($SENDMAIL = "sendmail");
+
+### Our sending facilities:
+my $Sender = "sendmail";
+my %SenderArgs = (
+ "sendmail" => ["$SENDMAIL -t -oi -oem"],
+ "smtp" => [],
+ "sub" => [],
+);
+
+### Boundary counter:
+my $BCount = 0;
+
+### Known Mail/MIME fields... these, plus some general forms like
+### "x-*", are recognized by build():
+my %KnownField = map {$_=>1}
+qw(
+ bcc cc comments date encrypted
+ from keywords message-id mime-version organization
+ received references reply-to return-path sender
+ subject to
+
+ approved
+ );
+
+### What external packages do we use for encoding?
+my @Uses;
+
+### Header order:
+my @FieldOrder;
+
+
+#==============================
+#==============================
+#
+# PRIVATE UTILITY FUNCTIONS...
+
+#------------------------------
+#
+# fold STRING
+#
+# Make STRING safe as a field value. Remove leading/trailing whitespace,
+# and make sure newlines are represented as newline+space
+
+sub fold {
+ my $str = shift;
+ $str =~ s/^\s*|\s*$//g; ### trim
+ $str =~ s/\n/\n /g;
+ $str;
+}
+
+#------------------------------
+#
+# gen_boundary
+#
+# Generate a new boundary to use.
+# The unsupported $VANILLA is for test purposes only.
+
+sub gen_boundary {
+ return ("_----------=_".($VANILLA ? '' : int(time).$$).$BCount++);
+}
+
+#------------------------------
+#
+# known_field FIELDNAME
+#
+# Is this a recognized Mail/MIME field?
+
+sub known_field {
+ my $field = lc(shift);
+ $KnownField{$field} or ($field =~ m{^(content|resent|x)-.});
+}
+
+#------------------------------
+#
+# is_mime_field FIELDNAME
+#
+# Is this a field I manage?
+
+sub is_mime_field {
+ $_[0] =~ /^(mime\-|content\-)/i;
+}
+
+#------------------------------
+#
+# extract_addrs STRING
+#
+# Split STRING into an array of email addresses: somewhat of a KLUDGE.
+#
+# Unless paranoid, we try to load the real code before supplying our own.
+
+my $ATOM = '[^ \000-\037()<>@,;:\134"\056\133\135]+';
+my $QSTR = '".*?"';
+my $WORD = '(?:' . $QSTR . '|' . $ATOM . ')';
+my $DOMAIN = '(?:' . $ATOM . '(?:' . '\\.' . $ATOM . ')*' . ')';
+my $LOCALPART = '(?:' . $WORD . '(?:' . '\\.' . $WORD . ')*' . ')';
+my $ADDR = '(?:' . $LOCALPART . '@' . $DOMAIN . ')';
+my $PHRASE = '(?:' . $WORD . ')+';
+my $SEP = "(?:^\\s*|\\s*,\\s*)"; ### before elems in a list
+
+sub my_extract_addrs {
+ my $str = shift;
+ my @addrs;
+ $str =~ s/\s/ /g; ### collapse whitespace
+
+ pos($str) = 0;
+ while ($str !~ m{\G\s*\Z}gco) {
+ ### print STDERR "TACKLING: ".substr($str, pos($str))."\n";
+ if ($str =~ m{\G$SEP$PHRASE\s*<\s*($ADDR)\s*>}gco) {push @addrs,$1}
+ elsif ($str =~ m{\G$SEP($ADDR)}gco) {push @addrs,$1}
+ elsif ($str =~ m{\G$SEP($ATOM)}gco) {push @addrs,$1}
+ else {
+ my $problem = substr($str, pos($str));
+ die "can't extract address at <$problem> in <$str>\n";
+ }
+ }
+ return @addrs;
+}
+
+if (eval "require Mail::Address") {
+ push @Uses, "A$Mail::Address::VERSION";
+ eval q{
+ sub extract_addrs {
+ return map { $_->format } Mail::Address->parse($_[0]);
+ }
+ }; ### q
+}
+else {
+ eval q{
+ sub extract_addrs {
+ return my_extract_addrs(@_);
+ }
+ }; ### q
+} ### if
+
+
+
+#==============================
+#==============================
+#
+# PRIVATE ENCODING FUNCTIONS...
+
+#------------------------------
+#
+# encode_base64 STRING
+#
+# Encode the given string using BASE64.
+# Unless paranoid, we try to load the real code before supplying our own.
+
+if (!$PARANOID and eval "require MIME::Base64") {
+ import MIME::Base64 qw(encode_base64);
+ push @Uses, "B$MIME::Base64::VERSION";
+}
+else {
+ eval q{
+sub encode_base64 {
+ my $res = "";
+ my $eol = "\n";
+
+ pos($_[0]) = 0; ### thanks, Andreas!
+ while ($_[0] =~ /(.{1,45})/gs) {
+ $res .= substr(pack('u', $1), 1);
+ chop($res);
+ }
+ $res =~ tr|` -_|AA-Za-z0-9+/|;
+
+ ### Fix padding at the end:
+ my $padding = (3 - length($_[0]) % 3) % 3;
+ $res =~ s/.{$padding}$/'=' x $padding/e if $padding;
+
+ ### Break encoded string into lines of no more than 76 characters each:
+ $res =~ s/(.{1,76})/$1$eol/g if (length $eol);
+ return $res;
+} ### sub
+ } ### q
+} ### if
+
+#------------------------------
+#
+# encode_qp STRING
+#
+# Encode the given string, LINE BY LINE, using QUOTED-PRINTABLE.
+# Stolen from MIME::QuotedPrint by Gisle Aas, with a slight bug fix: we
+# break lines earlier. Notice that this seems not to work unless
+# encoding line by line.
+#
+# Unless paranoid, we try to load the real code before supplying our own.
+
+if (!$PARANOID and eval "require MIME::QuotedPrint") {
+ import MIME::QuotedPrint qw(encode_qp);
+ push @Uses, "Q$MIME::QuotedPrint::VERSION";
+}
+else {
+ eval q{
+sub encode_qp {
+ my $res = shift;
+ local($_);
+ $res =~ s/([^ \t\n!-<>-~])/sprintf("=%02X", ord($1))/eg; ### rule #2,#3
+ $res =~ s/([ \t]+)$/
+ join('', map { sprintf("=%02X", ord($_)) }
+ split('', $1)
+ )/egm; ### rule #3 (encode whitespace at eol)
+
+ ### rule #5 (lines shorter than 76 chars, but can't break =XX escapes:
+ my $brokenlines = "";
+ $brokenlines .= "$1=\n" while $res =~ s/^(.{70}([^=]{2})?)//; ### 70 was 74
+ $brokenlines =~ s/=\n$// unless length $res;
+ "$brokenlines$res";
+} ### sub
+ } ### q
+} ### if
+
+
+#------------------------------
+#
+# encode_8bit STRING
+#
+# Encode the given string using 8BIT.
+# This breaks long lines into shorter ones.
+
+sub encode_8bit {
+ my $str = shift;
+ $str =~ s/^(.{990})/$1\n/mg;
+ $str;
+}
+
+#------------------------------
+#
+# encode_7bit STRING
+#
+# Encode the given string using 7BIT.
+# This NO LONGER protects people through encoding.
+
+sub encode_7bit {
+ my $str = shift;
+ $str =~ s/[\x80-\xFF]//g;
+ $str =~ s/^(.{990})/$1\n/mg;
+ $str;
+}
+
+#==============================
+#==============================
+
+=head2 Construction
+
+=over 4
+
+=cut
+
+
+#------------------------------
+
+=item new [PARAMHASH]
+
+I<Class method, constructor.>
+Create a new message object.
+
+If any arguments are given, they are passed into C<build()>; otherwise,
+just the empty object is created.
+
+=cut
+
+sub new {
+ my $class = shift;
+
+ ### Create basic object:
+ my $self = {
+ Attrs => {}, ### MIME attributes
+ Header => [], ### explicit message headers
+ Parts => [], ### array of parts
+ };
+ bless $self, $class;
+
+ ### Build, if needed:
+ return (@_ ? $self->build(@_) : $self);
+}
+
+
+#------------------------------
+
+=item attach PART
+
+=item attach PARAMHASH...
+
+I<Instance method.>
+Add a new part to this message, and return the new part.
+
+If you supply a single PART argument, it will be regarded
+as a MIME::Lite object to be attached. Otherwise, this
+method assumes that you are giving in the pairs of a PARAMHASH
+which will be sent into C<new()> to create the new part.
+
+One of the possibly-quite-useful hacks thrown into this is the
+"attach-to-singlepart" hack: if you attempt to attach a part (let's
+call it "part 1") to a message that doesn't have a content-type
+of "multipart" or "message", the following happens:
+
+=over 4
+
+=item *
+
+A new part (call it "part 0") is made.
+
+=item *
+
+The MIME attributes and data (but I<not> the other headers)
+are cut from the "self" message, and pasted into "part 0".
+
+=item *
+
+The "self" is turned into a "multipart/mixed" message.
+
+=item *
+
+The new "part 0" is added to the "self", and I<then> "part 1" is added.
+
+=back
+
+One of the nice side-effects is that you can create a text message
+and then add zero or more attachments to it, much in the same way
+that a user agent like Netscape allows you to do.
+
+=cut
+
+sub attach {
+ my $self = shift;
+
+ ### Create new part, if necessary:
+ my $part1 = ((@_ == 1) ? shift : ref($self)->new(Top=>0, @_));
+
+ ### Do the "attach-to-singlepart" hack:
+ if ($self->attr('content-type') !~ m{^(multipart|message)/}i) {
+
+ ### Create part zero:
+ my $part0 = ref($self)->new;
+
+ ### Cut MIME stuff from self, and paste into part zero:
+ foreach (qw(Attrs Data Path FH)) {
+ $part0->{$_} = $self->{$_}; delete($self->{$_});
+ }
+ $part0->top_level(0); ### clear top-level attributes
+
+ ### Make self a top-level multipart:
+ $self->{Attrs} ||= {}; ### reset
+ $self->attr('content-type' => 'multipart/mixed');
+ $self->attr('content-type.boundary' => gen_boundary());
+ $self->attr('content-transfer-encoding' => '7bit');
+ $self->top_level(1); ### activate top-level attributes
+
+ ### Add part 0:
+ push @{$self->{Parts}}, $part0;
+ }
+
+ ### Add the new part:
+ push @{$self->{Parts}}, $part1;
+ $part1;
+}
+
+#------------------------------
+
+=item build [PARAMHASH]
+
+I<Class/instance method, initializer.>
+Create (or initialize) a MIME message object.
+Normally, you'll use the following keys in PARAMHASH:
+
+ * Data, FH, or Path (either one of these, or none if multipart)
+ * Type (e.g., "image/jpeg")
+ * From, To, and Subject (if this is the "top level" of a message)
+
+The PARAMHASH can contain the following keys:
+
+=over 4
+
+=item (fieldname)
+
+Any field you want placed in the message header, taken from the
+standard list of header fields (you don't need to worry about case):
+
+ Approved Encrypted Received Sender
+ Bcc From References Subject
+ Cc Keywords Reply-To To
+ Comments Message-ID Resent-* X-*
+ Content-* MIME-Version Return-Path
+ Date Organization
+
+To give experienced users some veto power, these fields will be set
+I<after> the ones I set... so be careful: I<don't set any MIME fields>
+(like C<Content-type>) unless you know what you're doing!
+
+To specify a fieldname that's I<not> in the above list, even one that's
+identical to an option below, just give it with a trailing C<":">,
+like C<"My-field:">. When in doubt, that I<always> signals a mail
+field (and it sort of looks like one too).
+
+=item Data
+
+I<Alternative to "Path" or "FH".>
+The actual message data. This may be a scalar or a ref to an array of
+strings; if the latter, the message consists of a simple concatenation
+of all the strings in the array.
+
+=item Datestamp
+
+I<Optional.>
+If given true (or omitted), we force the creation of a C<Date:> field
+stamped with the current date/time if this is a top-level message.
+You may want this if using L<send_by_smtp()|/send_by_smtp>.
+If you don't want this to be done, either provide your own Date
+or explicitly set this to false.
+
+=item Disposition
+
+I<Optional.>
+The content disposition, C<"inline"> or C<"attachment">.
+The default is C<"inline">.
+
+=item Encoding
+
+I<Optional.>
+The content transfer encoding that should be used to encode your data:
+
+ Use encoding: | If your message contains:
+ ------------------------------------------------------------
+ 7bit | Only 7-bit text, all lines <1000 characters
+ 8bit | 8-bit text, all lines <1000 characters
+ quoted-printable | 8-bit text or long lines (more reliable than "8bit")
+ base64 | Largely non-textual data: a GIF, a tar file, etc.
+
+The default is taken from the Type; generally it is "binary" (no
+encoding) for text/*, message/*, and multipart/*, and "base64" for
+everything else. A value of C<"binary"> is generally I<not> suitable
+for sending anything but ASCII text files with lines under 1000
+characters, so consider using one of the other values instead.
+
+In the case of "7bit"/"8bit", long lines are automatically chopped to
+legal length; in the case of "7bit", all 8-bit characters are
+automatically I<removed>. This may not be what you want, so pick your
+encoding well! For more info, see L<"A MIME PRIMER">.
+
+=item FH
+
+I<Alternative to "Data" or "Path".>
+Filehandle containing the data, opened for reading.
+See "ReadNow" also.
+
+=item Filename
+
+I<Optional.>
+The name of the attachment. You can use this to supply a
+recommended filename for the end-user who is saving the attachment
+to disk. You only need this if the filename at the end of the
+"Path" is inadequate, or if you're using "Data" instead of "Path".
+You should I<not> put path information in here (e.g., no "/"
+or "\" or ":" characters should be used).
+
+=item Id
+
+I<Optional.>
+Same as setting "content-id".
+
+=item Length
+
+I<Optional.>
+Set the content length explicitly. Normally, this header is automatically
+computed, but only under certain circumstances (see L<"Limitations">).
+
+=item Path
+
+I<Alternative to "Data" or "FH".>
+Path to a file containing the data... actually, it can be any open()able
+expression. If it looks like a path, the last element will automatically
+be treated as the filename.
+See "ReadNow" also.
+
+=item ReadNow
+
+I<Optional, for use with "Path".>
+If true, will open the path and slurp the contents into core now.
+This is useful if the Path points to a command and you don't want
+to run the command over and over if outputting the message several
+times. B<Fatal exception> raised if the open fails.
+
+=item Top
+
+I<Optional.>
+If defined, indicates whether or not this is a "top-level" MIME message.
+The parts of a multipart message are I<not> top-level.
+Default is true.
+
+=item Type
+
+I<Optional.>
+The MIME content type, or one of these special values (case-sensitive):
+
+ "TEXT" means "text/plain"
+ "BINARY" means "application/octet-stream"
+
+The default is C<"TEXT">.
+
+=back
+
+A picture being worth 1000 words (which
+is of course 2000 bytes, so it's probably more of an "icon" than a "picture",
+but I digress...), here are some examples:
+
+ $msg = MIME::Lite->build(
+ From => 'yelling@inter.com',
+ To => 'stocking@fish.net',
+ Subject => "Hi there!",
+ Type => 'TEXT',
+ Encoding => '7bit',
+ Data => "Just a quick note to say hi!");
+
+ $msg = MIME::Lite->build(
+ From => 'dorothy@emerald-city.oz',
+ To => 'gesundheit@edu.edu.edu',
+ Subject => "A gif for U"
+ Type => 'image/gif',
+ Path => "/home/httpd/logo.gif");
+
+ $msg = MIME::Lite->build(
+ From => 'laughing@all.of.us',
+ To => 'scarlett@fiddle.dee.de',
+ Subject => "A gzipp'ed tar file",
+ Type => 'x-gzip',
+ Path => "gzip < /usr/inc/somefile.tar |",
+ ReadNow => 1,
+ Filename => "somefile.tgz");
+
+To show you what's really going on, that last example could also
+have been written:
+
+ $msg = new MIME::Lite;
+ $msg->build(Type => 'x-gzip',
+ Path => "gzip < /usr/inc/somefile.tar |",
+ ReadNow => 1,
+ Filename => "somefile.tgz");
+ $msg->add(From => "laughing@all.of.us");
+ $msg->add(To => "scarlett@fiddle.dee.de");
+ $msg->add(Subject => "A gzipp'ed tar file");
+
+=cut
+
+sub build {
+ my $self = shift;
+ my %params = @_;
+ my @params = @_;
+ my $key;
+
+ ### Miko's note: reorganized to check for exactly one of Data, Path, or FH
+ (defined($params{Data})+defined($params{Path})+defined($params{FH}) <= 1)
+ or croak "supply exactly zero or one of (Data|Path|FH).\n";
+
+ ### Create new instance, if necessary:
+ ref($self) or $self = $self->new;
+
+
+ ### CONTENT-TYPE....
+ ###
+
+ ### Get content-type:
+ my $type = ($params{Type} || 'TEXT');
+ ($type eq 'TEXT') and $type = 'text/plain';
+ ($type eq 'BINARY') and $type = 'application/octet-stream';
+ $type = lc($type);
+ $self->attr('content-type' => $type);
+
+ ### Get some basic attributes from the content type:
+ my $is_multipart = ($type =~ m{^(multipart)/}i);
+
+ ### Add in the multipart boundary:
+ if ($is_multipart) {
+ my $boundary = gen_boundary();
+ $self->attr('content-type.boundary' => $boundary);
+ }
+
+
+ ### CONTENT-ID...
+ ###
+ $self->attr('content-id' => $params{Id}) if defined($params{Id});
+
+
+ ### DATA OR PATH...
+ ### Note that we must do this *after* we get the content type,
+ ### in case read_now() is invoked, since it needs the binmode().
+
+ ### Get data, as...
+ ### ...either literal data:
+ if (defined($params{Data})) {
+ $self->data($params{Data});
+ }
+ ### ...or a path to data:
+ elsif (defined($params{Path})) {
+ $self->path($params{Path}); ### also sets filename
+ $self->read_now if $params{ReadNow};
+ }
+ ### ...or a filehandle to data:
+ ### Miko's note: this part works much like the path routine just above,
+ elsif (defined($params{FH})) {
+ $self->fh($params{FH});
+ $self->read_now if $params{ReadNow}; ### implement later
+ }
+
+
+ ### FILENAME... (added by Ian Smith <ian@safeway.dircon.co.uk> on 8/4/97)
+ ### Need this to make sure the filename is added. The Filename
+ ### attribute is ignored, otherwise.
+ if (defined($params{Filename})) {
+ $self->filename($params{Filename});
+ }
+
+
+ ### CONTENT-TRANSFER-ENCODING...
+ ###
+
+ ### Get it:
+ my $enc = ($params{Encoding} ||
+ ($AUTO_ENCODE and $self->suggest_encoding($type)) ||
+ 'binary');
+ $self->attr('content-transfer-encoding' => lc($enc));
+
+ ### Sanity check:
+ if ($type =~ m{^(multipart|message)/}) {
+ ($enc =~ m{^(7bit|8bit|binary)\Z}) or
+ croak "illegal MIME: can't have encoding $enc with type $type\n";
+ }
+
+ ### CONTENT-DISPOSITION...
+ ### Default is inline for single, none for multis:
+ ###
+ my $disp = ($params{Disposition} or ($is_multipart ? undef : 'inline'));
+ $self->attr('content-disposition' => $disp);
+
+ ### CONTENT-LENGTH...
+ ###
+ my $length;
+ if (exists($params{Length})) { ### given by caller:
+ $self->attr('content-length' => $params{Length});
+ }
+ else { ### compute it ourselves
+ $self->get_length;
+ }
+
+ ### Init the top-level fields:
+ my $is_top = defined($params{Top}) ? $params{Top} : 1;
+ $self->top_level($is_top);
+
+ ### Datestamp if desired:
+ my $ds_wanted = $params{Datestamp};
+ my $ds_defaulted = ($is_top and !exists($params{Datestamp}));
+ if (($ds_wanted or $ds_defaulted) and !exists($params{Date})) {
+ my ($u_wdy, $u_mon, $u_mdy, $u_time, $u_y4) =
+ split /\s+/, gmtime().""; ### should be non-locale-dependent
+ my $date = "$u_wdy, $u_mdy $u_mon $u_y4 $u_time UT";
+ $self->add("date", $date);
+ }
+
+ ### Set message headers:
+ my @paramz = @params;
+ my $field;
+ while (@paramz) {
+ my ($tag, $value) = (shift(@paramz), shift(@paramz));
+
+ ### Get tag, if a tag:
+ if ($tag =~ /^-(.*)/) { ### old style, backwards-compatibility
+ $field = lc($1);
+ }
+ elsif ($tag =~ /^(.*):$/) { ### new style
+ $field = lc($1);
+ }
+ elsif (known_field($field = lc($tag))) { ### known field
+ ### no-op
+ }
+ else { ### not a field:
+ next;
+ }
+
+ ### Add it:
+ $self->add($field, $value);
+ }
+
+ ### Done!
+ $self;
+}
+
+=back
+
+=cut
+
+
+#==============================
+#==============================
+
+=head2 Setting/getting headers and attributes
+
+=over 4
+
+=cut
+
+#------------------------------
+#
+# top_level ONOFF
+#
+# Set/unset the top-level attributes and headers.
+# This affects "MIME-Version" and "X-Mailer".
+
+sub top_level {
+ my ($self, $onoff) = @_;
+ if ($onoff) {
+ $self->attr('MIME-Version' => '1.0');
+ my $uses = (@Uses ? ("(" . join("; ", @Uses) . ")") : '');
+ $self->replace('X-Mailer' => "MIME::Lite $VERSION $uses")
+ unless $VANILLA;
+ }
+ else {
+ $self->attr('MIME-Version' => undef);
+ $self->delete('X-Mailer');
+ }
+}
+
+#------------------------------
+
+=item add TAG,VALUE
+
+I<Instance method.>
+Add field TAG with the given VALUE to the end of the header.
+The TAG will be converted to all-lowercase, and the VALUE
+will be made "safe" (returns will be given a trailing space).
+
+B<Beware:> any MIME fields you "add" will override any MIME
+attributes I have when it comes time to output those fields.
+Normally, you will use this method to add I<non-MIME> fields:
+
+ $msg->add("Subject" => "Hi there!");
+
+Giving VALUE as an arrayref will cause all those values to be added.
+This is only useful for special multiple-valued fields like "Received":
+
+ $msg->add("Received" => ["here", "there", "everywhere"]
+
+Giving VALUE as the empty string adds an invisible placeholder
+to the header, which can be used to suppress the output of
+the "Content-*" fields or the special "MIME-Version" field.
+When suppressing fields, you should use replace() instead of add():
+
+ $msg->replace("Content-disposition" => "");
+
+I<Note:> add() is probably going to be more efficient than C<replace()>,
+so you're better off using it for most applications if you are
+certain that you don't need to delete() the field first.
+
+I<Note:> the name comes from Mail::Header.
+
+=cut
+
+sub add {
+ my $self = shift;
+ my $tag = lc(shift);
+ my $value = shift;
+
+ ### If a dangerous option, warn them:
+ carp "Explicitly setting a MIME header field ($tag) is dangerous:\n".
+ "use the attr() method instead.\n"
+ if (is_mime_field($tag) && !$QUIET);
+
+ ### Get array of clean values:
+ my @vals = ((ref($value) and (ref($value) eq 'ARRAY'))
+ ? @{$value}
+ : ($value.''));
+ map { s/\n/\n /g } @vals;
+
+ ### Add them:
+ foreach (@vals) {
+ push @{$self->{Header}}, [$tag, $_];
+ }
+}
+
+#------------------------------
+
+=item attr ATTR,[VALUE]
+
+I<Instance method.>
+Set MIME attribute ATTR to the string VALUE.
+ATTR is converted to all-lowercase.
+This method is normally used to set/get MIME attributes:
+
+ $msg->attr("content-type" => "text/html");
+ $msg->attr("content-type.charset" => "US-ASCII");
+ $msg->attr("content-type.name" => "homepage.html");
+
+This would cause the final output to look something like this:
+
+ Content-type: text/html; charset=US-ASCII; name="homepage.html"
+
+Note that the special empty sub-field tag indicates the anonymous
+first sub-field.
+
+Giving VALUE as undefined will cause the contents of the named
+subfield to be deleted.
+
+Supplying no VALUE argument just returns the attribute's value:
+
+ $type = $msg->attr("content-type"); ### returns "text/html"
+ $name = $msg->attr("content-type.name"); ### returns "homepage.html"
+
+=cut
+
+sub attr {
+ my ($self, $attr, $value) = @_;
+ $attr = lc($attr);
+
+ ### Break attribute name up:
+ my ($tag, $subtag) = split /\./, $attr;
+ defined($subtag) or $subtag = '';
+
+ ### Set or get?
+ if (@_ > 2) { ### set:
+ $self->{Attrs}{$tag} ||= {}; ### force hash
+ delete $self->{Attrs}{$tag}{$subtag}; ### delete first
+ if (defined($value)) { ### set...
+ $value =~ s/[\r\n]//g; ### make clean
+ $self->{Attrs}{$tag}{$subtag} = $value;
+ }
+ }
+
+ ### Return current value:
+ $self->{Attrs}{$tag}{$subtag};
+}
+
+sub _safe_attr {
+ my ($self, $attr) = @_;
+ my $v = $self->attr($attr);
+ defined($v) ? $v : '';
+}
+
+#------------------------------
+
+=item delete TAG
+
+I<Instance method.>
+Delete field TAG with the given VALUE to the end of the header.
+The TAG will be converted to all-lowercase.
+
+ $msg->delete("Subject");
+
+I<Note:> the name comes from Mail::Header.
+
+=cut
+
+sub delete {
+ my $self = shift;
+ my $tag = lc(shift);
+
+ ### Delete from the header:
+ my $hdr = [];
+ my $field;
+ foreach $field (@{$self->{Header}}) {
+ push @$hdr, $field if ($field->[0] ne $tag);
+ }
+ $self->{Header} = $hdr;
+ $self;
+}
+
+
+#------------------------------
+
+=item field_order FIELD,...FIELD
+
+I<Class/instance method.>
+Change the order in which header fields are output for this object:
+
+ $msg->field_order('from', 'to', 'content-type', 'subject');
+
+When used as a class method, changes the default settings for
+all objects:
+
+ MIME::Lite->field_order('from', 'to', 'content-type', 'subject');
+
+Case does not matter: all field names will be coerced to lowercase.
+In either case, supply the empty array to restore the default ordering.
+
+=cut
+
+sub field_order {
+ my $self = shift;
+ if (ref($self)) { $self->{FieldOrder} = [ map { lc($_) } @_ ] }
+ else { @FieldOrder = map { lc($_) } @_ }
+}
+
+#------------------------------
+
+=item fields
+
+I<Instance method.>
+Return the full header for the object, as a ref to an array
+of C<[TAG, VALUE]> pairs, where each TAG is all-lowercase.
+Note that any fields the user has explicitly set will override the
+corresponding MIME fields that we would otherwise generate.
+So, don't say...
+
+ $msg->set("Content-type" => "text/html; charset=US-ASCII");
+
+unless you want the above value to override the "Content-type"
+MIME field that we would normally generate.
+
+I<Note:> I called this "fields" because the header() method of
+Mail::Header returns something different, but similar enough to
+be confusing.
+
+You can change the order of the fields: see L</header_order>.
+You really shouldn't need to do this, but some people have to
+deal with broken mailers.
+
+=cut
+
+sub fields {
+ my $self = shift;
+ my @fields;
+
+ ### Get a lookup-hash of all *explicitly-given* fields:
+ my %explicit = map { $_->[0] => 1 } @{$self->{Header}};
+
+ ### Start with any MIME attributes not given explicitly:
+ my $tag;
+ foreach $tag (sort keys %{$self->{Attrs}}) {
+
+ ### Skip if explicit:
+ next if ($explicit{$tag});
+
+ ### Skip if no subtags:
+ my @subtags = keys %{$self->{Attrs}{$tag}};
+ @subtags or next;
+
+ ### Create string:
+ my $value;
+ defined($value = $self->{Attrs}{$tag}{''}) or next; ### need default
+ foreach (sort @subtags) {
+ next if ($_ eq '');
+ $value .= qq{; $_="$self->{Attrs}{$tag}{$_}"};
+ }
+
+ ### Add to running fields;
+ push @fields, [$tag, $value];
+ }
+
+ ### Add remaining fields (note that we duplicate the array for safety):
+ foreach (@{$self->{Header}}) {
+ push @fields, [@{$_}];
+ }
+
+ ### Final step:
+ ### If a suggested ordering was given, we "sort" by that ordering.
+ ### The idea is that we give each field a numeric rank, which is
+ ### (1000 * order(field)) + origposition.
+ my @order = @{$self->{FieldOrder} || []}; ### object-specific
+ @order or @order = @FieldOrder; ### no? maybe generic
+ if (@order) { ### either?
+
+ ### Create hash mapping field names to 1-based rank:
+ my %rank = map {$order[$_] => (1+$_)} (0..$#order);
+
+ ### Create parallel array to @fields, called @ranked.
+ ### It contains fields tagged with numbers like 2003, where the
+ ### 3 is the original 0-based position, and 2000 indicates that
+ ### we wanted ths type of field to go second.
+ my @ranked = map {
+ [
+ ($_ + 1000*($rank{lc($fields[$_][0])} || (2+$#order))),
+ $fields[$_]
+ ]
+ } (0..$#fields);
+ # foreach (@ranked) {
+ # print STDERR "RANKED: $_->[0] $_->[1][0] $_->[1][1]\n";
+ # }
+
+ ### That was half the Schwartzian transform. Here's the rest:
+ @fields = map { $_->[1] }
+ sort { $a->[0] <=> $b->[0] }
+ @ranked;
+ }
+
+ ### Done!
+ return \@fields;
+}
+
+
+#------------------------------
+
+=item filename [FILENAME]
+
+I<Instance method.>
+Set the filename which this data will be reported as.
+This actually sets both "standard" attributes.
+
+With no argument, returns the filename as dictated by the
+content-disposition.
+
+=cut
+
+sub filename {
+ my ($self, $filename) = @_;
+ if (@_ > 1) {
+ $self->attr('content-type.name' => $filename);
+ $self->attr('content-disposition.filename' => $filename);
+ }
+ $self->attr('content-disposition.filename');
+}
+
+#------------------------------
+
+=item get TAG,[INDEX]
+
+I<Instance method.>
+Get the contents of field TAG, which might have been set
+with set() or replace(). Returns the text of the field.
+
+ $ml->get('Subject', 0);
+
+If the optional 0-based INDEX is given, then we return the INDEX'th
+occurence of field TAG. Otherwise, we look at the context:
+In a scalar context, only the first (0th) occurence of the
+field is returned; in an array context, I<all> occurences are returned.
+
+I<Warning:> this should only be used with non-MIME fields.
+Behavior with MIME fields is TBD, and will raise an exception for now.
+
+=cut
+
+sub get {
+ my ($self, $tag, $index) = @_;
+ $tag = lc($tag);
+ croak "get: can't be used with MIME fields\n" if is_mime_field($tag);
+
+ my @all = map { ($_->[0] eq $tag) ? $_->[1] : ()} @{$self->{Header}};
+ (defined($index) ? $all[$index] : (wantarray ? @all : $all[0]));
+}
+
+#------------------------------
+
+=item get_length
+
+I<Instance method.>
+Recompute the content length for the message I<if the process is trivial>,
+setting the "content-length" attribute as a side-effect:
+
+ $msg->get_length;
+
+Returns the length, or undefined if not set.
+
+I<Note:> the content length can be difficult to compute, since it
+involves assembling the entire encoded body and taking the length
+of it (which, in the case of multipart messages, means freezing
+all the sub-parts, etc.).
+
+This method only sets the content length to a defined value if the
+message is a singlepart with C<"binary"> encoding, I<and> the body is
+available either in-core or as a simple file. Otherwise, the content
+length is set to the undefined value.
+
+Since content-length is not a standard MIME field anyway (that's right, kids:
+it's not in the MIME RFCs, it's an HTTP thing), this seems pretty fair.
+
+=cut
+
+#----
+# Miko's note: I wasn't quite sure how to handle this, so I waited to hear
+# what you think. Given that the content-length isn't always required,
+# and given the performance cost of calculating it from a file handle,
+# I thought it might make more sense to add some some sort of computelength
+# property. If computelength is false, then the length simply isn't
+# computed. What do you think?
+#
+# Eryq's reply: I agree; for now, we can silently leave out the content-type.
+
+sub get_length {
+ my $self = shift;
+
+ my $is_multipart = ($self->attr('content-type') =~ m{^multipart/}i);
+ my $enc = lc($self->attr('content-transfer-encoding') || 'binary');
+ my $length;
+ if (!$is_multipart && ($enc eq "binary")){ ### might figure it out cheap:
+ if (defined($self->{Data})) { ### it's in core
+ $length = length($self->{Data});
+ }
+ elsif (defined($self->{FH})) { ### it's in a filehandle
+ ### no-op: it's expensive, so don't bother
+ }
+ elsif (defined($self->{Path})) { ### it's a simple file!
+ $length = (-s $self->{Path}) if (-e $self->{Path});
+ }
+ }
+ $self->attr('content-length' => $length);
+ return $length;
+}
+
+#------------------------------
+
+=item replace TAG,VALUE
+
+I<Instance method.>
+Delete all occurences of fields named TAG, and add a new
+field with the given VALUE. TAG is converted to all-lowercase.
+
+B<Beware> the special MIME fields (MIME-version, Content-*):
+if you "replace" a MIME field, the replacement text will override
+the I<actual> MIME attributes when it comes time to output that field.
+So normally you use attr() to change MIME fields and add()/replace() to
+change I<non-MIME> fields:
+
+ $msg->replace("Subject" => "Hi there!");
+
+Giving VALUE as the I<empty string> will effectively I<prevent> that
+field from being output. This is the correct way to suppress
+the special MIME fields:
+
+ $msg->replace("Content-disposition" => "");
+
+Giving VALUE as I<undefined> will just cause all explicit values
+for TAG to be deleted, without having any new values added.
+
+I<Note:> the name of this method comes from Mail::Header.
+
+=cut
+
+sub replace {
+ my ($self, $tag, $value) = @_;
+ $self->delete($tag);
+ $self->add($tag, $value) if defined($value);
+}
+
+
+#------------------------------
+
+=item scrub
+
+I<Instance method.>
+B<This is Alpha code. If you use it, please let me know how it goes.>
+Recursively goes through the "parts" tree of this message and tries
+to find MIME attributes that can be removed.
+With an array argument, removes exactly those attributes; e.g.:
+
+ $msg->scrub(['content-disposition', 'content-length']);
+
+Is the same as recursively doing:
+
+ $msg->replace('Content-disposition' => '');
+ $msg->replace('Content-length' => '');
+
+=cut
+
+sub scrub {
+ my ($self, @a) = @_;
+ my ($expl) = @a;
+ local $QUIET = 1;
+
+ ### Scrub me:
+ if (!@a) { ### guess
+
+ ### Scrub length always:
+ $self->replace('content-length', '');
+
+ ### Scrub disposition if no filename, or if content-type has same info:
+ if (!$self->_safe_attr('content-disposition.filename') ||
+ $self->_safe_attr('content-type.name')) {
+ $self->replace('content-disposition', '');
+ }
+
+ ### Scrub encoding if effectively unencoded:
+ if ($self->_safe_attr('content-transfer-encoding') =~
+ /^(7bit|8bit|binary)$/i) {
+ $self->replace('content-transfer-encoding', '');
+ }
+
+ ### Scrub charset if US-ASCII:
+ if ($self->_safe_attr('content-type.charset') =~ /^(us-ascii)/i) {
+ $self->attr('content-type.charset' => undef);
+ }
+
+ ### TBD: this is not really right for message/digest:
+ if ((keys %{$self->{Attrs}{'content-type'}} == 1) and
+ ($self->_safe_attr('content-type') eq 'text/plain')) {
+ $self->replace('content-type', '');
+ }
+ }
+ elsif ($expl and (ref($expl) eq 'ARRAY')) {
+ foreach (@{$expl}) { $self->replace($_, ''); }
+ }
+
+ ### Scrub my kids:
+ foreach (@{$self->{Parts}}) { $_->scrub(@a); }
+}
+
+=back
+
+=cut
+
+
+#==============================
+#==============================
+
+=head2 Setting/getting message data
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item binmode [OVERRIDE]
+
+I<Instance method.>
+With no argument, returns whether or not it thinks that the data
+(as given by the "Path" argument of C<build()>) should be read using
+binmode() (for example, when C<read_now()> is invoked).
+
+The default behavior is that any content type other than
+C<text/*> or C<message/*> is binmode'd; this should in general work fine.
+
+With a defined argument, this method sets an explicit "override"
+value. An undefined argument unsets the override.
+The new current value is returned.
+
+=cut
+
+sub binmode {
+ my $self = shift;
+ $self->{Binmode} = shift if (@_); ### argument? set override
+ return (defined($self->{Binmode})
+ ? $self->{Binmode}
+ : ($self->attr("content-type") !~ m{^(text|message)/}i));
+}
+
+#------------------------------
+
+=item data [DATA]
+
+I<Instance method.>
+Get/set the literal DATA of the message. The DATA may be
+either a scalar, or a reference to an array of scalars (which
+will simply be joined).
+
+I<Warning:> setting the data causes the "content-length" attribute
+to be recomputed (possibly to nothing).
+
+=cut
+
+sub data {
+ my $self = shift;
+ if (@_) {
+ $self->{Data} = ((ref($_[0]) eq 'ARRAY') ? join('', @{$_[0]}) : $_[0]);
+ $self->get_length;
+ }
+ $self->{Data};
+}
+
+
+#------------------------------
+
+=item path [PATH]
+
+Get/set the PATH to the message data.
+
+I<Warning:> setting the path recomputes any existing "content-length" field,
+and re-sets the "filename" (to the last element of the path if it
+looks like a simple path, and to nothing if not).
+
+=cut
+
+sub path {
+ my $self = shift;
+ if (@_) {
+
+ ### Set the path, and invalidate the content length:
+ $self->{Path} = shift;
+
+ ### Re-set filename, extracting it from path if possible:
+ my $filename;
+ if ($self->{Path} and ($self->{Path} !~ /\|$/)) { ### non-shell path:
+ ($filename = $self->{Path}) =~ s/^<//;
+ ($filename) = ($filename =~ m{([^\/]+)\Z});
+ }
+ $self->filename($filename);
+
+ ### Reset the length:
+ $self->get_length;
+ }
+ $self->{Path};
+}
+
+#------------------------------
+
+=item fh [FILEHANDLE]
+
+Get/set the FILEHANDLE which contains the message data.
+
+Takes a filehandle as an input and stores it in the object.
+This routine is similar to path(); one important difference is that
+no attempt is made to set the content length.
+
+=cut
+
+sub fh {
+ my $self = shift;
+ $self->{FH} = shift if @_;
+ $self->{FH};
+}
+
+#------------------------------
+
+=item resetfh [FILEHANDLE]
+
+Set the current position of the filehandle back to the beginning.
+Only applies if you used "FH" in build() or attach() for this message.
+
+Returns false if unable to reset the filehandle (since not all filehandles
+are seekable).
+
+=cut
+
+#----
+# Miko's note: With the Data and Path, the same data could theoretically
+# be reused. However, file handles need to be reset to be reused,
+# so I added this routine.
+#
+# Eryq reply: beware... not all filehandles are seekable (think about STDIN)!
+
+sub resetfh {
+ my $self = shift;
+ seek($self->{FH},0,0);
+}
+
+#------------------------------
+
+=item read_now
+
+Forces data from the path/filehandle (as specified by C<build()>)
+to be read into core immediately, just as though you had given it
+literally with the C<Data> keyword.
+
+Note that the in-core data will always be used if available.
+
+Be aware that everything is slurped into a giant scalar: you may not want
+to use this if sending tar files! The benefit of I<not> reading in the data
+is that very large files can be handled by this module if left on disk
+until the message is output via C<print()> or C<print_body()>.
+
+=cut
+
+sub read_now {
+ my $self = shift;
+ local $/ = undef;
+
+ if ($self->{FH}) { ### data from a filehandle:
+ my $chunk;
+ my @chunks;
+ CORE::binmode($self->{FH}) if $self->binmode;
+ while (read($self->{FH}, $chunk, 1024)) {
+ push @chunks, $chunk;
+ }
+ $self->{Data} = join '', @chunks;
+ }
+ elsif ($self->{Path}) { ### data from a path:
+ open SLURP, $self->{Path} or croak "open $self->{Path}: $!\n";
+ CORE::binmode(SLURP) if $self->binmode;
+ $self->{Data} = <SLURP>; ### sssssssssssssslurp...
+ close SLURP; ### ...aaaaaaaaahhh!
+ }
+}
+
+#------------------------------
+
+=item sign PARAMHASH
+
+Sign the message. This forces the message to be read into core,
+after which the signature is appended to it.
+
+=over 4
+
+=item Data
+
+As in C<build()>: the literal signature data.
+Can be either a scalar or a ref to an array of scalars.
+
+=item Path
+
+As in C<build()>: the path to the file.
+
+=back
+
+If no arguments are given, the default is:
+
+ Path => "$ENV{HOME}/.signature"
+
+The content-length is recomputed.
+
+=cut
+
+sub sign {
+ my $self = shift;
+ my %params = @_;
+
+ ### Default:
+ @_ or $params{Path} = "$ENV{HOME}/.signature";
+
+ ### Force message in-core:
+ defined($self->{Data}) or $self->read_now;
+
+ ### Load signature:
+ my $sig;
+ if (!defined($sig = $params{Data})) { ### not given explicitly:
+ local $/ = undef;
+ open SIG, $params{Path} or croak "open sig $params{Path}: $!\n";
+ $sig = <SIG>; ### sssssssssssssslurp...
+ close SIG; ### ...aaaaaaaaahhh!
+ }
+ $sig = join('',@$sig) if (ref($sig) and (ref($sig) eq 'ARRAY'));
+
+ ### Append, following Internet conventions:
+ $self->{Data} .= "\n-- \n$sig";
+
+ ### Re-compute length:
+ $self->get_length;
+ 1;
+}
+
+#------------------------------
+#
+# =item suggest_encoding CONTENTTYPE
+#
+# I<Class/instance method.>
+# Based on the CONTENTTYPE, return a good suggested encoding.
+# C<text> and C<message> types have their bodies scanned line-by-line
+# for 8-bit characters and long lines; lack of either means that the
+# message is 7bit-ok. Other types are chosen independent of their body:
+#
+# Major type: 7bit ok? Suggested encoding:
+# ------------------------------------------------------------
+# text yes 7bit
+# no quoted-printable
+# unknown binary
+#
+# message yes 7bit
+# no binary
+# unknown binary
+#
+# multipart n/a binary (in case some parts are not ok)
+#
+# (other) n/a base64
+#
+#=cut
+
+sub suggest_encoding {
+ my ($self, $ctype) = @_;
+
+ my ($type) = split '/', lc($ctype);
+ if (($type eq 'text') || ($type eq 'message')) { ### scan message body
+ return 'binary';
+ }
+ else {
+ return ($type eq 'multipart') ? 'binary' : 'base64';
+ }
+}
+
+#------------------------------
+
+=item verify_data
+
+I<Instance method.>
+Verify that all "paths" to attached data exist, recursively.
+It might be a good idea for you to do this before a print(), to
+prevent accidental partial output if a file might be missing.
+Raises exception if any path is not readable.
+
+=cut
+
+sub verify_data {
+ my $self = shift;
+
+ ### Verify self:
+ my $path = $self->{Path};
+ if ($path and ($path !~ /\|$/)) { ### non-shell path:
+ $path =~ s/^<//;
+ (-r $path) or die "$path: not readable\n";
+ }
+
+ ### Verify parts:
+ foreach my $part (@{$self->{Parts}}) { $part->verify_data }
+ 1;
+}
+
+=back
+
+=cut
+
+
+#==============================
+#==============================
+
+=head2 Output
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item print [OUTHANDLE]
+
+I<Instance method.>
+Print the message to the given output handle, or to the currently-selected
+filehandle if none was given.
+
+All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+=cut
+
+sub print {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Output head, separator, and body:
+ $out->print($self->header_as_string, "\n");
+ $self->print_body($out);
+}
+
+#------------------------------
+#
+# print_for_smtp
+#
+# Instance method, private.
+# Print, but filter out the topmost "Bcc" field.
+# This is because qmail apparently doesn't do this for us!
+#
+sub print_for_smtp {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Create a safe head:
+ my @fields = grep { $_->[0] ne 'bcc' } @{$self->fields};
+ my $header = $self->fields_as_string(\@fields);
+
+ ### Output head, separator, and body:
+ $out->print($header, "\n");
+ $self->print_body($out);
+}
+
+#------------------------------
+
+=item print_body [OUTHANDLE]
+
+I<Instance method.>
+Print the body of a message to the given output handle, or to
+the currently-selected filehandle if none was given.
+
+All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+B<Fatal exception> raised if unable to open any of the input files,
+or if a part contains no data, or if an unsupported encoding is
+encountered.
+
+=cut
+
+sub print_body {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Output either the body or the parts.
+ ### Notice that we key off of the content-type! We expect fewer
+ ### accidents that way, since the syntax will always match the MIME type.
+ my $type = $self->attr('content-type');
+ if ($type =~ m{^multipart/}i) {
+ my $boundary = $self->attr('content-type.boundary');
+
+ ### Preamble:
+ $out->print("This is a multi-part message in MIME format.\n");
+
+ ### Parts:
+ my $part;
+ foreach $part (@{$self->{Parts}}) {
+ $out->print("\n--$boundary\n");
+ $part->print($out);
+ }
+
+ ### Epilogue:
+ $out->print("\n--$boundary--\n\n");
+ }
+ elsif ($type =~ m{^message/}) {
+ my @parts = @{$self->{Parts}};
+
+ ### It's a toss-up; try both data and parts:
+ if (@parts == 0) { $self->print_simple_body($out) }
+ elsif (@parts == 1) { $parts[0]->print($out) }
+ else { croak "can't handle message with >1 part\n"; }
+ }
+ else {
+ $self->print_simple_body($out);
+ }
+ 1;
+}
+
+#------------------------------
+#
+# print_simple_body [OUTHANDLE]
+#
+# I<Instance method, private.>
+# Print the body of a simple singlepart message to the given
+# output handle, or to the currently-selected filehandle if none
+# was given.
+#
+# Note that if you want to print "the portion after
+# the header", you don't want this method: you want
+# L<print_body()|/print_body>.
+#
+# All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+# any object that responds to a print() message.
+#
+# B<Fatal exception> raised if unable to open any of the input files,
+# or if a part contains no data, or if an unsupported encoding is
+# encountered.
+#
+sub print_simple_body {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Get content-transfer-encoding:
+ my $encoding = uc($self->attr('content-transfer-encoding'));
+
+ ### Notice that we don't just attempt to slurp the data in from a file:
+ ### by processing files piecemeal, we still enable ourselves to prepare
+ ### very large MIME messages...
+
+ ### Is the data in-core? If so, blit it out...
+ if (defined($self->{Data})) {
+ DATA:
+ { local $_ = $encoding;
+
+ /^BINARY$/ and do {
+ $out->print($self->{Data});
+ last DATA;
+ };
+ /^8BIT$/ and do {
+ $out->print(encode_8bit($self->{Data}));
+ last DATA;
+ };
+ /^7BIT$/ and do {
+ $out->print(encode_7bit($self->{Data}));
+ last DATA;
+ };
+ /^QUOTED-PRINTABLE$/ and do {
+ ### UNTAINT since m//mg on tainted data loops forever:
+ my ($untainted) = ($self->{Data} =~ m/\A(.*)\Z/s);
+
+ ### Encode it line by line:
+ while ($untainted =~ m{^(.*[\r\n]*)}mg) {
+ $out->print(encode_qp($1)); ### have to do it line by line...
+ }
+ last DATA;
+ };
+ /^BASE64/ and do {
+ $out->print(encode_base64($self->{Data}));
+ last DATA;
+ };
+ croak "unsupported encoding: `$_'\n";
+ }
+ }
+
+ ### Else, is the data in a file? If so, output piecemeal...
+ ### Miko's note: this routine pretty much works the same with a path
+ ### or a filehandle. the only difference in behaviour is that it does
+ ### not attempt to open anything if it already has a filehandle
+ elsif (defined($self->{Path}) || defined($self->{FH})) {
+ no strict 'refs'; ### in case FH is not an object
+ my $DATA;
+
+ ### Open file if necessary:
+ if (defined($self->{Path})) {
+ $DATA = new FileHandle || croak "can't get new filehandle\n";
+ $DATA->open("$self->{Path}") or croak "open $self->{Path}: $!\n";
+ }
+ else {
+ $DATA=$self->{FH};
+ }
+ CORE::binmode($DATA) if $self->binmode;
+
+ ### Encode piece by piece:
+ PATH:
+ { local $_ = $encoding;
+
+ /^BINARY$/ and do {
+ $out->print($_) while read($DATA, $_, 2048);
+ last PATH;
+ };
+ /^8BIT$/ and do {
+ $out->print(encode_8bit($_)) while (<$DATA>);
+ last PATH;
+ };
+ /^7BIT$/ and do {
+ $out->print(encode_7bit($_)) while (<$DATA>);
+ last PATH;
+ };
+ /^QUOTED-PRINTABLE$/ and do {
+ $out->print(encode_qp($_)) while (<$DATA>);
+ last PATH;
+ };
+ /^BASE64$/ and do {
+ $out->print(encode_base64($_)) while (read($DATA, $_, 45));
+ last PATH;
+ };
+ croak "unsupported encoding: `$_'\n";
+ }
+
+ ### Close file:
+ close $DATA if defined($self->{Path});
+ }
+
+ else {
+ croak "no data in this part\n";
+ }
+ 1;
+}
+
+#------------------------------
+
+=item print_header [OUTHANDLE]
+
+I<Instance method.>
+Print the header of the message to the given output handle,
+or to the currently-selected filehandle if none was given.
+
+All OUTHANDLE has to be is a filehandle (possibly a glob ref), or
+any object that responds to a print() message.
+
+=cut
+
+sub print_header {
+ my ($self, $out) = @_;
+
+ ### Coerce into a printable output handle:
+ $out = wrap MIME::Lite::IO_Handle $out;
+
+ ### Output the header:
+ $out->print($self->header_as_string);
+ 1;
+}
+
+#------------------------------
+
+=item as_string
+
+I<Instance method.>
+Return the entire message as a string, with a header and an encoded body.
+
+=cut
+
+sub as_string {
+ my $self = shift;
+ my @buf;
+ my $io = (wrap MIME::Lite::IO_ScalarArray \@buf);
+ $self->print($io);
+ join '', @buf;
+}
+*stringify = \&as_string; ### backwards compatibility
+
+#------------------------------
+
+=item body_as_string
+
+I<Instance method.>
+Return the encoded body as a string.
+This is the portion after the header and the blank line.
+
+I<Note:> actually prepares the body by "printing" to a scalar.
+Proof that you can hand the C<print*()> methods any blessed object
+that responds to a C<print()> message.
+
+=cut
+
+sub body_as_string {
+ my $self = shift;
+ my @buf;
+ my $io = (wrap MIME::Lite::IO_ScalarArray \@buf);
+ $self->print_body($io);
+ join '', @buf;
+}
+*stringify_body = \&body_as_string; ### backwards compatibility
+
+#------------------------------
+#
+# fields_as_string FIELDS
+#
+# PRIVATE! Return a stringified version of the given header
+# fields, where FIELDS is an arrayref like that returned by fields().
+#
+sub fields_as_string {
+ my ($self, $fields) = @_;
+ my @lines;
+ foreach (@$fields) {
+ my ($tag, $value) = @$_;
+ next if ($value eq ''); ### skip empties
+ $tag =~ s/\b([a-z])/uc($1)/ge; ### make pretty
+ $tag =~ s/^mime-/MIME-/ig; ### even prettier
+ push @lines, "$tag: $value\n";
+ }
+ join '', @lines;
+}
+
+#------------------------------
+
+=item header_as_string
+
+I<Instance method.>
+Return the header as a string.
+
+=cut
+
+sub header_as_string {
+ my $self = shift;
+ $self->fields_as_string($self->fields);
+}
+*stringify_header = \&header_as_string; ### backwards compatibility
+
+=back
+
+=cut
+
+
+
+#==============================
+#==============================
+
+=head2 Sending
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item send
+
+=item send HOW, HOWARGS...
+
+I<Class/instance method.>
+This is the principal method for sending mail, and for configuring
+how mail will be sent.
+
+I<As an instance method> (with no arguments), sends the message by whatever
+means has been set up (the default is to use the Unix "sendmail" program).
+Returns whatever the mail-handling routine returns: this should be true
+on success, false/exception on error:
+
+ $msg = MIME::Lite->new(From=>...);
+ $msg->send || die "you DON'T have mail!";
+
+I<As a class method> (with a HOW argument and optional HOWARGS), sets up
+how the instance method will work for all objects until further notice
+It treats HOW as a facility name, with optional HOWARGS handled by
+the facility (and returns the previous HOW and HOWARGS as an array).
+There are three facilities:
+
+=over 4
+
+=item "sendmail", ARGS...
+
+Send a message by piping it into the "sendmail" command.
+Uses the L<send_by_sendmail()|/send_by_sendmail> method, giving it the ARGS.
+This usage implements (and deprecates) the C<sendmail()> method.
+
+=item "smtp", [HOSTNAME]
+
+Send a message by SMTP, using optional HOSTNAME as SMTP-sending host.
+Uses the L<send_by_smtp()|/send_by_smtp> method.
+
+=item "sub", \&SUBREF, ARGS...
+
+Sends a message MSG by invoking the subroutine SUBREF of your choosing,
+with MSG as the first argument, and ARGS following.
+
+=back
+
+I<For example:> let's say you're on an OS which lacks the usual Unix
+"sendmail" facility, but you've installed something a lot like it, and
+you need to configure your Perl script to use this "sendmail.exe" program.
+Do this following in your script's setup:
+
+ MIME::Lite->send('sendmail', "d:\\programs\\sendmail.exe");
+
+Then, whenever you need to send a message $msg, just say:
+
+ $msg->send;
+
+That's it. Now, if you ever move your script to a Unix box, all you
+need to do is change that line in the setup and you're done.
+All of your $msg-E<gt>send invocations will work as expected.
+
+=cut
+
+sub send {
+ my $self = shift;
+
+ if (ref($self)) { ### instance method:
+ my $method = "send_by_$Sender";
+ my @args = @{$SenderArgs{$Sender} || []};
+ $self->verify_data if $AUTO_VERIFY; ### prevents missing parts!
+ return $self->$method(@args);
+ }
+ else { ### class method:
+ my @old = ($Sender, @{$SenderArgs{$Sender}});
+ $Sender = shift;
+ $SenderArgs{$Sender} = [@_]; ### remaining args
+ return @old;
+ }
+}
+
+#------------------------------
+
+=item send_by_sendmail SENDMAILCMD
+
+=item send_by_sendmail PARAM=>VALUE, ...
+
+I<Instance method.>
+Send message via an external "sendmail" program
+(this will probably only work out-of-the-box on Unix systems).
+
+Returns true on success, false or exception on error.
+
+You can specify the program and all its arguments by giving a single
+string, SENDMAILCMD. Nothing fancy is done; the message is simply
+piped in.
+
+However, if your needs are a little more advanced, you can specify
+zero or more of the following PARAM/VALUE pairs; a Unix-style,
+taint-safe "sendmail" command will be constructed for you:
+
+=over 4
+
+=item Sendmail
+
+Full path to the program to use.
+Default is "/usr/lib/sendmail".
+
+=item BaseArgs
+
+Ref to the basic array of arguments we start with.
+Default is C<["-t", "-oi", "-oem"]>.
+
+=item SetSender
+
+Unless this is I<explicitly> given as false, we attempt to automatically
+set the C<-f> argument to the first address that can be extracted from
+the "From:" field of the message (if there is one).
+
+I<What is the -f, and why do we use it?>
+Suppose we did I<not> use C<-f>, and you gave an explicit "From:"
+field in your message: in this case, the sendmail "envelope" would
+indicate the I<real> user your process was running under, as a way
+of preventing mail forgery. Using the C<-f> switch causes the sender
+to be set in the envelope as well.
+
+I<So when would I NOT want to use it?>
+If sendmail doesn't regard you as a "trusted" user, it will permit
+the C<-f> but also add an "X-Authentication-Warning" header to the message
+to indicate a forged envelope. To avoid this, you can either
+(1) have SetSender be false, or
+(2) make yourself a trusted user by adding a C<T> configuration
+ command to your I<sendmail.cf> file
+ (e.g.: C<Teryq> if the script is running as user "eryq").
+
+=item FromSender
+
+If defined, this is identical to setting SetSender to true,
+except that instead of looking at the "From:" field we use
+the address given by this option.
+Thus:
+
+ FromSender => 'me@myhost.com'
+
+=back
+
+=cut
+
+sub send_by_sendmail {
+ my $self = shift;
+
+ if (@_ == 1) { ### Use the given command...
+ my $sendmailcmd = shift @_;
+
+ ### Do it:
+ open SENDMAIL, "|$sendmailcmd" or croak "open |$sendmailcmd: $!\n";
+ $self->print(\*SENDMAIL);
+ close SENDMAIL;
+ return (($? >> 8) ? undef : 1);
+ }
+ else { ### Build the command...
+ my %p = @_;
+ $p{Sendmail} ||= "/usr/lib/sendmail";
+
+ ### Start with the command and basic args:
+ my @cmd = ($p{Sendmail}, @{$p{BaseArgs} || ['-t', '-oi', '-oem']});
+
+ ### See if we are forcibly setting the sender:
+ $p{SetSender} = 1 if defined($p{FromSender});
+
+ ### Add the -f argument, unless we're explicitly told NOT to:
+ unless (exists($p{SetSender}) and !$p{SetSender}) {
+ my $from = $p{FromSender} || ($self->get('From'))[0];
+ if ($from) {
+ my ($from_addr) = extract_addrs($from);
+ push @cmd, "-f$from_addr" if $from_addr;
+ }
+ }
+
+ ### Open the command in a taint-safe fashion:
+ my $pid = open SENDMAIL, "|-";
+ defined($pid) or die "open of pipe failed: $!\n";
+ if (!$pid) { ### child
+ exec(@cmd) or die "can't exec $p{Sendmail}: $!\n";
+ ### NOTREACHED
+ }
+ else { ### parent
+ $self->print(\*SENDMAIL);
+ close SENDMAIL || die "error closing $p{Sendmail}: $! (exit $?)\n";
+ return 1;
+ }
+ }
+}
+
+#------------------------------
+
+=item send_by_smtp ARGS...
+
+I<Instance method.>
+Send message via SMTP, using Net::SMTP.
+The optional ARGS are sent into Net::SMTP::new(): usually, these are
+
+ MAILHOST, OPTION=>VALUE, ...
+
+Note that the list of recipients is taken from the
+"To", "Cc" and "Bcc" fields.
+
+Returns true on success, false or exception on error.
+
+=cut
+
+### Provided by Andrew McRae. Version 0.2 anm 09Sep97
+### Copyright 1997 Optimation New Zealand Ltd.
+### May be modified/redistributed under the same terms as Perl.
+#
+sub send_by_smtp {
+ my ($self, @args) = @_;
+
+ ### We need the "From:" and "To:" headers to pass to the SMTP mailer:
+ my $hdr = $self->fields();
+ my $from = $self->get('From');
+ my $to = $self->get('To');
+
+ ### Sanity check:
+ defined($to) or croak "send_by_smtp: missing 'To:' address\n";
+
+ ### Get the destinations as a simple array of addresses:
+ my @to_all = extract_addrs($to);
+ if ($AUTO_CC) {
+ foreach my $field (qw(Cc Bcc)) {
+ my $value = $self->get($field);
+ push @to_all, extract_addrs($value) if defined($value);
+ }
+ }
+
+ ### Create SMTP client:
+ require Net::SMTP;
+ my $smtp = MIME::Lite::SMTP->new(@args)
+ or croak "Failed to connect to mail server: $!\n";
+ $smtp->mail($from)
+ or croak "SMTP MAIL command failed: $!\n";
+ $smtp->to(@to_all)
+ or croak "SMTP RCPT command failed: $!\n";
+ $smtp->data()
+ or croak "SMTP DATA command failed: $!\n";
+
+ ### MIME::Lite can print() to anything with a print() method:
+ $self->print_for_smtp($smtp);
+ $smtp->dataend();
+ $smtp->quit;
+ 1;
+}
+
+#------------------------------
+#
+# send_by_sub [\&SUBREF, [ARGS...]]
+#
+# I<Instance method, private.>
+# Send the message via an anonymous subroutine.
+#
+sub send_by_sub {
+ my ($self, $subref, @args) = @_;
+ &$subref($self, @args);
+}
+
+#------------------------------
+
+=item sendmail COMMAND...
+
+I<Class method, DEPRECATED.>
+Declare the sender to be "sendmail", and set up the "sendmail" command.
+I<You should use send() instead.>
+
+=cut
+
+sub sendmail {
+ my $self = shift;
+ $self->send('sendmail', join(' ', @_));
+}
+
+=back
+
+=cut
+
+
+
+#==============================
+#==============================
+
+=head2 Miscellaneous
+
+=over 4
+
+=cut
+
+#------------------------------
+
+=item quiet ONOFF
+
+I<Class method.>
+Suppress/unsuppress all warnings coming from this module.
+
+ MIME::Lite->quiet(1); ### I know what I'm doing
+
+I recommend that you include that comment as well. And while
+you type it, say it out loud: if it doesn't feel right, then maybe
+you should reconsider the whole line. C<;-)>
+
+=cut
+
+sub quiet {
+ my $class = shift;
+ $QUIET = shift if @_;
+ $QUIET;
+}
+
+=back
+
+=cut
+
+
+
+#============================================================
+
+package MIME::Lite::SMTP;
+
+#============================================================
+# This class just adds a print() method to Net::SMTP.
+# Notice that we don't use/require it until it's needed!
+
+use strict;
+use vars qw( @ISA );
+@ISA = qw(Net::SMTP);
+
+sub print { shift->datasend(@_) }
+
+
+
+#============================================================
+
+package MIME::Lite::IO_Handle;
+
+#============================================================
+
+### Wrap a non-object filehandle inside a blessed, printable interface:
+### Does nothing if the given $fh is already a blessed object.
+sub wrap {
+ my ($class, $fh) = @_;
+ no strict 'refs';
+
+ ### Get default, if necessary:
+ $fh or $fh = select; ### no filehandle means selected one
+ ref($fh) or $fh = \*$fh; ### scalar becomes a globref
+
+ ### Stop right away if already a printable object:
+ return $fh if (ref($fh) and (ref($fh) ne 'GLOB'));
+
+ ### Get and return a printable interface:
+ bless \$fh, $class; ### wrap it in a printable interface
+}
+
+### Print:
+sub print {
+ my $self = shift;
+ print {$$self} @_;
+}
+
+
+#============================================================
+
+package MIME::Lite::IO_Scalar;
+
+#============================================================
+
+### Wrap a scalar inside a blessed, printable interface:
+sub wrap {
+ my ($class, $scalarref) = @_;
+ defined($scalarref) or $scalarref = \"";
+ bless $scalarref, $class;
+}
+
+### Print:
+sub print {
+ my $self = shift;
+ $$self .= join('', @_);
+ 1;
+}
+
+
+#============================================================
+
+package MIME::Lite::IO_ScalarArray;
+
+#============================================================
+
+### Wrap an array inside a blessed, printable interface:
+sub wrap {
+ my ($class, $arrayref) = @_;
+ defined($arrayref) or $arrayref = [];
+ bless $arrayref, $class;
+}
+
+### Print:
+sub print {
+ my $self = shift;
+ push @$self, @_;
+ 1;
+}
+
+1;
+__END__
+
+
+#============================================================
+
+=head1 NOTES
+
+
+=head2 Benign limitations
+
+This is "lite", after all...
+
+=over 4
+
+=item *
+
+There's no parsing. Get MIME-tools if you need to parse MIME messages.
+
+=item *
+
+MIME::Lite messages are currently I<not> interchangeable with
+either Mail::Internet or MIME::Entity objects. This is a completely
+separate module.
+
+=item *
+
+A content-length field is only inserted if the encoding is binary,
+the message is a singlepart, and all the document data is available
+at C<build()> time by virtue of residing in a simple path, or in-core.
+Since content-length is not a standard MIME field anyway (that's right, kids:
+it's not in the MIME RFCs, it's an HTTP thing), this seems pretty fair.
+
+=item *
+
+MIME::Lite alone cannot help you lose weight. You must supplement
+your use of MIME::Lite with a healthy diet and exercise.
+
+=back
+
+
+=head2 Cheap and easy mailing
+
+I thought putting in a default "sendmail" invocation wasn't too bad an
+idea, since a lot of Perlers are on UNIX systems.
+The out-of-the-box configuration is:
+
+ MIME::Lite->send('sendmail', "/usr/lib/sendmail -t -oi -oem");
+
+By the way, these arguments to sendmail are:
+
+ -t Scan message for To:, Cc:, Bcc:, etc.
+
+ -oi Do NOT treat a single "." on a line as a message terminator.
+ As in, "-oi vey, it truncated my message... why?!"
+
+ -oem On error, mail back the message (I assume to the
+ appropriate address, given in the header).
+ When mail returns, circle is complete. Jai Guru Deva -oem.
+
+Note that these are the same arguments you get if you configure to use
+the smarter, taint-safe mailing:
+
+ MIME::Lite->send('sendmail');
+
+If you get "X-Authentication-Warning" headers from this, you can forgo
+diddling with the envelope by instead specifying:
+
+ MIME::Lite->send('sendmail', SetSender=>0);
+
+And, if you're not on a Unix system, or if you'd just rather send mail
+some other way, there's always:
+
+ MIME::Lite->send('smtp', "smtp.myisp.net");
+
+Or you can set up your own subroutine to call.
+In any case, check out the L<send()|/send> method.
+
+
+
+=head1 WARNINGS
+
+=head2 Good-vs-bad email addresses with send_by_smtp()
+
+If using L<send_by_smtp()|/send_by_smtp>, be aware that you are
+forcing MIME::Lite to extract email addresses out of a possible list
+provided in the C<To:>, C<Cc:>, and C<Bcc:> fields. This is tricky
+stuff, and as such only the following sorts of addresses will work
+reliably:
+
+ username
+ full.name@some.host.com
+ "Name, Full" <full.name@some.host.com>
+
+This last form is discouraged because SMTP must be able to get
+at the I<name> or I<name@domain> portion.
+
+B<Disclaimer:>
+MIME::Lite was never intended to be a Mail User Agent, so please
+don't expect a full implementation of RFC-822. Restrict yourself to
+the common forms of Internet addresses described herein, and you should
+be fine. If this is not feasible, then consider using MIME::Lite
+to I<prepare> your message only, and using Net::SMTP explicitly to
+I<send> your message.
+
+
+=head2 Formatting of headers delayed until print()
+
+This class treats a MIME header in the most abstract sense,
+as being a collection of high-level attributes. The actual
+RFC-822-style header fields are not constructed until it's time
+to actually print the darn thing.
+
+
+=head2 Encoding of data delayed until print()
+
+When you specify message bodies
+(in L<build()|/build> or L<attach()|/attach>) --
+whether by B<FH>, B<Data>, or B<Path> -- be warned that we don't
+attempt to open files, read filehandles, or encode the data until
+L<print()|/print> is invoked.
+
+In the past, this created some confusion for users of sendmail
+who gave the wrong path to an attachment body, since enough of
+the print() would succeed to get the initial part of the message out.
+Nowadays, $AUTO_VERIFY is used to spot-check the Paths given before
+the mail facility is employed. A whisker slower, but tons safer.
+
+Note that if you give a message body via FH, and try to print()
+a message twice, the second print() will not do the right thing
+unless you explicitly rewind the filehandle.
+
+You can get past these difficulties by using the B<ReadNow> option,
+provided that you have enough memory to handle your messages.
+
+
+=head2 MIME attributes are separate from header fields!
+
+B<Important:> the MIME attributes are stored and manipulated separately
+from the message header fields; when it comes time to print the
+header out, I<any explicitly-given header fields override the ones that
+would be created from the MIME attributes.> That means that this:
+
+ ### DANGER ### DANGER ### DANGER ### DANGER ### DANGER ###
+ $msg->add("Content-type", "text/html; charset=US-ASCII");
+
+will set the exact C<"Content-type"> field in the header I write,
+I<regardless of what the actual MIME attributes are.>
+
+I<This feature is for experienced users only,> as an escape hatch in case
+the code that normally formats MIME header fields isn't doing what
+you need. And, like any escape hatch, it's got an alarm on it:
+MIME::Lite will warn you if you attempt to C<set()> or C<replace()>
+any MIME header field. Use C<attr()> instead.
+
+
+=head2 Beware of lines consisting of a single dot
+
+Julian Haight noted that MIME::Lite allows you to compose messages
+with lines in the body consisting of a single ".".
+This is true: it should be completely harmless so long as "sendmail"
+is used with the -oi option (see L<"Cheap and easy mailing">).
+
+However, I don't know if using Net::SMTP to transfer such a message
+is equally safe. Feedback is welcomed.
+
+My perspective: I don't want to magically diddle with a user's
+message unless absolutely positively necessary.
+Some users may want to send files with "." alone on a line;
+my well-meaning tinkering could seriously harm them.
+
+
+=head2 Infinite loops may mean tainted data!
+
+Stefan Sautter noticed a bug in 2.106 where a m//gc match was
+failing due to tainted data, leading to an infinite loop inside
+MIME::Lite.
+
+I am attempting to correct for this, but be advised that my fix will
+silently untaint the data (given the context in which the problem
+occurs, this should be benign: I've labelled the source code with
+UNTAINT comments for the curious).
+
+So: don't depend on taint-checking to save you from outputting
+tainted data in a message.
+
+
+=head1 A MIME PRIMER
+
+=head2 Content types
+
+The "Type" parameter of C<build()> is a I<content type>.
+This is the actual type of data you are sending.
+Generally this is a string of the form C<"majortype/minortype">.
+
+Here are the major MIME types.
+A more-comprehensive listing may be found in RFC-2046.
+
+=over 4
+
+=item application
+
+Data which does not fit in any of the other categories, particularly
+data to be processed by some type of application program.
+C<application/octet-stream>, C<application/gzip>, C<application/postscript>...
+
+=item audio
+
+Audio data.
+C<audio/basic>...
+
+=item image
+
+Graphics data.
+C<image/gif>, C<image/jpeg>...
+
+=item message
+
+A message, usually another mail or MIME message.
+C<message/rfc822>...
+
+=item multipart
+
+A message containing other messages.
+C<multipart/mixed>, C<multipart/alternative>...
+
+=item text
+
+Textual data, meant for humans to read.
+C<text/plain>, C<text/html>...
+
+=item video
+
+Video or video+audio data.
+C<video/mpeg>...
+
+=back
+
+
+=head2 Content transfer encodings
+
+The "Encoding" parameter of C<build()>.
+This is how the message body is packaged up for safe transit.
+
+Here are the 5 major MIME encodings.
+A more-comprehensive listing may be found in RFC-2045.
+
+=over 4
+
+=item 7bit
+
+Basically, no I<real> encoding is done. However, this label guarantees that no
+8-bit characters are present, and that lines do not exceed 1000 characters
+in length.
+
+=item 8bit
+
+Basically, no I<real> encoding is done. The message might contain 8-bit
+characters, but this encoding guarantees that lines do not exceed 1000
+characters in length.
+
+=item binary
+
+No encoding is done at all. Message might contain 8-bit characters,
+and lines might be longer than 1000 characters long.
+
+The most liberal, and the least likely to get through mail gateways.
+Use sparingly, or (better yet) not at all.
+
+=item base64
+
+Like "uuencode", but very well-defined. This is how you should send
+essentially binary information (tar files, GIFs, JPEGs, etc.).
+
+=item quoted-printable
+
+Useful for encoding messages which are textual in nature, yet which contain
+non-ASCII characters (e.g., Latin-1, Latin-2, or any other 8-bit alphabet).
+
+=back
+
+
+
+=head1 VERSION
+
+$Id: Lite.pm,v 2.108 2001/03/30 06:16:54 eryq Exp $
+
+
+=head1 CHANGE LOG
+
+=over 4
+
+
+=item Version 2.108
+
+New C<field_order()> allows you to set the header order, both on a
+per-message basis, and package-wide.
+I<Thanks to Thomas Stromberg for suggesting this.>
+
+Added code to try and divine "sendmail" path more intelligently.
+I<Thanks to Slaven Rezic for the suggestion.>
+
+
+=item Version 2.107 (2001/03/27)
+
+Fixed serious bug where tainted data with quoted-printable encoding
+was causing infinite loops. The "fix" untaints the data in question,
+which is not optimal, but it's probably benign in this case.
+I<Thanks to Stefan Sautter for tracking this nasty little beast down.>
+I<Thanks to Larry Geralds for a related patch.>
+
+ "Doctor, O doctor:
+ it's painful when I do *this* --"
+ "Simple: don't *do* that."
+
+Fixed bugs where a non-local C<$_> was being modified... again!
+Will I never learn?
+I<Thanks to Maarten Koskamp for reporting this.>
+
+ Dollar-underscore
+ can poison distant waters;
+ 'local' must it be.
+
+Fixed buglet in C<add()> where all value references were being treated
+as arrayrefs, instead of as possibly-self-stringifying object refs.
+Now you can send in an object ref as the 2nd argument.
+I<Thanks to dLux for the bug report.>
+
+ That ref is a string?
+ Operator overload
+ has ruined my day.
+
+Added "Approved" as an acceptable header field for C<new()>, as per RFC1036.
+I<Thanks to Thomax for the suggestion regarding MIME-tools.>
+
+Small improvements to docs to make different uses of attach()
+and various arguments clearer.
+I<Thanks to Sven Rassman and Roland Walter for the suggestions.>
+
+
+=item Version 2.106 (2000/11/21)
+
+Added Alpha version of scrub() to make it easy for people to suppress
+the printing of unwanted MIME attributes (like Content-length).
+I<Thanks to the many people who asked for this.>
+
+Headers with empty-strings for their values are no longer
+printed. This seems sensible, and helps us implement scrub().
+
+
+=item Version 2.105 (2000/10/14)
+
+The regression-test failure was identified, and it was my fault.
+Apparently some of the \-quoting in my "autoloaded" code was
+making Perl 5.6 unhappy. For this nesting-related idiocy,
+a nesting kaiku.
+I<Thanks to Scott Schwartz for identifying the problem.>
+
+ In a pattern, my
+ backslash-s dwells peacefully,
+ unambiguous --
+
+ but I embed it
+ in a double-quoted string
+ doubling the backslash --
+
+ interpolating
+ that same double-quoted string
+ in other patterns --
+
+ and, worlds within worlds,
+ I single-quote the function
+ to autoload it --
+
+ changing the meaning
+ of the backslash and the 's';
+ and Five-Point-Six growls.
+
+
+=item Version 2.104 (2000/09/28)
+
+Now attempts to load and use Mail::Address for parsing email
+addresses I<before> falling back to our own method.
+I<Thanks to numerous people for suggesting this.>
+
+ Parsing addresses
+ is too damn hard. One last hope:
+ Let Graham Barr do it!
+
+For the curious, the version of Mail::Address appears
+as the "A" number in the X-Mailer:
+
+ X-Mailer: MIME::Lite 2.104 (A1.15; B2.09; Q2.03)
+
+Added B<FromSender> option to send_by_sendmail().
+I<Thanks to Bill Moseley for suggesting this feature.>
+
+
+=item Version 2.101 (2000/06/06)
+
+Major revision to print_body() and body_as_string() so that
+"body" really means "the part after the header", which is what most
+people would want in this context. This is B<not> how it was used
+1.x, where "body" only meant "the body of a simple singlepart".
+Hopefully, this change will solve many problems and create very few ones.
+
+Added support for attaching a part to a "message/rfc822", treating
+the "message" type as a multipart-like container.
+
+Now takes care not to include "Bcc:" in header when using send_by_smtp,
+as a safety precaution against qmail's behavior.
+I<Thanks to Tatsuhiko Miyagawa for identifying this problem.>
+
+Improved efficiency of many stringifying operations by using
+string-arrays which are joined, instead of doing multiple appends
+to a scalar.
+
+Cleaned up the "examples" directory.
+
+
+=item Version 1.147 (2000/06/02)
+
+Fixed buglet where lack of Cc:/Bcc: was causing extract_addrs
+to emit "undefined variable" warnings. Also, lack of a "To:" field
+now causes a croak.
+I<Thanks to David Mitchell for the bug report and suggested patch.>
+
+
+=item Version 1.146 (2000/05/18)
+
+Fixed bug in parsing of addresses; please read the WARNINGS section
+which describes recommended address formats for "To:", "Cc:", etc.
+Also added automatic inclusion of a UT "Date:" at top level unless
+explicitly told not to.
+I<Thanks to Andy Jacobs for the bug report and the suggestion.>
+
+=item Version 1.145 (2000/05/06)
+
+Fixed bug in encode_7bit(): a lingering C</e> modifier was removed.
+I<Thanks to Michael A. Chase for the patch.>
+
+
+=item Version 1.142 (2000/05/02)
+
+Added new, taint-safe invocation of "sendmail", one which also
+sets up the C<-f> option. Unfortunately, I couldn't make this automatic:
+the change could have broken a lot of code out there which used
+send_by_sendmail() with unusual "sendmail" variants.
+So you'll have to configure "send" to use the new mechanism:
+
+ MIME::Lite->send('sendmail'); ### no args!
+
+I<Thanks to Jeremy Howard for suggesting these features.>
+
+
+=item Version 1.140 (2000/04/27)
+
+Fixed bug in support for "To", "Cc", and "Bcc" in send_by_smtp():
+multiple (comma-separated) addresses should now work fine.
+We try real hard to extract addresses from the flat text strings.
+I<Thanks to John Mason for motivating this change.>
+
+Added automatic verification that attached data files exist,
+done immediately before the "send" action is invoked.
+To turn this off, set $MIME::Lite::AUTO_VERIFY to false.
+
+=item Version 1.137 (2000/03/22)
+
+Added support for "Cc" and "Bcc" in send_by_smtp().
+To turn this off, set $MIME::Lite::AUTO_CC to false.
+I<Thanks to Lucas Maneos for the patch, and tons of others for
+the suggestion.>
+
+Chooses a better default content-transfer-encoding if the content-type
+is "image/*", "audio/*", etc.
+To turn this off, set $MIME::Lite::AUTO_ENCODE to false.
+I<Thanks to many folks for the suggestion.>
+
+Fixed bug in QP-encoding where a non-local C<$_> was being modified.
+I<Thanks to Jochen Stenzel for finding this very obscure bug!>
+
+Removed references to C<$`>, C<$'>, and C<$&> (bad variables
+which slow things down).
+
+Added an example of how to send HTML files with enclosed in-line
+images, per popular demand.
+
+
+=item Version 1.133 (1999/04/17)
+
+Fixed bug in "Data" handling: arrayrefs were not being handled
+properly.
+
+
+=item Version 1.130 (1998/12/14)
+
+Added much larger and more-flexible send() facility.
+I<Thanks to Andrew McRae (and Optimation New Zealand Ltd)
+for the Net::SMTP interface. Additional thanks to the many folks
+who requested this feature.>
+
+Added get() method for extracting basic attributes.
+
+New... "t" tests!
+
+
+=item Version 1.124 (1998/11/13)
+
+Folded in filehandle (FH) support in build/attach.
+I<Thanks to Miko O'Sullivan for the code.>
+
+
+=item Version 1.122 (1998/01/19)
+
+MIME::Base64 and MIME::QuotedPrint are used if available.
+
+The 7bit encoding no longer does "escapes"; it merely strips 8-bit characters.
+
+
+=item Version 1.121 (1997/04/08)
+
+Filename attribute is now no longer ignored by build().
+I<Thanks to Ian Smith for finding and patching this bug.>
+
+
+=item Version 1.120 (1997/03/29)
+
+Efficiency hack to speed up MIME::Lite::IO_Scalar.
+I<Thanks to David Aspinwall for the patch.>
+
+
+=item Version 1.116 (1997/03/19)
+
+Small bug in our private copy of encode_base64() was patched.
+I<Thanks to Andreas Koenig for pointing this out.>
+
+New, prettier way of specifying mail message headers in C<build()>.
+
+New quiet method to turn off warnings.
+
+Changed "stringify" methods to more-standard "as_string" methods.
+
+
+=item Version 1.112 (1997/03/06)
+
+Added C<read_now()>, and C<binmode()> method for our non-Unix-using brethren:
+file data is now read using binmode() if appropriate.
+I<Thanks to Xiangzhou Wang for pointing out this bug.>
+
+
+=item Version 1.110 (1997/03/06)
+
+Fixed bug in opening the data filehandle.
+
+
+=item Version 1.102 (1997/03/01)
+
+Initial release.
+
+
+=item Version 1.101 (1997/03/01)
+
+Baseline code.
+
+=back
+
+
+=head1 TERMS AND CONDITIONS
+
+Copyright (c) 1997 by Eryq.
+Copyright (c) 1998 by ZeeGee Software Inc.
+All rights reserved. This program is free software; you can redistribute
+it and/or modify it under the same terms as Perl itself.
+
+This software comes with B<NO WARRANTY> of any kind.
+See the COPYING file in the distribution for details.
+
+
+=head1 NUTRITIONAL INFORMATION
+
+For some reason, the US FDA says that this is now required by law
+on any products that bear the name "Lite"...
+
+ MIME::Lite |
+ ------------------------------------------------------------
+ Serving size: | 1 module
+ Servings per container: | 1
+ Calories: | 0
+ Fat: | 0g
+ Saturated Fat: | 0g
+
+Warning: for consumption by hardware only! May produce
+indigestion in humans if taken internally.
+
+
+=head1 AUTHOR
+
+Eryq (F<eryq@zeegee.com>).
+President, ZeeGee Software Inc. (F<http://www.zeegee.com>).
+
+Created: 11 December 1996. Ho ho ho.
+
+=cut
+