From eea2c34e5bebdaab143ffd7851c685fd9fa42454 Mon Sep 17 00:00:00 2001 From: fukachan Date: Fri, 6 Apr 2001 12:54:55 +0000 Subject: Initial revision --- cpan/dist/MIME-Lite/COPYING | 248 ++ cpan/dist/MIME-Lite/INSTALLING | 26 + cpan/dist/MIME-Lite/MANIFEST | 35 + cpan/dist/MIME-Lite/Makefile.PL | 20 + cpan/dist/MIME-Lite/README | 1357 +++++++++ cpan/dist/MIME-Lite/README.system | 8 + cpan/dist/MIME-Lite/docs/MIME/Lite.pm.html | 1976 +++++++++++++ cpan/dist/MIME-Lite/docs/MIME/icons/h1bullet.gif | Bin 0 -> 421 bytes cpan/dist/MIME-Lite/docs/MIME/icons/h2bullet.gif | Bin 0 -> 345 bytes cpan/dist/MIME-Lite/docs/MIME/icons/zeegee.gif | Bin 0 -> 5269 bytes cpan/dist/MIME-Lite/docs/icons/h1bullet.gif | Bin 0 -> 421 bytes cpan/dist/MIME-Lite/docs/icons/h2bullet.gif | Bin 0 -> 345 bytes cpan/dist/MIME-Lite/docs/icons/zeegee.gif | Bin 0 -> 5269 bytes cpan/dist/MIME-Lite/docs/index-menu.html | 27 + cpan/dist/MIME-Lite/docs/index.html | 13 + cpan/dist/MIME-Lite/docs/index.menu | 24 + cpan/dist/MIME-Lite/docs/mime_fwd.html | 55 + cpan/dist/MIME-Lite/docs/mime_gif.html | 56 + cpan/dist/MIME-Lite/docs/mime_hack.html | 55 + cpan/dist/MIME-Lite/docs/mime_longlines.html | 72 + cpan/dist/MIME-Lite/docs/mime_postcard.html | 59 + cpan/dist/MIME-Lite/examples/mime_fwd | 69 + cpan/dist/MIME-Lite/examples/mime_gif | 93 + cpan/dist/MIME-Lite/examples/mime_hack | 58 + cpan/dist/MIME-Lite/examples/mime_longlines | 92 + cpan/dist/MIME-Lite/examples/mime_postcard | 79 + cpan/dist/MIME-Lite/lib/MIME/Lite.pm | 3227 ++++++++++++++++++++++ cpan/dist/MIME-Lite/t/ExtUtils/TBone.pm | 534 ++++ cpan/dist/MIME-Lite/t/Utils.pm | 23 + cpan/dist/MIME-Lite/t/addrs.t | 87 + cpan/dist/MIME-Lite/t/data.t | 55 + cpan/dist/MIME-Lite/t/head.t | 87 + cpan/dist/MIME-Lite/t/verify.t | 39 + cpan/dist/MIME-Lite/testin/README | 1 + cpan/dist/MIME-Lite/testin/hello | 2 + cpan/lib/MIME/Lite.pm | 3227 ++++++++++++++++++++++ 36 files changed, 11704 insertions(+) create mode 100644 cpan/dist/MIME-Lite/COPYING create mode 100644 cpan/dist/MIME-Lite/INSTALLING create mode 100644 cpan/dist/MIME-Lite/MANIFEST create mode 100755 cpan/dist/MIME-Lite/Makefile.PL create mode 100644 cpan/dist/MIME-Lite/README create mode 100644 cpan/dist/MIME-Lite/README.system create mode 100644 cpan/dist/MIME-Lite/docs/MIME/Lite.pm.html create mode 100644 cpan/dist/MIME-Lite/docs/MIME/icons/h1bullet.gif create mode 100644 cpan/dist/MIME-Lite/docs/MIME/icons/h2bullet.gif create mode 100644 cpan/dist/MIME-Lite/docs/MIME/icons/zeegee.gif create mode 100644 cpan/dist/MIME-Lite/docs/icons/h1bullet.gif create mode 100644 cpan/dist/MIME-Lite/docs/icons/h2bullet.gif create mode 100644 cpan/dist/MIME-Lite/docs/icons/zeegee.gif create mode 100644 cpan/dist/MIME-Lite/docs/index-menu.html create mode 100644 cpan/dist/MIME-Lite/docs/index.html create mode 100644 cpan/dist/MIME-Lite/docs/index.menu create mode 100644 cpan/dist/MIME-Lite/docs/mime_fwd.html create mode 100644 cpan/dist/MIME-Lite/docs/mime_gif.html create mode 100644 cpan/dist/MIME-Lite/docs/mime_hack.html create mode 100644 cpan/dist/MIME-Lite/docs/mime_longlines.html create mode 100644 cpan/dist/MIME-Lite/docs/mime_postcard.html create mode 100755 cpan/dist/MIME-Lite/examples/mime_fwd create mode 100755 cpan/dist/MIME-Lite/examples/mime_gif create mode 100755 cpan/dist/MIME-Lite/examples/mime_hack create mode 100755 cpan/dist/MIME-Lite/examples/mime_longlines create mode 100755 cpan/dist/MIME-Lite/examples/mime_postcard create mode 100644 cpan/dist/MIME-Lite/lib/MIME/Lite.pm create mode 100644 cpan/dist/MIME-Lite/t/ExtUtils/TBone.pm create mode 100644 cpan/dist/MIME-Lite/t/Utils.pm create mode 100644 cpan/dist/MIME-Lite/t/addrs.t create mode 100644 cpan/dist/MIME-Lite/t/data.t create mode 100644 cpan/dist/MIME-Lite/t/head.t create mode 100644 cpan/dist/MIME-Lite/t/verify.t create mode 100644 cpan/dist/MIME-Lite/testin/README create mode 100644 cpan/dist/MIME-Lite/testin/hello create mode 100644 cpan/lib/MIME/Lite.pm 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. + + + Copyright (C) 19yy + + 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. + + , 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., "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 =>'

Hello

', + ); + $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{ + Here's my image: + + } + ); + $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" + + 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 @@ + + + MIME::Lite + + +ZeeGee Software

MIME::Lite

+
+ + +


+

Top NAME

+ + +

MIME::Lite - low-calorie MIME generator + + + +


+

Top 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;
+      
+
+ + +


+

Top 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. + + + +


+

Top MORE EXAMPLES

+ + + +


+

Top 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'
+                 );
+
+ + +


+

Top 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);
+
+ + +


+

Top 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();
+
+ + +


+

Top 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); 
+
+ + +


+

Top 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;
+
+ + +


+

Top 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
+
+ + +


+

Top FAQ

+ + + +


+

Top 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. + +
+ + + +


+

Top 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. + + + +


+

Top PUBLIC INTERFACE

+ + + +


+

Top 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. + +
+ + + +


+

Top 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: 
7bitOnly 7-bit text, all lines <1000 characters
8bit8-bit text, all lines <1000 characters
quoted-printable8-bit text or long lines (more reliable than "8bit")
base64Largely 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 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 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");  
+
+
+ + + +


+

Top 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 header_order. +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'      => '');
+
+
+ + + +


+

Top 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. + +
+ + + +


+

Top 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. + +
+ + + +


+

Top 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. + +
+ + + +


+

Top 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. ;-) + +

+ + + +


+

Top NOTES

+ + + +


+

Top 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. + +

+ + + +


+

Top 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. + + + +


+

Top WARNINGS

+ + + +


+

Top 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. + + + +


+

Top 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. + + + +


+

Top 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. + + + +


+

Top 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. + + + +


+

Top 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 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. + + + +


+

Top 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. + + + +


+

Top A MIME PRIMER

+ + + +


+

Top 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... + +
+ + + +


+

Top 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). + +
+ + + +


+

Top VERSION

+ + +

$Id: Lite.pm,v 2.108 2001/03/30 06:16:54 eryq Exp $ + + + +


+

Top 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. + +
+ + + +


+

Top 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. + + + +


+

Top 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. + + + +


+

Top AUTHOR

+ + +

Eryq (eryq@zeegee.com). +President, ZeeGee Software Inc. (http://www.zeegee.com). + + +

Created: 11 December 1996. Ho ho ho. + +


+
+Generated Fri Mar 30 01:17:20 2001 by cvu_pod2html +
+
+ 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 Binary files /dev/null and b/cpan/dist/MIME-Lite/docs/MIME/icons/h1bullet.gif 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 Binary files /dev/null and b/cpan/dist/MIME-Lite/docs/MIME/icons/h2bullet.gif 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 Binary files /dev/null and b/cpan/dist/MIME-Lite/docs/MIME/icons/zeegee.gif 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 Binary files /dev/null and b/cpan/dist/MIME-Lite/docs/icons/h1bullet.gif 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 Binary files /dev/null and b/cpan/dist/MIME-Lite/docs/icons/h2bullet.gif 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 Binary files /dev/null and b/cpan/dist/MIME-Lite/docs/icons/zeegee.gif 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 @@ + + +perlmod + + + + + + +
Overview
MIME::Lite
+
+ + + + + + + + + + + + +
Examples
mime_fwd
mime_gif
mime_hack
mime_longlines
mime_postcard
+
+
+ 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 @@ + +perlmod + + + + + + + + <BODY> + Go <A HREF="menu.html">here</A> + </BODY> + 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 @@ + + + mime_fwd + + +ZeeGee Software

mime_fwd

+
+ + +


+

Top NAME

+ + +

mime_fwd - test the ability to embed messages + + + +


+

Top SYNOPSIS

+ + +

Usage: + +

+    mime_fwd 
+
+ + +


+

Top DESCRIPTION

+ + +

Create a simple message, then wrap it in a "forward" and +then a "reply". + + + +


+

Top AUTHOR

+ + +

Eryq, eryq@zeegee.com + +


+
+Generated Fri Mar 30 01:17:33 2001 by cvu_pod2html +
+
+ 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 @@ + + + mime_gif + + +ZeeGee Software

mime_gif

+
+ + +


+

Top NAME

+ + +

mime_gif - encode a single gif by reading data different ways + + + +


+

Top SYNOPSIS

+ + +

Usage: + +

+    mime_gif /path/to/some.gif
+
+ + +


+

Top 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. + + + +


+

Top AUTHOR

+ + +

Eryq, eryq@zeegee.com + +


+
+Generated Fri Mar 30 01:17:36 2001 by cvu_pod2html +
+
+ 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 @@ + + + mime_hack + + +ZeeGee Software

mime_hack

+
+ + +


+

Top NAME

+ + +

mime_hack - test the "attach to singlepart" hack + + + +


+

Top SYNOPSIS

+ + +

Usage: + +

+    mime_hack /path/to/some.gif
+
+ + +


+

Top DESCRIPTION

+ + +

Encode a multipart message by starting with a text message, +and attaching a GIF file to it. + + + +


+

Top AUTHOR

+ + +

Eryq, eryq@zeegee.com + +


+
+Generated Fri Mar 30 01:17:39 2001 by cvu_pod2html +
+
+ 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 @@ + + + mime_longlines + + +ZeeGee Software

mime_longlines

+
+ + +


+

Top NAME

+ + +

mime_longlines - generate a test message with long lines + + + +


+

Top SYNOPSIS

+ + +

Usage: + +

+    mime_longlines [-s]
+
+ +

Options: + +

+    -s   Stringify message first, and print the *string* to STDOUT.
+
+ + +


+

Top 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. + + + +


+

Top AUTHOR

+ + +

Eryq, eryq@zeegee.com + +


+
+Generated Fri Mar 30 01:17:41 2001 by cvu_pod2html +
+
+ 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 @@ + + + mime_postcard + + +ZeeGee Software

mime_postcard

+
+ + +


+

Top NAME

+ + +

mime_postcard - output a multipart/alternative message + + + +


+

Top 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. + + + +


+

Top DESCRIPTION

+ + +

This send a mesasge both as HTML and plain text. +I use "Data"; you would probably use "Path". + + + +


+

Top AUTHOR

+ + +

Eryq, eryq@zeegee.com + +


+
+Generated Fri Mar 30 01:17:44 2001 by cvu_pod2html +
+
+ 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 = <'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<

Hey there!

\n>, + qq< Having a wonderful time... take a look!\n >, + qq<
Snapshot
>]); +$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 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., "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 =>'

Hello

', + ); + $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{ + Here's my image: + + } + ); + $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 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 scrub it for plain +text, and you can I 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 there are reports of brain-dead MUAs out there that +do the wrong thing if you I 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 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, this changes the default +order in which headers are output for I messages. + + +=item MIME::Lite->quiet() + +This L can be used to suppress/unsuppress +all warnings coming from this module. + + +=item MIME::Lite->send() + +When used as a L, 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. + + +=item $MIME::Lite::AUTO_ENCODE + +If true, automatically choose the encoding from the content type. +Default is B. + + +=item $MIME::Lite::AUTO_CC + +If true, automatically send to the Cc/Bcc addresses for send_by_smtp(). +Default is B. + + +=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. + +=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 +Create a new message object. + +If any arguments are given, they are passed into C; 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 +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 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 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 "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 +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 the ones I set... so be careful: I +(like C) unless you know what you're doing! + +To specify a fieldname that's I 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 signals a mail +field (and it sort of looks like one too). + +=item Data + +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. + +=item Datestamp + +I +If given true (or omitted), we force the creation of a C field +stamped with the current date/time if this is a top-level message. +You may want this if using L. +If you don't want this to be done, either provide your own Date +or explicitly set this to false. + +=item Disposition + +I +The content disposition, C<"inline"> or C<"attachment">. +The default is C<"inline">. + +=item Encoding + +I +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 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. This may not be what you want, so pick your +encoding well! For more info, see L<"A MIME PRIMER">. + +=item FH + +I +Filehandle containing the data, opened for reading. +See "ReadNow" also. + +=item Filename + +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 +"Path" is inadequate, or if you're using "Data" instead of "Path". +You should I put path information in here (e.g., no "/" +or "\" or ":" characters should be used). + +=item Id + +I +Same as setting "content-id". + +=item Length + +I +Set the content length explicitly. Normally, this header is automatically +computed, but only under certain circumstances (see L<"Limitations">). + +=item Path + +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 "ReadNow" also. + +=item ReadNow + +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 raised if the open fails. + +=item Top + +I +If defined, indicates whether or not this is a "top-level" MIME message. +The parts of a multipart message are I top-level. +Default is true. + +=item Type + +I +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 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 +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 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 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 add() is probably going to be more efficient than C, +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 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 +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 +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 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 +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 +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 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. +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 +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 +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 occurences are returned. + +I 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 +Recompute the content length for the message I, +setting the "content-length" attribute as a side-effect: + + $msg->get_length; + +Returns the length, or undefined if not set. + +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.). + +This method only sets the content length to a defined value if the +message is a singlepart with C<"binary"> encoding, I 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 +Delete all occurences of fields named TAG, and add a new +field with the given VALUE. TAG is converted to all-lowercase. + +B the special MIME fields (MIME-version, Content-*): +if you "replace" a MIME field, the replacement text will override +the 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 fields: + + $msg->replace("Subject" => "Hi there!"); + +Giving VALUE as the I will effectively I that +field from being output. This is the correct way to suppress +the special MIME fields: + + $msg->replace("Content-disposition" => ""); + +Giving VALUE as I will just cause all explicit values +for TAG to be deleted, without having any new values added. + +I 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 +B +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 +With no argument, returns whether or not it thinks that the data +(as given by the "Path" argument of C) should be read using +binmode() (for example, when C is invoked). + +The default behavior is that any content type other than +C or C 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 +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 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 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); + + ### 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) +to be read into core immediately, just as though you had given it +literally with the C 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 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 or C. + +=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} = ; ### 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: the literal signature data. +Can be either a scalar or a ref to an array of scalars. + +=item Path + +As in C: 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 = ; ### 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 +# Based on the CONTENTTYPE, return a good suggested encoding. +# C and C 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 +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/^{Parts}}) { $part->verify_data } + 1; +} + +=back + +=cut + + +#============================== +#============================== + +=head2 Output + +=over 4 + +=cut + +#------------------------------ + +=item print [OUTHANDLE] + +I +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 +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 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 +# 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. +# +# All OUTHANDLE has to be is a filehandle (possibly a glob ref), or +# any object that responds to a print() message. +# +# 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. +# +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 +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 +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 +Return the encoded body as a string. +This is the portion after the header and the blank line. + +I actually prepares the body by "printing" to a scalar. +Proof that you can hand the C methods any blessed object +that responds to a C 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 +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 +This is the principal method for sending mail, and for configuring +how mail will be sent. + +I (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 (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 method, giving it the ARGS. +This usage implements (and deprecates) the C method. + +=item "smtp", [HOSTNAME] + +Send a message by SMTP, using optional HOSTNAME as SMTP-sending host. +Uses the L 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 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-Esend 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 +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 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 +Suppose we did I use C<-f>, and you gave an explicit "From:" +field in your message: in this case, the sendmail "envelope" would +indicate the I 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 +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 configuration + command to your I file + (e.g.: C 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 +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 +# Send the message via an anonymous subroutine. +# +sub send_by_sub { + my ($self, $subref, @args) = @_; + &$subref($self, @args); +} + +#------------------------------ + +=item sendmail COMMAND... + +I +Declare the sender to be "sendmail", and set up the "sendmail" command. +I + +=cut + +sub sendmail { + my $self = shift; + $self->send('sendmail', join(' ', @_)); +} + +=back + +=cut + + + +#============================== +#============================== + +=head2 Miscellaneous + +=over 4 + +=cut + +#------------------------------ + +=item quiet ONOFF + +I +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 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 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 method. + + + +=head1 WARNINGS + +=head2 Good-vs-bad email addresses with send_by_smtp() + +If using L, be aware that you are +forcing MIME::Lite to extract email addresses out of a possible list +provided in the C, C, and C 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" + +This last form is discouraged because SMTP must be able to get +at the I or I portion. + +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 your message only, and using Net::SMTP explicitly to +I 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 or L) -- +whether by B, B, or B -- be warned that we don't +attempt to open files, read filehandles, or encode the data until +L 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 option, +provided that you have enough memory to handle your messages. + + +=head2 MIME attributes are separate from header fields! + +B the MIME attributes are stored and manipulated separately +from the message header fields; when it comes time to print the +header out, I 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 + +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 C or C +any MIME header field. Use C 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 is a I. +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, C, C... + +=item audio + +Audio data. +C