MIME-tools-5.509/0000755000076400007640000000000013071231525011542 5ustar dfsdfsMIME-tools-5.509/ChangeLog0000644000076400007640000013135413071225105013320 0ustar dfsdfs5.509 2017-04-05 Dianne Skoll * VERSION 5.509 RELEASED * Fix CPAN bug https://rt.cpan.org/Ticket/Display.html?id=120871 Makefile.PL fails with no '.' in @INC * Fix CPAN bug https://rt.cpan.org/Ticket/Display.html?id=118262 Test t/Ref.t fails on Windows install * Fix CPAN bug https://rt.cpan.org/Ticket/Display.html?id=119166 MIME::Parser::parse_data() should check what it gets back... * Fix CPAN bug https://rt.cpan.org/Ticket/Display.html?id=119568 Allow \r\n to be used as line-end delimeter when outputting MIME message. 5.508 2016-08-29 Dianne Skoll * VERSION 5.508 RELEASED * Fix test broken by Perl update https://rt.cpan.org/Ticket/Display.html?id=113887 5.507 2015-09-30 Dianne Skoll * VERSION 5.507 RELEASED * Fix parsing bug https://rt.cpan.org/Public/Bug/Display.html?id=105455 * Fix typo that broke MIME::Body::incore->open() on Perl 5.20 5.506 2015-04-22 Dianne Skoll * VERSION 5.506 RELEASED * Update maintainer's name to "Dianne Skoll" 5.505 2013-11-14 Dianne Skoll * VERSION 5.505 RELEASED * Fix documentation typos. https://rt.cpan.org/Public/Bug/Display.html?id=80473 * Fix broken test. https://rt.cpan.org/Public/Bug/Display.html?id=84668 * Don't run Kwalitee tests unless author or release tests are enabled. https://rt.cpan.org/Public/Bug/Display.html?id=87094 * Fix many documentation typos. https://rt.cpan.org/Public/Bug/Display.html?id=87783 * Fix bug in header parsing that would fail to parse a header like: Content-Type: ; name="malware.zip" 5.504 2013-01-30 Dianne Skoll * VERSION 5.504 RELEASED * Fix encoding of MIME parameters that contain a quoted string: "like \"this" https://rt.cpan.org/Public/Bug/Display.html?id=80433 * Suppress useless warnings from tests https://rt.cpan.org/Public/Bug/Display.html?id=80679 * Fix long-standing bug in encode_mimewords that can break multibyte-encodings (eg, utf-8) https://rt.cpan.org/Public/Bug/Display.html?id=5462 5.503 2012-06-08 Dianne Skoll * VERSION 5.503 RELEASED * Avoid inappropriately untainting data https://rt.cpan.org/Public/Bug/Display.html?id=67119 * Localise $\ to avoid parsing problems if it's set elsewhere https://rt.cpan.org/Public/Bug/Display.html?id=71041 * Improve exorcising of filenames https://rt.cpan.org/Public/Bug/Display.html?id=71677 * Fix potential race condition in t/Smtpsend.t https://rt.cpan.org/Public/Bug/Display.html?id=68879 * Allow native I/O on File::Handle objects https://rt.cpan.org/Public/Bug/Display.html?id=72538 * Add "recommends Convert::BinHex" clause to Makefile.PL https://rt.cpan.org/Public/Bug/Display.html?id=72223 * Add module_name to Makefile.PL https://rt.cpan.org/Public/Bug/Display.html?id=77138 * Fix "Uninitialized value" warning https://rt.cpan.org/Public/Bug/Display.html?id=77190 * Don't run t/Smtpsend.t on systems that lack fork() https://rt.cpan.org/Public/Bug/Display.html?id=77351 * Add "use strict" everywhere https://rt.cpan.org/Public/Bug/Display.html?id=77582 5.502 2011-03-08 Dianne Skoll * VERSION 5.502 RELEASED * NOTE to packagers (Debian, Red Hat, FreeBSD, etc.): Do not ship MIME::tools 5.500 or 5.501. They both had serious bugs! * Fix parsing bug: https://rt.cpan.org/Ticket/Display.html?id=66025 * Fix typo: https://rt.cpan.org/Ticket/Display.html?id=65387 * Fix unit tests on Perl 5.8.x: https://rt.cpan.org/Ticket/Display.html?id=66188 * Fix unit test failure on Win32: (https://rt.cpan.org/Ticket/Display.html?id=66286) 5.501 2011-02-17 Dianne Skoll * VERSION 5.501 RELEASED * Add build_requires 'Test::Deep'; to Makefile (rt.cpan.org #64659) * Fix spelling errors (rt.cpan.org #64610) * Fix double-decoding bug when decoding RFC-2231-encoded parameters (rt.cpan.org #65162) * Fix inappropriate inclusion of CR characters in parsed headers (rt.cpan.org #65681) * Document that MIME::WordDecoder is mostly deprecated. * Document that MIME::Head->get(...) can include a trailing newline. * Increase buffer size from 2kB to 8kB in MIME::Entity and MIME::Body (part of rt.cpan.org #65162) 5.500 2011-01-07 Dave O'Neill * VERSION 5.500 RELEASED * (cleanup) IO-Stringy (specifically, IO::ScalarArray, IO::Lines, and IO::InnerFile) is no longer used * (ticket 22684) Fix deadlock in filter() when invoking external programs such as gzip. (Alexey Tourbin ) * Remove auto_install from Makefile.PL * (ticket 60931) If preamble is empty, make sure it's still empty after roundtripping through MIME::Entity * (ticket 63739) Properly decude RFC2231 encodings in attachment filenames 5.428 2010-04-22 Dave O'Neill * VERSION 5.428 RELEASED * (ticket 56764) Build release with a newer Module::Install * (ticket 52924) ensure we add <> around Content-id data * (ticket 48036) make mimesend example script a bit more useful (courtesy of Jerrad Pierce) * (ticket 43439) fix for parsing of doubled ; in multipart headers * (ticket 41632) If both RFC-2231 and non-RFC-2231 parameters are present, use only the RFC-2231 ones * (ticket 40715) Reference Encode::MIME::Header in docs * (ticket 39985) correct POD typos * Only bind to localhost in smtpsend test, rather than to all available interfaces. This might avoid some of the test failures seen on cpantesters. 5.427 2008-06-30 Dave O'Neill * VERSION 5.427 RELEASED * (bugfix) fix remove_sig() on invalid multipart message (RT #11901) * (bugfix) make_singlepart() no longer creates bizzare Content-Type: headers (RT #37139) * (bugfix) process_part() no longer sets incorrect charset on empty parts (RT #35369) * (bugfix) fix runtime warnings caused by incorrect pack() string (RT #34451, bugs.debian.org #446342) * (docs) add "SEE ALSO" sections to POD docs (RT #30391) * (docs) fix documentation of MIME::Head::get() (RT #34552, bugs.debian.org #235189) * (packaging) Depend on IO::File 1.1.3, for its binmode() support (RT #34178) 5.426 2008-03-07 Dave O'Neill * VERSION 5.426 RELEASED * (bugfix) require File::Temp 0.18 or newer, as we need seek() (RT#31032) * (bugfix) Don't hang forever in t/Smtpsend.t (RT#31082) * (bugfix) require Perl 5.8.0 or newer in Makefile.PL (RT#30927) * (bugfix) encode_mimewords() no longer removes spaces between two encoded words (RT#5462) 5.425 2007-11-17 Dave O'Neill * VERSION 5.425 RELEASED * (bugfix) A stub for MIME::Parser's tmp_recycling() method has been re-added to preserve compatibility. Since recycling of tempfiles never worked and has been removed, any code calling tmp_recycling() should stop attempting to use the feature. 5.424 2007-11-07 Dianne Skoll * VERSION 5.424 RELEASED * (bugfix) [rt.cpan.org #29864] - lines in $entity->body() should be newline-terminated. 5.423 2007-09-27 Dave O'Neill * VERSION 5.423 RELEASED * (bugfix) Fix API regression - MIME::Entity::body() should return an arrayref. Fixes RT 29643. 5.422 2007-09-25 Dave O'Neill * VERSION 5.422 RELEASED * (bugfix) Require File::Temp 0.17 or newer for IO::Seekable support. This fixes test failures seen on Darwin. * (bugfix) Clear filer's purgeable() before calling init_parse(). Fixes RT 7858. 5.421 2007-09-21 Dave O'Neill * VERSION 5.421 RELEASED * (enhancement) Use File::Temp for tempfile generation. MIME::Parser now has a tmp_dir() method for changing the temporary directory on a per-parser basis. 5.420_02 2007-08-29 Dave O'Neill * VERSION 5.420_02 (developer release) * (bugfix) Correct 'use vars' and add a 'use strict' (fixes RT #22681) * (bugfix) Don't allow all-whitespace filenames in recommended_filename() (fixes RT #6115) * (bugfix) Require IO-stringy 2.110. Fixes RT tickets 11312, 11452, 12375, 12784, and 18791 * (docs) Updated RFC references to refer to MIME RFCs 2045-2049 (RT #14119) * (cleanup) Warn if no decoder is found for a given encoding. (RT #22682) * (cleanup) IO::Wrap no longer used, IO::ScalarArray use minimized 5.420_01 2007-06-18 Dave O'Neill * VERSION 5.420_01 (developer release) * (bugfix) Fix warning generated by a header of "Content-Type: /". Previous versions would warn about undefined variables. We now set a blank type and subtype. * (cleanup) Partial removal of dependencies on IO::Scalar and IO::ScalarArray. We now use Perl's built-in I/O on scalars as much as possible. NOTE THAT THIS REQUIRES PERL 5.8! * (cleanup) FileHandle usage removed in favour of IO::File * (cleanup) Remove broken utility methods -- shellquote() because it didn't really make anything safe, and catfile(), because File::Spec is better. * (cleanup) Multiple test cleanups, including removal of ExtUtils/TBone.pm. Tests now use Test::More. * (cleanup) Remove support for recycling tempfiles ( tmp_recycling() and its usage in new_tmpfile() ) * (cleanup) Remove nasty "eval join('',<::DATA>) unless caller()" testing code from various modules * (cleanup) Merge all changelog information from README and MIME/Tools.pm into ChangeLog 5.420 2006-03-17 Dianne Skoll * VERSION 5.420 RELEASED * Fix regression introduced in 5.419 -- quoted-printable encoding would sometimes fail on "textual" MIME parts. 5.419 2005-12-22 Dianne Skoll * VERSION 5.419 RELEASED * Added MIME::Parser->decode_bodies method. This lets you force MIME::Tools to store body parts WITHOUT decoding them. Useful if you need the exact unmangled message source (for example, for GPG-signing.) Patch submitted by Jörn Reder. 5.418 2005-09-29 Dianne Skoll * VERSION 5.418 RELEASED * MIME/Decoder/QuotedPrint.pm: Localize "$_" in a couple of places. * MIME/WordDecoder.pm: Turn off useless debugging output to STDERR * MIME/Entity.pm: Make the stringify method use IO::ScalarArray instead of IO::Scalar. For small messages, performance may be worse; for large messages, it is definitely much better. * MANIFEST: Remove some useless internal files from the manifest. They were never meant to be part of the actual distribution. 5.417 2005-01-20 Dianne Skoll * VERSION 5.417 RELEASED * Require MIME::QuotedPrint 3.03 to use the three-argument "encode_qp" function. If we have an earlier version of MIME::QuotedPrint, fall back to the one-argument version. * Field/ParamVal.pm: The patch to strip trailing whitespace on parameters was buggy and caused decoding errors. This has been fixed. 5.416 2005-01-03 Dianne Skoll * VERSION 5.416 RELEASED * Allow MIME::Tools to work with MIME::QuotedPrint 2.20 again. The Makefile.PL will warn about potential problems, but will allow you to proceed. * Field/ParamVal.pm: Strip trailing whitespace when extracting parameters. Apparently, not doing so can cause Perl to core dump on certain badly-formed messages. 5.415 2004-10-27 Dianne Skoll * VERSION 5.415 RELEASED * Fixed parsing of parameter="" in headers, and fixed case where multipart boundary is "" 5.414 2004-10-06 Dianne Skoll * VERSION 5.414 RELEASED * Remove MIME::QuotedPrint 3.03 as a dependency and add MIME::Base64 3.03 instead. * Check return values of I/O operations like open(), close(), etc. and die if they fail. Problem reported by Mark Martinec. 5.413 2004-09-15 Dianne Skoll * VERSION 5.413 RELEASED * Fix some $VERSION = xxx assignments that were broken; make sure VERSION shows up as 5.413 everywhere. Sorry about that! 5.412 2004-09-09 Dianne Skoll * VERSION 5.412 RELEASED * Recognize "binhex40", "mac-binhex" and "mac-binhex40" Content-Transfer-Encodings. * Filer.pm: Be much more strict in evil_filename, allowing only a set of known good characters. 2004-09-08 Dianne Skoll * Skip BinHex decoding if prerequisite modules not installed. * Fix BinHex decoder so it encodes correctly; regression test for BinHex encoding now passes. * Require MIME::QuotedPrint 3.03 or newer. * Rename variable "$jkfis" to "$how_encoded" * Correct attribution of changes in changelog. * Correct bad regexp test for "bad PDF" files. 2004-09-07 Dianne Skoll * lib/MIME/Parser/Filer.pm (evil_filename): Make evil_filename more paranoid (Julian Field and Martin Blapp) * lib/MIME/Parser/Filer.pm (exorcise_filename): Delete leading and trailing whitespace (Julian Field) * Remove all the Benchmark code (Martin Blapp) * lib/MIME/Decoder.pm: Add support for BinHex encoded attachments (Julian Field) * lib/MIME/Decoder.pm: Require MIME::QuotedPrint 3.03 or newer for correct decoding of binary attachments. (Alexey Kravchuk) * lib/MIME/Decoder/QuotedPrint.pm: Attempt to deal sanely with PDF files encoded using quoted-printable encoding by Outlook, which does not follow the RFC guidelines. (Martin Blapp) * lib/MIME/Field/ParamVal.pm: Deal with RFC2231-encoded parameters. * lib/MIME/Head.pm: Correct "7-bit", "7 bit" and "7_bit" to 7bit; likewise for 8bit lookalikes. (Martin Blapp) * lib/MIME/Parser.pm: Add max_parts method to limit maximum number of MIME parts we are willing to parse. * DSKOLL took over maintainership of MIME::tools at version 5.411a. Version 5.411 Regenerated docs. Bug in HTML docs, now all fixed. Version 5.410 (2000/11/23) Better detection of evil filenames. Now we check for filenames which are suspiciously long, and a new MIME::Filer::exorcise_filename() method is used to try and remove the evil. *Thanks to Jason Haar for the suggestion.* Version 5.409 (2000/11/12) Added functionality to MIME::WordDecoder, including support for plain US-ASCII. MIME::Tools::tmpopen() made more flexible. You can now override the tmpfile-opening behavior. Version 5.408 (2000/11/10) Added new Beta unmime() mechanism. See the MIME::WordDecoder manpage for full details. Also see the section on "Understand how international characters are represented". Version 5.405 (2000/11/05) Added a purge() that does what people want it to. Now, when a parse finishes and you want to delete everything that was created by it, you can invoke `purge()' on the parser's filer. All files/directories created during the last parse should vanish. *Thanks to everyone who complained about MIME::Entity::purge.* Version 5.404 (2000/11/04) Added new automatic MIME-decoding of attachment filenames with encoded (non-ASCII) characters. Hopefully this will do more good than harm. The use of MIME::Parser::decode_headers() and MIME::Head::decode() has been deprecated in favor of the new MIME::Words "unmime" mechanism. Please see the "unmime" entry in the MIME::Words manpage. Added tolerance for unquoted =?...?= in param values. This is in violation of the RFCs, but then, so are some MUAs. *Thanks to desti for bringing this to my attention.* Fixed supposedly-bad B-encoding. *Thanks to Otto Frost for bringing this to my attention.* Version 5.316 (2000/09/21) Increased tolerance in MIME::Parser. Now will ignore bogus POP3 "+OK" line before header, as well as bogus mailbox "From " line (both with warnings). *Thanks to Antony OSullivan (ajos1) for suggesting this feature.* Fixed small epilogue-related bug in MIME::Entity::print_body(). Now it only outputs a final newline if the epilogue does not end in one already. Support for checking the preamble/epilogue in regression tests was also added. *Thanks to Lars Hecking for bringing this issue up.* Updated documentation. All module manual pages should now direct readers to the main MIME-tools manual page. Version 5.314 (2000/09/06) Fixed Makefile.PL to have less-restrictive requirement for File::Spec (0.6). Version 5.313 (2000/09/05) Fixed nasty bug with evil filenames. Certain evil filenames were getting replaced by internally-generated filenames which were just as evil... ouch! If your parser occasionally throws a fatal exception with a "write-open" error message, then you have this bug. *Thanks to Julian Field and Antony OSullivan (ajos1) for delivering the evidence!* Beware the doctor who cures seasonal head cold by killing patient Improved naming of extracted files. If a filename is regarded as evil, we guess that it might just be because of part information, and attempt to find and use the final path element. Simplified message logging and made it more consistent. For details, see the section on "Message-logging". Version 5.312 (2000/09/03) Fixed a Perl 5.7 select() incompatibility which caused "make test" to fail. *Thanks to Nick Ing-Simmons for the patch.* Version 5.311 (2000/08/16) Blind fix for Win32 uudecoding bug. A missing binmode seems to be the culprit here; let's see if this fixes it. *Thanks to ajos1 for finding the culprit!* The carriage return thumbs its nose at me, laughing: DOS I/O *still* sucks Version 5.310 (2000/08/15) Fixed a bug in the back-compat output_prefix() method of MIME::Parser. Basically, output prefixes were not being set through this mechanism. *Thanks to ajos1 for the alert.* shift @_, ### "shift at-underscore" or @_ will have bogus "self" object Added some backcompat methods, like parse_FH(). *Thanks (and apologies) to Alain Kotoujansky.* Added filenames-with-spaces support to MIME::Decoder::UU. *Thanks to Richard Pun for the suggestion.* Version 5.305 (2000/07/20) Added MIME::Entity::parts_DFS as convenient way to "get all parts". *Thanks to Xavier Armengou for suggesting this method.* Removed the Alpha notice. Still a few features to tweak, but those will be minor. Version 5.303 (2000/07/07) Fixed output bugs in new Filers. Scads of them: bad handling of filename collisions, bad implementation of output_under(), bad linking to results, POD errors, you name it. If this had gone to CPAN, I'd have issued a factory recall. `:-(' Errors, like beetles, Multiply ferociously In the small hours Version 5.301 (2000/07/06) READ ME BEFORE UPGRADING PAST THIS POINT! New MIME::Parser::Filer class -- not fully backwards-compatible. In response to demand for more-comprehensive file-output strategies, I have decided that the best thing to do is to split all the file-output logic (output_path(), evil_filename(), etc.) into its own separate class, inheriting from the new MIME::Parser::Filer class. If you *override* any of the following in a MIME::Parser subclass, you will need to change your code accordingly: evil_filename output_dir output_filename output_path output_prefix output_under My sincere apologies for any inconvenience this will cause, but it's ultimately for the best, and is quite likely the last structural change to 5.x. *Thanks to Tyson Ackland for all the ideas.* Incidentally, the new code also fixes a bug where identically-named files in the same message could clobber each other. A message arrives: "Here are three files, all named 'Foo'" Only one survives. :-( Fixed bug in MIME::Words header decoding. Underscores were not being handled properly. *Thanks to Dominique Unruh and Doru Petrescu,* who independently submitted the same fix within 2 hours of each other, after this bug has lain dormant for months: Two users, same bug, same patch -- mere hours apart: Truly, life is odd. Removed escaping of underscore in regexps. Escaping the underscore (\_) in regexps was sloppy and wrong (escaped metacharacters may include anything in \w), and the newest Perls warn about it. *Thanks to David Dyck for bringing this to my attention.* What, then, is a word? Some letters, digits, and, yes: Underscores as well Added Force option to MIME::Entity's make_multipart. *Thanks to Bob Glickstein for suggesting this.* Numerous fixlets to example code. *Thanks to Doru Petrescu for these.* Added REQUIREMENTS section in docs. Long-overdue. *Thanks to Ingo Schmiegel for motivating this.* Version 5.211 (2000/06/24) Fixed auto-uudecode bug. Parser was failing with "part did not end with expected boundary" error when uuencoded entity was a *singlepart* message (ironically, uuencoded parts of multiparts worked fine). *Thanks to Michael Mohlere for testing uudecode and finding this.* The hurrying bee Flies far for nectar, missing The nearest flowers Say ten thousand times: Complex cases may succeed Where simple ones fail Parse errors now generate warnings. Parser errors now cause warn()s to be generated if they are not turned into fatal exceptions. This might be a little redundant, seeing as they are available in the "results", but parser-warnings already cause warn()s. I can always put in a "quiet" switch if people complain. Miscellaneous cleanup. Documentation of MIME::Parser improved slightly, and a redundant warning was removed. Version 5.210 (2000/06/20) Change in "evil" filename. Made MIME::Parser's evil_filename stricter by having it reject "path" characters: any of '/' '\' ':' '[' ']'. Just as with beauty The eye of the beholder Is where "evil" lives. Documentation fixes. Corrected a number of docs in MIME::Entity which were obsoleted in the transition from 4.x to 5.x. *Thanks to Michael Fischer for pointing these out.* For this one, a special 5- 5-5-5 Haiku of anagrams: Documentation in mutant code, O! Edit -- no, CUT! [moan] I meant to un-doc... IO::Lines usage bug fixed. MIME::Entity was missing a "use IO::Lines", which caused an exception when you tried to use the body() method of MIME::Entity. *Thanks to Hideyo Imazu and Michael Fischer for pointing this out.* Bareword looks fine, but Perl cries: "Whoa there... IO::Lines? Never heard of it." Version 5.209 (2000/06/10) Autodetection of uuencode. You can now tell the parser to hunt for uuencode inside what should be text parts. See extract_uuencode() for full details. Beware: this is largely untested at the moment. *Special thanks to Michael Mohlere at ADJE Webmail, who was the first -- and most-insistent -- user to request this feature.* Faster parsing. Sped up the MIME::Decoder::NBit decoder quite a bit by using a variant of the chunking trick I used for MIME::Decoder::Base64. I suspect that the same trick (reading a big chunk plus the next line to get a big block of lines) would work with MIME::Decoder::QuotedPrint, but I don't have the time or resources to check that right now (tested contributions would be welcome). NBit encoding is more-conveniently done line-by-line for now, because individual line lengths must be checked. Better use of core. MIME::Body::InCore is now used when you build() an entity with the Data parameter, instead of MIME::Body::Scalar. More documentation on toolkit configuration. Version 5.207 (2000/06/09) Fixed whine() bug in MIME::Parser where the "warning" method whine() was called as a static function instead of invoked as an instance method. *Thanks to Todd A. Bradfute for reporting this.* A simple warning Invokes method as function: "Warning" makes us die Version 5.206 (2000/06/08) Ahem. Cough cough: Way too many bugs Thus, a self-imposed penance: Write haiku for each Fixed bug in MIME::Parser: the reader was not handling the odd (but legal) case where a multipart boundary is followed by linear whitespace. *Thanks to Jon Agnew for reporting this with the RFC citation.* Legal message fails And 'round the globe, thousands cry: READ THE RFC Empty preambles are now handled properly by MIME::Entity when printing: there is now no space between the header-terminator and the initial boundary. *Thanks to "sen_ml" for suggesting this.* Nature hates vacuum But please refrain from tossing Newlines in the void Started using Benchmark for benchmarking. Version 5.205 (2000/06/06) Added terminating newline to all parser messages, and fixed small parser bug that was dropping parts when errors occurred in certain places. Version 5.203 (2000/06/05) Brand new parser based on new (private) MIME::Parser::Reader and (public) MIME::Parser::Results. Fast and yet simple and very tolerant of bad MIME when desired. Message reporting needs some muzzling. MIME::Parser now has ignore_errors() set true by default. Version 5.116 (2000/05/26) Removed Tmpfile.t test, which was causing a bogus failure in "make test". Now we require 5.004 for MIME::Parser anyway, so we don't need it. *Thanks to Jonathan Cohn for reporting this.* Version 5.115 (2000/05/24) Fixed Ref.t bug, and documented how to remove parts from a MIME::Entity. Version 5.114 (2000/05/23) Entity now uses MIME::Lite-style default suggested encoding. More regression test have been added, and the "Size" tests in Ref.t are skipped for text document (due to CRLF differences between platforms). Version 5.113 (2000/05/21) Major speed and structural improvements to the parser. *Major, MAJOR thanks to Noel Burton-Krahn, Jeremy Gilbert, and Doru Petrescu for all the patches, benchmarking, and Beta-testing!* Convenient new one-directory-per-message parsing mechanism. Now through `MIME::Parser' method `output_under()', you can tell the parser that you want it to create a unique directory for each message parsed, to hold the resulting parts. Elimination of $', $` and $&. Wow... I still can't believe I missed this. D'OH! *Thanks to Noel Burton-Krahn for all his patches.* Parser is more tolerant of weird EOL termination. Some mailagents are can terminate lines with "\r\r\n". We're okay with that now when we extract the header. *Thanks to Joao Fonseca for pointing this out.* Parser is tolerant of "From " lines in headers. *Thanks to Joachim Wieland, Anthony Hinsinger, Marius Stan, and numerous others.* Parser catches syntax errors in headers. *Thanks to Russell P. Sutherland for catching this.* Parser no longer warns when subtype is undefined. *Thanks to Eric- Olivier Le Bigot for his fix.* Better integration with Mail::Internet. For example, smtpsend() should work fine. *Thanks to Michael Fischer and others for the patch.* Miscellaneous cleanup. *Thanks to Marcus Brinkmann for additional helpful input.* *Thanks to Klaus Seidenfaden for good feedback on 5.x Alpha!* Version 4.123 (1999/05/12) Cleaned up some of the tests for non-Unix OS'es. Will require a few iterations, no doubt. Version 4.122 (1999/02/09) Resolved CORE::open warnings for 5.005. *Thanks to several folks for this bug report.* Version 4.121 (1998/06/03) Fixed MIME::Words infinite recursion. *Thanks to several folks for this bug report.* Version 4.117 (1998/05/01) Nicer MIME::Entity::build. No longer outputs warnings with undefined Filename, and now accepts Charset as well. *Thanks to Jason Tibbits III for the inspirational patch.* Documentation fixes. Hopefully we've seen the last of the pod2man warnings... Better test logging. Now uses ExtUtils::TBone. Version 4.116 (1998/02/14) Bug fix: MIME::Head and MIME::Entity were not downcasing the content-type as they claimed. This has now been fixed. *Thanks to Rodrigo de Almeida Siqueira for finding this.* Version 4.114 (1998/02/12) Gzip64-encoding has been improved, and turned off as a default, since it depends on having gzip installed. See MIME::Decoder::Gzip64 if you want to activate it in your app. You can now set up the gzip/gunzip commands to use, as well. *Thanks to Paul J. Schinder for finding this bug.* Version 4.113 (1998/01/20) Bug fix: MIME::ParserBase was accidentally folding newlines in header fields. *Thanks to Jason L. Tibbitts III for spotting this.* Version 4.112 (1998/01/17) MIME::Entity::print_body now recurses when printing multipart entities, and prints "everything following the header." This is more likely what people expect to happen. PLEASE read the "two body problem" section of MIME::Entity's docs. Version 4.111 (1998/01/14) Clean build/test on Win95 using 5.004. Whew. Version 4.110 (1998/01/11) Added make_multipart() and make_singlepart() in MIME::Entity. Improved handling/saving of preamble/epilogue. Version 4.109 (1998/01/10) Overall Major version shift to 4.x accompanies numerous structural changes, and the deletion of some long-deprecated code. Many apologies to those who are inconvenienced by the upgrade. MIME::IO deprecated. You'll see IO::Scalar, IO::ScalarArray, and IO::Wrap to make this toolkit work. MIME::Entity deep code. You can now deep-copy MIME entities (except for on-disk data files). Encoding/decoding MIME::Latin1 deprecated, and 8-to-7 mapping removed. Really, MIME::Latin1 was one of my more dumber ideas. It's still there, but if you want to map 8-bit characters to Latin1 ASCII approximations when 7bit encoding, you'll have to request it explicitly. *But use quoted-printable for your 8-bit documents; that's what it's there for!* 7bit and 8bit "encoders" no longer encode. As per RFC-2045, these just do a pass-through of the data, but they'll warn you if you send bad data through. MIME::Entity suggests encoding. Now you can ask MIME::Entity's build() method to "suggest" a legal encoding based on the body and the content-type. No more guesswork! See the "mimesend" example. New module structure for MIME::Decoder classes. It should be easier for you to see what's happening. New MIME decoders! Support added for decoding `x-uuencode', and for decoding/encoding `x-gzip64'. You'll need "gzip" to make the latter work. Quoted-printable back on track... and then some. The 'quoted- printable' decoder now uses the newest MIME::QuotedPrint, and amends its output with guideline #8 from RFC2049 (From/.). *Thanks to Denis N. Antonioli for suggesting this.* Parsing Preamble and epilogue are now saved. These are saved in the parsed entities as simple string-arrays, and are output by print() if there. *Thanks to Jason L. Tibbitts for suggesting this.* The "multipart/digest" semantics are now preserved. Parts of digest messages have their mime_type() defaulted to "message/rfc822" instead of "text/plain", as per the RFC. *Thanks to Carsten Heyl for suggesting this.* Output Well-defined, more-complete print() output. When printing an entity, the output is now well-defined if the entity came from a MIME::Parser, even if using parse_nested_messages. See MIME::Entity for details. You can prevent recommended filenames from being output. This possible security hole has been plugged; when building MIME entities, you can specify a body path but suppress the filename in the header. *Thanks to Jason L. Tibbitts for suggesting this.* Bug fixes Win32 installations should work. The binmode() calls should work fine on Win32 now. *Thanks to numerous folks for their patches.* MIME::Head::add() now no longer downcases its argument. *Thanks to Brandon Browning & Jason L. Tibbitts for finding this bug.* Version 3.204 Bug in MIME::Head::original_text fixed. Well, it took a while, but another bug surfaced from my transition from 1.x to 2.x. This method was, quite idiotically, sorting the header fields. *Thanks, as usual, to Andreas Koenig for spotting this one.* MIME::ParserBase no longer defaults to RFC-1522-decoding headers. The documentation correctly stated that the default setting was to *not* RFC-1522-decode the headers. The code, on the other hand, was init'ing this parser option in the "on" position. This has been fixed. MIME::ParserBase::parse_nested_messages reexamined. If you use this feature, please re-read the documentation. It explains a little more precisely what the ramifications are. MIME::Entity tries harder to ensure MIME compliance. It is now a fatal error to use certain bad combinations of content type and encoding when "building", or to attempt to "attach" to anything that is not a multipart document. My apologies if this inconveniences anyone, but it was just too darn easy before for folks to create bad MIME, and gosh darn it, good libraries should at least *try* to protect you from mistakes. The "make" now halts if you don't have the right stuff, provided your MakeMaker supports PREREQ_PM. See the section on "REQUIREMENTS" for what you need to install this package. I still provide old courtesy copies of the MIME:: decoding modules. *Thanks to Hugo van der Sanden for suggesting this.* The "make test" is far less chatty. Okay, okay, STDERR is evil. Now a `"make test"' will just give you the important stuff: do a `"make test TEST_VERBOSE=1"' if you want the gory details (advisable if sending me a bug report). *Thanks to Andreas Koenig for suggesting this.* Version 3.203 No, there haven't been any major changes between 2.x and 3.x. The major-version increase was from a few more tweaks to get $VERSION to be calculated better and more efficiently (I had been using RCS version numbers in a way which created problems for users of CPAN::). After a couple of false starts, all modules have been upgraded to RCS 3.201 or higher. You can now parse a MIME message from a scalar, an array-of-scalars, or any MIME::IO-compliant object (including IO:: objects.) Take a look at parse_data() in MIME::ParserBase. The parser code has been modified to support the MIME::IO interface. *Thanks to fellow Chicagoan Tim Pierce (and countless others) for asking.* More sensible toolkit configuration. A new config() method in MIME::ToolUtils makes a lot of toolkit-wide configuration cleaner. Your old calls will still work, but with deprecation warnings. You can now sign messages just like in Mail::Internet. See MIME::Entity for the interface. You can now remove signatures from messages just like in Mail::Internet. See MIME::Entity for the interface. You can now compute/strip content lengths and other non-standard MIME fields. See sync_headers() in MIME::Entity. *Thanks to Tim Pierce for bringing the basic problem to my attention.* Many warnings are now silent unless $^W is true. That means unless you run your Perl with `-w', you won't see deprecation warnings, non-fatal-error messages, etc. But of course you run with `-w', so this doesn't affect you. `:-)' Completed the 7-bit encodings in MIME::Latin1. We hadn't had complete coverage in the conversion from 8- to 7-bit; now we do. *Thanks to Rolf Nelson for bringing this to my attention.* Fixed broken parse_two() in MIME::ParserBase. BTW, if your code worked with the "broken" code, it should *still* work. *Thanks again to Tim Pierce for bringing this to my attention.* Version 2.14 Just a few bug fixes to improve compatibility with Mail-Tools 1.08, and with the upcoming Perl 5.004 release. *Thanks to Jason L. Tibbitts III for reporting the problems so quickly.* Version 2.13 New features Added RFC-1522-style decoding of encoded header fields. Header decoding can now be done automatically during parsing via the new `decode()' method in MIME::Head... just tell your parser object that you want to `decode_headers()'. *Thanks to Kent Boortz for providing the idea, and the baseline RFC-1522- decoding code!* Building MIME messages is even easier. Now, when you use MIME::Entity's `build()' or `attach()', you can also supply individual mail headers to set (e.g., `-Subject', `-From', `- To'). Added `Disposition' to MIME::Entity's `build()' method. *Thanks to Kurt Freytag for suggesting this feature.* An `X-Mailer' header is now output by default in all MIME- Entity-prepared messages, so any bad MIME we generate can be traced back to this toolkit. Added `purge()' method to MIME::Entity for deleteing leftover files. *Thanks to Jason L. Tibbitts III for suggesting this feature.* Added `seek()' and `tell()' methods to built-in MIME::IO classes. Only guaranteed to work when reading! *Thanks to Jason L. Tibbitts III for suggesting this feature.* When parsing a multipart message with apparently no boundaries, the error message you get has been improved. *Thanks to Andreas Koenig for suggesting this.* Bug fixes Patched over a Perl 5.002 (and maybe earlier and later) bug involving FileHandle::new_tmpfile. It seems that the underlying filehandles were not being closed when the FileHandle objects went out of scope! There is now an internal routine that creates true FileHandle objects for anonymous temp files. *Thanks to Dragomir R. Radev and Zyx for reporting the weird behavior that led to the discovery of this bug.* MIME::Entity's `build()' method now warns you if you give it an illegal boundary string, and substitutes one of its own. MIME::Entity's `build()' method now generates safer, fully-RFC- 1521-compliant boundary strings. Bug in MIME::Decoder's `install()' method was fixed. *Thanks to Rolf Nelson and Nickolay Saukh for finding this.* Changed FileHandle::new_tmpfile to FileHandle->new_tmpfile, so some Perl installations will be happier. *Thanks to Larry W. Virden for finding this bug.* Gave `=over' an arg of 4 in all PODs. *Thanks to Larry W. Virden for pointing out the problems of bare =over's* Version 2.04 A bug in MIME::Entity's output method was corrected. MIME::Entity::print now outputs everything to the desired filehandle explicitly. *Thanks to Jake Morrison for pointing out the incompatibility with Mail::Header.* Version 2.03 Fixed bug in autogenerated filenames resulting from transposed "if" statement in MIME::Parser, removing spurious printing of header as well. (Annoyingly, this bug is invisible if debugging is turned on!) *Thanks to Andreas Koenig for bringing this to my attention.* Fixed bug in MIME::Entity::body() where it was using the bodyhandle completely incorrectly. *Thanks to Joel Noble for bringing this to my attention.* Fixed MIME::Head::VERSION so CPAN:: is happier. *Thanks to Larry Virden for bringing this to my attention.* Fixed undefined-variable warnings when dumping skeleton (happened when there was no Subject: line) *Thanks to Joel Noble for bringing this to my attention.* Version 2.02 Stupid, stupid bugs in both BASE64 encoding and decoding were fixed. *Thanks to Phil Abercrombie for locating them.* Version 2.01 Modules now inherit from the new Mail:: modules! This means big changes in behavior. MIME::Parser can now store message data in-core. There were a *lot* of requests for this feature. MIME::Entity can now compose messages. There were a *lot* of requests for this feature. Added option to parse `"message/rfc822"' as a pseduo-multipart document. *Thanks to Andreas Koenig for suggesting this.* Version 1.13 MIME::Head now no longer requires space after ":", although either a space or a tab after the ":" will be swallowed if there. *Thanks to Igor Starovoitov for pointing out this shortcoming.* Version 1.12 Fixed bugs in parser where CRLF-terminated lines were blowing out the handling of preambles/epilogues. *Thanks to Russell Sutherland for reporting this bug.* Fixed idiotic is_multipart() bug. *Thanks to Andreas Koenig for noticing it.* Added untested binmode() calls to parser for DOS, etc. systems. No idea if this will work... Reorganized the output_path() methods to allow easy use of inheritance, as per Achim Bohnet's suggestion. Changed MIME::Head to report mime_type more accurately. POSIX module no longer loaded by Parser if perl >= 5.002. Hey, 5.001'ers: let me know if this breaks stuff, okay? Added unsupported ./examples directory. Version 1.11 Converted over to using Makefile.PL. *Thanks to Andreas Koenig for the much-needed kick in the pants...* Added t/*.t files for testing. Eeeeeeeeeeeh...it's a start. Fixed bug in default parsing routine for generating output paths; it was warning about evil filenames if there simply *were* no recommended filenames. D'oh! Fixed redefined parts() method in Entity. Fixed bugs in Head where field name wasn't being case folded. Version 1.10 A typo was causing the epilogue of an inner multipart message to be swallowed to the end of the OUTER multipart message; this has now been fixed. *Thanks to Igor Starovoitov for reporting this bug.* A bad regexp for parameter names was causing some parameters to be parsed incorrectly; this has also been fixed. *Thanks again to Igor Starovoitov for reporting this bug.* It is now possible to get full control of the filenaming algorithm before output files are generated, and the default algorithm is safer. *Thanks to Laurent Amon for pointing out the problems, and suggesting some solutions.* Fixed illegal "simple" multipart test file. D'OH! Version 1.9 No changes: 1.8 failed CPAN registration Version 1.8 Fixed incompatibility with 5.001 and FileHandle::new_tmpfile Added COPYING file, and improved README. MIME-tools-5.509/t/0000755000076400007640000000000013071231525012005 5ustar dfsdfsMIME-tools-5.509/t/Ref.t0000644000076400007640000001467212775011742012727 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More; use MIME::Tools; use File::Path; use File::Spec; use File::Basename; use MIME::WordDecoder qw(unmime); use lib qw( ./t/ ); use Globby; use MIME::Parser; #print STDERR "\n"; ### Verify directory paths: (-d "testout") or die "missing testout directory\n"; my $output_dir = File::Spec->catdir(".", "testout", "Ref_t"); ### Get messages to process: my @refpaths = @ARGV; if (!@refpaths) { opendir DIR, "testmsgs" or die "opendir: $!\n"; @refpaths = map { File::Spec->catfile(".", "testmsgs", $_) } grep /\w.*\.ref$/, readdir(DIR); closedir DIR; } plan( tests => 2 * scalar(@refpaths) ); ### For each reference: foreach my $refpath (@refpaths) { ### Get message: my $msgpath = $refpath; $msgpath =~ s/\.ref$/.msg/; # print STDERR " $msgpath\n"; ### HACK HACK HACK: MailTools behaviour has changed!!! if ($msgpath =~ /hdr-fakeout.msg$/ && $::Mail::Header::VERSION > 2.14) { $refpath = 'testmsgs/hdr-fakeout-newmailtools-ref'; } ### Get reference, as ref to array: my $ref = read_ref($refpath); if ($ref->{Parser}{Message}) { $msgpath = File::Spec->catfile(".", (split /\//, $ref->{Parser}{Message})); } # diag("Trying $refpath [$msgpath]\n"); ### Create parser which outputs to testout/scratch: my $parser = MIME::Parser->new; $parser->output_dir($output_dir); $parser->extract_nested_messages($ref->{Parser}{ExtractNested}); $parser->extract_uuencode($ref->{Parser}{ExtractUuencode}); $parser->output_to_core(0); $parser->ignore_errors(0); ### Set character set: my $tgt = $ref->{Parser}{Charset} || 'ISO-8859-1'; my $wd; if ($tgt =~ /^ISO-8859-(\d+)/) { $wd = new MIME::WordDecoder::ISO_8859 $1; } else { $wd = new MIME::WordDecoder([uc($tgt) => 'KEEP', 'US-ASCII' => 'KEEP', '*' => 'WARN']); } # diag("Default charset: $tgt"); MIME::WordDecoder->default($wd); ### Pre-clean: rmtree($output_dir); (-d $output_dir) or mkpath($output_dir) or die "mkpath $output_dir: $!\n"; ### Parse: my $ent = eval { $parser->parse_open($msgpath) }; my $parse_error = $@; ### Output parse log: # diag("PARSE LOG FOR $refpath [$msgpath]"); if ($parser->results) { # diag($parser->results->msgs); } else { diag("Parse failed before results object was created"); } ### Interpret results: if ($parse_error || !$ent) { ok($ref->{Msg}{Fail}, "$refpath, problem: $parse_error" ); } else { # TODO: check_ref is evil my $ok = eval { check_ref($msgpath, $ent, $ref) }; if( $@ ) { diag("Eval failed: $@"); } ok($ok, "$refpath Message => $msgpath, Parser => " . ($ref->{Parser}{Name} || 'default')); } ### Is purge working? my @a_files = list_dir($output_dir); my @p_files = $parser->filer->purgeable; $parser->filer->purge; my @z_files = list_dir($output_dir); is(@z_files, 0, 'Did purge work?'); ### Cleanup for real: rmtree($output_dir); } ### Done! exit(0); 1; #------------------------------ sub list_dir { my $dir = shift; opendir DIR, $dir or die "opendir $dir; $!\n"; my @files = grep !/^\.+$/, readdir DIR; closedir DIR; return sort @files; } #------------------------------ sub read_ref { my $path = shift; open IN, "<$path" or die "open $path: $!\n"; my $expr = join('', ); close IN; my $ref = eval $expr; $@ and die "syntax error in $path\n"; $ref; } #------------------------------ sub trim { local $_ = shift; s/^\s*//; s/\s*$//; $_; } #------------------------------ # TODO: replace with cmp_deeply from Test::Deep? sub check_ref { my ($msgpath, $ent, $ref) = @_; my $wd = supported MIME::WordDecoder 'UTF-8'; ### For each Msg in the ref: MSG: foreach my $partname (sort keys %$ref) { $partname =~ /^(Msg|Part_)/ or next; my $msg_ref = $ref->{$partname}; my $part = get_part($ent, $partname) || die "no such part: $partname\n"; my $head = $part->head; $head->unfold; my $body = $part->bodyhandle; ### For each attribute in the Msg: ATTR: foreach (sort keys %$msg_ref) { my $want = $msg_ref->{$_}; my $got = undef; if (/^Boundary$/) { $got = $head->multipart_boundary; } elsif (/^From$/) { $got = trim($head->get("From", 0)); $want = trim($want); } elsif (/^To$/) { $got = trim($head->get("To", 0)); $want = trim($want); } elsif (/^Subject$/) { $got = trim($head->get("Subject", 0)); $want = trim($want); } elsif (/^Charset$/) { $got = $head->mime_attr("content-type.charset"); } elsif (/^Disposition$/) { $got = $head->mime_attr("content-disposition"); } elsif (/^Type$/) { $got = $head->mime_type; } elsif (/^Encoding$/) { $got = $head->mime_encoding; } elsif (/^Filename$/) { $got = $head->recommended_filename; } elsif (/^BodyFilename$/) { $got = (($body and $body->path) ? basename($body->path) : undef); } elsif (/^Preamble$/) { $got = join('', @{$part->preamble}); } elsif (/^Epilogue$/) { $got = join('', @{$part->epilogue}); } elsif (/^Size$/) { if ($head->mime_type =~ m{^(text|message)}) { # diag("Skipping Size evaluation in text message ". # "due to variations in local newline ". # "conventions\n\n"); next ATTR; } if ($body and $body->path) { $got = (-s $body->path) } } else { die "$partname: unrecognized reference attribute: $_\n"; } ### Log this sub-test: # diag("SUB-TEST: msg=$msgpath; part=$partname; attr=$_:\n"); # diag(" want: ".encode($want)."\n"); # diag(" got: ".encode($got )."\n"); # diag("\n"); next ATTR if (!defined($want) and !defined($got)); next ATTR if ($want eq $got); die "$partname: wanted qq{$want}, got qq{$got}\n"; } } 1; } # Encode a string sub encode { local $_ = shift; return '' if !defined($_); s{([\n\t\x00-\x1F\x7F-\xFF\\\"])} {'\\'.sprintf("%02X",ord($1)) }exg; s{\\0A}{\\n}g; return qq{"$_"}; } #------------------------------ sub get_part { my ($ent, $name) = @_; if ($name eq 'Msg') { return $ent; } elsif ($name =~ /^Part_(.*)$/) { my @path = split /_/, $1; my $part = $ent; while (@path) { my $i = shift @path; $part = $part->parts($i - 1); } return $part; } undef; } 1; MIME-tools-5.509/t/ticket-22684.t0000644000076400007640000000256512541013575014154 0ustar dfsdfs#!/usr/bin/perl use Test::More tests => 3; use MIME::Decoder; use IO::File; # Ticket 22684 - use select() for IO multiplexing (to prevent filter() deadlock) SKIP: { skip "Need Proc::ProcessTable for this test", 3 unless eval "use Proc::ProcessTable; 1;"; require MIME::Decoder::Gzip64; install MIME::Decoder::Gzip64 'x-gzip64'; my $input_data = ''; for(1..(1024 * 512)) { $input_data .= chr(int(rand(256))); } my $input_fh = IO::File->new(\$input_data, '<:scalar'); my $output_data = ''; my $output_fh = IO::File->new(\$output_data, '>:scalar'); my $decoder = MIME::Decoder->new('x-gzip64'); eval { local $SIG{ALRM} = sub { die 'timeout' }; alarm(20); $decoder->encode( $input_fh, $output_fh ); alarm(0); }; my $error = ''; my $bad_kids = 0; if( $@ ) { $error = $@; my $pt = Proc::ProcessTable->new(); my @children = grep { $_->ppid == $$ } @{$pt->table()}; foreach my $c (@children) { diag('Killing wayward child '. $c->pid . ' (' . $c->cmndline . ')'); kill('TERM', $c->pid); $bad_kids++; } } # If we didn't deadlock, we should complete in a timely manner and produce # output. MIME-encoded gzipped randomness should be nearly as large, if not # larger, than the input data. unlike( $error, qr/^timeout/, '->encode completed within 20s'); is( $bad_kids, 0, 'No wayward gzip children'); cmp_ok( length($output_data), '>=', 400_000, 'Output data was generated'); } MIME-tools-5.509/t/ticket-60931.t0000644000076400007640000000161612541013575014145 0ustar dfsdfs#!/usr/bin/perl use Test::More tests => 2; use MIME::Parser; # RT#60931: Printing of empty preamble added extra newline before first boundary my $original = do { local $/; }; close(DATA); my $generated = ''; my $fh = IO::File->new( \$generated, ">:" ); my $parser = MIME::Parser->new(); $parser->output_to_core(1); my $entity = $parser->parse_data($original); isa_ok( $entity, 'MIME::Entity'); $entity->print($fh); $fh->close; is( $original, $generated, 'Message with empty preamble roundtrips back to original'); __DATA__ MIME-Version: 1.0 Received: by 10.220.78.157 with HTTP; Thu, 26 Aug 2010 21:33:17 -0700 (PDT) Content-Type: multipart/alternative; boundary=90e6ba4fc6ea25d329048ec69d99 --90e6ba4fc6ea25d329048ec69d99 Content-Type: text/plain; charset=ISO-8859-1 HELLO --90e6ba4fc6ea25d329048ec69d99 Content-Type: text/html; charset=ISO-8859-1 HELLO
--90e6ba4fc6ea25d329048ec69d99-- MIME-tools-5.509/t/ticket-43439.t0000644000076400007640000000104612541013575014146 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 4; # Handle a double semicolon in the Content-Type: header use MIME::Head; my $head = MIME::Head->new->from_file('testmsgs/double-semicolon.msg'); is ($head->mime_type, 'multipart/alternative', 'Got expected MIME type'); is ($head->multipart_boundary, 'foo', 'Got expected boundary'); $head = MIME::Head->new->from_file('testmsgs/double-semicolon2.msg'); is ($head->mime_type, 'multipart/alternative', 'Got expected MIME type'); is ($head->multipart_boundary, 'foo', 'Got expected boundary'); MIME-tools-5.509/t/attachment-filename-encoding.t0000644000076400007640000000522612541013575017675 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More; use File::Temp qw(tempdir); use utf8; binmode STDOUT, ":utf8"; binmode STDERR, ":utf8"; plan tests => 7; main: { #-- Load MIME::Parser use_ok("MIME::Parser"); #-- Prepare parser my $parser = MIME::Parser->new(); $parser->output_to_core(1); #-- Parse message file with attachment filename in Latin1 my $msgfile = "testmsgs/attachment-filename-encoding-Latin1.msg"; my $entity = parse_attachment_msg($parser, $msgfile); #-- Check if parsed recommended filename is in UTF-8 my $filename = find_attachment_filename($entity); is(utf8::is_utf8($filename), 1, "Parsed filename should have UTF-8 flag on"); #-- Check if parsed recommended filename matches the expected string is($filename, "attachment.äöü", "Parsed filename should match expectation"); #-- Parse message file with attachment filename in Latin1 $msgfile = "testmsgs/attachment-filename-encoding-UTF8.msg"; $entity = parse_attachment_msg($parser, $msgfile); #-- Check if parsed recommended filename is in UTF-8 $filename = find_attachment_filename($entity); is(utf8::is_utf8($filename), 1, "Parsed filename should have UTF-8 flag on"); #-- Check if parsed recommended filename matches the expected string is($filename, "attachment.äöü", "Parsed filename should match expectation"); # CPAN ticket #65162 # We need the default parser to tickle the bug my $dir = tempdir(CLEANUP => 1); $parser = MIME::Parser->new(); $parser->output_to_core(0); $parser->output_under($dir); $entity = $parser->parse_data("From: test\@example.com\nSubject: test\nDate: Tue, 25 Jan 2011 14:35:04 +0100\nMessage-Id: <123\@example.com>\nContent-Type: text/plain; name*=utf-8''%CE%B2CURE%2Etxt\n\ntest\n"); $filename = $entity->head->recommended_filename; is(utf8::is_utf8($filename), 1, "Parsed filename should have UTF-8 flag on"); is($filename, "\x{3b2}CURE.txt", 'Got expected filename'); } #-- Parse quoted printable file and return MIME::Entity sub parse_attachment_msg { my $parser = shift; my $msgfile = shift; open (my $fh, $msgfile) or die "can't open $msgfile: $!"; my $entity = $parser->parse($fh); close $fh; return $entity; } sub find_attachment_filename { my $entity = shift; return '' unless $entity; if ($entity->is_multipart) { foreach my $subpart ($entity->parts) { my $filename = find_attachment_filename($subpart); return $filename if $filename; } } else { my $head = $entity->head; my $rfn = $head->recommended_filename; return $rfn if $rfn; } return ''; } 1; MIME-tools-5.509/t/ticket-119568.t0000644000076400007640000001155013071230463014232 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 4; use MIME::Entity; use MIME::Parser; use lib qw( ./t ); my $e = MIME::Entity->build(From => 'dfs@roaringpenguin.com', To => 'dfs2@roaringpenguin.com', Subject => 'End-of-line test', Data => ["Line 1\n", "Line 2\n"],); my $str = $e->as_string(); is ($str, "Content-Type: text/plain\nContent-Disposition: inline\nContent-Transfer-Encoding: binary\nMIME-Version: 1.0\nX-Mailer: MIME-tools 5.509 (Entity 5.509)\nFrom: dfs\@roaringpenguin.com\nTo: dfs2\@roaringpenguin.com\nSubject: End-of-line test\n\nLine 1\nLine 2\n", 'Got expected line endings'); my $delim = "\r\n"; $MIME::Entity::BOUNDARY_DELIMITER = $delim; $e = MIME::Entity->build(From => 'dfs@roaringpenguin.com', To => 'dfs2@roaringpenguin.com', Subject => 'End-of-line test', Data => ["Line 1$delim", "Line 2$delim"],); $str = $e->as_string(); is ($str, "Content-Type: text/plain${delim}Content-Disposition: inline${delim}Content-Transfer-Encoding: binary${delim}MIME-Version: 1.0${delim}X-Mailer: MIME-tools 5.509 (Entity 5.509)${delim}From: dfs\@roaringpenguin.com${delim}To: dfs2\@roaringpenguin.com${delim}Subject: End-of-line test${delim}${delim}Line 1${delim}Line 2${delim}", 'Got expected line endings'); $e->attach(Data => ["More Text$delim"], Type => "text/plain"); $e = MIME::Entity->build(From => 'dfs@roaringpenguin.com', To => 'dfs2@roaringpenguin.com', Subject => 'End-of-line test', Type => 'multipart/mixed', Boundary => 'foo'); $e->attach(Data => ["Text$delim"], Type => "text/plain"); $e->attach(Data => ["More Text$delim"], Type => "text/plain"); $str = $e->as_string(); is ($str, "Content-Type: multipart/mixed; boundary=\"foo\"${delim}Content-Transfer-Encoding: binary${delim}MIME-Version: 1.0${delim}X-Mailer: MIME-tools 5.509 (Entity 5.509)${delim}From: dfs\@roaringpenguin.com${delim}To: dfs2\@roaringpenguin.com${delim}Subject: End-of-line test${delim}${delim}This is a multi-part message in MIME format...${delim}${delim}--foo${delim}Content-Type: text/plain${delim}Content-Disposition: inline${delim}Content-Transfer-Encoding: binary${delim}${delim}Text${delim}${delim}--foo${delim}Content-Type: text/plain${delim}Content-Disposition: inline${delim}Content-Transfer-Encoding: binary${delim}${delim}More Text${delim}${delim}--foo--${delim}", 'Got expected line endings'); $e = MIME::Entity->build(From => 'dfs@roaringpenguin.com', To => 'dfs2@roaringpenguin.com', Subject => 'End-of-line test', Type => 'multipart/mixed', Boundary => 'foo'); $e->attach(Data => ["Text\n"], Type => "text/plain", Encoding => 'Base64'); $e->attach(Data => ["More Text\n", 'LongLine' x 120], Type => "text/plain", Encoding => 'Base64'); $str = $e->as_string(); is ($str, "Content-Type: multipart/mixed; boundary=\"foo\"${delim}Content-Transfer-Encoding: binary${delim}MIME-Version: 1.0${delim}X-Mailer: MIME-tools 5.509 (Entity 5.509)${delim}From: dfs\@roaringpenguin.com${delim}To: dfs2\@roaringpenguin.com${delim}Subject: End-of-line test${delim}${delim}This is a multi-part message in MIME format...${delim}${delim}--foo${delim}Content-Type: text/plain${delim}Content-Disposition: inline${delim}Content-Transfer-Encoding: Base64${delim}${delim}VGV4dAo=${delim}${delim}--foo${delim}Content-Type: text/plain${delim}Content-Disposition: inline${delim}Content-Transfer-Encoding: Base64${delim}${delim}TW9yZSBUZXh0CkxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9u${delim}Z0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5l${delim}TG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdM${delim}aW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxv${delim}bmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGlu${delim}ZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25n${delim}TGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVM${delim}b25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xp${delim}bmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9u${delim}Z0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5l${delim}TG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdM${delim}aW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxv${delim}bmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGlu${delim}ZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25n${delim}TGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVM${delim}b25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xp${delim}bmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9u${delim}Z0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5l${delim}TG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdM${delim}aW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZUxv${delim}bmdMaW5lTG9uZ0xpbmVMb25nTGluZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGlu${delim}ZUxvbmdMaW5lTG9uZ0xpbmVMb25nTGluZQ==${delim}${delim}--foo--${delim}", 'Got expected line endings for Base64 encoding'); MIME-tools-5.509/t/Smtpsend.t0000644000076400007640000000420612541013575013775 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Config; use Test::More; $ENV{MAILDOMAIN}='example.com'; my $can_fork = $Config{d_fork} || $Config{d_pseudofork} || (($^O eq 'MSWin32' || $^O eq 'NetWare') and $Config{useithreads} and $Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/); if ($can_fork) { plan tests => 9; } else { plan skip_all => 'This system cannot fork'; } use MIME::Tools; use MIME::Entity; use IO::Socket::INET; # Listen on port 5225 to pretend to be an SMTP server my $sock = IO::Socket::INET->new(Listen => 5, LocalAddr => 'localhost:5225', ReuseAddr => 1, Type => SOCK_STREAM, Timeout => 10, Proto => 'tcp'); die("can't create socket: $!") unless $sock; my $top = MIME::Entity->build( Type => 'multipart/mixed', From => 'devnull@roaringpenguin.com', To => 'devnull@roaringpenguin.com', Subject => 'smtpsend test'); $top->attach( Data => 'plain', Type => 'text/plain'); my $pid = fork(); if (!defined($pid)) { die("fork() failed: $!"); } if (!$pid) { # In the child sleep(1); $top->smtpsend(Host => '127.0.0.1', Port => 5225); exit(0); } # In the parent my $s = $sock->accept(); if (!$s) { sleep(1); $s = $sock->accept(); if (!$s) { kill(9, $pid); die("accept failed: $!"); } } $s->print("220 Go ahead\n"); $s->flush(); my $line = $s->getline(); like($line, qr/^EHLO/i); $s->print("220 Hi there\n"); $s->flush(); $line = $s->getline(); like($line, qr/^MAIL/i); $s->print("220 OK\n"); $s->flush(); $line = $s->getline(); like($line, qr/^RCPT/i); $s->print("220 OK\n"); $s->flush(); $line = $s->getline(); like($line, qr/^DATA/i); $s->print("311 Send it\n"); $s->flush(); my $body = ''; while(<$s>) { last if ($_ =~ /^\./); $body .= $_; } $s->print("220 Got it all; thanks\n"); $s->flush(); $line = $s->getline(); like($line, qr/^QUIT/i); $s->print("220 See ya\n"); $s->flush(); $s->close(); my @lines = split("\n", $body); # Get the end of headers while($lines[0] ne "\r") { shift(@lines); } shift(@lines); is(scalar(@lines), 9); is($lines[0], "This is a multi-part message in MIME format...\r"); is($lines[3], "Content-Type: text/plain\r"); is($lines[7], "plain\r"); MIME-tools-5.509/t/ticket-11901.t0000644000076400007640000000720512541013575014136 0ustar dfsdfs#!/usr/bin/perl use Test::More tests => 2; use MIME::Parser; # Ticket 11901 - malformed multipart/mixed caused remove_sig() to die. my $entity = MIME::Parser->new->parse(\*DATA); isa_ok( $entity, 'MIME::Entity'); is($entity->remove_sig(), undef, "Can't remove sig from broken message"); __DATA__ Return-Path: X-Original-To: info2001@lists.sch.bme.hu Delivered-To: info2001@lists.sch.bme.hu Received: by lists.sch.bme.hu (Postfix, from userid 102) id 1CDBB11E21; Mon, 14 Mar 2005 22:41:52 +0100 (CET) Received: from lists.sch.bme.hu ([127.0.0.1]) by localhost (kaa.sch.bme.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 25096-10 for ; Mon, 14 Mar 2005 22:41:50 +0100 (CET) Received: from balu.sch.bme.hu (balu.sch.bme.hu [152.66.208.40]) by lists.sch.bme.hu (Postfix) with ESMTP id 8D03D11E21 for ; Mon, 14 Mar 2005 22:41:50 +0100 (CET) Received: from 69.183.13.242.adsl.snet.net ([69.183.13.242]) by balu.sch.bme.hu (Sun ONE Messaging Server 6.0 Patch 1 (built Jan 28 2004)) with SMTP id <0IDD00LL92XIUK80@balu.sch.bme.hu> for info2001@lists.sch.bme.hu (ORCPT info2001@sch.bme.hu); Mon, 14 Mar 2005 22:41:50 +0100 (CET) Received: from 99.94.255.218 by 69.183.13.242.adsl.snet.net Mon, 14 Mar 2005 08:30:34 -0800 Date: Mon, 14 Mar 2005 11:19:01 -0800 From: Justine Cornett To: info2001@sch.bme.hu Message-id: <426080426772888074962@email.msn.com> MIME-version: 1.0 X-Mailer: diana 65.261.2493443 Content-type: multipart/mixed; boundary="Boundary_(ID_tz+jdqVflLNHHe1DVt0NoA)" X-Priority: 3 X-IP: 139.190.7.62 Spam-test: True ; 7.0 / 5.0 ; ALL_TRUSTED,BAYES_99,BIZ_TLD,HTML_30_40,HTML_FONT_TINY,HTML_MESSAGE,LONGWORDS,PLING_QUERY,RCVD_BY_IP,RCVD_DOUBLE_IP_LOOSE,URIBL_SBL,URIBL_WS_SURBL X-Virus-Scanned: by amavisd-new at kaa.sch.bme.hu Subject: [info2001] Have you heard of Rolex Timepieces ? Come on in ! [propel] Reply-To: info2001@sch.bme.hu X-Loop: info2001@sch.bme.hu X-Sequence: 19626 Errors-to: info2001-owner@sch.bme.hu Precedence: list X-no-archive: yes List-Id: List-Id: List-Help: List-Subscribe: List-Unsubscribe: List-Post: List-Owner: List-Archive: ë÷M7ß½¼ß]º ‰íz{Sʗ­{†Ù¥r«±ëºÆ¬r(‚¢{^žÔëj{z±'r‡bžŠØmšVèw#ږ('qéµêÅ8ÔÜ¢Z+}ýÓM…©äʋŸ¢¼¨º¸§µê޲اEêe‰Æ–j×!zÃÃ…8Ôÿ=دjX ÂǞ׫Þ~¶Ÿÿ²ˆñ’Û$~ö–GáŠwèý+Âê.³­raz·¿v+ÃjX ÂǞ׫ãSr‰h­÷ÓM4!ü¨ºÇžj|­†)à¶­š(!¶)íz·¬·*.¢¸ŸÊ‹¡j÷šŸ*®zËb¢{)•æ¬yÚ'¶¬ŠÖ­zÚ/ŠÈ­¢êðy»"µæ­üÿÅ8ÔÃjX ÂǞ׫Þ~¶Ÿÿ¥×¯më-¡ûay¸³ü̎8Ã¥Âæ'È1·*ç©–'ë\…ëk6«üÃn¶ën»)j{-ÊWãSH†DߚmãS-€+‰©\­©ÞŠºÞ¦Vœy¦åzšw'墊ڙ§^ºË^†¶§ž'!¢V¬¦‹-êۮÚânëZ¯(–X®š «¹Ú(®Ièm¶¥Ã§/j«Ê‹Þ¸«v §Ÿ+kj隶ë$…æ¥v+-ŠY^¯&ëªëzÛlŠ{¨ºÆ«nŠÞ¶é¦¢Ê®y©eºÈ¯zÊ(¶ڂ§‚›­·'^z—š­ÚîšØ^²˜šÂÊ%¢fèz˜œº·¬ªçžÂ眡ÊjV¬‘ªh—+^rârÜ"µÈr™©º»nëmz·ÚµºïjW§¶)ÞjZlž‹mŠx!jfëþÊZŸöèw/á¶ië}ÓM֕o7×n‚¢{^žÔò¥ë^Æß镨§r«±ëºÆ¬r(‚¢{^žÔëj{z±'r‡bžۊÔh•ìb³Z´ŒžÜ¨ºÚ0yªü÷®zÓ­5îm§ÿîÊ8ò½ÉÛª'lžÆâÃúˆ²Æ8­úõõ§ª¢j­ª8¥ë÷M7ß½¼ß]º --Boundary_(ID_tz+jdqVflLNHHe1DVt0NoA)-- MIME-tools-5.509/t/Entity.t0000644000076400007640000002263012541013575013455 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 39; use MIME::Entity; use MIME::Parser; use lib qw( ./t ); use Globby; # TODO: WTF? my $line; my $LINE; #diag("Testing build()"); {local $SIG{__WARN__} = sub { die "caught warning: ",@_ }; { my $e = MIME::Entity->build(Path => "./testin/short.txt"); my $name = 'short.txt'; my $got; #-----test------ $got = $e->head->mime_attr('content-type.name'); is($got, $name, 'Path: with no Filename, got default content-type.name'); #-----test------ $got = $e->head->mime_attr('content-disposition.filename'); is($got, $name, 'Path: with no Filename, got default content-disp.filename'); #-----test------ $got = $e->head->recommended_filename; is($got, $name, 'Path: with no Filename, got default recommended filename'); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/short.txt", Filename => undef); my $got = $e->head->mime_attr('content-type.name'); ok(!$got, 'Path: with explicitly undef Filename, got no filename'); my $x = $e->stringify(); my $version = $MIME::Entity::VERSION; my $desired = "Content-Type: text/plain\nContent-Disposition: inline\nContent-Transfer-Encoding: binary\nMIME-Version: 1.0\nX-Mailer: MIME-tools $version (Entity $version)\n\nDear «François Müller»,\n\nAs you requested, I have rewritten the MIME:: parser modules to support\nthe creation of MIME messages.\n\nEryq\n"; is($x, $desired, 'Tested stringify'); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/short.txt", Filename => "foo.txt"); my $got = $e->head->mime_attr('content-type.name'); is($got, "foo.txt", "Path: verified explicit 'Filename'" ); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/sig" ); my $got = $e->head->mime_attr('content-type'); is($got, 'text/plain', 'Type: default ok'); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/sig", Type => "text/foo"); my $got = $e->head->mime_attr('content-type'); is($got, 'text/foo', 'Type: explicit ok'); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/sig", Encoding => '-SUGGEST'); my $got = $e->head->mime_attr('content-transfer-encoding'); is($got, '7bit', 'Encoding: -SUGGEST yields 7bit'); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/short.txt", Encoding => '-SUGGEST'); my $got = $e->head->mime_attr('content-transfer-encoding'); is($got, 'quoted-printable', 'Encoding: -SUGGEST yields qp'); } { #-----test------ my $e = MIME::Entity->build(Type => 'image/gif', Path => "./testin/mime-sm.gif", Encoding => '-SUGGEST'); my $got = $e->head->mime_attr('content-transfer-encoding'); is($got, 'base64', 'Encoding: -SUGGEST yields base64'); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/short.txt" ); my $got = $e->head->mime_attr('content-type.charset'); ok(!$got, 'Charset: default ok'); } { #-----test------ my $e = MIME::Entity->build(Path => "./testin/short.txt", Charset => 'iso8859-1'); my $got = $e->head->mime_attr('content-type.charset'); is($got, 'iso8859-1', 'Charset: explicit'); } { #-----test------ my $croaked = 1; eval { my $e = MIME::Entity->build(Type => 'message/rfc822', Encoding => 'base64', Data => "Subject: phooey\n\nBlat\n"); $croaked = 0; }; ok($croaked, 'MIME::Entity->build croaked on message/rfc822 with base64 encoding'); ok($@ =~ /can't have encoding base64 for message type message\/rfc822/, 'and it croaked with expected error.'); } { #-----test------ my $croaked = 1; eval { my $e = MIME::Entity->build(Type => 'message/global', Encoding => 'base64', Data => "Subject: phooey\n\nBlat\n"); $croaked = 0; }; ok(!$croaked, 'MIME::Entity->build did not croak on message/global with base64 encoding'); } { #-----test------ my $croaked = 1; eval { my $e = MIME::Entity->build(Type => 'multipart/ALTERNATIVE', Encoding => 'base64', Data => "Subject: phooey\n\nBlat\n"); $croaked = 0; }; ok($croaked, 'MIME::Entity->build croaked on multipart/alternative with base64 encoding'); ok($@ =~ /can't have encoding base64 for message type multipart\/ALTERNATIVE/, 'and it croaked with expected error.'); } } #diag("Create an entity"); # Create the top-level, and set up the mail headers in a couple # of different ways: my $top = MIME::Entity->build(Type => "multipart/mixed", -From => "me\@myhost.com", -To => "you\@yourhost.com"); $top->head->add('subject', "Hello, nurse!"); $top->preamble([]); $top->epilogue([]); # Attachment #0: a simple text document: attach $top Path=>"./testin/short.txt"; # Attachment #1: a GIF file: attach $top Path => "./testin/mime-sm.gif", Type => "image/gif", Encoding => "base64", Disposition => "attachment"; # Attachment #2: a document we'll create manually: my $attach = new MIME::Entity; $attach->head(new MIME::Head ["X-Origin: fake\n", "Content-transfer-encoding: quoted-printable\n", "Content-type: text/plain\n"]); $attach->bodyhandle(new MIME::Body::Scalar); my $io = $attach->bodyhandle->open("w"); $io->print(<close; $top->add_part($attach); # Attachment #3: a document we'll create, not-so-manually: $LINE = "This is the first and last line, with no CR at the end."; $attach = attach $top Data=>$LINE; #-----test------ unlink globby("testout/entity.msg*"); #diag("Check body"); my $bodylines = $top->parts(0)->body; is( ref $bodylines, 'ARRAY', '->body returns an array reference'); is( scalar @$bodylines, 6, '... of the correct size'); my $preamble_str = join '', @{$top->preamble || []}; my $epilogue_str = join '', @{$top->epilogue || []}; #diag("Output msg1 to explicit filehandle glob"); open TMP, ">testout/entity.msg1" or die "open: $!"; $top->print(\*TMP); close TMP; #-----test------ ok(-s "testout/entity.msg1", "wrote msg1 to filehandle glob"); #diag("Output msg2 to selected filehandle"); open TMP, ">testout/entity.msg2" or die "open: $!"; my $oldfh = select TMP; $top->print; select $oldfh; close TMP; #-----test------ ok(-s "testout/entity.msg2", "write msg2 to selected filehandle"); #diag("Compare"); # Same? is(-s "testout/entity.msg1", -s "testout/entity.msg2", "message files are same length"); #diag("Parse it back in, to check syntax"); my $parser = new MIME::Parser; $parser->output_dir("testout"); open IN, "./testout/entity.msg1" or die "open: $!"; $top = $parser->parse(\*IN); #diag($parser->results->msgs); #-----test------ ok($top, "parsed msg1 back in"); my $preamble_str2 = join '', @{$top->preamble || []}; my $epilogue_str2 = join '', @{$top->epilogue || []}; #-----test------ is($preamble_str, $preamble_str2, 'preamble strings match'); #-----test------ is($epilogue_str, $epilogue_str2, "epilogue strings match"); #diag("Check the number of parts"); is($top->parts, 4, "number of parts is correct (4)"); #diag("Check attachment 1 [the GIF]"); my $gif_real = (-s "./testin/mime-sm.gif"); my $gif_this = (-s "./testout/mime-sm.gif"); #-----test------ is($gif_real, $gif_this, "GIF is right size (real = $gif_real, this = $gif_this)"); my $part = ($top->parts)[1]; #-----test------ is($part->head->mime_type, 'image/gif', "GIF has correct MIME type"); #diag("Check attachment 3 [the short message]"); $part = ($top->parts)[3]; $io = $part->bodyhandle->open("r"); $line = ($io->getline); $io->close; #-----test------ is($line, $LINE, "getline gets correct value (IO = $io, <$line>, <$LINE>)"); #-----test------ is($part->head->mime_type, 'text/plain', "MIME type okay"); #-----test------ is($part->head->mime_encoding, 'binary', "MIME encoding okay"); #diag("Write it out, and compare"); open TMP, ">testout/entity.msg3" or die "open: $!"; $top->print(\*TMP); close TMP; #-----test------ is(-s 'testout/entity.msg2', -s 'testout/entity.msg3', 'msg2 same size as msg3'); #diag("Duplicate"); my $dup = $top->dup; open TMP, ">testout/entity.dup3" or die "open: $!"; $dup->print(\*TMP); close TMP; my $msg3_s = -s "testout/entity.msg3"; my $dup3_s = -s "testout/entity.dup3"; #-----test------ is($msg3_s, $dup3_s, "msg3 size ($msg3_s) is same as dup3 size ($dup3_s)"); #diag("Test signing"); $top->sign(File=>"./testin/sig"); $top->remove_sig; $top->sign(File=>"./testin/sig2", Remove=>56); $top->sign(File=>"./testin/sig3"); #diag("Write it out again, after synching"); $top->sync_headers(Nonstandard=>'ERASE', Length=>'COMPUTE'); open TMP, ">testout/entity.msg4" or die "open: $!"; $top->print(\*TMP); close TMP; ## Test that parts() replacement works my @newparts = $top->parts; pop @newparts; $top->parts( \@newparts ); is($top->parts, 3, "number of parts is correct (3)"); $bodylines = $top->parts(0)->body; is( ref $bodylines, 'ARRAY', '->body returns an array reference'); is( scalar @$bodylines, 12, '... of the correct size (12 incl. signature)'); $part = ($top->parts)[1]; #-----test------ is($part->head->mime_type, 'image/gif', "GIF has correct MIME type"); #diag("Purge the files"); $top->purge; #-----test------ ok(!-e "./testout/mime-sm.gif", "purge worked"); 1; MIME-tools-5.509/t/Gauntlet.t0000644000076400007640000000543512541013575013770 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 63; use MIME::Parser; # Are on a machine where binmode matters? my $txtmode = "./testout/textmode"; open TEXTMODE, ">$txtmode" or die "open textmode file!"; print TEXTMODE "abc\ndef\nghi\n"; close TEXTMODE; my $uses_crlf = ((-s $txtmode) == 12) ? 0 : 1; # Actual length of message: my $MSGLEN = 669; my $MSGLINES = 20; my $MSGLEN_text = $MSGLEN + ($uses_crlf * $MSGLINES); # Gout... sub gout { my ($h, $ent) = @_; my $test; my $pos1; my $pos2; no strict 'refs'; my $sh = (ref($h) ? $h : \*$h); print $sh "\n", "=" x 30, " ", ($test = "ent->print"), "\n"; $pos1 = tell($sh); eval { $ent->print($h) }; $pos2 = tell($sh); ok((!$@ and (($pos2 - $pos1) == $MSGLEN_text)), "$h, $test [$pos1-$pos2 == $MSGLEN_text]"); print $sh "\n", "=" x 30, " ", ($test = "print ent->as_string"), "\n"; $pos1 = tell($sh); eval { print $h $ent->as_string }; $pos2 = tell($sh); ok((!$@ and (($pos2 - $pos1) == $MSGLEN_text)), "$h, $test [$pos1-$pos2]"); print $sh "\n", "=" x 30, " ", ($test = "ent->print_header"), "\n"; eval { $ent->print_header($h) }; ok(!$@, "$h, $test: $@"); print $sh "\n", "=" x 30, " ", ($test = "ent->print_body"), "\n"; eval { $ent->print_body($h) }; ok(!$@, "$h, $test: $@"); print $sh "\n", "=" x 30, " ", ($test = "ent->bodyhandle->print"), "\n"; eval { $ent->bodyhandle->print($h) }; ok(!$@, "$h, $test: $@"); print $sh "\n", "=" x 30, " ",($test = "print ent->bodyhandle->data"),"\n"; eval { print $h $ent->bodyhandle->data }; ok(!$@, "$h, $test: $@"); 1; } # Loops: # When adjusting these, make sure to increment test count. Should be: # 21 * scalar @corelims * scalar @msgfiles my @msgfiles = qw(simple.msg); my @corelims = qw(ALL NONE 512); # Create a parser: my $parser = new MIME::Parser; $parser->output_dir("./testout"); # For each message: my $msgfile; foreach $msgfile (@msgfiles) { my $corelim; foreach $corelim (@corelims) { # Set opt: $parser->output_to_core($corelim); # Parse: my $ent = $parser->parse_open("./testin/$msgfile"); my $out = "./testout/gauntlet.out"; my $outsize = 3201 + ($uses_crlf * 97); # Open output stream 1: open GOUT, ">$out" or die "$!"; gout('::GOUT', $ent); close GOUT; my $s1 = -s $out; is($s1, $outsize, "BARE FH: size $out ($s1) == $outsize?"); # Open output stream 2: open GOUT, ">$out" or die "$!"; gout(\*GOUT, $ent); close GOUT; my $s2 = -s $out; is($s2, $outsize, "GLOB ref: size $out ($s2) == $outsize?"); # Open output stream 3: my $GOUT = IO::File->new($out, '>') || die "$!"; gout($GOUT, $ent); $GOUT->close; my $s3 = -s $out; is($s3, $outsize, "IO::File: size $out ($s3) == $outsize?"); } } 1; MIME-tools-5.509/t/02-pod-coverage.t0000644000076400007640000000042712541013575014773 0ustar dfsdfsuse Test::More; plan skip_all => 'Test::Pod::Coverage disabled. TEST_POD_COVERAGE=1 if you want it.' unless $ENV{TEST_POD_COVERAGE}; eval "use Test::Pod::Coverage 1.00"; plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage" if $@; all_pod_coverage_ok(); MIME-tools-5.509/t/obfuscated-zip.t0000644000076400007640000000075312225564741015127 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 2; # Handle a missing type in the Content-Type: header use MIME::Parser; my $parser = MIME::Parser->new(); $parser->output_to_core(0); $parser->output_under("testout"); my $entity = $parser->parse_open("testmsgs/malformed-content-type-zip.msg"); is(scalar($entity->parts), 2, 'Entity has two parts'); is($entity->parts(1)->head->mime_attr('content-type.name'), 'payroll_report_429047_10092013.zip', 'Got expected attachment name'); 1; MIME-tools-5.509/t/ParserPreamble.t0000644000076400007640000000172412541013575015106 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 7; use Test::Deep; my %files = ( 'testmsgs/empty-preamble.msg' => [ '' ], 'testmsgs/multi-simple.msg' => [ "This is the preamble. It is to be ignored, though it\n", "is a handy place for mail composers to include an\n", "explanatory note to non-MIME conformant readers." ], 'testmsgs/ticket-60931.msg' => [ ], ); #-- Load MIME::Parser use_ok("MIME::Parser"); #-- Prepare parser my $parser = MIME::Parser->new(); $parser->output_to_core(1); $parser->decode_bodies(0); foreach my $file (keys %files) { #-- Parse quoted-printable encoded file open (my $fh, $file) or die "can't open testmsgs/empty-preamble.msg: $!"; my $entity = $parser->parse($fh); $fh->seek(0,0); my $expected = do { local $/; <$fh> }; close $fh; cmp_deeply( $entity->preamble(), $files{$file}, 'Preamble is as expected'); is( $entity->as_string(), $expected, 'File with preamble roundtripped correctly'); } 1; MIME-tools-5.509/t/ticket-66025.t0000644000076400007640000000024112541013575014136 0ustar dfsdfsuse Test::More tests => 1; use Test::Deep; use MIME::Words; cmp_deeply(MIME::Words::decode_mimewords("\nx"), ["\nx"], "Fix for ticket #66025 passes"); MIME-tools-5.509/t/99-prepare.t0000644000076400007640000000046712541013575014102 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 1; # TBone used to do this, but thankfully, we've done away with that my $output_dir = './testout'; if( ! -d $output_dir ) { mkdir $output_dir or warn "Could not make output directory: $!" } ok( -d $output_dir, "$output_dir exists" ); 1; MIME-tools-5.509/t/ParserEncoded.t0000644000076400007640000000352112541013575014715 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More; plan tests => 5; main: { my ($fh, $mail_text, $entity, $parser); #-- Check whether Digest::MD5 is available my $has_md5 = eval "require Digest::MD5"; #-- Load MIME::Parser use_ok("MIME::Parser"); #-- Prepare parser $parser = MIME::Parser->new(); $parser->output_to_core(1); #-- Switch parser to encoded mode $parser->decode_bodies(0); #-- Parse quoted-printable encoded file $entity = parse_qp_file($parser); #-- Check if body is stored encoded ok($entity->bodyhandle->is_encoded, "Entity stored encoded"); #-- Check if MD5 resp. length match as expected $mail_text = $entity->as_string; if ( $has_md5 ) { my $md5 = Digest::MD5::md5_hex($mail_text); ok($md5 eq "a00f9b070d3153bbdc43d09a849730df", "Encoded MD5 match"); } else { my $len = length($mail_text); ok($len == 665, "Encoded length match"); } #-- Switch parser to decoded mode $parser->decode_bodies(1); #-- Parse quoted-printable encoded file $entity = parse_qp_file($parser); #-- Check if body is now stored decoded ok(!$entity->bodyhandle->is_encoded, "Entity stored decoded"); #-- Check if MD5 resp. length match as expected $mail_text = $entity->as_string; if ( $has_md5 ) { my $md5 = Digest::MD5::md5_hex($mail_text); ok($md5 eq "54a4ccb3a16f83e851581ffa5178f68a", "Decoded MD5 match"); } else { my $len = length($mail_text); ok($len == 609, "Decoded length match"); } } #-- Parse quoted printable file and return MIME::Entity sub parse_qp_file { my ($parser) = @_; open (my $fh, "testmsgs/german-qp.msg") or die "can't open testmsgs/german-qp.msg: $!"; my $entity = $parser->parse($fh); close $fh; return $entity; } 1; MIME-tools-5.509/t/ticket-71041.t0000644000076400007640000000101012541013575014123 0ustar dfsdfsuse Test::More tests => 1; use MIME::Parser; my $parser = MIME::Parser->new(); $parser->output_to_core(1); my $message = <<'EOF'; From: To: Subject: Ticket #71041 test Message-Id: MIME-Version: 1.0 Content-Type: text/plain This should parse properly. EOF # Set $\ to something wacky $\ = "\n"; my $entity = $parser->parse_data($message); my $head = $entity->head; is ($head->get('From'), "\n", 'Header was parsed as expected'); MIME-tools-5.509/t/02-kwalitee.t0000644000076400007640000000044612541013575014226 0ustar dfsdfsBEGIN { use Test::More; unless ($ENV{AUTHOR_TESTING}||$ENV{RELEASE_TESTING}) { plan(skip_all => 'These tests are for author or release candidate testing'); } } eval { require Test::Kwalitee; Test::Kwalitee->import() }; plan( skip_all => 'Test::Kwalitee not installed; skipping' ) if $@; MIME-tools-5.509/t/Body.t0000644000076400007640000000445312541013575013101 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 30; use MIME::Body; use MIME::Tools; use Cwd; # Check bodies: my @bodies = ( MIME::Body::Scalar->new(), MIME::Body::File->new('./testout/fbody'), MIME::Body::InCore->new(), ); my $buf; my @lines; my $line; my $pos; foreach my $body ( @bodies ) { my $io; my $class = ref($body); # diag("Checking class: ", ref($body)); # Open body for writing, and write stuff: $io = $body->open("w"); ok($io, "$class: opened for writing"); $io->print("Line 1\nLine 2\nLine 3"); $io->close; # Open body for reading: $io = $body->open("r"); ok($io, "$class: able to open body for reading?"); # Read all lines: @lines = $io->getlines; ok((($lines[0] eq "Line 1\n") && ($lines[1] eq "Line 2\n") && ($lines[2] eq "Line 3")), "$class: getlines method works?" ); # Seek forward, read: $io->seek(3, 0); $io->read($buf, 3); is($buf, 'e 1', "$class: seek(SEEK_START) plus read works?"); # Tell, seek, and read: $pos = $io->tell; $io->seek(-5, 1); $pos = $io->tell; is($pos, 1, "$class: tell and seek(SEEK_CUR) works?"); $io->read($buf, 5); is($buf, 'ine 1', "$class: seek(SEEK_CUR) plus read works?"); # Read all lines, one at a time: @lines = (); $io->seek(0, 0); while ($line = $io->getline()) { push @lines, $line } ok((($lines[0] eq "Line 1\n") && ($lines[1] eq "Line 2\n") && ($lines[2] eq "Line 3")), "$class: getline works?" ); # Done! $io->close; # Slurp lines: @lines = $body->as_lines; ok((($lines[0] eq "Line 1\n") && ($lines[1] eq "Line 2\n") && ($lines[2] eq "Line 3")), "$class: as_lines works?" ); # Slurp string: my $str = $body->as_string; is($str, "Line 1\nLine 2\nLine 3", "$class: as_string works?"); } # Check that we can open files with leading whitespace in name # (RT ticket #22680) { my $cwd = cwd(); ok( chdir './testout', 'chdir to ./testout to avoid clutter'); eval { my $body = MIME::Body::File->new(" bad file "); my $fh = $body->open('w'); $fh->close(); ok( -e ' bad file ', 'file created with leading whitespace, as expected'); unlink(' bad file '); }; ok( chdir $cwd, 'chdir back'); } 1; MIME-tools-5.509/t/02-pod.t0000644000076400007640000000033712541013575013202 0ustar dfsdfsuse strict; use Test::More; eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; my @poddirs = qw( lib ); # Should probably be blib... all_pod_files_ok( all_pod_files( @poddirs ) ); MIME-tools-5.509/t/Head.t0000644000076400007640000001354012541013575013042 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 20; use MIME::Head; #------------------------------------------------------------ ##diag("Read a bogus file (this had better fail...)"); #------------------------------------------------------------ my $WARNS = $SIG{'__WARN__'}; $SIG{'__WARN__'} = sub { }; my $head = MIME::Head->from_file('BLAHBLAH'); ok(!$head, "parse failed as expected?"); $SIG{'__WARN__'} = $WARNS; #------------------------------------------------------------ ##diag("Parse in the crlf.hdr file:"); #------------------------------------------------------------ # TODO: use lives_ok from Test::Exception ? ($head = MIME::Head->from_file('./testin/crlf.hdr')) or die "couldn't parse input"; # stop now ok('HERE', "parse of good file succeeded as expected?"); #------------------------------------------------------------ ##diag("Did we get all the fields?"); #------------------------------------------------------------ my @actuals = qw(path from newsgroups subject date organization lines message-id nntp-posting-host mime-version content-type content-transfer-encoding x-mailer x-url ); push(@actuals, "From "); my $actual = join '|', sort( map {lc($_)} @actuals); my $parsed = join '|', sort( map {lc($_)} $head->tags); is($parsed, $actual, 'got all fields we expected?'); #------------------------------------------------------------ ##diag("Could we get() the 'subject'? (it'll end in \\r\\n)"); #------------------------------------------------------------ my $subject; ($subject) = ($head->get('subject',0)); # force array context, see if okay is($subject, "EMPLOYMENT: CHICAGO, IL UNIX/CGI/WEB/DBASE\r\n", "got the subject okay?" ); #------------------------------------------------------------ ##diag("Could we replace() the 'Subject', and get it as 'SUBJECT'?"); #------------------------------------------------------------ my $newsubject = "Hellooooooo, nurse!\r\n"; $head->replace('Subject', $newsubject); $subject = $head->get('SUBJECT'); is($subject, $newsubject, 'able to set Subject, and get SUBJECT?'); #------------------------------------------------------------ ##diag("Does the count() method work?"); #------------------------------------------------------------ ok($head->count('NNTP-Posting-Host') && $head->count('nntp-POSTING-HOST') && !$head->count('Doesnt-Exist'), 'count method working?'); #------------------------------------------------------------ ##diag("Create a custom structured field, and extract parameters"); #------------------------------------------------------------ $head->replace('X-Files', 'default ; name="X Files Test"; LENgth=60 ;setting="6"'); my $params; $params = $head->params('X-Files'); ok($params, "got the parameter hash?"); is($params->{_} , 'default', "got the default field?"); is($params->{'name'} , 'X Files Test', "got the name?"); is($params->{'length'} , '60', "got the length?"); is($params->{'setting'}, '6', "got the setting?"); #------------------------------------------------------------ ##diag("Output to a desired file"); #------------------------------------------------------------ open TMP, ">./testout/tmp.head" or die "open: $!"; $head->print(\*TMP); close TMP; ok((-s "./testout/tmp.head") > 50, "output is a decent size?"); # looks okay #------------------------------------------------------------ ##diag("Parse in international header, decode and unfold it"); #------------------------------------------------------------ ($head = MIME::Head->from_file('./testin/encoded.hdr')) or die "couldn't parse input"; # stop now $head->decode; $head->unfold; $subject = $head->get('subject',0); $subject =~ s/\r?\n\Z//; my $to = $head->get('to',0); $to =~ s/\r?\n\Z//; my $tsubject = "If you can read this you understand the example... cool!"; my $tto = "Keld J\370rn Simonsen "; is($to, $tto, "Q decoding okay?"); is($subject, $tsubject, "B encoding and compositing okay?"); #------------------------------------------------------------ ##diag("Parse in header with 'From ', and check field order"); #------------------------------------------------------------ # Prep: ($head = MIME::Head->from_file('./testin/third.hdr')) or die "couldn't parse input"; # stop now my @orighdrs; my @realhdrs = qw(From Path: From: Newsgroups: Subject: Date: Organization: Lines: Message-ID: NNTP-Posting-Host: Mime-Version: Content-Type: Content-Transfer-Encoding: X-Mailer: X-URL:); my @curhdrs; # Does it work? @orighdrs = map {/^\S+:?/ ? $& : ''} (split(/\r?\n/, $head->stringify)); @curhdrs = @realhdrs; is(lc(join('|',@orighdrs)), lc(join('|',@curhdrs)), "field order preserved under stringify?"); # Does it work if we add/replace fields? $head->replace("X-New-Addition", "Hi there!"); $head->replace("Subject", "Hi there again!"); @curhdrs = (@realhdrs, "X-New-Addition:"); @orighdrs = map {/^\S+:?/ ? $& : ''} (split(/\r?\n/, $head->stringify)); is(lc(join('|',@orighdrs)), lc(join('|',@curhdrs)), "field order preserved under stringify after fields added?"); # Does it work if we decode the header? $head->decode; @orighdrs = map {/^\S+:?/ ? $& : ''} (split(/\r?\n/, $head->stringify)); is(lc(join('|',@orighdrs)), lc(join('|',@curhdrs)), "field order is preserved under stringify after decoding?"); { my $h = MIME::Head->new(); $h->replace('Content-disposition', 'inline; filename=good.file'); is($h->recommended_filename(), 'good.file', 'Simple case, good filename'); $h->replace('Content-disposition', 'inline; filename=" "'); $h->replace('Content-type', 'text/x-fake; name="second.choice"'); is($h->recommended_filename(), 'second.choice', 'Simple case, second-best choice of filename'); $h->replace('Content-type', 'text/x-fake; name=" "'); is($h->recommended_filename(), undef, 'no filenames found'); } 1; MIME-tools-5.509/t/Filer.t0000644000076400007640000000214412541013575013240 0ustar dfsdfs#!/usr/bin/perl use strict; use warnings; use Test::More tests => 17; use Config; binmode(STDOUT, ":utf8"); binmode(STDERR, ":utf8"); binmode( Test::More->builder()->output(), ':encoding(utf-8)' ); # Perl < 5.10.0 did not handle Unicode at all... my $wookie; if ($Config{'PERL_REVISION'} == 5 && $Config{'PERL_VERSION'} <= 8) { $wookie = 'wookie%D0.doc'; } else { $wookie = 'wookie%42D.doc'; } BEGIN { use_ok('MIME::Parser::Filer'); } # Tests for CPAN ticket 6789, and others { my $filer = MIME::Parser::Filer->new(); # All of these filenames should be considered evil my %evil = ( ' ' => '.dat' , ' leading_space' => 'leading_space.dat', 'trailing_space ' => 'trailing_space.dat', '.' => '..dat', '..' => '...dat', 'index[1].html' => 'index_1_.html', " wookie\x{f8}.doc" => "wookie%F8.doc", " wookie\x{042d}.doc" => $wookie, ); foreach my $name (keys %evil) { ok( $filer->evil_filename( $name ), "$name is evil"); } while( my ($evil, $clean) = each %evil ) { is( $filer->exorcise_filename( $evil), $clean, "$evil was exorcised"); } } MIME-tools-5.509/t/ticket-65681.t0000644000076400007640000000141012541013575014144 0ustar dfsdfs#!/usr/bin/perl use Test::More tests => 2; use MIME::Parser; open(IN, ' }; close(IN); my $data_with_crlf = $data; # This one MUST have CRLF $data_with_crlf =~ s/\r\n|\n\r|\n|\r/\r\n/g; # This one MUST NOT have CRLF $data =~ s/\r\n|\n\r|\n|\r/\n/g; my $parser = MIME::Parser->new(); $parser->output_to_core(1); my $entity = $parser->parse_data($data); my $entity_crlf = $parser->parse_data($data_with_crlf); is ($entity->head->get('Subject', 0), $entity_crlf->head->get('Subject', 0), 'Headers unchanged by line-ending conventions'); is ($entity->head->get('Subject', 0), 'Request for Leave' . "\n", 'Got expected subject'); #print STDERR "\n\nMIME::tools version is " . $MIME::Tools::VERSION . "\n\n"; MIME-tools-5.509/t/ticket-37139.t0000644000076400007640000000602612541013575014151 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 2; # Bug discovered by RJBS (rt.cpan.org, ticket 37139) # # Sometimes, when collapsing a message into single part, the # Content-type is horked up. # # It starts as: # # Content-Type: multipart/related; boundary=xyzzy; type=foo # # ...and ends as: # # Content-Type: text/plain; boundary=xyzzy; type=foo # use MIME::Parser; my $parser = MIME::Parser->new(); $parser->output_to_core(1); my $entity = $parser->parse(\*DATA); sub cleanup_mime { # Forcibly trash ->parts() to reproduce bug my ($entity) = @_; foreach my $part ($entity->parts) { cleanup_mime($part); $entity->parts([]); } } #diag( $entity->as_string); cleanup_mime($entity); #diag( $entity->as_string); is($entity->make_singlepart, 'DONE', 'make_singlepart() succeeded'); is($entity->head->get('Content-type'), "text/plain\n"); #diag( $entity->as_string); __DATA__ Received: from indigo.pobox.com (indigo.pobox.com [207.106.133.17]) by chiclet.listbox.com (Postfix) with ESMTP id 2AE91214A41 for ; Tue, 24 Jun 2008 01:22:44 -0400 (EDT) Received: from vip-2fed93075f2 (unknown [116.60.133.101]) by indigo.pobox.com (Postfix) with SMTP id 4DE1A6BF4D; Tue, 24 Jun 2008 01:22:30 -0400 (EDT) From: "ÕÅÃÈÉú"<ÕÅÃÈÉú> Reply-To: "h7w4v4c1@umail.hinet.net" To: "devnull@pobox.com" Subject: =?gb2312?B?uePW3crQwaq3or34s/a/2sOz0tfT0M/euavLvg==?= Date: Tue, 24 Jun 08 13:22:18 +0800 MIME-Version: 1.0 Content-type: multipart/related; type="multipart/alternative"; boundary="----=_NextPart_000_0015_1963AAAC.4C2B0004" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1158 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 Message-Id: <20080624052230.4DE1A6BF4D@indigo.pobox.com> This is a multi-part message in MIME format. ------=_NextPart_000_0015_1963AAAC.4C2B0004 Content-Type: multipart/alternative; boundary="----=_NextPart_001_0016_1963AAAC.4C2B0004" ------=_NextPart_001_0016_1963AAAC.4C2B0004 Content-Type: text/html; charset=gb2312 Content-Transfer-Encoding: base64 PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwvL0VO Ij4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD1odHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29t L2ludGVsbGlzZW5zZS9pZTUgDQpuYW1lPXZzX3RhcmdldFNjaGVtYT4NCjxNRVRBIGh0dHAtZXF1aXY9 Q29udGVudC1UeXBlIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD1nYjIzMTIiPg0KPE1FVEEgY29u dGVudD0iTVNIVE1MIDYuMDAuMjkwMC4zMzU0IiBuYW1lPUdFTkVSQVRPUj48L0hFQUQ+DQo8Qk9EWSBz dHlsZT0iRk9OVC1TSVpFOiA5cHQ7IEZPTlQtRkFNSUxZOiDLzszlIj4NCjxQPsT6usMhPEJSPiZuYnNw OyZuYnNwOyCxvrmry77XqMPFzqq498Oz0tfJzLvyyfqy+rOnvNK0+sDtu/XO7734s/a/2rGoudihoiAN CsnMvOyhorWl1qShosjrstahorGoudjK1tD4oaLNz7O1oaLW0LjbLLT6sOy499bWsvq12NakyukuwarP tcjLo7rVxc/Iyfogyta7+jEzNjMyMjc4MzMyJm5ic3A7IFRFTDAyMC0zNzIzMjYwNiANCjYxMDMwOTY0 IEZBWDAyMC02MTAzMDUxNSC12Na3o7q549bdytDM7LrTx/jR4MHrwrcxMjC6xb3w0eC088/DIMjn09C0 8sjFx+u8+8HCITxCUj48L1A+PC9CT0RZPjwvSFRNTD4NCg== ------=_NextPart_001_0016_1963AAAC.4C2B0004-- ------=_NextPart_000_0015_1963AAAC.4C2B0004-- MIME-tools-5.509/t/ParamVal.t0000644000076400007640000000355112543007422013701 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 13; use MIME::Field::ContType; use MIME::WordDecoder; use Encode; # Trivial test { my $field = Mail::Field->new('Content-type'); isa_ok( $field, 'MIME::Field::ParamVal'); isa_ok( $field, 'Mail::Field'); $field->param('_', 'stuff'); $field->param('answer', 42); is( $field->stringify, 'stuff; answer="42"', 'Object stringified to expected value'); } # Test for CPAN RT #34451 { my $header = 'stuff; answer*=utf-8\'\'%c3%be%20%c3%bf'; my $field = Mail::Field->new('Content-type'); $field->parse( $header ); is( $field->param('_'), 'stuff', 'Got body of header'); # We get it back in UTF-8! my $expected = pack('CCCCC', 0xc3, 0xbe, 0x20, 0xc3, 0xbf); my $wd = supported MIME::WordDecoder 'UTF-8'; is( encode('utf8', $wd->decode($field->param('answer'))), $expected, 'answer param was unpacked correctly'); } # Test for CPAN RT #105455 { my $header = 'attachment; filename=wookie.zip size=3; junk=cabbage'; my $field = Mail::Field->new('Content-type'); $field->parse( $header ); is( $field->param('_'), 'attachment', 'Got body of header'); is ($field->param('filename'), 'wookie.zip', 'Got correct filename'); is ($field->param('junk'), 'cabbage', 'Got correct final param'); $header = 'attachment; filename="wookie.zip size=3"'; $field = Mail::Field->new('Content-type'); $field->parse( $header ); is( $field->param('_'), 'attachment', 'Got body of header'); is ($field->param('filename'), 'wookie.zip size=3', 'Got correct filename'); $header = 'attachment; filename="wookie.zip;x=1"; (crap); (more_crap) adhesive=glueme'; $field = Mail::Field->new('Content-type'); $field->parse( $header ); is( $field->param('_'), 'attachment', 'Got body of header'); is ($field->param('filename'), 'wookie.zip;x=1', 'Got correct filename'); is ($field->param('adhesive'), 'glueme', 'Got correct final parameter'); } MIME-tools-5.509/t/WordEncoder.t0000644000076400007640000000513712541013575014417 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 8; use MIME::Words qw(:all); is(encode_mimeword('wookie', 'Q', 'ISO-8859-1'), '=?ISO-8859-1?Q?wookie?='); is(encode_mimeword('François', 'Q', 'ISO-8859-1'), '=?ISO-8859-1?Q?Fran=E7ois?='); is(encode_mimewords('Me and François'), 'Me and =?ISO-8859-1?Q?Fran=E7ois?='); is(decode_mimewords('Me and =?ISO-8859-1?Q?Fran=E7ois?='), 'Me and François'); is(encode_mimewords('Me and François and François and François and François and François and François'), 'Me and =?ISO-8859-1?Q?Fran=E7ois=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois?='); is(decode_mimewords('Me and =?ISO-8859-1?Q?Fran=E7ois=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois?='), 'Me and François and François and François and François and François and François'); is(encode_mimewords('Me and François and François and François and François and François and François and wookie and wookie and wookie and wookie and wookie and wookie'), 'Me and =?ISO-8859-1?Q?Fran=E7ois=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20?=and wookie and wookie and wookie and wookie and wookie and wookie'); is(decode_mimewords('Me and =?ISO-8859-1?Q?Fran=E7ois=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?=and =?ISO-8859-1?Q?Fran=E7ois=20?=and wookie and wookie and wookie and wookie and wookie and wookie'), 'Me and François and François and François and François and François and François and wookie and wookie and wookie and wookie and wookie and wookie'); MIME-tools-5.509/t/ticket-5462.t0000644000076400007640000000071712541013575014064 0ustar dfsdfsuse MIME::Words qw(:all); use MIME::WordDecoder; use Encode; my $s = "Служба поддержки"; use Test::More tests => 2; is(MIME::Words::encode_mimewords($s, Charset => 'utf-8'), '=?UTF-8?Q?=D0=A1=D0=BB=D1=83=D0=B6=D0=B1=D0=B0=20?= =?UTF-8?Q?=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B8?='); is(decode_mimewords('=?UTF-8?Q?=D0=A1=D0=BB=D1=83=D0=B6=D0=B1=D0=B0=20?= =?UTF-8?Q?=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B8?='), $s); MIME-tools-5.509/t/ticket-41632.t0000644000076400007640000000246612541013575014146 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 6; # Handle the case of both RFC-2231 and non-RFC-2231 parameter values. # In this case, we ignore the non-RFC-2231 parameters use MIME::Field::ParamVal; use MIME::WordDecoder; my $params; my $wd = supported MIME::WordDecoder 'UTF-8'; $params = MIME::Field::ParamVal->parse_params('inline; filename="foo"; filename*1="ar"; filename*0="b"'); is($params->{'_'}, 'inline', 'Got the "inline" right'); is($wd->decode($params->{'filename'}), 'bar', 'Ignored non-RFC-2231 value if RFC-2231 parameters are present'); $params = MIME::Field::ParamVal->parse_params('inline; filename="foo"'); is($wd->decode($params->{'filename'}), 'foo', 'Got filename if RFC-2231 parameters are absent'); $params = MIME::Field::ParamVal->parse_params('inline; filename*1="ar"; filename*0="b"'); is($wd->decode($params->{'filename'}), 'bar', 'Got RFC-2231 value'); $params = MIME::Field::ParamVal->parse_params('inline; filename*1="ar"; filename="foo"; filename*0="b"'); is($wd->decode($params->{'filename'}), 'bar', 'Ignored non-RFC-2231 value if RFC-2231 parameters are present'); $params = MIME::Field::ParamVal->parse_params('inline; filename*1="ar"; filename*0="b"; filename="foo"'); is($wd->decode($params->{'filename'}), 'bar', 'Ignored non-RFC-2231 value if RFC-2231 parameters are present'); MIME-tools-5.509/t/ticket-52924.t0000644000076400007640000000110412541013575014140 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 2; # Ticket 52924: Ensure we add < > arround Content-ID header contents. use MIME::Entity; my $bare_id = '123456789.09876@host.example.com'; my $e = MIME::Entity->build( Path => "./testin/short.txt", Id => $bare_id, ); is( $e->head->mime_attr('content-id'), "<$bare_id>", '<> added around bare Id value when creating'); undef $e; $e = MIME::Entity->build( Path => "./testin/short.txt", Id => "<$bare_id>", ); is( $e->head->mime_attr('content-id'), "<$bare_id>", '<> not added around Id value when already present'); MIME-tools-5.509/t/Decoder.t0000644000076400007640000000426312541013575013550 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More; use File::Spec; use MIME::Tools; use MIME::Decoder; #------------------------------------------------------------ # BEGIN #------------------------------------------------------------ # Is gzip available? Quick and dirty test: my $has_gzip; foreach (split $^O eq "MSWin32" ? ';' : ':', $ENV{PATH}) { last if ($has_gzip = -x "$_/gzip"); } if ($has_gzip) { require MIME::Decoder::Gzip64; install MIME::Decoder::Gzip64 'x-gzip64'; } # Get list of encodings we think we provide: my @encodings = ('base64', 'quoted-printable', '7bit', '8bit', 'binary', ($has_gzip ? 'x-gzip64' : ()), 'x-uuencode', 'binhex'); plan( tests => scalar @encodings); # Report what tests we may be skipping: diag($has_gzip ? "Using gzip: $has_gzip" : "No gzip: skipping x-gzip64 test"); # Test each encoding in turn: my ($e, $eno) = (undef, 0); foreach $e (@encodings) { ++$eno; my $warning; local $SIG{__WARN__} = sub { $warning = $@; }; my $decoder = MIME::Decoder->new($e); unless(defined($decoder)) { my $msg = "Encoding/decoding of $e not supported -- skipping test"; if( $warning =~ /^Can't locate ([^\s]+)/ ) { $msg .= " (Can't locate $1)"; } pass($msg); next; } my $infile = File::Spec->catfile('.', 'testin', 'fun.txt'); my $encfile = File::Spec->catfile('.', 'testout', "fun.en$eno"); my $decfile = File::Spec->catfile('.', 'testout', "fun.de$eno"); # Encode: open IN, "<$infile" or die "open $infile: $!"; open OUT, ">$encfile" or die "open $encfile: $!"; binmode IN; binmode OUT; $decoder->encode(\*IN, \*OUT) or next; close OUT; close IN; # Decode: open IN, "<$encfile" or die "open $encfile: $!"; open OUT, ">$decfile" or die "open $decfile: $!"; binmode IN; binmode OUT; $decoder->decode(\*IN, \*OUT) or next; close OUT; close IN; # Can we compare? if ($e =~ /^(binhex|base64|quoted-printable|binary|x-gzip64|x-uuencode)$/i) { is(-s $infile, -s $decfile, "Encoding/decoding of $e: size of $infile == size of $decfile"); } else { pass("Encoding/decoding of $e: size not comparable, marking pass anyway"); } } MIME-tools-5.509/t/BodyPrint.t0000644000076400007640000000107412541013575014112 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 7; use MIME::Body; use MIME::Tools; my $body = MIME::Body::InCore->new("hi\n"); my $fh = $body->open("r"); my @ary = <$fh>; $fh->close(); is(scalar(@ary), 1); is($ary[0], "hi\n"); $body = MIME::Body::InCore->new(\"hi\n"); $fh = $body->open("r"); @ary = <$fh>; $fh->close(); is(scalar(@ary), 1); is($ary[0], "hi\n"); $body = MIME::Body::InCore->new(["line 1\n", "line 2\n"]); $fh = $body->open("r"); @ary = <$fh>; $fh->close(); is(scalar(@ary), 2); is($ary[0], "line 1\n"); is($ary[1], "line 2\n"); MIME-tools-5.509/t/ticket-80433.t0000644000076400007640000000051412541013575014140 0ustar dfsdfsuse strict; use warnings; use Test::More tests => 2; # proper quoting of params and parsing them use MIME::Field::ParamVal; my $field = MIME::Field::ParamVal->parse( 'inline; filename="f\oo\"bar\"b\az\\\\"' ); is($field->param('filename'), 'foo"bar"baz\\'); is($field->stringify, 'inline; filename="foo\\"bar\\"baz\\\\"'); MIME-tools-5.509/t/EmptyPart.t0000644000076400007640000000134612541013575014127 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 6; use MIME::Tools; use lib "./t"; use Globby; use MIME::Parser; my $DIR = "./testout"; ((-d $DIR) && (-w $DIR)) or die "no output directory $DIR"; unlink globby("$DIR/[a-z]*"); my $parser = MIME::Parser->new(); $parser->output_dir($DIR); my $data = <parse_data($data); ok($entity, 'Got an entity'); is($entity->mime_type, 'multipart/alternative'); is($entity->parts, 3, 'Got three parts'); is($entity->parts(0)->mime_type, 'text/plain'); is($entity->parts(1)->mime_type, 'text/plain'); is($entity->parts(2)->mime_type, 'text/plain'); MIME-tools-5.509/t/Words.t0000644000076400007640000000236712541013575013304 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 20; use MIME::QuotedPrint qw(decode_qp); use MIME::Words qw( :all ); { local($/) = ''; open WORDS, ") { s{\A\s+|\s+\Z}{}g; # trim my ($isgood, $expect, $enc) = split /\n/, $_, 3; # Create the expected data $expect = eval $expect; my $dec = decode_mimewords($enc); if( $isgood eq 'GOOD' ) { ok( ! $@, 'No exceptions'); is( $dec, $expect, "$enc produced correct output"); } else { ok( $@, 'Got an exception as expected'); } } close WORDS; } # Test case for ticket 5462 { my $source = 'hé hé'; my $encoded = encode_mimewords($source, ('Encode' => 'Q', 'Charset' => 'iso-8859-1')); my $decoded = decode_mimewords($encoded); is( $decoded, $source, 'encode/decode of string with spaces matches original'); } # Second test case for ticket 5462 { my $source = 'Ñто ÑпециальныйÑабжект Ð´Ð»Ñ Ñ‚ÐµÑта ÑиÑтемы тикетов'; my $encoded = encode_mimewords($source, ('Encode' => 'Q', 'Charset' => 'utf8')); my $decoded = decode_mimewords($encoded); is( $decoded, $source, 'encode/decode of string with spaces matches original'); } # vim: set encoding=utf8 fileencoding=utf8: MIME-tools-5.509/t/WordDecoder.t0000644000076400007640000000225612541013575014404 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 22; use MIME::QuotedPrint qw(decode_qp); use MIME::WordDecoder; use utf8; binmode STDOUT, ":utf8"; binmode STDERR, ":utf8"; my $mwd = (new MIME::WordDecoder::ISO_8859 1); { local($/) = ''; open WORDS, ") { s{\A\s+|\s+\Z}{}g; # trim my ($isgood, $expect, $enc) = split /\n/, $_, 3; # Create the expected data $expect = eval $expect; my $dec = $mwd->decode($enc); if( $isgood eq 'GOOD' ) { ok( ! $@, 'No exceptions'); is( $dec, $expect, "$enc produced correct output"); } else { ok( $@, 'Got an exception as expected'); } } close WORDS; } my $wd = supported MIME::WordDecoder 'UTF-8'; my $perl_string = $wd->decode('To: =?ISO-8859-1?Q?J=F8rn?= '); is($perl_string, "To: J\x{00f8}rn ", 'Got back expected UTF-8 string'); is(utf8::is_utf8($perl_string), 1, 'Converted string has UTF-8 flag on'); $perl_string = mime_to_perl_string('To: =?ISO-8859-1?Q?J=F8rn?= '); is($perl_string, "To: J\x{00f8}rn ", 'Got back expected UTF-8 string'); is(utf8::is_utf8($perl_string), 1, 'Converted string has UTF-8 flag on'); MIME-tools-5.509/t/Globby.pm0000644000076400007640000000124212541013575013564 0ustar dfsdfspackage Globby; # More-portable but limited glob(). It does what we need. use Exporter; use vars qw(@ISA @EXPORT); @ISA = qw(Exporter); @EXPORT = qw(globby); sub globby { my $globpath = shift; # full glob my %r = ('.'=>'\.', '*'=>'.*', '?'=>'.'); # Get directory and regexp: my ($dir, $glob) = ($globpath =~ m{^(.*?)/?([^/]+\Z)}); defined($dir) or $dir = ''; my $re = $glob; $re =~ s{([\.\*\?])}{$r{$1}}g; # Get files which match pattern: my @f; if (opendir DIR, $dir) { @f = grep /^$re\Z/, sort(readdir(DIR)); closedir DIR; } # Return as full paths: map { ($dir ne '') ? "$dir/$_" : $_} @f; } 1; MIME-tools-5.509/t/Misc.t0000644000076400007640000001011012541013575013062 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 14; use MIME::Head; use MIME::Parser; use Mail::Field; use MIME::Head; use MIME::Decoder::QuotedPrint; #------------------------------ # Bug 971008 from Michael W. Normandin : #------------------------------ # I've found something you may be interested in : # Header: # Content-Type: application/vnd.ms-powerpoint; name="June97V4.0.ppt" # Code: # $mtype = $pentity->head->mime_type; # print "$mytype\n"; # # Produces: # application/vnd # { my $head = MIME::Head->new([ 'Content-Type: application/vnd.ms-powerpoint; name="June97V4.0.ppt"' ]); is($head->mime_type, "application/vnd.ms-powerpoint", "bug 971008-MWN: are MIME attributes parsed ok?"); } #------------------------------ # Bug 970822 from Anselm Lingnau #------------------------------ # use Mail::Field; # use MIME::Head; # $field = Mail::Field->new('Content-type', 'text/HTML; charset="US-ASCII"'); # print $field->type, "\n"; # # but all I see is: # # Can't locate object method "parse" via package "Mail::Field::ContType" # at /local/pkg/perl/5.004/lib/site_perl/Mail/Field.pm line 306. # # I suppose this has to do with the fact that it is `MIME::Field' rather # than `Mail::Field', but I am at a loss as to what to do next. Maybe you # can help? Thank you very much. { my $field = Mail::Field->new('Content-type', 'text/HTML; charset="US-ASCII"'); is($field->paramstr('_'), "text/HTML", "bug 970822-AL: Mail::Field register problem (paramstr)"); is($field->type, "text/html", "bug 970822-AL: Mail::Field register problem (type)"); } #------------------------------ # Bug 970725 from Denis N. Antonioli #------------------------------ # Were it possible to incorporate the guideline #8 from RFC 2049? # The change involved is minim: just adding the 2 lines # $res =~ s/\./=2E/go; # $res =~ s/From /=46rom /go; # at the start of encode_qp_really in MIME::Decoder::QuotedPrint? # # Textual mode. { my $pair; foreach $pair (["From me", "=46rom me=\n"], [".", ".=\n"], # soft line-break [".\n", "=2E\n"], # line-break [" From you", " From you=\n"]) { my $out = MIME::Decoder::QuotedPrint::encode_qp_really($pair->[0], 1); is($out, $pair->[1], "bug 970725-DNA: QP use of RFC2049 guideline 8"); } } # Binary mode { my $pair; foreach $pair (["From me", "=46rom me=\n"], [".", ".=\n"], # soft line-break [".\n", ".=0A=\n"], # line-break [" From you", " From you=\n"]) { my $out = MIME::Decoder::QuotedPrint::encode_qp_really($pair->[0], 0); is($out, $pair->[1], "bug 970725-DNA: QP use of RFC2049 guideline 8"); } } #------------------------------ # Bug 970626 from Sun, Tong #------------------------------ # @history = $head->get_all('Received'); # # The above code does not work. It confused me at the beginning. Then, I # found out it is only a spelling error: when I changed the 'Received' to # 'received', it works ( you know why ). { my $head = MIME::Head->new(["Received: first\n", "Received: second\n", "received: third\n", "Received: fourth\n", "subject: hi!\n"]); my @received = $head->get_all('Received'); is(scalar @received, 4, "bug 970626-TS: header get_all() case problem fixed?"); } #------------------------------ # Bug 980430 from Jason L Tibbitts III #------------------------------ # Boundary-parsing errors for this message. { my $parser = new MIME::Parser; $parser->output_to_core('ALL'); my $e = eval { $parser->parse_open("testin/jt-0498.msg") }; is(scalar $e->parts, 2, "bug 980430-JT: did we get 2 parts?"); } # Bug reported by Marcel Brouillet. MT 5.416 would parse as a single part. { my $parser = new MIME::Parser; $parser->output_to_core('ALL'); my $e = eval { $parser->parse_open("testin/twopart.msg") }; is( scalar $e->parts, 2, "bug: did we get 2 parts?"); } 1; MIME-tools-5.509/t/ticket-71677.t0000644000076400007640000000115712541013575014156 0ustar dfsdfs#!/usr/bin/perl use Test::More tests => 2; use MIME::Parser; my $msg = <<'EOF'; From: To: Subject: Weird filename test MIME-Version: 1.0 Content-Type: application/octet-stream; name="[wookie].bin" Content-Disposition: attachment; filename="[wookie].bin" Wookie EOF my $parser = MIME::Parser->new(); $parser->output_to_core(0); $parser->output_under("testout"); my $entity = $parser->parse_data($msg); my $body = $entity->bodyhandle; my $path = $body->path; ok(defined($path), 'Path exists'); ok($path =~ /_wookie_\.bin$/, 'And has the expected form'); $parser->filer->purge; MIME-tools-5.509/t/Parser.t0000644000076400007640000001173612541013575013442 0ustar dfsdfs#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 31; use MIME::Tools; use lib "./t"; use Globby; use MIME::Parser; # Set the counter, for filenames: my $Counter = 0; # Check and clear the output directory: my $DIR = "./testout"; ((-d $DIR) && (-w $DIR)) or die "no output directory $DIR"; unlink globby("$DIR/[a-z]*"); #------------------------------------------------------------ # BEGIN #------------------------------------------------------------ my $parser; my $entity; my $msgno; my $infile; my $type; my $enc; #------------------------------------------------------------ package MyParser; @MyParser::ISA = qw(MIME::Parser); sub output_path { my ($parser, $head) = @_; # Get the recommended filename: my $filename = $head->recommended_filename; if (defined($filename) && $parser->evil_filename($filename)) { ## diag("Parser.t: ignoring an evil recommended filename ($filename)"); $filename = undef; # forget it: it was evil } if (!defined($filename)) { # either no name or an evil name ++$Counter; $filename = "message-$Counter.dat"; } # Get the output filename: my $outdir = $parser->output_dir; "$outdir/$filename"; } package main; #------------------------------------------------------------ $parser = new MyParser; $parser->output_dir($DIR); #------------------------------------------------------------ ##diag("Read a nested multipart MIME message"); #------------------------------------------------------------ open IN, "./testmsgs/multi-nested.msg" or die "open: $!"; $entity = $parser->parse(\*IN); ok($entity, "parse of nested multipart"); #------------------------------------------------------------ ##diag("Check the various output files"); #------------------------------------------------------------ is(-s "$DIR/3d-vise.gif", 419, "vise gif size ok"); is(-s "$DIR/3d-eye.gif" , 357, "3d-eye gif size ok"); for $msgno (1..4) { ok(-s "$DIR/message-$msgno.dat", "message $msgno has a size"); } #------------------------------------------------------------ ##diag("Same message, but CRLF-terminated and no output path hook"); #------------------------------------------------------------ $parser = new MIME::Parser; $parser->output_dir($DIR); open IN, "./testmsgs/multi-nested2.msg" or die "open: $!"; $entity = $parser->parse(\*IN); ok($entity, "parse of CRLF-terminated message"); #------------------------------------------------------------ ##diag("Read a simple in-core MIME message, three ways"); #------------------------------------------------------------ my $data_scalar = <This is test one. EOF my $data_scalarref = \$data_scalar; my $data_arrayref = [ map { "$_\n" } (split "\n", $data_scalar) ]; $parser->output_to_core('ALL'); foreach my $data_test ($data_scalar, $data_scalarref, $data_arrayref) { $entity = $parser->parse_data($data_test); isa_ok($entity, 'MIME::Entity'); is($entity->head->mime_type, 'text/html', 'type is text/html'); } $parser->output_to_core('NONE'); #------------------------------------------------------------ ##diag("Simple message, in two parts"); #------------------------------------------------------------ $entity = $parser->parse_two("./testin/simple.msgh", "./testin/simple.msgb"); my $es = ($entity ? $entity->head->get('subject',0) : ''); like($es, qr/^Request for Leave$/, " parse of 2-part simple message (subj <$es>)"); # diag('new_tmpfile(), with real temp file'); { my $fh; eval { local $parser->{MP5_TmpToCore} = 0; $fh = $parser->new_tmpfile(); }; ok( ! $@, '->new_tmpfile() lives'); ok( $fh->print("testing\n"), '->print on fh ok'); ok( $fh->seek(0,0), '->seek on fh ok'); my $line = <$fh>; is( $line, "testing\n", 'Read line back in OK'); } # diag('new_tmpfile(), with in-core temp file'); { my $fh; eval { local $parser->{MP5_TmpToCore} = 1; $fh = $parser->new_tmpfile(); }; ok( ! $@, '->new_tmpfile() lives'); ok( $fh->print("testing\n"), '->print on fh ok'); ok( $fh->seek(0,0), '->seek on fh ok'); my $line = <$fh>; is( $line, "testing\n", 'Read line back in OK'); } # diag('new_tmpfile(), with temp files elsewhere'); { my $fh; eval { local $parser->{MP5_TmpDir} = $DIR; $fh = $parser->new_tmpfile(); }; ok( ! $@, '->new_tmpfile() lives'); ok( $fh->print("testing\n"), '->print on fh ok'); ok( $fh->seek(0,0), '->seek on fh ok'); my $line = <$fh>; is( $line, "testing\n", 'Read line back in OK'); } # diag('native_handle() on various things we might get'); { my $io_file_scalar = IO::File->new( do { my $foo = ''; \$foo }, '>:' ); ok( MIME::Parser::Reader::native_handle( $io_file_scalar ), 'FH on scalar is OK'); my $io_file_real = IO::File->new_tmpfile(); ok( MIME::Parser::Reader::native_handle( $io_file_real ), 'FH on real file is OK'); my $globref = \*STDOUT; ok( MIME::Parser::Reader::native_handle( $globref ), 'globref is OK'); } # diag('tmp_recycling() exists again, as a no-op'); { my $rc = $parser->tmp_recycling(1); is( $rc, undef, 'tmp_recycling no-op method returned undef'); } MIME-tools-5.509/examples/0000755000076400007640000000000013071231525013360 5ustar dfsdfsMIME-tools-5.509/examples/mimeprint0000755000076400007640000000403212541013575015315 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimeprint - parse a MIME stream, and print the parsed entity =head1 SYNOPSIS mimeprint Give usage. mimeprint [options] infile Parse a MIME stream from infile (- means stdin), and print entity to stdout. =head1 DESCRIPTION Parse a MIME stream, and output the resulting entity. This is a nice way of eyeballing whether or not MIME-tools "understood" your MIME message. Due to nonuniqueness of MIME encodings, there is a very good chance that your output will not I resemble your input. =head1 AUTHOR Eryq, eryq@zeegee.com =cut use lib "./lib"; use strict; use Getopt::Std; use vars qw($opt_d $opt_e $opt_h $opt_n $opt_v $opt_s $opt_u); use MIME::Parser; # Usage? $ARGV[0] or die <debugging($opt_v); # Set up parser: my $parser = new MIME::Parser; if ($opt_d) { $parser->output_to_core(0); $parser->output_under($opt_d); } else { $parser->output_to_core('ALL'); } $parser->extract_nested_messages($opt_n) if defined($opt_n); $parser->extract_uuencode($opt_u || 0); $parser->decode_headers($opt_h || 0); $parser->ignore_errors(1); # Parse: my $ent = $parser->parse_open($ARGV[0]); $ent or die "MIME parsing failed!\n"; print STDERR $parser->results->msgs; if ($opt_e and !$ent->is_multipart) { supported MIME::Decoder $opt_e or die "unsupported encoding: $opt_e\n"; $ent->head->mime_attr("Content-transfer-encoding" => $opt_e); } ($opt_s ? $ent->dump_skeleton(\*STDOUT) : $ent->print(\*STDOUT)); 1; MIME-tools-5.509/examples/mimeencode0000755000076400007640000000152112541013575015416 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimeencode - encode a file =head1 SYNOPSIS mimeencode Give usage. mimeencode [-d] encoding outfile Encode/decode stdin to stdout. =head1 DESCRIPTION Encode (or, with -d, decode) stdin with the given encoding, writing results to stdout. This does not do MIME parsing; it merely exercises the decoder modules. =head1 AUTHOR Eryq, eryq@zeegee.com =cut use lib "./lib"; use strict; use Getopt::Std; use vars qw($opt_d); use MIME::Decoder; # Usage? $ARGV[0] or die <outfile EOF # Args: getopts("d"); my $enc = shift @ARGV; # Get decoder: my $decoder = new MIME::Decoder $enc or die "unsupported encoding ($enc)\n"; # Do it! my $action = ($opt_d ? 'decode' : 'encode'); $decoder->$action(\*STDIN, \*STDOUT); 1; MIME-tools-5.509/examples/mimedump0000755000076400007640000000445612541013575015140 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimedump - dump out the contents of a parsed MIME message =head1 DESCRIPTION Read a MIME stream from the stdin, and dump its contents to the stdout. =head1 SYNOPSIS mimedump < mime.msg =head1 AUTHOR Andreas Koenig suggested this, and wrote the original code. Eryq perverted the hell out of it. =cut use MIME::Parser; #------------------------------ # # dump_entity ENTITY, NAME # # Recursive routine for dumping an entity. # sub dump_entity { my ($entity, $name) = @_; defined($name) or $name = "'anonymous'"; my $IO; # Output the head: print "\n", '=' x 60, "\n"; print "Message $name: "; print "\n", '=' x 60, "\n\n"; print $entity->head->original_text; print "\n"; # Output the body: my @parts = $entity->parts; if (@parts) { # multipart... my $i; foreach $i (0 .. $#parts) { # dump each part... dump_entity($parts[$i], ("$name, part ".(1+$i))); } } else { # single part... # Get MIME type, and display accordingly... my ($type, $subtype) = split('/', $entity->head->mime_type); my $body = $entity->bodyhandle; if ($type =~ /^(text|message)$/) { # text: display it... if ($IO = $body->open("r")) { print $_ while (defined($_ = $IO->getline)); $IO->close; } else { # d'oh! print "$0: couldn't find/open '$name': $!"; } } else { # binary: just summarize it... my $path = $body->path; my $size = ($path ? (-s $path) : '???'); print ">>> This is a non-text message, $size bytes long.\n"; print ">>> It is stored in ", ($path ? "'$path'" : 'core'),".\n\n"; } } 1; } #------------------------------ # # main # sub main { print STDERR "(reading from stdin)\n" if (-t STDIN); # Create a new MIME parser: my $parser = new MIME::Parser; # Create and set the output directory: (-d "mimedump-tmp") or mkdir "mimedump-tmp",0755 or die "mkdir: $!"; (-w "mimedump-tmp") or die "can't write to directory"; $parser->output_dir("mimedump-tmp"); # Read the MIME message: $entity = $parser->read(\*STDIN) or die "couldn't parse MIME stream"; # Dump it out: dump_entity($entity); } exit(&main ? 0 : -1); #------------------------------ 1; MIME-tools-5.509/examples/mimeref0000755000076400007640000000606412541013575014744 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimeref - create a .ref file for a message =head1 SYNOPSIS Usage: mimeref [-options] *.msg Options: -d DIR Output directory for parser (default is ./testout/mimeref) -w Write the .ref file =head1 DESCRIPTION Parse a message file, and spit out a .ref file. The .ref files are not really useful; they're just used by the t/Ref.t test. =head1 AUTHOR Eryq, eryq@zeegee.com =cut use strict; use lib "./lib"; use MIME::Parser; use File::Path; use Getopt::Std; use Data::Dumper; ### Get options: my %opts; getopts("d:wv", \%opts) || die "usage error ($!)\n"; my (@msgs) = @ARGV; @msgs or die "missing message\n"; ### Get path to output space: my $output_base = $opts{'d'} || "./testout/mimeref"; (-d $output_base) or mkdir($output_base, 0777) or die "mkdir $output_base: $!\n"; MIME::Tools->debugging($opts{'v'}); $Data::Dumper::Terse = 1; $Data::Dumper::Indent = 1; $Data::Dumper::Useqq = 1; foreach my $msg (@msgs) { do_msg($msg); } exit 0; #------------------------------ sub do_msg { my $msg = shift; ### Create a parser: my $parser = new MIME::Parser; $parser->output_under($output_base); $parser->extract_nested_messages(1); ### Parse: my $ent = eval { $parser->parse_open($msg) || die "parse failed: $!\n"; }; if (!$ent) { rmtree $parser->output_dir; die $@; } ### Decompose: my $ref = {}; $ref->{Parser} = { Name => "anonymous", Message => $msg, OutputToCore => $parser->output_to_core, ExtractNested => $parser->extract_nested_messages, }; summarize($ref, $ent); $ent->dump_skeleton() if $opts{'v'}; if ($opts{'w'}) { my $refpath = $msg; $refpath =~ s/\.msg$//; $refpath .= ".ref"; open OUT, ">$refpath" or die "$refpath: $!\n"; print OUT Dumper($ref); close OUT; print STDERR "Wrote: $refpath\n"; } else { print Dumper($ref); } rmtree $parser->output_dir; } #------------------------------ sub set { my ($hash, $param, $val) = @_; if (defined($val)) { $hash->{$param} = $val; } } sub c { my $x = shift; $x =~ s/\r?\n$// if defined($x); $x; } #------------------------------ sub summarize { my ($ref, $ent, $name) = @_; $name ||= "Msg"; my $head = $ent->head; $head->unfold; my $body = $ent->bodyhandle; my $sum = {}; set($sum, From => c($head->get("From", 0))); set($sum, To => c($head->get("To", 0))); set($sum, Subject => c($head->get("Subject", 0))); set($sum, Type => $head->mime_type); set($sum, Encoding=> $head->mime_encoding); set($sum, Charset => $head->mime_attr("content-type.charset")); set($sum, Boundary => $head->multipart_boundary); set($sum, Disposition => $head->mime_attr("content-disposition")); set($sum, Filename => $head->recommended_filename); if ($body and $body->path) { set($sum, Size => (-s $body->path)); } $ref->{$name} = $sum; my $root = (($name eq 'Msg') ? 'Part' : $name); for (1 .. $ent->parts) { summarize($ref, $ent->parts($_ - 1), "${root}_$_"); } } 1; MIME-tools-5.509/examples/mimetour0000755000076400007640000000147412541013575015161 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimetour - tour the possible encodings =head1 SYNOPSIS mimetour Just run it. =head1 DESCRIPTION Parse a message into core, and output it in all supported encodings. =head1 AUTHOR Eryq, eryq@zeegee.com =cut use strict; use lib "./lib"; use MIME::Parser; # The message: my $msg = < Hello world!

EOF # Parse: my $parser = new MIME::Parser; $parser->output_to_core('ALL'); my $entity = $parser->parse_data($msg); # Tour: my $enc; foreach $enc (sort (keys %{supported MIME::Decoder})) { print '-'x60, "\n"; $entity->head->replace('Content-transfer-encoding', $enc); $entity->print(\*STDOUT); print '-'x60, "\n\n"; } 1; MIME-tools-5.509/examples/mimesender0000755000076400007640000000171712541013575015450 0ustar dfsdfs#!/usr/bin/perl =head1 NAME mimesender - an example of integrating MIME-tools with Mail::Send. =head1 SYNOPSIS Usage: mimesender YOU@YOUR.HOST =head1 DESCRIPTION This just fakes up a little message and sends it by using Mail::Send and the 'sendmail' handler. =head1 AUTHOR Eryq, eryq@zeegee.com. =cut use Mail::Send; use MIME::Entity 4.113; use File::Spec; ### Args? my ($to) = @ARGV; $to or die "Usage: mimesender toaddr\n"; ### Create MIME entity, with attachment, sent to us: my $ent = MIME::Entity->build(From => "secret\@admirer.net", To => $to, Subject => 'Hello there!', Data => "Saluations..."); $ent->attach(Type => 'text/plain', Data => "...and Felicitations!"); ### Send it: $sender = new Mail::Send; foreach ($ent->head->tags) { # give the sender our headers $sender->set($_, map {chomp $_; $_} $ent->head->get($_)); } $fh = $sender->open('sendmail'); $ent->print_body($fh); $fh->close; MIME-tools-5.509/examples/README0000644000076400007640000000045712541013575014252 0ustar dfsdfsTHE PROGRAMS IN THIS DIRECTORY ARE CURRENTLY UNSUPPORTED EXAMPLES. Examine them, hack them up, learn from them, etc. They'll be nicer in the future, I promise... Many of these example programs will only work under Unix. If you are a Win32 user, stick to examples shown in the modules themselves. MIME-tools-5.509/examples/mimeabuse0000755000076400007640000000231212541013575015257 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimeabuse - try hard to break MIME parsing =head1 DESCRIPTION This is meant to be run from the MIME-tools distribution directory as a test. It will attempt to parse the same several messages 1000 times each. It does a purge after each parse, so it shouldn't fill up your disk; however, it should be a good test for hitting resource limits. I wrote this after I discovered that, under Perl 5.002 at least, FileHandle->new_tmpfile returned an object that did not get destructed automatically when it exited scope. :-( =head1 AUTHOR Eryq, eryq@zeegee.com =cut use MIME::Parser; my $parser = new MIME::Parser; ((-d "./testin") && (-d "./testout")) or die "run this from the MIME-tools distribution directory"; $parser->output_dir("./testout"); $parser->output_to_core("NONE"); foreach $input ( 'multi-simple.msg', 'multi-nested3.msg', 'mp-msg-rfc822.msg' ) { $parser->parse_nested_messages($input eq 'mp-msg-rfc822.msg'); for ($i = 0; $i < 1000; $i++) { print STDERR "$input: i = $i\n"; open IN, "testin/$input" or die "open testin/$input: $!"; $entity = $parser->read(\*IN) or die "MIME error"; close IN; $entity->purge; } } print "Who-hooo! Done!\n"; MIME-tools-5.509/examples/mimesend0000755000076400007640000000610012541013575015110 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimesend - send files via MIME mail, from the command line =head1 USAGE Pretty basic: mimesend [-n] [-t to] [-s subj] (-f file [-m type])+ -n Don't actually send it; just print it to stdout. -t to The "to" address. -s subj The subject of the message. -f file Path to attached file, or - for STDIN. -m type MIME type of previous -f; therefore -m must follow -f. For example: mimesend -t you@yourhost.com -s "Hello, nurse!" -f greetings.htm -f foo.gif =head1 AUTHOR Eryq, eryq@zeegee.com 8 Jan 1997 =cut use lib "./lib"; use MIME::Entity; # Lookup table: my %TypeFor = qw( txt text/plain sh text/x-sh csh text/x-csh pm text/x-perl pl text/x-perl jpg image/jpeg jpeg image/jpeg gif image/gif tif image/tiff tiff image/tiff xbm image/xbm pdf application/pdf ); # Usage: @ARGV or die <.\n"; } # Verify destination: $to or die "$0: missing [-t to]\n"; # Verify subject: $subj or die "$0: missing [-s subject]\n"; # Start with top-level entity: my $top; if (!@files) { die "$0: no files specified!\n"; } elsif (@files == 1) { my ($path, $type) = @{$files[0]}; # Build: $top = build MIME::Entity Type => ($type || type_for($path)), $path eq '-' ? (Data => [<>]) : (Path => $path), Encoding => '-SUGGEST'; $top->head->add('To', $to); $top->head->add('Subject', $subj); } else { # Start with top: $top = build MIME::Entity Type=>"multipart/mixed"; $top->head->add('To', $to); $top->head->add('Subject', $subj); # Attach files: foreach (@files) { my ($path, $type) = @{$_}; $top->attach(Type => ($type || type_for($path)), Path => $path, Encoding => '-SUGGEST'); } } # Launch mailer and send message? if (!$nosend) { open SENDMAIL, "|/usr/lib/sendmail -t -oi -oem" or die "$0: open sendmail: $!\n"; $top->print(\*SENDMAIL); close SENDMAIL; die "sendmail failed" if ($? >> 255); } else { $top->print(\*STDOUT); } 1; MIME-tools-5.509/examples/mimeexplode0000755000076400007640000000643312541013575015630 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimeexplode - explode one or more MIME messages =head1 SYNOPSIS mimeexplode ... someprocess | mimeexplode - =head1 DESCRIPTION Takes one or more files from the command line that contain MIME messages, and explodes their contents out into subdirectories of the current working directory. The subdirectories are just called C, C, C, etc. Existing directories are skipped over. The message information is output to the stdout, like this: Message: msg3 (inputfile1.msg) Part: msg3/filename-1.dat (text/plain) Part: msg3/filename-2.dat (text/plain) Message: msg5 (input-file2.msg) Part: msg5/dir.gif (image/gif) Part: msg5/face.jpg (image/jpeg) Message: msg6 (infile3) Part: msg6/filename-1.dat (text/plain) This was written as an example of the MIME:: modules in the MIME-parser package I wrote. It may prove useful as a quick-and-dirty way of splitting a MIME message if you need to decode something, and you don't have a MIME mail reader on hand. =head1 COMMAND LINE OPTIONS None yet. =head1 AUTHOR Eryq C, in a big hurry... =cut BEGIN { unshift @INC, ".." } # to test MIME:: stuff before installing it! require 5.001; use strict; use vars qw($Msgno); use MIME::Parser; use Getopt::Std; #------------------------------------------------------------ # make_msg - make and return the name of a msgXXX directory #------------------------------------------------------------ $Msgno = 0; sub make_msg { while (-d "msg$Msgno") { ++$Msgno; die "self-imposed limit reached" if $Msgno == 256; } mkdir "msg$Msgno",0755 or die "couldn't make msg$Msgno: $!"; "msg$Msgno"; } #------------------------------------------------------------ # dump_entity - dump an entity's file info #------------------------------------------------------------ sub dump_entity { my $ent = shift; my @parts = $ent->parts; if (@parts) { # multipart... map { dump_entity($_) } @parts; } else { # single part... print " Part: ", $ent->bodyhandle->path, " (", scalar($ent->head->mime_type), ")\n"; } } #------------------------------------------------------------ # main #------------------------------------------------------------ sub main { my $file; my $entity; # Sanity: (-w ".") or die "cwd not writable, you naughty boy..."; # Go through messages: @ARGV or unshift @ARGV, "-"; while (defined($file = shift @ARGV)) { my $msgdir = make_msg(); print "Message: $msgdir ($file)\n"; # Create a new parser object: my $parser = new MIME::Parser; ### $parser->parse_nested_messages('REPLACE'); # Optional: set up parameters that will affect how it extracts # documents from the input stream: $parser->output_dir($msgdir); # Parse an input stream: open FILE, $file or die "couldn't open $file"; $entity = $parser->read(\*FILE) or print STDERR "Couldn't parse MIME in $file; continuing...\n"; close FILE; # Congratulations: you now have a (possibly multipart) MIME entity! dump_entity($entity) if $entity; ### $entity->dump_skeleton if $entity; } 1; } exit (&main ? 0 : -1); #------------------------------------------------------------ 1; MIME-tools-5.509/examples/mimepostcard0000755000076400007640000000526412541013575016010 0ustar dfsdfs#!/usr/bin/perl -w =head1 NAME mimepostcard - send/output a multipart/alternative message =head1 SYNOPSIS Usage: mimepostcard /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 sends 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::Entity; use strict; use Getopt::Std; $SIG{__DIE__} = sub { die "mime_postcard: $_[0]\n" }; #------------------------------ # usage #------------------------------ sub usage { my $problem = join '',@_; print STDERR "\n"; print STDERR "Error: $problem\n" if $problem; my @usage; if (open O, '<'.$0){ local($/) = "\n"; 1 while (defined($_ = ) and !/^=head1\s+SYNOPSIS/); push @usage, $_ while (defined($_ = ) and !/^=/); close O; } my $u = join '', @usage; $u =~ s/\A\n+//; $u =~ s{\n\n+(\s+)}{\n$1}g; print STDERR $u, "\n"; exit -1; } #------------------------------ # main #------------------------------ sub main { ### Get options: my %opts; getopts("", \%opts); ### Get graphic: my $graphic = shift @ARGV || usage "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 || usage "missing destination\n"; ### The top-level message: my $msg = MIME::Entity->build(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... \n>, qq< take a look!\n >, qq<
Snapshot
> ]); $fancy->attach(Type => $graphic_type, Path => $graphic, Id => $gid); ### Print or send: if ($dest eq '-') { $msg->print; } else { $msg->smtpsend(); } } eval { main() }; die "$0: $@" if $@; MIME-tools-5.509/testmsgs/0000755000076400007640000000000013071231525013413 5ustar dfsdfsMIME-tools-5.509/testmsgs/uu-junk-extracted.ref0000644000076400007640000000201112541013575017466 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/uu-junk.msg", "ExtractUuencode" => 1, "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "mime::parser", "Type" => "multipart/mixed", "To" => "eryq\@zeegee.com", "From" => "\"ADJE Webmail Tech Support\" ", "Encoding" => "7bit", "Boundary" => "---------------------------7d033e3733c" }, "Part_1" => { "Size" => 373, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Type" => "multipart/mixed", "Encoding" => "7bit", }, "Part_2_1" => { "Size" => 93, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2_2" => { "Filename" => "up.gif", "Size" => 110, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" }, "Part_2_3" => { "Filename" => "zeegee.gif", "Size" => 4834, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" } } MIME-tools-5.509/testmsgs/multi-2evil.ref0000644000076400007640000000163012541013575016266 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/multi-2evil.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "Two images for you...", "Type" => "multipart/mixed", "To" => "john-bigboote\@eryq.pr.mcs.net", "From" => "Eryq ", "Encoding" => "7bit", "Boundary" => "------------299A70B339B65A93542D2AE", }, "Part_1" => { "Size" => 417, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Part_2" => { "Filename" => qq{/evil/because:ofpath3d-compress.gif}, "BodyFilename" => "because_ofpath3d-compress.gif", "Size" => 419, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" }, "Part_3" => { "BodyFilename" => "3d-eye-is-an-e.dat", "Size" => 357, "Type" => "image/gif", "Encoding" => "base64" }, } MIME-tools-5.509/testmsgs/multi-nested2.msg0000644000076400007640000000620112541013575016622 0ustar dfsdfsMIME-Version: 1.0 From: Lord John Whorfin To: Subject: A complex nested multipart example Content-Type: multipart/mixed; boundary=unique-boundary-1 The preamble of the outer multipart message. Mail readers that understand multipart format should ignore this preamble. If you are reading this text, you might want to consider changing to a mail reader that understands how to properly display multipart messages. --unique-boundary-1 Part 1 of the outer message. [Note that the preceding blank line means no header fields were given and this is text, with charset US ASCII. It could have been done with explicit typing as in the next part.] --unique-boundary-1 Content-type: text/plain; charset=US-ASCII Part 2 of the outer message. This could have been part of the previous part, but illustrates explicit versus implicit typing of body parts. --unique-boundary-1 Subject: Part 3 of the outer message is multipart! Content-Type: multipart/parallel; boundary=unique-boundary-2 A one-line preamble for the inner multipart message. --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-vise.gif" Subject: Part 1 of the inner message is a GIF, "3d-vise.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-eye.gif" Subject: Part 2 of the inner message is another GIF, "3d-eye.gif" R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --unique-boundary-2-- The epilogue for the inner multipart message. --unique-boundary-1 Content-type: text/richtext This is part 4 of the outer message as defined in RFC1341 Isn't it cool? --unique-boundary-1 Content-Type: message/rfc822; name="/evil/filename"; From: (mailbox in US-ASCII) To: (address in US-ASCII) Subject: Part 5 of the outer message is itself an RFC822 message! Content-Type: Text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: Quoted-printable Part 5 of the outer message is itself an RFC822 message! --unique-boundary-1-- The epilogue for the outer message. MIME-tools-5.509/testmsgs/multi-clen.ref0000644000076400007640000000135012541013575016165 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/multi-clen.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "Sample message", "Type" => "multipart/mixed", "To" => " Ned Freed ", "From" => "Nathaniel Borenstein ", "Encoding" => "7bit", "Boundary" => "simple boundary" }, "Part_1" => { "Size" => 76, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Size" => 30, "Type" => "text/x-numbers", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Part_3" => { "Size" => 600, "Type" => "text/x-alphabet", "Encoding" => "7bit", "Charset" => "us-ascii" }, } MIME-tools-5.509/testmsgs/ticket-60931.msg0000644000076400007640000000056612541013575016101 0ustar dfsdfsMIME-Version: 1.0 Received: by 10.220.78.157 with HTTP; Thu, 26 Aug 2010 21:33:17 -0700 (PDT) Content-Type: multipart/alternative; boundary=90e6ba4fc6ea25d329048ec69d99 --90e6ba4fc6ea25d329048ec69d99 Content-Type: text/plain; charset=ISO-8859-1 HELLO --90e6ba4fc6ea25d329048ec69d99 Content-Type: text/html; charset=ISO-8859-1 HELLO
--90e6ba4fc6ea25d329048ec69d99-- MIME-tools-5.509/testmsgs/bluedot-simple.ref0000644000076400007640000000047512541013575017050 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/bluedot-simple.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Filename" => "bluedot.jpg", "Size" => 4272, "Disposition" => "inline", "Type" => "image/jpeg", "Encoding" => "base64" }, } MIME-tools-5.509/testmsgs/hdr-fakeout-newmailtools-ref0000644000076400007640000000055712706225305021046 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/hdr-fakeout.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "test message 1", "Type" => "text/plain", "To" => "\"Russell P. Sutherland\" ", "From" => "\"Russell P. Sutherland\" ", "Encoding" => "7bit" } } MIME-tools-5.509/testmsgs/multi-digest.msg0000644000076400007640000000140012541013575016531 0ustar dfsdfsFrom: Nathaniel Borenstein To: Ned Freed Subject: Sample digest message MIME-Version: 1.0 Content-type: multipart/digest; boundary="simple boundary" This is the preamble. It is to be ignored, though it is a handy place for mail composers to include an explanatory note to non-MIME conformant readers. --simple boundary From: noone@nowhere.org Subject: embedded message 1 This is implicitly-typed ASCII text. It does NOT end with a linebreak. --simple boundary Content-type: message/rfc822; charset=us-ascii From: noone@nowhere.org Subject: embedded message 2 Content-type: text This is explicitly typed plain ASCII text. It DOES end with a linebreak. --simple boundary-- This is the epilogue. It is also to be ignored. MIME-tools-5.509/testmsgs/multi-frag.msg0000644000076400007640000000625212541013575016203 0ustar dfsdfsMIME-Version: 1.0 From: Lord John Whorfin To: Subject: A complex nested multipart example Content-Type: multipart/mixed; boundary=unique-boundary-1 The preamble of the outer multipart message. Mail readers that understand multipart format should ignore this preamble. If you are reading this text, you might want to consider changing to a mail reader that understands how to properly display multipart messages. --unique-boundary-1 Part 1 of the outer message. [Note that the preceding blank line means no header fields were given and this is text, with charset US ASCII. It could have been done with explicit typing as in the next part.] --unique-boundary-1 Content-type: text/plain; charset=US-ASCII Part 2 of the outer message. This could have been part of the previous part, but illustrates explicit versus implicit typing of body parts. --unique-boundary-1 Subject: Part 3 of the outer message is multipart! Content-Type: multipart/parallel; boundary=unique-boundary-2 A one-line preamble for the inner multipart message. --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-vise.gif" Subject: Part 1 of the inner message is a GIF, "3d-vise.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-eye.gif" Subject: Part 2 of the inner message is another GIF, "3d-eye.gif", but the terminating boundary is bad! R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 XXXXXX--unique-boundary-2-- The epilogue for the inner multipart message. --unique-boundary-1 Content-type: text/richtext This is part 4 of the outer message as defined in RFC1341 Isn't it cool? --unique-boundary-1 Content-Type: message/rfc822; name="nice.name"; From: (mailbox in US-ASCII) To: (address in US-ASCII) Subject: Part 5 of the outer message is itself an RFC822 message! Content-Type: Text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: Quoted-printable Part 5 of the outer message is itself an RFC822 message! --unique-boundary-1-- The epilogue for the outer message. MIME-tools-5.509/testmsgs/ak-0696-nest.ref0000644000076400007640000000165212541013575016065 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/ak-0696.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "[Fwd: Re: 34Mbit/s Netz]", "Type" => "multipart/mixed", "To" => "andreas.koenig\@mind.de, kun\@pop.combox.de, 101762.2307\@compuserve.com", "From" => "Juergen Specht ", "Encoding" => "7bit", "Boundary" => "------------70522FC73543" }, "Part_1" => { "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Part_2" => { "Disposition" => "inline", "Type" => "message/rfc822", "Encoding" => "7bit" }, "Part_2_1" => { "Subject" => "Re: 34Mbit/s Netz", "Type" => "text/plain", "To" => "Juergen Specht ", "From" => "deuschle\@mnh.telekom.de (Guenter Deuschle)", "Encoding" => "quoted-printable", "Charset" => "iso-8859-1" }, } MIME-tools-5.509/testmsgs/multi-weirdspace.ref0000644000076400007640000000150312541013575017372 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/multi-weirdspace.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "Two images for you...", "Type" => "multipart/mixed", "To" => "john-bigboote\@eryq.pr.mcs.net", "From" => "Eryq ", "Encoding" => "7bit", "Boundary" => "------------299A70B339B65A93542D2AE" }, "Part_1" => { "Size" => 420, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Part_2" => { "Filename" => "3d-compress.gif", "Size" => 419, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" }, "Part_3" => { "Filename" => "3d-eye.gif", "Size" => 357, "Type" => "image/gif", "Encoding" => "base64" }, } MIME-tools-5.509/testmsgs/multi-igor.msg0000644000076400007640000002451412541013575016225 0ustar dfsdfsDate: Thu, 6 Jun 1996 15:50:39 +0400 (MOW DST) From: Starovoitov Igor To: eryq@rhine.gsfc.nasa.gov Subject: Need help MIME-Version: 1.0 Content-Type: MULTIPART/MIXED; BOUNDARY="-490585488-806670346-834061839=:2195" This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. Send mail to mime@docserver.cac.washington.edu for more info. ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII Dear Sir, I have a problem with Your MIME-Parser-1.9 and multipart-nested messages. Not all parts are parsed. Here my Makefile, Your own multipart-nested.msg and its out after "make test". Some my messages not completely parsed too. Is this a bug? Thank You for help. Igor Starovoytov. ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII; name=Makefile Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: Makefile Iy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLQ0KIyBNYWtlZmlsZSBmb3IgTUlNRTo6DQojLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tDQoNCiMgV2hlcmUgdG8gaW5zdGFsbCB0aGUgbGlicmFy aWVzOg0KU0lURV9QRVJMID0gL3Vzci9saWIvcGVybDUNCg0KIyBXaGF0IFBl cmw1IGlzIGNhbGxlZCBvbiB5b3VyIHN5c3RlbSAobm8gbmVlZCB0byBnaXZl IGVudGlyZSBwYXRoKToNClBFUkw1ICAgICA9IHBlcmwNCg0KIyBZb3UgcHJv YmFibHkgd29uJ3QgbmVlZCB0byBjaGFuZ2UgdGhlc2UuLi4NCk1PRFMgICAg ICA9IERlY29kZXIucG0gRW50aXR5LnBtIEhlYWQucG0gUGFyc2VyLnBtIEJh c2U2NC5wbSBRdW90ZWRQcmludC5wbQ0KU0hFTEwgICAgID0gL2Jpbi9zaA0K DQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tDQojIEZvciBpbnN0YWxsZXJzLi4uDQojLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tDQoNCmhlbHA6CQ0KCUBlY2hvICJWYWxpZCB0YXJnZXRz OiB0ZXN0IGNsZWFuIGluc3RhbGwiDQoNCmNsZWFuOg0KCXJtIC1mIHRlc3Rv dXQvKg0KDQp0ZXN0Og0KIwlAZWNobyAiVEVTVElORyBIZWFkLnBtLi4uIg0K Iwkke1BFUkw1fSBNSU1FL0hlYWQucG0gICA8IHRlc3Rpbi9maXJzdC5oZHIg ICAgICAgPiB0ZXN0b3V0L0hlYWQub3V0DQojCUBlY2hvICJURVNUSU5HIERl Y29kZXIucG0uLi4iDQojCSR7UEVSTDV9IE1JTUUvRGVjb2Rlci5wbSA8IHRl c3Rpbi9xdW90LXByaW50LmJvZHkgPiB0ZXN0b3V0L0RlY29kZXIub3V0DQoj CUBlY2hvICJURVNUSU5HIFBhcnNlci5wbSAoc2ltcGxlKS4uLiINCiMJJHtQ RVJMNX0gTUlNRS9QYXJzZXIucG0gPCB0ZXN0aW4vc2ltcGxlLm1zZyAgICAg ID4gdGVzdG91dC9QYXJzZXIucy5vdXQNCiMJQGVjaG8gIlRFU1RJTkcgUGFy c2VyLnBtIChtdWx0aXBhcnQpLi4uIg0KIwkke1BFUkw1fSBNSU1FL1BhcnNl ci5wbSA8IHRlc3Rpbi9tdWx0aS0yZ2lmcy5tc2cgPiB0ZXN0b3V0L1BhcnNl ci5tLm91dA0KCUBlY2hvICJURVNUSU5HIFBhcnNlci5wbSAobXVsdGlfbmVz dGVkLm1zZykuLi4iDQoJJHtQRVJMNX0gTUlNRS9QYXJzZXIucG0gPCB0ZXN0 aW4vbXVsdGktbmVzdGVkLm1zZyA+IHRlc3RvdXQvUGFyc2VyLm4ub3V0DQoJ QGVjaG8gIkFsbCB0ZXN0cyBwYXNzZWQuLi4gc2VlIC4vdGVzdG91dC9NT0RV TEUqLm91dCBmb3Igb3V0cHV0Ig0KDQppbnN0YWxsOg0KCUBpZiBbICEgLWQg JHtTSVRFX1BFUkx9IF07IHRoZW4gXA0KCSAgICBlY2hvICJQbGVhc2UgZWRp dCB0aGUgU0lURV9QRVJMIGluIHlvdXIgTWFrZWZpbGUiOyBleGl0IC0xOyBc DQogICAgICAgIGZpICAgICAgICAgIA0KCUBpZiBbICEgLXcgJHtTSVRFX1BF Ukx9IF07IHRoZW4gXA0KCSAgICBlY2hvICJObyBwZXJtaXNzaW9uLi4uIHNo b3VsZCB5b3UgYmUgcm9vdD8iOyBleGl0IC0xOyBcDQogICAgICAgIGZpICAg ICAgICAgIA0KCUBpZiBbICEgLWQgJHtTSVRFX1BFUkx9L01JTUUgXTsgdGhl biBcDQoJICAgIG1rZGlyICR7U0lURV9QRVJMfS9NSU1FOyBcDQogICAgICAg IGZpDQoJaW5zdGFsbCAtbSAwNjQ0IE1JTUUvKi5wbSAke1NJVEVfUEVSTH0v TUlNRQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgRm9yIGRldmVsb3BlciBv bmx5Li4uDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNClBPRDJIVE1MX0ZMQUdTID0g LS1wb2RwYXRoPS4gLS1mbHVzaCAtLWh0bWxyb290PS4uDQpIVE1MUyAgICAg ICAgICA9ICR7TU9EUzoucG09Lmh0bWx9DQpWUEFUSCAgICAgICAgICA9IE1J TUUNCg0KLlNVRkZJWEVTOiAucG0gLnBvZCAuaHRtbA0KDQojIHYuMS44IGdl bmVyYXRlZCAzMCBBcHIgOTYNCiMgdi4xLjkgaXMgb25seSBiZWNhdXNlIDEu OCBmYWlsZWQgQ1BBTiBpbmdlc3Rpb24NCmRpc3Q6IGRvY3VtZW50ZWQJDQoJ VkVSU0lPTj0xLjkgOyBcDQoJbWtkaXN0IC10Z3ogTUlNRS1wYXJzZXItJCRW RVJTSU9OIDsgXA0KCWNwIE1LRElTVC9NSU1FLXBhcnNlci0kJFZFUlNJT04u dGd6ICR7SE9NRX0vcHVibGljX2h0bWwvY3Bhbg0KCQ0KZG9jdW1lbnRlZDog JHtIVE1MU30gJHtNT0RTfQ0KDQoucG0uaHRtbDoNCglwb2QyaHRtbCAke1BP RDJIVE1MX0ZMQUdTfSBcDQoJCS0tdGl0bGU9TUlNRTo6JCogXA0KCQktLWlu ZmlsZT0kPCBcDQoJCS0tb3V0ZmlsZT1kb2NzLyQqLmh0bWwNCg0KIy0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLQ0K ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="multi-nested.msg" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: test message TUlNRS1WZXJzaW9uOiAxLjANCkZyb206IExvcmQgSm9obiBXaG9yZmluIDx3 aG9yZmluQHlveW9keW5lLmNvbT4NClRvOiA8am9obi15YXlhQHlveW9keW5l LmNvbT4NClN1YmplY3Q6IEEgY29tcGxleCBuZXN0ZWQgbXVsdGlwYXJ0IGV4 YW1wbGUNCkNvbnRlbnQtVHlwZTogbXVsdGlwYXJ0L21peGVkOw0KICAgICBi b3VuZGFyeT11bmlxdWUtYm91bmRhcnktMQ0KDQpUaGUgcHJlYW1ibGUgb2Yg dGhlIG91dGVyIG11bHRpcGFydCBtZXNzYWdlLg0KTWFpbCByZWFkZXJzIHRo YXQgdW5kZXJzdGFuZCBtdWx0aXBhcnQgZm9ybWF0DQpzaG91bGQgaWdub3Jl IHRoaXMgcHJlYW1ibGUuDQpJZiB5b3UgYXJlIHJlYWRpbmcgdGhpcyB0ZXh0 LCB5b3UgbWlnaHQgd2FudCB0bw0KY29uc2lkZXIgY2hhbmdpbmcgdG8gYSBt YWlsIHJlYWRlciB0aGF0IHVuZGVyc3RhbmRzDQpob3cgdG8gcHJvcGVybHkg ZGlzcGxheSBtdWx0aXBhcnQgbWVzc2FnZXMuDQotLXVuaXF1ZS1ib3VuZGFy eS0xDQoNClBhcnQgMSBvZiB0aGUgb3V0ZXIgbWVzc2FnZS4NCltOb3RlIHRo YXQgdGhlIHByZWNlZGluZyBibGFuayBsaW5lIG1lYW5zDQpubyBoZWFkZXIg ZmllbGRzIHdlcmUgZ2l2ZW4gYW5kIHRoaXMgaXMgdGV4dCwNCndpdGggY2hh cnNldCBVUyBBU0NJSS4gIEl0IGNvdWxkIGhhdmUgYmVlbg0KZG9uZSB3aXRo IGV4cGxpY2l0IHR5cGluZyBhcyBpbiB0aGUgbmV4dCBwYXJ0Ll0NCg0KLS11 bmlxdWUtYm91bmRhcnktMQ0KQ29udGVudC10eXBlOiB0ZXh0L3BsYWluOyBj aGFyc2V0PVVTLUFTQ0lJDQoNClBhcnQgMiBvZiB0aGUgb3V0ZXIgbWVzc2Fn ZS4NClRoaXMgY291bGQgaGF2ZSBiZWVuIHBhcnQgb2YgdGhlIHByZXZpb3Vz IHBhcnQsDQpidXQgaWxsdXN0cmF0ZXMgZXhwbGljaXQgdmVyc3VzIGltcGxp Y2l0DQp0eXBpbmcgb2YgYm9keSBwYXJ0cy4NCg0KLS11bmlxdWUtYm91bmRh cnktMQ0KU3ViamVjdDogUGFydCAzIG9mIHRoZSBvdXRlciBtZXNzYWdlIGlz IG11bHRpcGFydCENCkNvbnRlbnQtVHlwZTogbXVsdGlwYXJ0L3BhcmFsbGVs Ow0KICAgICBib3VuZGFyeT11bmlxdWUtYm91bmRhcnktMg0KDQpBIG9uZS1s aW5lIHByZWFtYmxlIGZvciB0aGUgaW5uZXIgbXVsdGlwYXJ0IG1lc3NhZ2Uu DQotLXVuaXF1ZS1ib3VuZGFyeS0yDQpDb250ZW50LVR5cGU6IGltYWdlL2dp Zg0KQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0DQpDb250ZW50 LURpc3Bvc2l0aW9uOiBpbmxpbmU7IGZpbGVuYW1lPSIzZC1jb21wcmVzcy5n aWYiDQpTdWJqZWN0OiBQYXJ0IDEgb2YgdGhlIGlubmVyIG1lc3NhZ2UgaXMg YSBHSUYsICIzZC1jb21wcmVzcy5naWYiDQoNClIwbEdPRGRoS0FBb0FPTUFB QUFBQUFBQWdCNlEveTlQVDI1dWJuQ0FrS0JTTGI2K3Z1Zm41L1hlcy8rbEFQ LzZ6UUFBQUFBQQ0KQUFBQUFBQUFBQ3dBQUFBQUtBQW9BQUFFL2hESlNhdTll SkxNT3lZYmNveGthWjVvQ2tvSDZMNXdMTWZpV3FkNGJ0WmhteGJBDQpvRkNZ NDdFSXFNSmd5V3cyQVRqajdhUmtBcTVZd0RNbDlWR3RLTzBTaXVvaVRWbHNj c3h0OWM0SGdYeFVJQTBFQVZPVmZES1QNCjhIbDFCM2tEQVlZbGUyMDJYbkdH Z29NSGhZY2tpV1Z1UjMrT1RnQ0dlWlJzbG90d2dKMmxuWWlnZlpkVGpRVUxy N0FMQlpOMA0KcVR1cmpIZ0xLQXUwQjVXcW9wbTdKNzJldFFOOHQ4SWp1cnkr d010dnc4L0h2N1lsZnMwQnhDYkdxTW1LMHlPT1EwR1RDZ3JSDQoyYmh3Skds WEpRWUc2bU1Lb2VOb1dTYnpDV0lBQ2U1Snd4UW0zQWtEQWJVQVFDaVFoRFpF QmVCbDZhZmdDc09CckQ0NWVkSXYNClFjZUdXU01ldnBPWWhsNkNreWRCSGhC WlFtR0tqaWhWc2h5cGpCOUNsQUhaTVR1Z3pPVTdtemhCUGlTWjV1RE5uQTdi L2FUWg0KMG1oTW5mbDBwREJGYTZiVUVsU1BXYjBxdFl1SHJ4bHdjUjE3WXNX TXMyalRxbDNMRmtRRUFEcz0NCi0tdW5pcXVlLWJvdW5kYXJ5LTINCkNvbnRl bnQtVHlwZTogaW1hZ2UvZ2lmDQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5n OiBiYXNlNjQNCkNvbnRlbnQtRGlzcG9zaXRpb246IGlubGluZTsgZmlsZW5h bWU9IjNkLWV5ZS5naWYiDQpTdWJqZWN0OiBQYXJ0IDIgb2YgdGhlIGlubmVy IG1lc3NhZ2UgaXMgYW5vdGhlciBHSUYsICIzZC1leWUuZ2lmIg0KDQpSMGxH T0RkaEtBQW9BUE1BQUFBQUFBQUF6TjN1Lzc2K3ZvaUlpRzV1YnN6ZDd2Ly8v K2ZuNXdBQUFBQUFBQUFBQUFBQUFBQUENCkFBQUFBQUFBQUN3QUFBQUFLQUFv QUFBRS9oREpTYXU5ZUpiTU95NGJNb3hrYVo1b0Nrb0Q2TDV3TE1maVduczQx b1p0N2xNNw0KVnVqbkM5NklSVnNQV1FFNG54UGprdm1zUW11OG9jL0tCVVNW V2s3WGVwR0dMZU5yeG94Sk8xTWpJTGp0aGcva1dYUTZ3Ty83DQorM2RDZVJS amZBS0hpSW1KQVYrRENGMEJpVzVWQW8xQ0VsYVJoNU5qbGtlWW1weVRncGNU QUtHaWFhU2Zwd0twVlFheFZhdEwNCnJVOEdhUWRPQkFRQUI3K3lYbGlYVHJn QXhzVzR2RmFidjhCT3RCc0J0N2NHdndDSVQ5bk95TkVJeHVDNHpycUt6YzlY Yk9ESg0KdnM3WTVld0gzZDdGeGUzakI0cmo4dDZQdU5hNnIyYmhLUVhOMTdG WUNCTXFUR2lCelNOaHg1ZzBuRU1obHNTSmppUll2RGp3DQpFMGNkR3hRL2dz d29zb0tVa211VTJGbkpjc1NLR1RCanlweEpzeWFJQ0FBNw0KLS11bmlxdWUt Ym91bmRhcnktMi0tDQoNClRoZSBlcGlsb2d1ZSBmb3IgdGhlIGlubmVyIG11 bHRpcGFydCBtZXNzYWdlLg0KDQotLXVuaXF1ZS1ib3VuZGFyeS0xDQpDb250 ZW50LXR5cGU6IHRleHQvcmljaHRleHQNCg0KVGhpcyBpcyA8Ym9sZD5wYXJ0 IDQgb2YgdGhlIG91dGVyIG1lc3NhZ2U8L2JvbGQ+DQo8c21hbGxlcj5hcyBk ZWZpbmVkIGluIFJGQzEzNDE8L3NtYWxsZXI+PG5sPg0KPG5sPg0KSXNuJ3Qg aXQgPGJpZ2dlcj48YmlnZ2VyPmNvb2w/PC9iaWdnZXI+PC9iaWdnZXI+DQoN Ci0tdW5pcXVlLWJvdW5kYXJ5LTENCkNvbnRlbnQtVHlwZTogbWVzc2FnZS9y ZmM4MjINCg0KRnJvbTogKG1haWxib3ggaW4gVVMtQVNDSUkpDQpUbzogKGFk ZHJlc3MgaW4gVVMtQVNDSUkpDQpTdWJqZWN0OiBQYXJ0IDUgb2YgdGhlIG91 dGVyIG1lc3NhZ2UgaXMgaXRzZWxmIGFuIFJGQzgyMiBtZXNzYWdlIQ0KQ29u dGVudC1UeXBlOiBUZXh0L3BsYWluOyBjaGFyc2V0PUlTTy04ODU5LTENCkNv bnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IFF1b3RlZC1wcmludGFibGUNCg0K UGFydCA1IG9mIHRoZSBvdXRlciBtZXNzYWdlIGlzIGl0c2VsZiBhbiBSRkM4 MjIgbWVzc2FnZSENCg0KLS11bmlxdWUtYm91bmRhcnktMS0tDQoNClRoZSBl cGlsb2d1ZSBmb3IgdGhlIG91dGVyIG1lc3NhZ2UuDQo= ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="Parser.n.out" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: out from parser KiBXYWl0aW5nIGZvciBhIE1JTUUgbWVzc2FnZSBmcm9tIFNURElOLi4uDQo9 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT0NCkNvbnRlbnQtdHlwZTogbXVsdGlwYXJ0L21peGVk DQpCb2R5LWZpbGU6IE5PTkUNClN1YmplY3Q6IEEgY29tcGxleCBuZXN0ZWQg bXVsdGlwYXJ0IGV4YW1wbGUNCk51bS1wYXJ0czogMw0KLS0NCiAgICBDb250 ZW50LXR5cGU6IHRleHQvcGxhaW4NCiAgICBCb2R5LWZpbGU6IC4vdGVzdG91 dC9tc2ctMzUzOC0xLmRvYw0KICAgIC0tDQogICAgQ29udGVudC10eXBlOiB0 ZXh0L3BsYWluDQogICAgQm9keS1maWxlOiAuL3Rlc3RvdXQvbXNnLTM1Mzgt Mi5kb2MNCiAgICAtLQ0KICAgIENvbnRlbnQtdHlwZTogbXVsdGlwYXJ0L3Bh cmFsbGVsDQogICAgQm9keS1maWxlOiBOT05FDQogICAgU3ViamVjdDogUGFy dCAzIG9mIHRoZSBvdXRlciBtZXNzYWdlIGlzIG11bHRpcGFydCENCiAgICBO dW0tcGFydHM6IDINCiAgICAtLQ0KICAgICAgICBDb250ZW50LXR5cGU6IGlt YWdlL2dpZg0KICAgICAgICBCb2R5LWZpbGU6IC4vdGVzdG91dC8zZC1jb21w cmVzcy5naWYNCiAgICAgICAgU3ViamVjdDogUGFydCAxIG9mIHRoZSBpbm5l ciBtZXNzYWdlIGlzIGEgR0lGLCAiM2QtY29tcHJlc3MuZ2lmIg0KICAgICAg ICAtLQ0KICAgICAgICBDb250ZW50LXR5cGU6IGltYWdlL2dpZg0KICAgICAg ICBCb2R5LWZpbGU6IC4vdGVzdG91dC8zZC1leWUuZ2lmDQogICAgICAgIFN1 YmplY3Q6IFBhcnQgMiBvZiB0aGUgaW5uZXIgbWVzc2FnZSBpcyBhbm90aGVy IEdJRiwgIjNkLWV5ZS5naWYiDQogICAgICAgIC0tDQo9PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT0NCg0K ---490585488-806670346-834061839=:2195-- MIME-tools-5.509/testmsgs/re-fwd.msg0000644000076400007640000000141312541013575015312 0ustar dfsdfsContent-Disposition: inline Content-Transfer-Encoding: binary Content-Type: message/rfc822 MIME-Version: 1.0 X-Mailer: MIME::Lite 1.147 (B2.09; Q2.03) Date: Tue, 6 Jun 2000 03:20:11 UT From: user2 To: user0 Subject: Re: Fwd: hello world Content-Disposition: inline Content-Transfer-Encoding: binary Content-Type: message/rfc822 MIME-Version: 1.0 X-Mailer: MIME::Lite 1.147 (B2.09; Q2.03) Date: Tue, 6 Jun 2000 03:20:11 UT From: user1 To: user2 Subject: Fwd: hello world Content-Disposition: inline Content-Length: 60 Content-Transfer-Encoding: binary Content-Type: text/plain MIME-Version: 1.0 X-Mailer: MIME::Lite 1.147 (B2.09; Q2.03) Date: Tue, 6 Jun 2000 03:20:11 UT From: user0 To: user1 Subject: hello world This is the original message. Let's see if we can embed it! MIME-tools-5.509/testmsgs/double-semicolon2.msg0000644000076400007640000000036012541013575017450 0ustar dfsdfsMime-Version: 1.0 Content-Type: multipart/alternative ; ; ; ;; ;;;;;;;; boundary="foo" Preamble --foo Content-Type: text/plain; charset=us-ascii The better part --foo Content-Type: text/plain; charset=us-ascii The worse part --foo-- MIME-tools-5.509/testmsgs/multi-igor.ref0000644000076400007640000000176512541013575016216 0ustar dfsdfs{ "Part_1" => { "Size" => 293, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "US-ASCII" }, "Part_2" => { "Filename" => "Makefile", "Size" => 2442, "Type" => "text/plain", "Encoding" => "base64", "Charset" => "US-ASCII" }, "Part_3" => { "Filename" => "multi-nested.msg", "Size" => 3272, "Type" => "text/plain", "Encoding" => "base64", "Charset" => "US-ASCII" }, "Part_4" => { "Filename" => "Parser.n.out", "Size" => 906, "Type" => "text/plain", "Encoding" => "base64", "Charset" => "US-ASCII" }, "Msg" => { "Subject" => "Need help", "Type" => "multipart/mixed", "To" => "eryq\@rhine.gsfc.nasa.gov", "From" => "Starovoitov Igor ", "Encoding" => "7bit", "Boundary" => "-490585488-806670346-834061839=:2195" }, "Parser" => { "Message" => "testmsgs/multi-igor.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" } } MIME-tools-5.509/testmsgs/attachment-filename-encoding-Latin1.msg0000644000076400007640000000107012541013575022745 0ustar dfsdfsMIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050706070100080203090004" This is a multi-part message in MIME format. --------------050706070100080203090004 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Attachment Test --------------050706070100080203090004 Content-Type: text/plain; name="=?ISO-8859-1?B?YXR0YWNobWVudC7k9vw=?=" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename*=ISO-8859-1''%61%74%74%61%63%68%6D%65%6E%74%2E%E4%F6%FC VGVzdAo= --------------050706070100080203090004-- MIME-tools-5.509/testmsgs/hdr-fakeout.ref0000644000076400007640000000026712541013575016333 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/hdr-fakeout.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { Fail => 1, } } MIME-tools-5.509/testmsgs/multi-nested2.ref0000644000076400007640000000337612541013575016622 0ustar dfsdfs{ "Part_3_1" => { "Filename" => "3d-vise.gif", "Size" => 419, "Disposition" => "inline", "Subject" => "Part 1 of the inner message is a GIF, \"3d-vise.gif\"", "Type" => "image/gif", "Encoding" => "base64" }, "Part_3_2" => { "Filename" => "3d-eye.gif", "Size" => 357, "Disposition" => "inline", "Subject" => "Part 2 of the inner message is another GIF, \"3d-eye.gif\"", "Type" => "image/gif", "Encoding" => "base64" }, "Parser" => { "Message" => "testmsgs/multi-nested2.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Part_5_1" => { "Size" => 58, "Subject" => "Part 5 of the outer message is itself an RFC822 message!", "Type" => "text/plain", "To" => "(address in US-ASCII)", "From" => "(mailbox in US-ASCII)", "Encoding" => "quoted-printable", "Charset" => "ISO-8859-1" }, "Part_1" => { "Size" => 208, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Size" => 140, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "US-ASCII" }, "Part_3" => { "Subject" => "Part 3 of the outer message is multipart!", "Type" => "multipart/parallel", "Encoding" => "7bit", "Boundary" => "unique-boundary-2" }, "Part_4" => { "Size" => 148, "Type" => "text/richtext", "Encoding" => "7bit" }, "Part_5" => { "Filename" => "/evil/filename", "Type" => "message/rfc822", "Encoding" => "7bit" }, "Msg" => { "Subject" => "A complex nested multipart example", "Type" => "multipart/mixed", "To" => "", "From" => "Lord John Whorfin ", "Encoding" => "7bit", "Boundary" => "unique-boundary-1" } } MIME-tools-5.509/testmsgs/dup-names.ref0000644000076400007640000000200112541013575015777 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/dup-names.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Part_1" => { "Filename" => "one.gif", "BodyFilename" => "one.gif", "Size" => 419, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" }, "Part_2" => { "Filename" => "one.gif", "BodyFilename" => "one-1.gif", "Size" => 357, "Type" => "image/gif", "Encoding" => "base64" }, "Part_3" => { "Filename" => "two.nice.gif", "BodyFilename" => "two.nice.gif", "Size" => 419, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" }, "Part_4" => { "Filename" => "two.nice.gif", "BodyFilename" => "two-1.nice.gif", "Size" => 357, "Type" => "image/gif", "Encoding" => "base64" }, "Part_5" => { "Filename" => "two.nice.gif", "BodyFilename" => "two-2.nice.gif", "Size" => 357, "Type" => "image/gif", "Encoding" => "base64" }, } MIME-tools-5.509/testmsgs/simple.ref0000644000076400007640000000054112541013575015406 0ustar dfsdfs{ "Msg" => { "Size" => 443, "Subject" => "Request for Leave", "Type" => "text/plain", "To" => "sitaram\@selsvr.stx.com", "From" => "eryq\@rhine.gsfc.nasa.gov", "Encoding" => "7bit" }, "Parser" => { "Message" => "testmsgs/simple.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" } } MIME-tools-5.509/testmsgs/russian.ref0000644000076400007640000000041012541013575015574 0ustar dfsdfs{ "Msg" => { "Subject" => "Greetings", "Type" => "text/plain", "Filename" => "\x{421}\x{43f}\x{438}\x{441}\x{43e}\x{43a}.doc", }, "Parser" => { "Message" => "testmsgs/russian.msg", "OutputToCore" => "0", "Charset" => "KOI8-R", } } MIME-tools-5.509/testmsgs/bluedot-postcard.ref0000644000076400007640000000157612541013575017401 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/bluedot-postcard.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "A postcard for you", "Type" => "multipart/alternative", "To" => "noone", "Encoding" => "binary", "Boundary" => "----------=_961872013-1436-0" }, "Part_1" => { "Size" => 88, "Disposition" => "inline", "Type" => "text/plain", "Encoding" => "binary" }, "Part_2" => { "Type" => "multipart/related", "Encoding" => "binary", "Boundary" => "----------=_961872013-1436-1" }, "Part_2_1" => { "Size" => 123, "Disposition" => "inline", "Type" => "text/html", "Encoding" => "binary" }, "Part_2_2" => { "Filename" => "bluedot.jpg", "Size" => 4272, "Disposition" => "inline", "Type" => "image/jpeg", "Encoding" => "base64" } } MIME-tools-5.509/testmsgs/ak-0696-replace.ref0000644000076400007640000000150312541013575016522 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/ak-0696.msg", "ExtractNested" => "REPLACE", "OutputToCore" => 0, "Name" => "anonymous" }, "Msg" => { "Subject" => "[Fwd: Re: 34Mbit/s Netz]", "Type" => "multipart/mixed", "To" => "andreas.koenig\@mind.de, kun\@pop.combox.de, 101762.2307\@compuserve.com", "From" => "Juergen Specht ", "Encoding" => "7bit", "Boundary" => "------------70522FC73543" }, "Part_1" => { "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "us-ascii", }, "Part_2" => { "Charset" => "iso-8859-1", "Encoding" => "quoted-printable", "From" => "deuschle\@mnh.telekom.de (Guenter Deuschle)", "Subject" => "Re: 34Mbit/s Netz", "To" => "Juergen Specht ", "Type" => "text/plain", }, } MIME-tools-5.509/testmsgs/multi-nested3.ref0000644000076400007640000000337112541013575016616 0ustar dfsdfs{ "Part_3_1" => { "Filename" => "3d-vise.gif", "Size" => 419, "Disposition" => "inline", "Subject" => "Part 1 of the inner message is a GIF, \"3d-vise.gif\"", "Type" => "image/gif", "Encoding" => "base64" }, "Part_3_2" => { "Filename" => "3d-eye.gif", "Size" => 357, "Disposition" => "inline", "Subject" => "Part 2 of the inner message is another GIF, \"3d-eye.gif\"", "Type" => "image/gif", "Encoding" => "base64" }, "Parser" => { "Message" => "testmsgs/multi-nested3.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Part_5_1" => { "Size" => 57, "Subject" => "Part 5 of the outer message is itself an RFC822 message!", "Type" => "text/plain", "To" => "(address in US-ASCII)", "From" => "(mailbox in US-ASCII)", "Encoding" => "quoted-printable", "Charset" => "ISO-8859-1" }, "Part_1" => { "Size" => 208, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Size" => 140, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "US-ASCII" }, "Part_3" => { "Subject" => "Part 3 of the outer message is multipart!", "Type" => "multipart/parallel", "Encoding" => "7bit", "Boundary" => "unique-boundary-2" }, "Part_4" => { "Size" => 148, "Type" => "text/richtext", "Encoding" => "7bit" }, "Part_5" => { "Filename" => "nice.name", "Type" => "message/rfc822", "Encoding" => "7bit" }, "Msg" => { "Subject" => "A complex nested multipart example", "Type" => "multipart/mixed", "To" => "", "From" => "Lord John Whorfin ", "Encoding" => "7bit", "Boundary" => "unique-boundary-1" } } MIME-tools-5.509/testmsgs/multi-clen.msg0000644000076400007640000000243112541013575016200 0ustar dfsdfsFrom: Nathaniel Borenstein To: Ned Freed Subject: Sample message MIME-Version: 1.0 Content-type: multipart/mixed; boundary="simple boundary" This is the preamble. It is to be ignored, though it is a handy place for mail composers to include an explanatory note to non-MIME conformant readers. --simple boundary This is implicitly typed plain ASCII text. It does NOT end with a linebreak. --simple boundary Content-type: text/x-numbers; charset=us-ascii Content-length: 30 123456789 123456789 123456789 --simple boundary Content-type: text/x-alphabet; charset=us-ascii Content-length: 600 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 ABCDEFGHIJKLMNOPQRSTUVWXYZ012 --simple boundary-- This is the epilogue. It is also to be ignored. MIME-tools-5.509/testmsgs/ak-0696-none.ref0000644000076400007640000000123312541013575016046 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/ak-0696.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "[Fwd: Re: 34Mbit/s Netz]", "Type" => "multipart/mixed", "To" => "andreas.koenig\@mind.de, kun\@pop.combox.de, 101762.2307\@compuserve.com", "From" => "Juergen Specht ", "Encoding" => "7bit", "Boundary" => "------------70522FC73543" }, "Part_1" => { "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Part_2" => { "Disposition" => "inline", "Type" => "message/rfc822", "Encoding" => "7bit" }, } MIME-tools-5.509/testmsgs/multi-simple.ref0000644000076400007640000000114612541013575016540 0ustar dfsdfs{ "Part_1" => { "Size" => 76, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Size" => 73, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Msg" => { "Subject" => "Sample message", "Type" => "multipart/mixed", "To" => " Ned Freed ", "From" => "Nathaniel Borenstein ", "Encoding" => "7bit", "Boundary" => "simple boundary" }, "Parser" => { "Message" => "testmsgs/multi-simple.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" } } MIME-tools-5.509/testmsgs/multi-nested.msg0000644000076400007640000000620112541013575016540 0ustar dfsdfsMIME-Version: 1.0 From: Lord John Whorfin To: Subject: A complex nested multipart example Content-Type: multipart/mixed; boundary=unique-boundary-1 The preamble of the outer multipart message. Mail readers that understand multipart format should ignore this preamble. If you are reading this text, you might want to consider changing to a mail reader that understands how to properly display multipart messages. --unique-boundary-1 Part 1 of the outer message. [Note that the preceding blank line means no header fields were given and this is text, with charset US ASCII. It could have been done with explicit typing as in the next part.] --unique-boundary-1 Content-type: text/plain; charset=US-ASCII Part 2 of the outer message. This could have been part of the previous part, but illustrates explicit versus implicit typing of body parts. --unique-boundary-1 Subject: Part 3 of the outer message is multipart! Content-Type: multipart/parallel; boundary=unique-boundary-2 A one-line preamble for the inner multipart message. --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-vise.gif" Subject: Part 1 of the inner message is a GIF, "3d-vise.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-eye.gif" Subject: Part 2 of the inner message is another GIF, "3d-eye.gif" R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --unique-boundary-2-- The epilogue for the inner multipart message. --unique-boundary-1 Content-type: text/richtext This is part 4 of the outer message as defined in RFC1341 Isn't it cool? --unique-boundary-1 Content-Type: message/rfc822; name="/evil/filename"; From: (mailbox in US-ASCII) To: (address in US-ASCII) Subject: Part 5 of the outer message is itself an RFC822 message! Content-Type: Text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: Quoted-printable Part 5 of the outer message is itself an RFC822 message! --unique-boundary-1-- The epilogue for the outer message. MIME-tools-5.509/testmsgs/german.ref0000644000076400007640000000063112541013575015366 0ustar dfsdfs{ "Msg" => { "Subject" => "Re: 34Mbit/s Netz", "Type" => "text/plain", "To" => "Juergen Specht ", "From" => "deuschle\@mnh.telekom.de (Guenter Deuschle)", "Encoding" => "quoted-printable", "Charset" => "iso-8859-1" }, "Parser" => { "Message" => "testmsgs/german.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" } } MIME-tools-5.509/testmsgs/uu-junk-target.msg0000644000076400007640000002161112541013575017012 0ustar dfsdfsReturn-Path: Received: from virtual.mrf.mail.rcn.net ([207.172.4.103]) by mta02.mrf.mail.rcn.net (InterMail vM.4.01.02.27 201-229-119-110) with ESMTP id <20000425112650.ZPUD516.mta02.mrf.mail.rcn.net@virtual.mrf.mail.rcn.net> for ; Tue, 25 Apr 2000 07:26:50 -0400 Received: from [205.139.141.226] (helo=webmail.uwohali.com ident=root) by virtual.mrf.mail.rcn.net with esmtp (Exim 2.12 #3) id 12k3VX-00012G-00 for eryq@zeegee.com; Tue, 25 Apr 2000 07:27:59 -0400 Received: from webmail.uwohali.com (nobody@localhost [127.0.0.1]) by webmail.uwohali.com (8.8.7/8.8.7) with SMTP id GAA10264 for ; Tue, 25 Apr 2000 06:34:43 -0500 Date: Tue, 25 Apr 2000 06:34:43 -0500 Message-Id: <200004251134.GAA10264@webmail.uwohali.com> From: "ADJE Webmail Tech Support" To: eryq@zeegee.com Subject: mime::parser Content-type: multipart/mixed; boundary="---------------------------7d033e3733c" Mime-Version: 1.0 X-Mozilla-Status: 8001 -----------------------------7d033e3733c Content-Type: text/plain Eryq - I occasionally receive an email (see below) like this one, which MIME::Parser does not parse. Any ideas? Is this a valid way to send an attachment, or is the problem on the "sender's" side? Thanks for your time! Mike -->> Promote YOUR web site! FREE Perl CGI scripts add WEB ACCESS to your -->> E-Mail accounts! Download today!! http://webmail.uwohali.com -----------------------------7d033e3733c Content-type: multipart/mixed; boundary="----------=_960622044-2175-0" The following is a multipart MIME message which was extracted from a uuencoded message. ------------=_960622044-2175-0 Here's what he's talking about. I've uuencoded the ZeeGee logo and another GIF file below. ------------=_960622044-2175-0 Content-Type: image/gif; name="up.gif"; x-unix-mode="0644" Content-Disposition: inline; filename="up.gif" Content-Transfer-Encoding: base64 Mime-Version: 1.0 X-Mailer: MIME-tools 5.208 (Entity 5.204) R0lGODdhEwATAKEAAP///wAAAICAgMDAwCwAAAAAEwATAAACR4SPmcHtz0xQ FIgJ5ti8b3FJgEcOIKaV3SmSgcdmY9esoUw7XJwO0Gu6pX6MIGqm+giRSR5T 5UzulqCq9Yq6aq0oIrECPhQAADs= ------------=_960622044-2175-0 Content-Type: image/gif; name="zeegee.gif"; x-unix-mode="0644" Content-Disposition: inline; filename="zeegee.gif" Content-Transfer-Encoding: base64 Mime-Version: 1.0 X-Mailer: MIME-tools 5.208 (Entity 5.204) R0lGODdhWwBwAPcAAAAAAAgICBAQEDkAITkAKUIAKRgYGEoAKUoAMVIAMVIA OVoAMSEhIVoAOVIIMWMAOWMAQloIOWsAQmMIOWMIQikpKVoQOWsIQmsISmMQ OWMQQnMISjExMUIpMWsQSnsIUnMQUnMQSmsYQoQIUoQIWlIpOXMYQowIWjk5 OWshQkI5OZQIWpQIY4wQWnMhSoQYUoQYWpQQY1I5QnshUkJCQnMpSoQhSnMp UoQhUoQhWoQpUpQhY0pKSms5UnsxWnM5UpQpY1JSUmNKUlpSSpQxY5Qxa5wx a5Q5WpQ5Y4RCWpQ5a1paWoxCWoRKY6U5c5xCY4xKa605a5RKY5xCe2NjY3ta Y6VCc5RSa6VKa3tjY61Ka2tra61Kc61Ke4Rja5Rac3tra6VSe61Sc6Vaa7VS c3Nzc4xra61ac61ahLVahK1jc4xzc61je3t7e5Rzc61jhJxzc61re71je4x7 e5xze7Vre71jlJx7e4SEhL1rhJx7lKV7e71rjKV7hKV7lJyEe71zjKV7nN5j jIyMjK17nKWEhM5rlL17jK2EhLV7nM5zjK2EjLV7pd5rlJSUlK2MjLWEpb2E pbWMjLWMlNZ7nL2MjK2UjL2MlN57lN57nJycnN6ElL2UlMaUlMaUnNaMnKWl peeEpb2cnM6UnNaUnO+ErcacnNaUpd6Mtd6Mvc6cnM6cpd6Upb2lpe+Mpa2t rcalpc6lpeeUve+UtdalpdalreecrbW1td6lrd6lpd6ltfecpeelrfecrdat reeltd6treelvd6tte+lrf+ctf+cvb29ve+lvf+cxuetreette+lzvelvf+l ve+tvf+lxue1tf+lzvetxsbGxu+1td69te+1vf+tvfe1vee9ve+9vf+1zv+1 xve9vc7OzufGvfe9xv+9xv+9zvfGxv+93vfGztbW1v/Gxv/Gzv/G3v/G5//O zu/Wzv/O1t7e3v/O3v/W1v/W3v/W5+fn5//e3v/e5//n3v/n5//n7//n9+/v 7//v7/f39//39//3/////ywAAAAAWwBwAAcI/wD/CRxIsKDBgwgTKlzIsKHD hxAjSpxIsaLFixgzapQYqaNHSCBDihwZkpHJRIRSqlzJsmWglzBj+plJs+ZM PThz6lS4oafPnhiCYrhAtCiFo0ghKIXwoIHTp1AbKJiqIIHVqwiyatV6oGuB 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 WrzFXNzFXvzFYBzGYpwRAcEAOw== ------------=_960622044-2175-0-- -----------------------------7d033e3733c-- MIME-tools-5.509/testmsgs/double-semicolon.msg0000644000076400007640000000034012541013575017364 0ustar dfsdfsMime-Version: 1.0 Content-Type: multipart/alternative;; boundary="foo" Preamble --foo Content-Type: text/plain; charset=us-ascii The better part --foo Content-Type: text/plain; charset=us-ascii The worse part --foo-- MIME-tools-5.509/testmsgs/uu-zeegee.msg0000644000076400007640000001547012541013575016031 0ustar dfsdfsFrom: me To: you Subject: uudecoding I've uuencoded the ZeeGee logo and another GIF file below. begin 644 up.gif M1TE&.#=A$P`3`*$``/___P```("`@,#`P"P`````$P`3```"1X2/F<'MSTQ0 M%(@)YMB\;W%)@$<.(*:5W2F2@<=F8]>LH4P[7)P.T&NZI7Z,(&JF^@B121Y3 4Y4SNEJ"J]8JZ:JTH(K$"/A0``#L` ` end begin 644 zeegee.gif M1TE&.#=A6P!P`/<```````@("!`0$#D`(3D`*4(`*1@8&$H`*4H`,5(`,5(` M.5H`,2$A(5H`.5((,6,`.6,`0EH(.6L`0F,(.6,(0BDI*5H0.6L(0FL(2F,0 M.6,00G,(2C$Q,4(I,6L02GL(4G,04G,02FL80H0(4H0(6E(I.7,80HP(6CDY M.6LA0D(Y.90(6I0(8XP06G,A2H084H086I008U(Y0GLA4D)"0G,I2H0A2G,I M4H0A4H0A6H0I4I0A8TI*2FLY4GLQ6G,Y4I0I8U)24F-*4EI22I0Q8Y0Q:YPQ M:Y0Y6I0Y8X1"6I0Y:UI:6HQ"6H1*8Z4YV-C8WM: M8Z5"X1C:Y1:ZU2WM[>Y1S[UC>XQ[ M>YQS>[5K>[UCE)Q[>X2$A+UKA)Q[E*5[>[UKC*5[A*5[E)R$>[USC*5[G-YC MC(R,C*U[G*6$A,YKE+U[C*V$A+5[G,YSC*V$C+5[I=YKE)24E*V,C+6$I;V$ MI;6,C+6,E-9[G+V,C*V4C+V,E-Y[E-Y[G)R>$I;V^,I:VM MK<:EI>4O>^4M=:EI=:EK>>>EK?>>EM=ZMK>>EO=ZMM>^EK?^^EO?^MK>>MM>^ESO>EO?^E MO>^MO?^EQN>UM?^ESO>MQL;&QN^UM=Z]M>^UO?^MO?>UO>>]O>^]O?^USO^U MQO>]O<[.SN?&O?>]QO^]QO^]SO?&QO^]WO?&SM;6UO_&QO_&SO_&WO_&Y__. MSN_6SO_.UM[>WO_.WO_6UO_6WO_6Y^?GY__>WO_>Y__GWO_GY__G[__G]^_O M[__O[_?W]__W]__W_____RP`````6P!P``<(_P#_"1Q(L*#!@P@3*ES(L*'# MAQ`C2IQ(L:+%BQ@S:I08J:-'2"!#BAP9DI')1(12JES)LF6@ES!C^IE)L^9, M/3ASZE2XH:?/GAB"8KA`M"B%HT@A*(7PH('3IU`;*)BJ(('5JPBR:M5ZH&N! MKV#!$AA+8(#9LSQ__A0ZM"A1I$F7-HT:E6K5JUBW379 MU["/(]_0V3-SN:,=/_^&[/MW];YCL6>/C;S[7]U66H(+\-6C;;?&%)R%>U)U7 M@$(C*(CA=H9YQR&$$4;76XA]D5BBB?NAJ-Q[<.76HHL@9I5`!M.9=Z",,]*H M77LW(I9CA]#Q:)4-9#22R2:*".+"9'P1.4*1-&;8X'?./4?78PM$T8@K=4A1 M@P4U,*$($WN-F!`)6]9I9'9>!E7;BBQZJ(`5I6RBA@B1I7"(!7LI1`*==7+9 MI8UZJKADGXV]4`HQ9U@@759()+'5`8HNVJBC)N89J9*3BMG``W8\H\@,]('_ MB$,3>H6Z**-VWKG@9AJ"&:!3+\CBRA/B.6F5!F_4FM`)MXK:J*Z[$M8K@`%: M$4TC)M05JU6'*(O0"$>01)`(*@1NNN,_J M:NJ>H+VP##'$RL=;!F/D5:^]]SJ;ZYW[2GH4$>2$,!DDTBD`)G&&W,\*K0-NV4'.89XH-C)8RKP!*%XL8QPPAV3 M6RZ#21HB#AO4JDJ:&!D0F(#//[O\,L.0ZHG*-EB@FZK2#5R`!7T*L?!SU%)[ M_#'1&,BRC1(X/DAQ`Q'H@(48+@Q85=ABC]WRK5-3_[U=*MP4P>^DO]90BSWW MW*.+!G;CS<(*>MM;]I8P(W=U$>?ZVI0&M'S#3C_WL+/*`DY-Y3@+>4?.<="5 MJW6U$?V%[."#7[3B2S7L?).-+STCL$@#;Q81_K@P<`&RB,=QV!@.Q3X"S2` M8%IP:8(02C`$(0AA""5(P/\0(L`2IDYUXH*!';"A0/4UL('O4$<$7SC!=8`# M$!>47?0\4`49J."'*G!`5/_J94(!@@^%BWJ#-<[1PG:\,![Q>$<^@@'%>-!0 M@>C`QAF^!!B`$(>XK!.LH(@!)"`)@'"*;IP#'2U\(3SBD0YYS*** M5KSB.LX!CD_D`'IPT4(*(L`DC9T1C2?\612@X48FQI&&\CC&._`HQQJB@X_4 M4`(@*:"#)$CO5SY#9"+!E09&@N.-"EQ@`]NA#F2L@Y*53.4YSM$-:H3A2V(0 MP=8:`+5#HA%A>8"&-;HQ#E0^$A[M(`@P0;_X$`*?&(* MU,PH2E(F`QK:(*8QT^=$>&Q#&N!H9B6?&8H99O@$F47 M@*'_#&J$LYCC5!\WEH$-==*0G;.4IC:@`0Q-L@4'1T!57/`)+E\*T`FX``8T M_-F-4XYS'=R0QC#*6<55KB^5T$QH-Q::C%/H('9DT(##D*(H`EJ4!3$812TT MRE%P`!2.ZPB'-&SAQ'C0XQ[XN$<]Z(%,E&)QEN-0*#24`8Q+A(`[.V#"821* M@5`1\`0"Y`,M=KI1:X33HV\4QS-F<0XGU@,?_A#(/N[!5*=>4J7:>"=5:3&& MGIS!`YF#BZV^BKH=T&*L_!1F.#LZRW,TPQ8L;`<]\%&0?-0#'JE$QUWYV(V5 MZA48M/`$"(QPA!1)RE:+LBD@8G'8Q%+#K)T]93.:P0LX_\*C'OTP"#[B`LEQB'>\U@BN<`^KBDY<05KGTM)R$=:"3IC"%*I@K72_6=9BA((: ML06'=N-QCWV8>!]UY:,TQTM>:$`C&<`X;RQ,P0E$\"I)6AK!A,'E!$YXXL+0 MC2XP.$R,69Q"&TB.+1/+*<$]KGBE>4VPBV$,6O326!(^N+%R7C.J'<>!$YRP M<'V%#(Q>%.,0U'BM61?KT_!"=?_%2(ZR@I5!Y<.N0A6>X,0CFH`V/6%G7,L] M!)C#C&'61G<8R`"$,EQ<5FNL.JZ:?+MX*! M)"9Q"3#_.,.TR$4Q*)$+?BZ:T1M-% M0%T$21A;$J8N]"YF<0E<2U<9K[:UM%T,;6?7XM*9SC,G)%$(.,PO0\/NLA*. M;>QDLZ(8=3CL3IT-#&%`&]KN?KNNM\2M?5A=WYG7^O;U'[%YG_J`1]5V%HB-?"%\#PA#T97:%W&'QN\!Y7M0>++]3M^5/_?RE=?YA3W!]8P_0O!T<`,8JN`"(Y7= M(OQ(O>I7S_K6N_[UL(?]1A32>GW$_O:XSST_9D][U=M>]ZLO"/!?S_O>\^/W MPU_(\%5?_(',0Q\$\?WR$<(/=\SC^0))OD4&P8#N>]_[CG!'__2/O_S=%\08 M/!```-8?`!08XQ_`OT@;UD__^FO"_`,A__3S3X7Z&Z#^2X!\L8<1Y@`*!FB` MFA```,``YF`0YB=[^<=\V<<#Z\+!^CE`0 MW@`*FG"!U]=Z_U"`FJ`)&)AZ`U$&ZX<'$9AZMZ"`K]!ZT_""H`!]PG=]/9B" M0.@0\Z"`/#`/`^$.*%!_`!`$WA"#J><.%%A_/.`-0.@."K@%XZ=Z\V!]7F@, M'%!_`4`%^*'MQ"#YI"'=^B' MM[![(R@`^'=[\_`*"FB'>+A^%0!]_/]P@G7(`#S``.O'`&V($-.P?EOP@)3( M`=XP$--0`0#``<9@>Z*(`MZ@>MXPAA6`@11(!=D'?_`7@O"G#].@?CQ@#JIW MBT_8@L:`B^(G$(Z`BPPABA7PB0*A"788C,ZG?GC@#LIHB06A#_\W"/PPAGC@ MA>ZPC=RXC>;PA?V'`LRW>[>P?FG8?QP0@OPP@@#0@`GA""1($$$``#SP@O;X M@C0``#3@#?,8!/=HC_G(`_S0A&6@>J_@A/77!N9`B5OPCYK@")0X"+=`B53@ M"/\(D0`P"`FA#[BHA`,QA@A9?Q5@#B`9DA7(#V](`[]7CB;Y"MY@DO6W!0<) MD^M7!@G1?W'_6!!-6`$HL`14\)-`N01M,)`+&`1+<)1(>91#J8P!D(K'UXWN MD(;J]X7KQP-'"914<)6O,)-!@)59J968J(FTN`7T.`W,*'QDF8NL%WT<28\" MZ'OSZ('\0(GW1Q#Z,`_F-PW_IPG19PZ7:!!CR`%G*1`L"0K?.!#ZD)6ZF(D` M``K/9WZ)N00QJ(Q/B)>KIP]O*`"ZN(X+Z)'_<)>OX),"\8;2^)E1J0FB>1"@ M```!L(=0.0W3,(\!H)"I9PRG.!"RV08Q.)$`((ZJ-W]P6`:O8`Z:4`9Y&(BI M1XT+N(/\8`YXH(`V^)G_QP"EJ`_>T`;0B1#`&9*TF8^L:0"1Z)GZ_["&`0"> ME6B9JN<(B>B$##`-P=>'ZR<`!I"(2T`0=!B?\[E^L(@0$/E]WF<`=?D/@Y"' M<+@%E\@/;5"'!?J6J3$H-">LSB`.$VQB%([B'7QB" M:!A]*)I_M_""@3@/AQF%U@<*GYB!MNB#[O^H$.7H"%@H$-9'$*"@H`!0`;>@ MA.Q(?V19?PP0`"[*`Z"ZA`!@D_P`"@2ZG!#Z#WJ)`I28C1JXAO07!']IEP'@ MB<^G#VU(@T'0HO-P"Z+H"'YYA*TX#R?8?V4`"N6HD0*A#PH("@,!CZDX"*.8 MJ8?XJ=VWI?^WCW>9@P!Z?>XP@J6)$(@8`$N@@AY9CEP8?:)Z"]`G`.DX$,HH MA_]0`31@?DP9!-E'`PRPI?K(IZ+8K[\8`-"G#^[0?2[Z#R.XGPGAH)0H`&5@ M#@U(`TUI$,[*`^('K_AWD/3ZG,'(`Q6P!83X#UC:!OK@H7]YD&+ZBS0@J=1* MKP3A#A40`&=Z$*__0(F]J@^C.)@"$00&\'X&4`$;"P"O(*D92;(!@`=<^G[* M:`[N(`#Z:A#F$*;_<`L"4)];ZJ%."Y7A"@!ENJ)`.`]CZ`B9&`0\^P_S5Z5! M6X0'6;0"P0$""8_B%P";"+(D"P!MA#*.)SF5XXVR0$,F+#_((D"80`,(+G.A[WQ^N\CCA_#-M]^%>.D_L/ M\&B^`T&!4BH0%%@&OS<-3=A^4PH`Z7N^'2A^U:<)#&``LAM]\\BI!3%_Y9F? MFS@0;4H0Y0BS=UO`#>RB*/F=_R<`J&J^+VF3!(&(=FB>*'#!!G&"FL"X2]@& M61FQ!?$*7SL//_C#;:@/_SN'6_"3@P!]M_"EB.J`@_"36T#"5EK%5GS%6)S% 36KS%7-S%7OS%8!S&8IP1`<$`.P`` ` end MIME-tools-5.509/testmsgs/attachment-filename-encoding-UTF8.msg0000644000076400007640000000107312541013575022346 0ustar dfsdfsMIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050706070100080203090004" This is a multi-part message in MIME format. --------------050706070100080203090004 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Attachment Test --------------050706070100080203090004 Content-Type: text/plain; name="=?UTF-8?B?YXR0YWNobWVudC7DpMO2w7w=?=" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename*=UTF-8''%61%74%74%61%63%68%6D%65%6E%74%2E%C3%A4%C3%B6%C3%BC VGVzdAo= --------------050706070100080203090004-- MIME-tools-5.509/testmsgs/malformed-content-type-zip.msg0000644000076400007640000000120012541013575021315 0ustar dfsdfsMIME-Version: 1.0 To: someone@example.com Subject: Payroll Received by Intuit Content-Type: multipart/mixed; boundary="----=_Part_67482_7396105824.6005753659145" ------=_Part_67482_7396105824.6005753659145 Content-Type: text/plain; charset=windows-1251; format=flowed Content-Transfer-Encoding: 7bit Dear, We received your payroll on October 9, 2013 at 4:55 PM . ------=_Part_67482_7396105824.6005753659145 Content-Type: ; name="payroll_report_429047_10092013.zip" Content-Transfer-Encoding: base64 Content-Disposition: attachment; name="payroll_report_409401_10092013.zip" Z290Y2hhCg== ------=_Part_67482_7396105824.6005753659145-- MIME-tools-5.509/testmsgs/hdr-fakeout.msg0000644000076400007640000000077612541013575016352 0ustar dfsdfsReceived: (qmail 24486 invoked by uid 501); 20 May 2000 01:55:02 -0000 Date: Fri, 19 May 2000 21:55:02 -0400 From: "Russell P. Sutherland" To: "Russell P. Sutherland" Subject: test message 1 Message-ID: <20000519215502.A24482@quist.on.ca> Mime-Version: 1.0 Content-transfer-encoding: 7BIT Content-Type: text/plain; charset=us-ascii X-Mailer: Mutt 1.0us Organization: Quist Consulting The header is not properly terminated; the "blank line" actually has a space in it. MIME-tools-5.509/testmsgs/bluedot-simple.msg0000644000076400007640000001347212541013575017063 0ustar dfsdfsContent-Type: image/jpeg; name="bluedot.jpg" Content-Disposition: inline; filename="bluedot.jpg" Content-Transfer-Encoding: base64 Content-Id: my-graphic /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsL DBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/ 2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAEAAQADASIAAhEBAxEB/8QA HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUF BAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK FhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1 dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEB AQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAEC AxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRom JygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU 1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAoo ooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiii gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKA CiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoo ooAKKKKACiiigAooooAKKKKACiiigAooooAKKKjnnhtbeW4uJY4YIkLySSMF VFAySSeAAOc0ASUVw+p/E3TY1MeiW0uqzgkb8NBbjB6+ay/MCM4MauDgZIBB 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 KOGCJAkccahVRQMAADgADjFeFjM2veFD7/8AL/M+qy7h+zVXFf8AgP8An/l/ wxDp2nWmk6fDY2MCw20IwiAk9Tkkk8kkkkk5JJJJJNWqKK8I+r2CiiigAooo oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigDlNY+H2iarcPdQef pd1I5eWawKp5pJJJZGVkLEnJfbvOAN2OK5O88AeJ7PJt5dN1ONV3kqXtZCf7 iod6k8cEyKCTg4AyfV6K6aOLr0dIS0OLEZdhcRrVgm++z+9HiU2j+IrWJprr wzqccK/edDDORngfJFI7nn0U46nABNVP9L/6A2uf+Ce6/wDjde8UV2RzjELd J/L/AIJ5suHMG3o5L5r9UeEJHfzSLHFomttI5CoraZPGCT0BZ0Cr9WIA7kCt GHwx4ruZViXw7JbFv+Wt3dwLEvf5jG7t7DCnkjOBkj2ailLN8Q9rL5f5lQ4d wcd7v1f+SR5xYfDK7lkR9Z1lTCQGe2sITGc8ZQzMxJXGRlVRjwQV6V2ukeH9 I0GN00rTra0MgUSvHGA8u3ODI/3nPJ5Yk5JOeTWlRXBVr1KrvUdz1aGFo4dW pRSCiiisjoCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACi iigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKK KACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigA ooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//Z MIME-tools-5.509/testmsgs/german.msg0000644000076400007640000000760112541013575015404 0ustar dfsdfsX-POP3-Rcpt: specht@trachea Return-Path: hermes Received: (from hermes@localhost) by kulturbox.netmbx.de (8.7.1/8.7.1) id SAA04513 for specht; Wed, 19 Jun 1996 18:30:12 +0200 Received: by netmbx.netmbx.de (/\==/\ Smail3.1.28.1) from mail.cs.tu-berlin.de with smtp id ; Wed, 19 Jun 96 18:12 MES Received: (from nobody@localhost) by mail.cs.tu-berlin.de (8.6.12/8.6.12) id SAA12413; Wed, 19 Jun 1996 18:26:28 +0200 Resent-Date: Wed, 19 Jun 1996 18:26:28 +0200 Resent-Message-Id: <199606191626.SAA12413@mail.cs.tu-berlin.de> Resent-From: nobody@cs.tu-berlin.de Resent-To: kultur@kulturbox.netmbx.de Received: from gatekeeper.telekom.de ([194.25.15.11]) by mail.cs.tu-berlin.de (8.6.12/8.6.12) with SMTP id SAA11678 for ; Wed, 19 Jun 1996 18:11:29 +0200 Received: from ULM02.mnh.telekom.de by gatekeeper.telekom.de; (5.65v3.0/1.1.8.2/02Aug95-0132PM) id AA01376; Wed, 19 Jun 1996 18:11:27 +0200 Received: from ulm02.mnh.telekom.de (deuschle@mnh.telekom.de) by ULM02.mnh.telekom.de (8.6.10/3) with SMTP id SAA30680 for ; Wed, 19 Jun 1996 18:14:40 GMT Message-Id: <199606191814.SAA30680@ULM02.mnh.telekom.de> X-Sender: deuschle@ulm02.mnh.telekom.de X-Mailer: Windows Eudora Version 1.4.4 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Date: Wed, 19 Jun 1996 18:12:02 +0200 To: Juergen Specht From: deuschle@mnh.telekom.de (Guenter Deuschle) Subject: Re: 34Mbit/s Netz X-Mozilla-Status: 0011 Hallo Herr Specht, entschuldigen Sie vorab, dass ich Ihnen nicht telefonisch zur Verfuegung stehe, ich Praesentationen gehalten/ noch zu halten und viele Kundennachfragen zu projektieren. Nach Informationen des Produkt-Managers Temme steht der POP schon zur Verf=FCgung! Standort: voraussichtlich: Winterfeldstr. 21, 10781 Berlin. Der POP hat zur Zeit direkte 34M-Anbindungen zu folgenden Orten: Rostock, Hamburg, Hannover & Leipzig. 4 weitere werden in kuerze in Betrieb gehen. Damit haben Sie einen Besonderen Sicherheitsstandard verfuegbar! Kontakt muessen Sie ueber Ihre oerltliche Vertriebseinheit aufnehmen: entweder den Geschaefts-Kunden-Vertrieb oder das GrossKundenManagement. Diese Vertriebseinheiten greifen auf den oertlichen Technischen Vertriebs-Support zu. Die Informationen werden ueber TVS zur Vertriebseiheit gegeben und dann zu Ihnen. Sie benoetigen eine Standleitung von Ihrer Lokation zum Internet-POP Uebergabepunkt zu Ihrem Info-Server ist ein CISCO 1000-Router. Dann zahlen Sie neben den monatlichen Kosten fuer die Standleitung die Kosten fuer den Internet-Zugang: zB bei 64k: 1500DM bei 2GByte Freivolumen. 128K: 3000 DM bei 5 GB Freivolumen & 2M: 30.000 DM bei 50GB Freivolumen. Freundliche Gruesse=20 Guenter Deuschle >Sehr geehrter Herr Deuschle, >Sie sind mir von Herrn Meyendriesch empfohlen worden. >Ich versuche Informationen ueber das T-eigene 34Mbit/s Netz und den=20 >lokalen Pop-Berlin rauszufinden, bzw. was ein Anschluss kostet und=20 >wo man ihn herbekommt. Laut Herrn Schnick in Berlin gibt es den=20 >T-Pop nicht, laut Traceroute von Herrn Meyendriesch sehrwohl. Auch=20 >ist dies Netz in der IX vom Mai 96 erwaehnt. >Koennen Sie mir helfen? > >MfG >--=20 >Juergen Specht - KULTURBOX > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D Dipl.-Ing. Guenter D E U S C H L E Deutsche Telekom AG Niederlassung 3 Hannover GrossKundenManagement - Techn. Vertriebs-Support: Team-Leiter Internet Online-Dienste --------------------------------------------------- GrKM-TVS-IOD Tel: +49-511-333-2772 Vahrenwalder-Str. 245 FAX: +49-511-333-2751 30179 Hannover eMail: deuschle@mnh.telekom.de=20 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D MIME-tools-5.509/testmsgs/multi-nested.ref0000644000076400007640000000337512541013575016537 0ustar dfsdfs{ "Part_3_1" => { "Filename" => "3d-vise.gif", "Size" => 419, "Disposition" => "inline", "Subject" => "Part 1 of the inner message is a GIF, \"3d-vise.gif\"", "Type" => "image/gif", "Encoding" => "base64" }, "Part_3_2" => { "Filename" => "3d-eye.gif", "Size" => 357, "Disposition" => "inline", "Subject" => "Part 2 of the inner message is another GIF, \"3d-eye.gif\"", "Type" => "image/gif", "Encoding" => "base64" }, "Parser" => { "Message" => "testmsgs/multi-nested.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Part_5_1" => { "Size" => 57, "Subject" => "Part 5 of the outer message is itself an RFC822 message!", "Type" => "text/plain", "To" => "(address in US-ASCII)", "From" => "(mailbox in US-ASCII)", "Encoding" => "quoted-printable", "Charset" => "ISO-8859-1" }, "Part_1" => { "Size" => 208, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Size" => 140, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "US-ASCII" }, "Part_3" => { "Subject" => "Part 3 of the outer message is multipart!", "Type" => "multipart/parallel", "Encoding" => "7bit", "Boundary" => "unique-boundary-2" }, "Part_4" => { "Size" => 148, "Type" => "text/richtext", "Encoding" => "7bit" }, "Part_5" => { "Filename" => "/evil/filename", "Type" => "message/rfc822", "Encoding" => "7bit" }, "Msg" => { "Subject" => "A complex nested multipart example", "Type" => "multipart/mixed", "To" => "", "From" => "Lord John Whorfin ", "Encoding" => "7bit", "Boundary" => "unique-boundary-1" } } MIME-tools-5.509/testmsgs/uu-junk.ref0000644000076400007640000000114212541013575015511 0ustar dfsdfs{ "Part_1" => { "Size" => 373, "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Size" => 6965, "Type" => "text/plain", "Encoding" => "7bit" }, "Msg" => { "Subject" => "mime::parser", "Type" => "multipart/mixed", "To" => "eryq\@zeegee.com", "From" => "\"ADJE Webmail Tech Support\" ", "Encoding" => "7bit", "Boundary" => "---------------------------7d033e3733c" }, "Parser" => { "Message" => "testmsgs/uu-junk.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" } } MIME-tools-5.509/testmsgs/russian.msg0000644000076400007640000000027312541013575015615 0ustar dfsdfsContent-Type: text/plain; charset="US-ASCII"; name==?koi8-r?B?89DJ08/LLmRvYw==?= Content-Disposition: attachment; filename==?koi8-r?B?89DJ08/LLmRvYw==?= Subject: Greetings Salutations MIME-tools-5.509/testmsgs/multi-simple.msg0000644000076400007640000000117512541013575016554 0ustar dfsdfsFrom: Nathaniel Borenstein To: Ned Freed Subject: Sample message MIME-Version: 1.0 Content-type: multipart/mixed; boundary="simple boundary" This is the preamble. It is to be ignored, though it is a handy place for mail composers to include an explanatory note to non-MIME conformant readers. --simple boundary This is implicitly typed plain ASCII text. It does NOT end with a linebreak. --simple boundary Content-type: text/plain; charset=us-ascii This is explicitly typed plain ASCII text. It DOES end with a linebreak. --simple boundary-- This is the epilogue. It is also to be ignored. MIME-tools-5.509/testmsgs/german-qp.msg0000644000076400007640000000123112541013575016013 0ustar dfsdfsContent-Type: text/plain; charset="iso-8859-15" Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: JaM - Just A Mailer Subject: Testnachricht Return-Path: Date: Wed, 21 Dec 2005 22:02:44 +0100 To: joern@zyn.de From: =?ISO-8859-15?Q?J=F6rn?= Reder =0A= Hallo,=0A= =0A= das ist eine Testnachricht mit 8 Bit S=F6nderz=E4ichen, und obendrein noch= =20=0A= quoted-printable kodiert.=0A= =0A= Gr=FC=DFe,=0A= =0A= J=F6rn=0A= --=20=0A= .''`. J=F6rn Reder =0A= : :' : http://www.exit1.org/ http://www.zyn.de/=0A= `. `'=0A= `- Debian GNU/Linux -- The power of freedom=0A= MIME-tools-5.509/testmsgs/multi-weirdspace.msg0000644000076400007640000000437512541013575017416 0ustar dfsdfsReturn-Path: eryq@rhine.gsfc.nasa.gov Sender: john-bigboote Date: Thu, 11 Apr 1996 01:10:30 -0500 From: Eryq Organization: Yoyodyne Propulsion Systems X-Mailer: Mozilla 2.0 (X11; I; Linux 1.1.18 i486) MIME-Version: 1.0 To: john-bigboote@eryq.pr.mcs.net Subject: Two images for you... Content-Type: multipart/mixed; boundary="------------299A70B339B65A93542D2AE" --------------299A70B339B65A93542D2AE Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit When unpacked, this message should produce two GIF files: * The 1st should be called "3d-compress.gif" * The 2nd should be called "3d-eye.gif" There is an empty preamble, and linear space after the bounds. -- ____ __ / __/__________/_/ Eryq (eryq@rhine.gsfc.nasa.gov) / __/ _/ / / , / Hughes STX Corporation, NASA/Goddard /___/_/ \ /\ /___ /_/ /_____/ http://selsvr.stx.com/~eryq/ --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-compress.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --------------299A70B339B65A93542D2AE Content-Type: image/gif; name="3d-eye.gif" Content-Transfer-Encoding: base64 R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --------------299A70B339B65A93542D2AE-- MIME-tools-5.509/testmsgs/uu-zeegee.ref0000644000076400007640000000130212541013575016004 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/uu-zeegee.msg", "ExtractUuencode" => 1, "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "uudecoding", "Type" => "multipart/mixed", "To" => "you", "From" => "me", "Encoding" => "7bit", }, "Part_1" => { "Type" => "text/plain", "Encoding" => "7bit" }, "Part_2" => { "Filename" => "up.gif", "Size" => 110, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" }, "Part_3" => { "Filename" => "zeegee.gif", "Size" => 4834, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" } } MIME-tools-5.509/testmsgs/bluedot-postcard.msg0000644000076400007640000001543412541013575017411 0ustar dfsdfsContent-Type: multipart/alternative; boundary="----------=_961872013-1436-0" Content-Transfer-Encoding: binary Mime-Version: 1.0 X-Mailer: MIME-tools 5.211 (Entity 5.205) To: noone Subject: A postcard for you This is a multi-part message in MIME format... ------------=_961872013-1436-0 Content-Type: text/plain Content-Disposition: inline Content-Transfer-Encoding: binary Having a wonderful time... wish you were looking at HTML instead of this boring text! ------------=_961872013-1436-0 Content-Type: multipart/related; boundary="----------=_961872013-1436-1" Content-Transfer-Encoding: binary This is a multi-part message in MIME format... ------------=_961872013-1436-1 Content-Type: text/html Content-Disposition: inline Content-Transfer-Encoding: binary

Hey there!

Having a wonderful time... take a look!
Snapshot
------------=_961872013-1436-1 Content-Type: image/jpeg; name="bluedot.jpg" Content-Disposition: inline; filename="bluedot.jpg" Content-Transfer-Encoding: base64 Content-Id: my-graphic /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsL DBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/ 2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAEAAQADASIAAhEBAxEB/8QA HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUF BAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK FhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1 dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEB AQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAEC AxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRom JygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU 1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAoo ooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiii gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKA CiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoo ooAKKKKACiiigAooooAKKKKACiiigAooooAKKKjnnhtbeW4uJY4YIkLySSMF VFAySSeAAOc0ASUVw+p/E3TY1MeiW0uqzgkb8NBbjB6+ay/MCM4MauDgZIBB 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 KOGCJAkccahVRQMAADgADjFeFjM2veFD7/8AL/M+qy7h+zVXFf8AgP8An/l/ wxDp2nWmk6fDY2MCw20IwiAk9Tkkk8kkkkk5JJJJJNWqKK8I+r2CiiigAooo oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigDlNY+H2iarcPdQef pd1I5eWawKp5pJJJZGVkLEnJfbvOAN2OK5O88AeJ7PJt5dN1ONV3kqXtZCf7 iod6k8cEyKCTg4AyfV6K6aOLr0dIS0OLEZdhcRrVgm++z+9HiU2j+IrWJprr wzqccK/edDDORngfJFI7nn0U46nABNVP9L/6A2uf+Ce6/wDjde8UV2RzjELd J/L/AIJ5suHMG3o5L5r9UeEJHfzSLHFomttI5CoraZPGCT0BZ0Cr9WIA7kCt GHwx4ruZViXw7JbFv+Wt3dwLEvf5jG7t7DCnkjOBkj2ailLN8Q9rL5f5lQ4d wcd7v1f+SR5xYfDK7lkR9Z1lTCQGe2sITGc8ZQzMxJXGRlVRjwQV6V2ukeH9 I0GN00rTra0MgUSvHGA8u3ODI/3nPJ5Yk5JOeTWlRXBVr1KrvUdz1aGFo4dW pRSCiiisjoCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACi iigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKK KACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigA ooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//Z ------------=_961872013-1436-1-- ------------=_961872013-1436-0-- MIME-tools-5.509/testmsgs/dup-names.msg0000644000076400007640000000733312541013575016026 0ustar dfsdfsReturn-Path: eryq@rhine.gsfc.nasa.gov Sender: john-bigboote Date: Thu, 11 Apr 1996 01:10:30 -0500 From: Eryq Organization: Yoyodyne Propulsion Systems X-Mailer: Mozilla 2.0 (X11; I; Linux 1.1.18 i486) MIME-Version: 1.0 To: john-bigboote@eryq.pr.mcs.net Subject: Two images for you... Content-Type: multipart/mixed; boundary="------------299A70B339B65A93542D2AE" This is a multi-part message in MIME format. --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="one.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="one.gif" R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="two.nice.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="two.nice.gif" R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="two.nice.gif" R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --------------299A70B339B65A93542D2AE-- MIME-tools-5.509/testmsgs/re-fwd.ref0000644000076400007640000000133412541013575015302 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/re-fwd.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Disposition" => "inline", "Subject" => "Re: Fwd: hello world", "Type" => "message/rfc822", "To" => "user0", "From" => "user2", "Encoding" => "binary" }, "Part_1" => { "Disposition" => "inline", "Subject" => "Fwd: hello world", "Type" => "message/rfc822", "To" => "user2", "From" => "user1", "Encoding" => "binary" }, "Part_1_1" => { "Size" => 60, "Disposition" => "inline", "Subject" => "hello world", "Type" => "text/plain", "To" => "user1", "From" => "user0", "Encoding" => "binary" }, } MIME-tools-5.509/testmsgs/frag.msg0000644000076400007640000025277612541013575015071 0ustar dfsdfsFrom - Fri May 26 10:59:48 2000 Return-Path: Received: from virtual.mrf.mail.rcn.net ([207.172.4.103]) by mta05.mrf.mail.rcn.net (InterMail vM.4.01.02.27 201-229-119-110) with ESMTP id <20000524184032.XKFS1688.mta05.mrf.mail.rcn.net@virtual.mrf.mail.rcn.net> for ; Wed, 24 May 2000 14:40:32 -0400 Received: from mail.desktop.com ([166.90.128.242]) by virtual.mrf.mail.rcn.net with esmtp (Exim 2.12 #3) id 12ug50-00059f-00 for eryq@zeegee.com; Wed, 24 May 2000 14:40:30 -0400 Received: from mailandnews.com (jumpgate.desktop.com [166.90.128.243]) by mail.desktop.com (8.9.2/8.9.2) with ESMTP id LAA31102 for ; Wed, 24 May 2000 11:40:29 -0700 (PDT) (envelope-from omrec@mailandnews.com) Message-ID: <392C2385.4C402C55@mailandnews.com> Date: Wed, 24 May 2000 11:46:29 -0700 From: Sven Reply-To: omrec@mailandnews.com X-Mailer: Mozilla 4.7 [en] (WinNT; I) X-Accept-Language: en MIME-Version: 1.0 To: Eryq Subject: [Fwd: [Fwd: [Fwd: FW: Another Priceless Moment]]] Content-Type: multipart/mixed; boundary="------------ABE49921AF9E83E8F9A7667E" X-Mozilla-Status: 8001 This is a multi-part message in MIME format. --------------ABE49921AF9E83E8F9A7667E Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit --------------ABE49921AF9E83E8F9A7667E Content-Type: message/rfc822 Content-Transfer-Encoding: 7bit Content-Disposition: inline Received: from mail.vynce.org [63.198.43.13] (vynce@vynce.org); Tue, 23 May 2000 22:00:16 -0400 X-Envelope-To: omrec Received: from vynce.org (166.90.128.243) by mail.vynce.org with ESMTP (Eudora Internet Mail Server 1.3.1); Tue, 23 May 2000 19:05:52 -0700 Message-ID: <392B389A.1968998B@vynce.org> Date: Tue, 23 May 2000 19:04:10 -0700 From: Vynce Organization: Desktop.com X-Mailer: Mozilla 4.61 [en] (Win98; U) X-Accept-Language: en MIME-Version: 1.0 To: omrec@mailandnews.com Subject: [Fwd: [Fwd: FW: Another Priceless Moment]] Content-Type: multipart/mixed; boundary="------------4CEB5E448DC077F35050C4BE" X-Mozilla-Status2: 00000000 This is a multi-part message in MIME format. --------------4CEB5E448DC077F35050C4BE Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit just to add to your personal hell. --------------4CEB5E448DC077F35050C4BE Content-Type: message/rfc822 Content-Transfer-Encoding: 7bit Content-Disposition: inline Return-Path: Received: from iglou.com (192.107.41.3) by mail.vynce.org with SMTP (Eudora Internet Mail Server 1.3.1); Thu, 18 May 2000 16:10:02 -0700 Received: from [204.255.234.19] (helo=ntserver2.snesystems.com) by iglou.com with esmtp (8.9.3/8.9.3) id 12sZKw-0007JK-00; Thu, 18 May 2000 19:04:15 -0400 Received: from snesystems.com (sne-30.snesystems.com [204.255.234.30]) by ntserver2.snesystems.com with SMTP (Microsoft Exchange Internet Mail Service Version 5.5.2650.21) id LGJH8AYQ; Thu, 18 May 2000 19:03:40 -0400 Sender: root@mail.vynce.org Message-ID: <39247724.AF25EF83@snesystems.com> Date: Thu, 18 May 2000 19:05:08 -0400 From: root Reply-To: jasonc@snesystems.com Organization: SNE Systems, Inc. X-Mailer: Mozilla 4.72 [en] (X11; I; Linux 2.2.12-20 i686) X-Accept-Language: ja, en MIME-Version: 1.0 To: vynce@vynce.org Subject: [Fwd: FW: Another Priceless Moment] Content-Type: multipart/mixed; boundary="------------8B533A82922407D7C3D35A99" X-Mozilla-Status2: 00000000 This is a multi-part message in MIME format. --------------8B533A82922407D7C3D35A99 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit --------------8B533A82922407D7C3D35A99 Content-Type: message/rfc822 Content-Transfer-Encoding: 7bit Content-Disposition: inline Received: by ntserver2 id <01BFC0CA.C31F7A10@ntserver2>; Thu, 18 May 2000 09:12:47 -0400 Message-ID: <01D476341BDBD211B7C500A0CC209BA03DF5C6@ntserver2> From: Shawn Morgan To: Wayne Price , Tim Spayner , Gary Jones , Jason Chelliah Subject: FW: Another Priceless Moment Date: Thu, 18 May 2000 09:12:47 -0400 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01BFC0CA.C32A4450" This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_000_01BFC0CA.C32A4450 Content-Type: text/plain; charset="iso-8859-1" -----Original Message----- From: Shawn Morgan [mailto:cephalos@home.com] Sent: Wednesday, May 17, 2000 8:18 PM To: Shawn Morgan Subject: Fw: Another Priceless Moment ----- Original Message ----- From: Michele Morgan To: Sent: Tuesday, May 16, 2000 10:31 PM Subject: Fw: Another Priceless Moment > > ------_=_NextPart_000_01BFC0CA.C32A4450 Content-Type: image/jpeg; name="aprilfools.jpg" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="aprilfools.jpg" /9j/4AAQSkZJRgABAgEASABIAAD/7Q4uUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQABOEJJTQQNAAAAAAAEAAAAeDhCSU0D8wAAAAAACAAAAAAAAAAAOEJJTQQKAAAAAAAB AAA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9m ZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4 AAAAAABwAAD/////////////////////////////A+gAAAAA//////////////////////////// /wPoAAAAAP////////////////////////////8D6AAAAAD///////////////////////////// A+gAADhCSU0EAAAAAAAAAgACOEJJTQQCAAAAAAAGAAAAAAAAOEJJTQQIAAAAAAAQAAAAAQAAAkAA AAJAAAAAADhCSU0EFAAAAAAABAAAAAQ4QklNBAwAAAAADH4AAAABAAAAcAAAAFQAAAFQAABuQAAA DGIAGAAB/9j/4AAQSkZJRgABAgEASABIAAD/7gAOQWRvYmUAZIAAAAAB/9sAhAAMCAgICQgMCQkM EQsKCxEVDwwMDxUYExMVExMYEQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQ0L Cw0ODRAODhAUDg4OFBQODg4OFBEMDAwMDBERDAwMDAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM DAwMDAz/wAARCABUAHADASIAAhEBAxEB/90ABAAH/8QBPwAAAQUBAQEBAQEAAAAAAAAAAwABAgQF BgcICQoLAQABBQEBAQEBAQAAAAAAAAABAAIDBAUGBwgJCgsQAAEEAQMCBAIFBwYIBQMMMwEAAhED BCESMQVBUWETInGBMgYUkaGxQiMkFVLBYjM0coLRQwclklPw4fFjczUWorKDJkSTVGRFwqN0NhfS VeJl8rOEw9N14/NGJ5SkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2N0dXZ3eHl6e3x9fn9xEAAgIB AgQEAwQFBgcHBgU1AQACEQMhMRIEQVFhcSITBTKBkRShsUIjwVLR8DMkYuFygpJDUxVjczTxJQYW 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 AAEBAP/iDFhJQ0NfUFJPRklMRQABAQAADEhMaW5vAhAAAG1udHJSR0IgWFlaIAfOAAIACQAGADEA AGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD21gABAAAAANMtSFAgIAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MA AAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQAAAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJY WVoAAAJAAAAAFGRtbmQAAAJUAAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAA JGx1bWkAAAP4AAAAFG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8 AAAIDGJUUkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAEnNSR0Ig SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAG+i AAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPZGVzYwAAAAAA AAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAA LklFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAA LklFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAA AAAAAAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4gSUVD NjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYx OTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAAE6T+ABRfLgAQzxQAA+3M AAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFzAAAAAAAAAAEAAAAAAAAAAAAAAAAA AAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAAAAAABAAAAAAFAAoADwAUABkAHgAjACgALQAy ADcAOwBAAEUASgBPAFQAWQBeAGMAaABtAHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwA wQDGAMsA0ADVANsA4ADlAOsA8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFn AW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksC VAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+ A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE0wThBPAE /gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZBmoGewaMBp0GrwbA BtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8IMghGCFoIbgiCCJYIqgi+CNII 5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9ClQKagqBCpgKrgrFCtwK8wsLCyILOQtR C2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4MpwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMO Lg5JDmQOfw6bDrYO0g7uDwkPJQ9BD14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFP EW0RjBGqEckR6BIHEiYSRRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U 8BUSFTQVVhV4FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjV GPoZIBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1HR4d Rx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwhSCF1IaEhziH7 IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXHJfcmJyZXJocmtyboJxgn SSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5LG4soizX LQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQz DTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/ Obw5+To2OnQ6sjrvOy07azuqO+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRA pkDnQSlBakGsQe5CMEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgF SEtIkUjXSR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeSV+BYL1h9 WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ffs2AFYFdgqmD8YU9h omH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fpaD9olmjsaUNpmmnxakhqn2r3 a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1 KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+E f+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSK yoswi5aL/IxjjMqNMY2Yjf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0 lp+XCpd1l+CYTJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiai lqMGo3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2uoa8W r4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7LrunvCG8 m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8yTrJuco4 yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V0dZV1tjXXNfg2GTY 6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep 6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3 ivgZ+Kj5OPnH+lf65/t3/Af8mP0p/br+S/7c/23////uAA5BZG9iZQBkAAAAAAH/2wCEAAYEBAQF BAYFBQYJBgUGCQsIBgYICwwKCgsKCgwQDAwMDAwMEAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM DAwBBwcHDQwNGBAQGBQODg4UFA4ODg4UEQwMDAwMEREMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwM DAwMDAwMDAwMDP/AABEIAeACgAMBEQACEQEDEQH/3QAEAFD/xAGiAAAABwEBAQEBAAAAAAAAAAAE BQMCBgEABwgJCgsBAAICAwEBAQEBAAAAAAAAAAEAAgMEBQYHCAkKCxAAAgEDAwIEAgYHAwQCBgJz AQIDEQQABSESMUFRBhNhInGBFDKRoQcVsUIjwVLR4TMWYvAkcoLxJUM0U5KismNzwjVEJ5OjszYX VGR0w9LiCCaDCQoYGYSURUaktFbTVSga8uPzxNTk9GV1hZWltcXV5fVmdoaWprbG1ub2N0dXZ3eH l6e3x9fn9zhIWGh4iJiouMjY6PgpOUlZaXmJmam5ydnp+So6SlpqeoqaqrrK2ur6EQACAgECAwUF BAUGBAgDA20BAAIRAwQhEjFBBVETYSIGcYGRMqGx8BTB0eEjQhVSYnLxMyQ0Q4IWklMlomOywgdz 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 q4g+/wBOKrh0r3HTFVhDDqevhirVCHJ6bde+KtToWhNW2FT94xVbHVYIjy+P4eP0ZFtx8050pX1o zAcrJIF5xTyitZP99oRuvPsWwF22I0LRFvJLPKsdpEPWY8JpH2o7Ap8R8aimRbweJL7meWe3kjSO UvaExvyO5OKeClkl7cRWkcYqsZCgIdmr3APfFqlFM7DTF1O9Vbw8oYlqig05HwIxboZKRd/La6be W1jZIvqXFUdPskBlNfiwo+opNqVu73sUssKehH8MdtuSVU0K/NsDbE0jrTT71XJkkWJJBzSMmirT 7KqT+1kSmMt1trolrqv1u5aVXjtVHqK7GNUJH2zx3ffwwLOW6hNNM9otvLKtrKKRMXJU8gPhovU/ CcHCw4lDTvLWnwalZ3P6QNybct60YQqAT0JPsclEKSmEdhY/pPULm3kAiaNISUbYS8qlqftfD8OS Qp2OlST6tE87LPb2tJfTc8RV24Vp/qiuQRki7VJ5RexWkYItxLxZx/LyNA2GmyI2TjV7HTU0e4CR rGgjY8kFGFCKke+PCwjzWW19oT2SpAoeqEUNCWNMkESviSyGzt20uS6IaOW93EYruD9lae2LOORB 2ltqWlre2shKX1+EFjcH4yp2oK9sWUpWmd7o+qzzSSXrrLa3VuLa5h5lVDruZBX4a1xYjmgLCcLq S6dptuOUcPKYqQFb09uS02rizmo65BqepwTQWyvGaDkDxUU9hinYBlunaDaDSoUuwkzMimVpO527 9sBcMzNsb1prWaxS2QWz28CGKEsT6sbgn4dvtZFyNOLKF0qe3k0eS1nSnH+7+L4yxYfEoO/wqCuL dOA4il811c2T+jayFTUFX7jfo2LLw9l2tprss9p9ZijkkJohQ0oxFV38MWojhR2swxDg6SNb3USK 4eNvhSUAcipyJZjITAphqWiX0yW2pS3jzRafAtzJcn+5mc/7qiVeh/yssi4cJEFLtcv7SzeB76wW C8YJNHJQOOD9myLeBTa2ljqV4kt7cRSiMBo7cLWqnooAxZSyUuutEM90hsZPqkinZo6A8fkMWPjI fU9AtrSSDU74tdurUZpPiI49NsmEylxBqbWLOe1Z7cKxXiaKu9V37YWsR6Kia9pOqXltNf2EaSsw SW4XmgbagDKNmwJ8FEzeYdTewljs4WF3YzqZRAnOMwA9qdOS9sLXOFFj0t1BfeZnNvI9pb3ClpQP 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 Ec7jlsTUD2I8cWUrR9zpt9diNbG --------------8B533A82922407D7C3D35A99-- --------------4CEB5E448DC077F35050C4BE-- --------------ABE49921AF9E83E8F9A7667E-- MIME-tools-5.509/testmsgs/multi-igor2.ref0000644000076400007640000000176612541013575016301 0ustar dfsdfs{ "Part_1" => { "Size" => 293, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "US-ASCII" }, "Part_2" => { "Filename" => "Makefile", "Size" => 2442, "Type" => "text/plain", "Encoding" => "base64", "Charset" => "US-ASCII" }, "Part_3" => { "Filename" => "multi-nested.msg", "Size" => 3272, "Type" => "text/plain", "Encoding" => "base64", "Charset" => "US-ASCII" }, "Part_4" => { "Filename" => "Parser.n.out", "Size" => 906, "Type" => "text/plain", "Encoding" => "base64", "Charset" => "US-ASCII" }, "Msg" => { "Subject" => "Need help", "Type" => "multipart/mixed", "To" => "eryq\@rhine.gsfc.nasa.gov", "From" => "Starovoitov Igor ", "Encoding" => "7bit", "Boundary" => "-490585488-806670346-834061839=:2195" }, "Parser" => { "Message" => "testmsgs/multi-igor2.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" } } MIME-tools-5.509/testmsgs/multi-2gifs.ref0000644000076400007640000000202512541013575016256 0ustar dfsdfs{ "Parser" => { "Message" => "testmsgs/multi-2gifs.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" }, "Msg" => { "Subject" => "Two images for you...", "Type" => "multipart/mixed", "To" => "john-bigboote\@eryq.pr.mcs.net", "From" => "Eryq ", "Encoding" => "7bit", "Boundary" => "------------299A70B339B65A93542D2AE", "Preamble" => "This is a multi-part message in MIME format.\n", "Epilogue" => "That was a multi-part message in MIME format.\n", }, "Part_1" => { "Size" => 417, "Type" => "text/plain", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Part_2" => { "Filename" => "3d-compress.gif", "BodyFilename" => "3d-compress.gif", "Size" => 419, "Disposition" => "inline", "Type" => "image/gif", "Encoding" => "base64" }, "Part_3" => { "Filename" => "3d-eye.gif", "BodyFilename" => "3d-eye.gif", "Size" => 357, "Type" => "image/gif", "Encoding" => "base64" }, } MIME-tools-5.509/testmsgs/uu-junk.msg0000644000076400007640000002062112541013575015526 0ustar dfsdfsFrom - Fri Jun 9 23:17:56 2000 Return-Path: Received: from virtual.mrf.mail.rcn.net ([207.172.4.103]) by mta02.mrf.mail.rcn.net (InterMail vM.4.01.02.27 201-229-119-110) with ESMTP id <20000425112650.ZPUD516.mta02.mrf.mail.rcn.net@virtual.mrf.mail.rcn.net> for ; Tue, 25 Apr 2000 07:26:50 -0400 Received: from [205.139.141.226] (helo=webmail.uwohali.com ident=root) by virtual.mrf.mail.rcn.net with esmtp (Exim 2.12 #3) id 12k3VX-00012G-00 for eryq@zeegee.com; Tue, 25 Apr 2000 07:27:59 -0400 Received: from webmail.uwohali.com (nobody@localhost [127.0.0.1]) by webmail.uwohali.com (8.8.7/8.8.7) with SMTP id GAA10264 for ; Tue, 25 Apr 2000 06:34:43 -0500 Date: Tue, 25 Apr 2000 06:34:43 -0500 Message-Id: <200004251134.GAA10264@webmail.uwohali.com> From: "ADJE Webmail Tech Support" To: eryq@zeegee.com Subject: mime::parser Content-type: multipart/mixed; boundary="---------------------------7d033e3733c" Mime-Version: 1.0 X-Mozilla-Status: 8001 -----------------------------7d033e3733c Content-Type: text/plain Eryq - I occasionally receive an email (see below) like this one, which MIME::Parser does not parse. Any ideas? Is this a valid way to send an attachment, or is the problem on the "sender's" side? Thanks for your time! Mike -->> Promote YOUR web site! FREE Perl CGI scripts add WEB ACCESS to your -->> E-Mail accounts! Download today!! http://webmail.uwohali.com -----------------------------7d033e3733c Here's what he's talking about. I've uuencoded the ZeeGee logo and another GIF file below. begin 644 up.gif M1TE&.#=A$P`3`*$``/___P```("`@,#`P"P`````$P`3```"1X2/F<'MSTQ0 M%(@)YMB\;W%)@$<.(*:5W2F2@<=F8]>LH4P[7)P.T&NZI7Z,(&JF^@B121Y3 4Y4SNEJ"J]8JZ:JTH(K$"/A0``#L` ` end begin 644 zeegee.gif M1TE&.#=A6P!P`/<```````@("!`0$#D`(3D`*4(`*1@8&$H`*4H`,5(`,5(` M.5H`,2$A(5H`.5((,6,`.6,`0EH(.6L`0F,(.6,(0BDI*5H0.6L(0FL(2F,0 M.6,00G,(2C$Q,4(I,6L02GL(4G,04G,02FL80H0(4H0(6E(I.7,80HP(6CDY M.6LA0D(Y.90(6I0(8XP06G,A2H084H086I008U(Y0GLA4D)"0G,I2H0A2G,I M4H0A4H0A6H0I4I0A8TI*2FLY4GLQ6G,Y4I0I8U)24F-*4EI22I0Q8Y0Q:YPQ M:Y0Y6I0Y8X1"6I0Y:UI:6HQ"6H1*8Z4YV-C8WM: M8Z5"X1C:Y1:ZU2WM[>Y1S[UC>XQ[ M>YQS>[5K>[UCE)Q[>X2$A+UKA)Q[E*5[>[UKC*5[A*5[E)R$>[USC*5[G-YC MC(R,C*U[G*6$A,YKE+U[C*V$A+5[G,YSC*V$C+5[I=YKE)24E*V,C+6$I;V$ MI;6,C+6,E-9[G+V,C*V4C+V,E-Y[E-Y[G)R>$I;V^,I:VM MK<:EI>4O>^4M=:EI=:EK>>>EK?>>EM=ZMK>>EO=ZMM>^EK?^^EO?^MK>>MM>^ESO>EO?^E MO>^MO?^EQN>UM?^ESO>MQL;&QN^UM=Z]M>^UO?^MO?>UO>>]O>^]O?^USO^U MQO>]O<[.SN?&O?>]QO^]QO^]SO?&QO^]WO?&SM;6UO_&QO_&SO_&WO_&Y__. MSN_6SO_.UM[>WO_.WO_6UO_6WO_6Y^?GY__>WO_>Y__GWO_GY__G[__G]^_O M[__O[_?W]__W]__W_____RP`````6P!P``<(_P#_"1Q(L*#!@P@3*ES(L*'# MAQ`C2IQ(L:+%BQ@S:I08J:-'2"!#BAP9DI')1(12JES)LF6@ES!C^IE)L^9, M/3ASZE2XH:?/GAB"8KA`M"B%HT@A*(7PH('3IU`;*)BJ(('5JPBR:M5ZH&N! MKV#!$AA+8(#9LSQ__A0ZM"A1I$F7-HT:E6K5JUBW379 MU["/(]_0V3-SN:,=/_^&[/MW];YCL6>/C;S[7]U66H(+\-6C;;?&%)R%>U)U7 M@$(C*(CA=H9YQR&$$4;76XA]D5BBB?NAJ-Q[<.76HHL@9I5`!M.9=Z",,]*H M77LW(I9CA]#Q:)4-9#22R2:*".+"9'P1.4*1-&;8X'?./4?78PM$T8@K=4A1 M@P4U,*$($WN-F!`)6]9I9'9>!E7;BBQZJ(`5I6RBA@B1I7"(!7LI1`*==7+9 MI8UZJKADGXV]4`HQ9U@@759()+'5`8HNVJBC)N89J9*3BMG``W8\H\@,]('_ MB$,3>H6Z**-VWKG@9AJ"&:!3+\CBRA/B.6F5!F_4FM`)MXK:J*Z[$M8K@`%: M$4TC)M05JU6'*(O0"$>01)`(*@1NNN,_J M:NJ>H+VP##'$RL=;!F/D5:^]]SJ;ZYW[2GH4$>2$,!DDTBD`)G&&W,\*K0-NV4'.89XH-C)8RKP!*%XL8QPPAV3 M6RZ#21HB#AO4JDJ:&!D0F(#//[O\,L.0ZHG*-EB@FZK2#5R`!7T*L?!SU%)[ M_#'1&,BRC1(X/DAQ`Q'H@(48+@Q85=ABC]WRK5-3_[U=*MP4P>^DO]90BSWW MW*.+!G;CS<(*>MM;]I8P(W=U$>?ZVI0&M'S#3C_WL+/*`DY-Y3@+>4?.<="5 MJW6U$?V%[."#7[3B2S7L?).-+STCL$@#;Q81_K@P<`&RB,=QV!@.Q3X"S2` M8%IP:8(02C`$(0AA""5(P/\0(L`2IDYUXH*!';"A0/4UL('O4$<$7SC!=8`# M$!>47?0\4`49J."'*G!`5/_J94(!@@^%BWJ#-<[1PG:\,![Q>$<^@@'%>-!0 M@>C`QAF^!!B`$(>XK!.LH(@!)"`)@'"*;IP#'2U\(3SBD0YYS*** M5KSB.LX!CD_D`'IPT4(*(L`DC9T1C2?\612@X48FQI&&\CC&._`HQQJB@X_4 M4`(@*:"#)$CO5SY#9"+!E09&@N.-"EQ@`]NA#F2L@Y*53.4YSM$-:H3A2V(0 MP=8:`+5#HA%A>8"&-;HQ#E0^$A[M(`@P0;_X$`*?&(* MU,PH2E(F`QK:(*8QT^=$>&Q#&N!H9B6?&8H99O@$F47 M@*'_#&J$LYCC5!\WEH$-==*0G;.4IC:@`0Q-L@4'1T!57/`)+E\*T`FX``8T M_-F-4XYS'=R0QC#*6<55KB^5T$QH-Q::C%/H('9DT(##D*(H`EJ4!3$812TT MRE%P`!2.ZPB'-&SAQ'C0XQ[XN$<]Z(%,E&)QEN-0*#24`8Q+A(`[.V#"821* M@5`1\`0"Y`,M=KI1:X33HV\4QS-F<0XGU@,?_A#(/N[!5*=>4J7:>"=5:3&& MGIS!`YF#BZV^BKH=T&*L_!1F.#LZRW,TPQ8L;`<]\%&0?-0#'JE$QUWYV(V5 MZA48M/`$"(QPA!1)RE:+LBD@8G'8Q%+#K)T]93.:P0LX_\*C'OTP"#[B`LEQB'>\U@BN<`^KBDY<05KGTM)R$=:"3IC"%*I@K72_6=9BA((: ML06'=N-QCWV8>!]UY:,TQTM>:$`C&<`X;RQ,P0E$\"I)6AK!A,'E!$YXXL+0 MC2XP.$R,69Q"&TB.+1/+*<$]KGBE>4VPBV$,6O326!(^N+%R7C.J'<>!$YRP M<'V%#(Q>%.,0U'BM61?KT_!"=?_%2(ZR@I5!Y<.N0A6>X,0CFH`V/6%G7,L] M!)C#C&'61G<8R`"$,EQ<5FNL.JZ:?+MX*! M)"9Q"3#_.,.TR$4Q*)$+?BZ:T1M-% M0%T$21A;$J8N]"YF<0E<2U<9K[:UM%T,;6?7XM*9SC,G)%$(.,PO0\/NLA*. M;>QDLZ(8=3CL3IT-#&%`&]KN?KNNM\2M?5A=WYG7^O;U'[%YG_J`1]5V%HB-?"%\#PA#T97:%W&'QN\!Y7M0>++]3M^5/_?RE=?YA3W!]8P_0O!T<`,8JN`"(Y7= M(OQ(O>I7S_K6N_[UL(?]1A32>GW$_O:XSST_9D][U=M>]ZLO"/!?S_O>\^/W MPU_(\%5?_(',0Q\$\?WR$<(/=\SC^0))OD4&P8#N>]_[CG!'__2/O_S=%\08 M/!```-8?`!08XQ_`OT@;UD__^FO"_`,A__3S3X7Z&Z#^2X!\L8<1Y@`*!FB` MFA```,``YF`0YB=[^<=\V<<#Z\+!^CE`0 MW@`*FG"!U]=Z_U"`FJ`)&)AZ`U$&ZX<'$9AZMZ"`K]!ZT_""H`!]PG=]/9B" M0.@0\Z"`/#`/`^$.*%!_`!`$WA"#J><.%%A_/.`-0.@."K@%XZ=Z\V!]7F@, M'%!_`4`%^*'MQ"#YI"'=^B' MM[![(R@`^'=[\_`*"FB'>+A^%0!]_/]P@G7(`#S``.O'`&V($-.P?EOP@)3( M`=XP$--0`0#``<9@>Z*(`MZ@>MXPAA6`@11(!=D'?_`7@O"G#].@?CQ@#JIW MBT_8@L:`B^(G$(Z`BPPABA7PB0*A"788C,ZG?GC@#LIHB06A#_\W"/PPAGC@ MA>ZPC=RXC>;PA?V'`LRW>[>P?FG8?QP0@OPP@@#0@`GA""1($$$``#SP@O;X M@C0``#3@#?,8!/=HC_G(`_S0A&6@>J_@A/77!N9`B5OPCYK@")0X"+=`B53@ M"/\(D0`P"`FA#[BHA`,QA@A9?Q5@#B`9DA7(#V](`[]7CB;Y"MY@DO6W!0<) MD^M7!@G1?W'_6!!-6`$HL`14\)-`N01M,)`+&`1+<)1(>91#J8P!D(K'UXWN MD(;J]X7KQP-'"914<)6O,)-!@)59J968J(FTN`7T.`W,*'QDF8NL%WT<28\" MZ'OSZ('\0(GW1Q#Z,`_F-PW_IPG19PZ7:!!CR`%G*1`L"0K?.!#ZD)6ZF(D` M``K/9WZ)N00QJ(Q/B)>KIP]O*`"ZN(X+Z)'_<)>OX),"\8;2^)E1J0FB>1"@ M```!L(=0.0W3,(\!H)"I9PRG.!"RV08Q.)$`((ZJ-W]P6`:O8`Z:4`9Y&(BI M1XT+N(/\8`YXH(`V^)G_QP"EJ`_>T`;0B1#`&9*TF8^L:0"1Z)GZ_["&`0"> ME6B9JN<(B>B$##`-P=>'ZR<`!I"(2T`0=!B?\[E^L(@0$/E]WF<`=?D/@Y"' M<+@%E\@/;5"'!?J6J3$H-">LSB`.$VQB%([B'7QB" M:!A]*)I_M_""@3@/AQF%U@<*GYB!MNB#[O^H$.7H"%@H$-9'$*"@H`!0`;>@ MA.Q(?V19?PP0`"[*`Z"ZA`!@D_P`"@2ZG!#Z#WJ)`I28C1JXAO07!']IEP'@ MB<^G#VU(@T'0HO-P"Z+H"'YYA*TX#R?8?V4`"N6HD0*A#PH("@,!CZDX"*.8 MJ8?XJ=VWI?^WCW>9@P!Z?>XP@J6)$(@8`$N@@AY9CEP8?:)Z"]`G`.DX$,HH MA_]0`31@?DP9!-E'`PRPI?K(IZ+8K[\8`-"G#^[0?2[Z#R.XGPGAH)0H`&5@ M#@U(`TUI$,[*`^('K_AWD/3ZG,'(`Q6P!83X#UC:!OK@H7]YD&+ZBS0@J=1* MKP3A#A40`&=Z$*__0(F]J@^C.)@"$00&\'X&4`$;"P"O(*D92;(!@`=<^G[* M:`[N(`#Z:A#F$*;_<`L"4)];ZJ%."Y7A"@!ENJ)`.`]CZ`B9&`0\^P_S5Z5! M6X0'6;0"P0$""8_B%P";"+(D"P!MA#*.)SF5XXVR0$,F+#_((D"80`,(+G.A[WQ^N\CCA_#-M]^%>.D_L/ M\&B^`T&!4BH0%%@&OS<-3=A^4PH`Z7N^'2A^U:<)#&``LAM]\\BI!3%_Y9F? MFS@0;4H0Y0BS=UO`#>RB*/F=_R<`J&J^+VF3!(&(=FB>*'#!!G&"FL"X2]@& M61FQ!?$*7SL//_C#;:@/_SN'6_"3@P!]M_"EB.J`@_"36T#"5EK%5GS%6)S% 36KS%7-S%7OS%8!S&8IP1`<$`.P`` ` end -----------------------------7d033e3733c-- MIME-tools-5.509/testmsgs/empty-preamble.msg0000644000076400007640000000164212541013575017055 0ustar dfsdfsContent-Type: multipart/mixed; boundary="t0UkRYy7tHLRMCai" Content-Disposition: inline --t0UkRYy7tHLRMCai Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Das ist ein Test. --=20 sub i($){print$_[0]}*j=3D*ENV;sub w($){sleep$_[0]}sub _($){i"$p:$c> ",w+01 ,$_=3D$_[0],tr;i-za-h,;a-hi-z ;,i$_,w+01,i"\n"}$|=3D1;$f=3D'HO';($c=3D$j{PW= D})=3D~ s+$j{$f."ME"}+~+;$p.=3D"$j{USER}\@".`hostname`;chop$p;_"kl",$c=3D'~',_"zu,". "-zn,*",_"#,epg,lw,gwc,mfmkcbm,cvsvwev,uiqt,kwvbmvb?",i"$p:$c> ";w+1<<07 --t0UkRYy7tHLRMCai Content-Type: image/png Content-Disposition: attachment; filename="dot.png" Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAACXBIWXMAAAsTAAALEwEAmpwY AAAAB3RJTUUH1AUbFQQ0Vbb7XQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ TVDvZCVuAAAAFklEQVR42mP8//8/AwMDEwMDAwMDAwAkBgMB/umWrAAAAABJRU5ErkJggg== --t0UkRYy7tHLRMCai-- MIME-tools-5.509/testmsgs/multi-2evil.msg0000644000076400007640000000500412541013575016277 0ustar dfsdfsReturn-Path: eryq@rhine.gsfc.nasa.gov Sender: john-bigboote Date: Thu, 11 Apr 1996 01:10:30 -0500 From: Eryq Organization: Yoyodyne Propulsion Systems X-Mailer: Mozilla 2.0 (X11; I; Linux 1.1.18 i486) MIME-Version: 1.0 To: john-bigboote@eryq.pr.mcs.net Subject: Two images for you... Content-Type: multipart/mixed; boundary="------------299A70B339B65A93542D2AE" This is a multi-part message in MIME format. --------------299A70B339B65A93542D2AE Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit When unpacked, this message should produce two GIF files: * The 1st should be called "3d-compress.gif" * The 2nd should be called "3d-eye.gif" Different ways of specifying the filenames have been used. -- ____ __ / __/__________/_/ Eryq (eryq@rhine.gsfc.nasa.gov) / __/ _/ / / , / Hughes STX Corporation, NASA/Goddard /___/_/ \ /\ /___ /_/ /_____/ http://selsvr.stx.com/~eryq/ --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="/evil/because:of\path\3d-=?ISO-8859-1?Q?=63?=om=?US-ASCII*EN?Q?pr?=ess.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --------------299A70B339B65A93542D2AE Content-Type: image/gif; name="3d-eye-is-an-evil-filename because of excessive length and verbosity. Unfortunately what can we do given an idiotic situation such as this?" Content-Transfer-Encoding: base64 R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --------------299A70B339B65A93542D2AE-- That was a multi-part message in MIME format. MIME-tools-5.509/testmsgs/multi-digest.ref0000644000076400007640000000163612541013575016532 0ustar dfsdfs{ "Part_1" => { "Type" => "message/rfc822", "Encoding" => "7bit" }, "Part_2" => { "Type" => "message/rfc822", "Encoding" => "7bit", "Charset" => "us-ascii" }, "Part_1_1" => { "Size" => 70, "Subject" => "embedded message 1", "Type" => "text/plain", "From" => "noone\@nowhere.org", "Encoding" => "7bit" }, "Part_2_1" => { "Size" => 73, "Subject" => "embedded message 2", "Type" => "text", "From" => "noone\@nowhere.org", "Encoding" => "7bit" }, "Msg" => { "Subject" => "Sample digest message", "Type" => "multipart/digest", "To" => " Ned Freed ", "From" => "Nathaniel Borenstein ", "Encoding" => "7bit", "Boundary" => "simple boundary" }, "Parser" => { "Message" => "testmsgs/multi-digest.msg", "ExtractNested" => 1, "OutputToCore" => "0", "Name" => "anonymous" } } MIME-tools-5.509/testmsgs/simple.msg0000644000076400007640000000123512541013575015421 0ustar dfsdfsReturn-Path: eryq@rhine.gsfc.nasa.gov Date: Wed, 20 Dec 95 19:59 CST From: eryq@rhine.gsfc.nasa.gov To: sitaram@selsvr.stx.com Cc: johnson@killians.gsfc.nasa.gov,harvel@killians.gsfc.nasa.gov, eryq Subject: Request for Leave I will be taking vacation from Friday, 12/22/95, through 12/26/95. I will be back on Wednesday, 12/27/95. Advance notice: I may take a second stretch of vacation after that, around New Year's. Thanks, ____ __ | _/__________/_/ Eryq (eryq@rhine.gsfc.nasa.gov) | _| _/ | | . | Hughes STX Corporation, NASA/Goddard Space Flight Cntr. |___|_|\_ |_ |___ | | |____/ http://selsvr.stx.com/~eryq/ `-' MIME-tools-5.509/testmsgs/multi-2gifs.msg0000644000076400007640000000450612541013575016276 0ustar dfsdfsReturn-Path: eryq@rhine.gsfc.nasa.gov Sender: john-bigboote Date: Thu, 11 Apr 1996 01:10:30 -0500 From: Eryq Organization: Yoyodyne Propulsion Systems X-Mailer: Mozilla 2.0 (X11; I; Linux 1.1.18 i486) MIME-Version: 1.0 To: john-bigboote@eryq.pr.mcs.net Subject: Two images for you... Content-Type: multipart/mixed; boundary="------------299A70B339B65A93542D2AE" This is a multi-part message in MIME format. --------------299A70B339B65A93542D2AE Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit When unpacked, this message should produce two GIF files: * The 1st should be called "3d-compress.gif" * The 2nd should be called "3d-eye.gif" Different ways of specifying the filenames have been used. -- ____ __ / __/__________/_/ Eryq (eryq@rhine.gsfc.nasa.gov) / __/ _/ / / , / Hughes STX Corporation, NASA/Goddard /___/_/ \ /\ /___ /_/ /_____/ http://selsvr.stx.com/~eryq/ --------------299A70B339B65A93542D2AE Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-compress.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --------------299A70B339B65A93542D2AE Content-Type: image/gif; name="3d-eye.gif" Content-Transfer-Encoding: base64 R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --------------299A70B339B65A93542D2AE-- That was a multi-part message in MIME format. MIME-tools-5.509/testmsgs/multi-nested3.msg0000644000076400007640000000617412541013575016634 0ustar dfsdfsMIME-Version: 1.0 From: Lord John Whorfin To: Subject: A complex nested multipart example Content-Type: multipart/mixed; boundary=unique-boundary-1 The preamble of the outer multipart message. Mail readers that understand multipart format should ignore this preamble. If you are reading this text, you might want to consider changing to a mail reader that understands how to properly display multipart messages. --unique-boundary-1 Part 1 of the outer message. [Note that the preceding blank line means no header fields were given and this is text, with charset US ASCII. It could have been done with explicit typing as in the next part.] --unique-boundary-1 Content-type: text/plain; charset=US-ASCII Part 2 of the outer message. This could have been part of the previous part, but illustrates explicit versus implicit typing of body parts. --unique-boundary-1 Subject: Part 3 of the outer message is multipart! Content-Type: multipart/parallel; boundary=unique-boundary-2 A one-line preamble for the inner multipart message. --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-vise.gif" Subject: Part 1 of the inner message is a GIF, "3d-vise.gif" R0lGODdhKAAoAOMAAAAAAAAAgB6Q/y9PT25ubnCAkKBSLb6+vufn5/Xes/+lAP/6zQAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJLMOyYbcoxkaZ5oCkoH6L5wLMfiWqd4btZhmxbA oFCY47EIqMJgyWw2ATjj7aRkAq5YwDMl9VGtKO0SiuoiTVlscsxt9c4HgXxUIA0EAVOVfDKT 8Hl1B3kDAYYle202XnGGgoMHhYckiWVuR3+OTgCGeZRslotwgJ2lnYigfZdTjQULr7ALBZN0 qTurjHgLKAu0B5Wqopm7J72etQN8t8Ijury+wMtvw8/Hv7Ylfs0BxCbGqMmK0yOOQ0GTCgrR 2bhwJGlXJQYG6mMKoeNoWSbzCWIACe5JwxQm3AkDAbUAQCiQhDZEBeBl6afgCsOBrD45edIv QceGWSMevpOYhl6CkydBHhBZQmGKjihVshypjB9ClAHZMTugzOU7mzhBPiSZ5uDNnA7b/aTZ 0mhMnfl0pDBFa6bUElSPWb0qtYuHrxlwcR17YsWMs2jTql3LFkQEADs= --unique-boundary-2 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="3d-eye.gif" Subject: Part 2 of the inner message is another GIF, "3d-eye.gif" R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7 VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7 +3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7 --unique-boundary-2-- The epilogue for the inner multipart message. --unique-boundary-1 Content-type: text/richtext This is part 4 of the outer message as defined in RFC1341 Isn't it cool? --unique-boundary-1 Content-Type: message/rfc822; name="nice.name"; From: (mailbox in US-ASCII) To: (address in US-ASCII) Subject: Part 5 of the outer message is itself an RFC822 message! Content-Type: Text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: Quoted-printable Part 5 of the outer message is itself an RFC822 message! --unique-boundary-1-- The epilogue for the outer message. MIME-tools-5.509/testmsgs/multi-igor2.msg0000644000076400007640000002451412541013575016307 0ustar dfsdfsDate: Thu, 6 Jun 1996 15:50:39 +0400 (MOW DST) From: Starovoitov Igor To: eryq@rhine.gsfc.nasa.gov Subject: Need help MIME-Version: 1.0 Content-Type: MULTIPART/MIXED; BOUNDARY="-490585488-806670346-834061839=:2195" This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. Send mail to mime@docserver.cac.washington.edu for more info. ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII Dear Sir, I have a problem with Your MIME-Parser-1.9 and multipart-nested messages. Not all parts are parsed. Here my Makefile, Your own multipart-nested.msg and its out after "make test". Some my messages not completely parsed too. Is this a bug? Thank You for help. Igor Starovoytov. ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII; name=Makefile Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: Makefile Iy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLQ0KIyBNYWtlZmlsZSBmb3IgTUlNRTo6DQojLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tDQoNCiMgV2hlcmUgdG8gaW5zdGFsbCB0aGUgbGlicmFy aWVzOg0KU0lURV9QRVJMID0gL3Vzci9saWIvcGVybDUNCg0KIyBXaGF0IFBl cmw1IGlzIGNhbGxlZCBvbiB5b3VyIHN5c3RlbSAobm8gbmVlZCB0byBnaXZl IGVudGlyZSBwYXRoKToNClBFUkw1ICAgICA9IHBlcmwNCg0KIyBZb3UgcHJv YmFibHkgd29uJ3QgbmVlZCB0byBjaGFuZ2UgdGhlc2UuLi4NCk1PRFMgICAg ICA9IERlY29kZXIucG0gRW50aXR5LnBtIEhlYWQucG0gUGFyc2VyLnBtIEJh c2U2NC5wbSBRdW90ZWRQcmludC5wbQ0KU0hFTEwgICAgID0gL2Jpbi9zaA0K DQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tDQojIEZvciBpbnN0YWxsZXJzLi4uDQojLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tDQoNCmhlbHA6CQ0KCUBlY2hvICJWYWxpZCB0YXJnZXRz OiB0ZXN0IGNsZWFuIGluc3RhbGwiDQoNCmNsZWFuOg0KCXJtIC1mIHRlc3Rv dXQvKg0KDQp0ZXN0Og0KIwlAZWNobyAiVEVTVElORyBIZWFkLnBtLi4uIg0K Iwkke1BFUkw1fSBNSU1FL0hlYWQucG0gICA8IHRlc3Rpbi9maXJzdC5oZHIg ICAgICAgPiB0ZXN0b3V0L0hlYWQub3V0DQojCUBlY2hvICJURVNUSU5HIERl Y29kZXIucG0uLi4iDQojCSR7UEVSTDV9IE1JTUUvRGVjb2Rlci5wbSA8IHRl c3Rpbi9xdW90LXByaW50LmJvZHkgPiB0ZXN0b3V0L0RlY29kZXIub3V0DQoj CUBlY2hvICJURVNUSU5HIFBhcnNlci5wbSAoc2ltcGxlKS4uLiINCiMJJHtQ RVJMNX0gTUlNRS9QYXJzZXIucG0gPCB0ZXN0aW4vc2ltcGxlLm1zZyAgICAg ID4gdGVzdG91dC9QYXJzZXIucy5vdXQNCiMJQGVjaG8gIlRFU1RJTkcgUGFy c2VyLnBtIChtdWx0aXBhcnQpLi4uIg0KIwkke1BFUkw1fSBNSU1FL1BhcnNl ci5wbSA8IHRlc3Rpbi9tdWx0aS0yZ2lmcy5tc2cgPiB0ZXN0b3V0L1BhcnNl ci5tLm91dA0KCUBlY2hvICJURVNUSU5HIFBhcnNlci5wbSAobXVsdGlfbmVz dGVkLm1zZykuLi4iDQoJJHtQRVJMNX0gTUlNRS9QYXJzZXIucG0gPCB0ZXN0 aW4vbXVsdGktbmVzdGVkLm1zZyA+IHRlc3RvdXQvUGFyc2VyLm4ub3V0DQoJ QGVjaG8gIkFsbCB0ZXN0cyBwYXNzZWQuLi4gc2VlIC4vdGVzdG91dC9NT0RV TEUqLm91dCBmb3Igb3V0cHV0Ig0KDQppbnN0YWxsOg0KCUBpZiBbICEgLWQg JHtTSVRFX1BFUkx9IF07IHRoZW4gXA0KCSAgICBlY2hvICJQbGVhc2UgZWRp dCB0aGUgU0lURV9QRVJMIGluIHlvdXIgTWFrZWZpbGUiOyBleGl0IC0xOyBc DQogICAgICAgIGZpICAgICAgICAgIA0KCUBpZiBbICEgLXcgJHtTSVRFX1BF Ukx9IF07IHRoZW4gXA0KCSAgICBlY2hvICJObyBwZXJtaXNzaW9uLi4uIHNo b3VsZCB5b3UgYmUgcm9vdD8iOyBleGl0IC0xOyBcDQogICAgICAgIGZpICAg ICAgICAgIA0KCUBpZiBbICEgLWQgJHtTSVRFX1BFUkx9L01JTUUgXTsgdGhl biBcDQoJICAgIG1rZGlyICR7U0lURV9QRVJMfS9NSU1FOyBcDQogICAgICAg IGZpDQoJaW5zdGFsbCAtbSAwNjQ0IE1JTUUvKi5wbSAke1NJVEVfUEVSTH0v TUlNRQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgRm9yIGRldmVsb3BlciBv bmx5Li4uDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNClBPRDJIVE1MX0ZMQUdTID0g LS1wb2RwYXRoPS4gLS1mbHVzaCAtLWh0bWxyb290PS4uDQpIVE1MUyAgICAg ICAgICA9ICR7TU9EUzoucG09Lmh0bWx9DQpWUEFUSCAgICAgICAgICA9IE1J TUUNCg0KLlNVRkZJWEVTOiAucG0gLnBvZCAuaHRtbA0KDQojIHYuMS44IGdl bmVyYXRlZCAzMCBBcHIgOTYNCiMgdi4xLjkgaXMgb25seSBiZWNhdXNlIDEu OCBmYWlsZWQgQ1BBTiBpbmdlc3Rpb24NCmRpc3Q6IGRvY3VtZW50ZWQJDQoJ VkVSU0lPTj0xLjkgOyBcDQoJbWtkaXN0IC10Z3ogTUlNRS1wYXJzZXItJCRW RVJTSU9OIDsgXA0KCWNwIE1LRElTVC9NSU1FLXBhcnNlci0kJFZFUlNJT04u dGd6ICR7SE9NRX0vcHVibGljX2h0bWwvY3Bhbg0KCQ0KZG9jdW1lbnRlZDog JHtIVE1MU30gJHtNT0RTfQ0KDQoucG0uaHRtbDoNCglwb2QyaHRtbCAke1BP RDJIVE1MX0ZMQUdTfSBcDQoJCS0tdGl0bGU9TUlNRTo6JCogXA0KCQktLWlu ZmlsZT0kPCBcDQoJCS0tb3V0ZmlsZT1kb2NzLyQqLmh0bWwNCg0KIy0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLQ0K ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="multi-nested.msg" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: test message TUlNRS1WZXJzaW9uOiAxLjANCkZyb206IExvcmQgSm9obiBXaG9yZmluIDx3 aG9yZmluQHlveW9keW5lLmNvbT4NClRvOiA8am9obi15YXlhQHlveW9keW5l LmNvbT4NClN1YmplY3Q6IEEgY29tcGxleCBuZXN0ZWQgbXVsdGlwYXJ0IGV4 YW1wbGUNCkNvbnRlbnQtVHlwZTogbXVsdGlwYXJ0L21peGVkOw0KICAgICBi b3VuZGFyeT11bmlxdWUtYm91bmRhcnktMQ0KDQpUaGUgcHJlYW1ibGUgb2Yg dGhlIG91dGVyIG11bHRpcGFydCBtZXNzYWdlLg0KTWFpbCByZWFkZXJzIHRo YXQgdW5kZXJzdGFuZCBtdWx0aXBhcnQgZm9ybWF0DQpzaG91bGQgaWdub3Jl IHRoaXMgcHJlYW1ibGUuDQpJZiB5b3UgYXJlIHJlYWRpbmcgdGhpcyB0ZXh0 LCB5b3UgbWlnaHQgd2FudCB0bw0KY29uc2lkZXIgY2hhbmdpbmcgdG8gYSBt YWlsIHJlYWRlciB0aGF0IHVuZGVyc3RhbmRzDQpob3cgdG8gcHJvcGVybHkg ZGlzcGxheSBtdWx0aXBhcnQgbWVzc2FnZXMuDQotLXVuaXF1ZS1ib3VuZGFy eS0xDQoNClBhcnQgMSBvZiB0aGUgb3V0ZXIgbWVzc2FnZS4NCltOb3RlIHRo YXQgdGhlIHByZWNlZGluZyBibGFuayBsaW5lIG1lYW5zDQpubyBoZWFkZXIg ZmllbGRzIHdlcmUgZ2l2ZW4gYW5kIHRoaXMgaXMgdGV4dCwNCndpdGggY2hh cnNldCBVUyBBU0NJSS4gIEl0IGNvdWxkIGhhdmUgYmVlbg0KZG9uZSB3aXRo IGV4cGxpY2l0IHR5cGluZyBhcyBpbiB0aGUgbmV4dCBwYXJ0Ll0NCg0KLS11 bmlxdWUtYm91bmRhcnktMQ0KQ29udGVudC10eXBlOiB0ZXh0L3BsYWluOyBj aGFyc2V0PVVTLUFTQ0lJDQoNClBhcnQgMiBvZiB0aGUgb3V0ZXIgbWVzc2Fn ZS4NClRoaXMgY291bGQgaGF2ZSBiZWVuIHBhcnQgb2YgdGhlIHByZXZpb3Vz IHBhcnQsDQpidXQgaWxsdXN0cmF0ZXMgZXhwbGljaXQgdmVyc3VzIGltcGxp Y2l0DQp0eXBpbmcgb2YgYm9keSBwYXJ0cy4NCg0KLS11bmlxdWUtYm91bmRh cnktMQ0KU3ViamVjdDogUGFydCAzIG9mIHRoZSBvdXRlciBtZXNzYWdlIGlz IG11bHRpcGFydCENCkNvbnRlbnQtVHlwZTogbXVsdGlwYXJ0L3BhcmFsbGVs Ow0KICAgICBib3VuZGFyeT11bmlxdWUtYm91bmRhcnktMg0KDQpBIG9uZS1s aW5lIHByZWFtYmxlIGZvciB0aGUgaW5uZXIgbXVsdGlwYXJ0IG1lc3NhZ2Uu DQotLXVuaXF1ZS1ib3VuZGFyeS0yDQpDb250ZW50LVR5cGU6IGltYWdlL2dp Zg0KQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0DQpDb250ZW50 LURpc3Bvc2l0aW9uOiBpbmxpbmU7IGZpbGVuYW1lPSIzZC1jb21wcmVzcy5n aWYiDQpTdWJqZWN0OiBQYXJ0IDEgb2YgdGhlIGlubmVyIG1lc3NhZ2UgaXMg YSBHSUYsICIzZC1jb21wcmVzcy5naWYiDQoNClIwbEdPRGRoS0FBb0FPTUFB QUFBQUFBQWdCNlEveTlQVDI1dWJuQ0FrS0JTTGI2K3Z1Zm41L1hlcy8rbEFQ LzZ6UUFBQUFBQQ0KQUFBQUFBQUFBQ3dBQUFBQUtBQW9BQUFFL2hESlNhdTll SkxNT3lZYmNveGthWjVvQ2tvSDZMNXdMTWZpV3FkNGJ0WmhteGJBDQpvRkNZ NDdFSXFNSmd5V3cyQVRqajdhUmtBcTVZd0RNbDlWR3RLTzBTaXVvaVRWbHNj c3h0OWM0SGdYeFVJQTBFQVZPVmZES1QNCjhIbDFCM2tEQVlZbGUyMDJYbkdH Z29NSGhZY2tpV1Z1UjMrT1RnQ0dlWlJzbG90d2dKMmxuWWlnZlpkVGpRVUxy N0FMQlpOMA0KcVR1cmpIZ0xLQXUwQjVXcW9wbTdKNzJldFFOOHQ4SWp1cnkr d010dnc4L0h2N1lsZnMwQnhDYkdxTW1LMHlPT1EwR1RDZ3JSDQoyYmh3Skds WEpRWUc2bU1Lb2VOb1dTYnpDV0lBQ2U1Snd4UW0zQWtEQWJVQVFDaVFoRFpF QmVCbDZhZmdDc09CckQ0NWVkSXYNClFjZUdXU01ldnBPWWhsNkNreWRCSGhC WlFtR0tqaWhWc2h5cGpCOUNsQUhaTVR1Z3pPVTdtemhCUGlTWjV1RE5uQTdi L2FUWg0KMG1oTW5mbDBwREJGYTZiVUVsU1BXYjBxdFl1SHJ4bHdjUjE3WXNX TXMyalRxbDNMRmtRRUFEcz0NCi0tdW5pcXVlLWJvdW5kYXJ5LTINCkNvbnRl bnQtVHlwZTogaW1hZ2UvZ2lmDQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5n OiBiYXNlNjQNCkNvbnRlbnQtRGlzcG9zaXRpb246IGlubGluZTsgZmlsZW5h bWU9IjNkLWV5ZS5naWYiDQpTdWJqZWN0OiBQYXJ0IDIgb2YgdGhlIGlubmVy IG1lc3NhZ2UgaXMgYW5vdGhlciBHSUYsICIzZC1leWUuZ2lmIg0KDQpSMGxH T0RkaEtBQW9BUE1BQUFBQUFBQUF6TjN1Lzc2K3ZvaUlpRzV1YnN6ZDd2Ly8v K2ZuNXdBQUFBQUFBQUFBQUFBQUFBQUENCkFBQUFBQUFBQUN3QUFBQUFLQUFv QUFBRS9oREpTYXU5ZUpiTU95NGJNb3hrYVo1b0Nrb0Q2TDV3TE1maVduczQx b1p0N2xNNw0KVnVqbkM5NklSVnNQV1FFNG54UGprdm1zUW11OG9jL0tCVVNW V2s3WGVwR0dMZU5yeG94Sk8xTWpJTGp0aGcva1dYUTZ3Ty83DQorM2RDZVJS amZBS0hpSW1KQVYrRENGMEJpVzVWQW8xQ0VsYVJoNU5qbGtlWW1weVRncGNU QUtHaWFhU2Zwd0twVlFheFZhdEwNCnJVOEdhUWRPQkFRQUI3K3lYbGlYVHJn QXhzVzR2RmFidjhCT3RCc0J0N2NHdndDSVQ5bk95TkVJeHVDNHpycUt6YzlY Yk9ESg0KdnM3WTVld0gzZDdGeGUzakI0cmo4dDZQdU5hNnIyYmhLUVhOMTdG WUNCTXFUR2lCelNOaHg1ZzBuRU1obHNTSmppUll2RGp3DQpFMGNkR3hRL2dz d29zb0tVa211VTJGbkpjc1NLR1RCanlweEpzeWFJQ0FBNw0KLS11bmlxdWUt Ym91bmRhcnktMi0tDQoNClRoZSBlcGlsb2d1ZSBmb3IgdGhlIGlubmVyIG11 bHRpcGFydCBtZXNzYWdlLg0KDQotLXVuaXF1ZS1ib3VuZGFyeS0xDQpDb250 ZW50LXR5cGU6IHRleHQvcmljaHRleHQNCg0KVGhpcyBpcyA8Ym9sZD5wYXJ0 IDQgb2YgdGhlIG91dGVyIG1lc3NhZ2U8L2JvbGQ+DQo8c21hbGxlcj5hcyBk ZWZpbmVkIGluIFJGQzEzNDE8L3NtYWxsZXI+PG5sPg0KPG5sPg0KSXNuJ3Qg aXQgPGJpZ2dlcj48YmlnZ2VyPmNvb2w/PC9iaWdnZXI+PC9iaWdnZXI+DQoN Ci0tdW5pcXVlLWJvdW5kYXJ5LTENCkNvbnRlbnQtVHlwZTogbWVzc2FnZS9y ZmM4MjINCg0KRnJvbTogKG1haWxib3ggaW4gVVMtQVNDSUkpDQpUbzogKGFk ZHJlc3MgaW4gVVMtQVNDSUkpDQpTdWJqZWN0OiBQYXJ0IDUgb2YgdGhlIG91 dGVyIG1lc3NhZ2UgaXMgaXRzZWxmIGFuIFJGQzgyMiBtZXNzYWdlIQ0KQ29u dGVudC1UeXBlOiBUZXh0L3BsYWluOyBjaGFyc2V0PUlTTy04ODU5LTENCkNv bnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IFF1b3RlZC1wcmludGFibGUNCg0K UGFydCA1IG9mIHRoZSBvdXRlciBtZXNzYWdlIGlzIGl0c2VsZiBhbiBSRkM4 MjIgbWVzc2FnZSENCg0KLS11bmlxdWUtYm91bmRhcnktMS0tDQoNClRoZSBl cGlsb2d1ZSBmb3IgdGhlIG91dGVyIG1lc3NhZ2UuDQo= ---490585488-806670346-834061839=:2195 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="Parser.n.out" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: out from parser KiBXYWl0aW5nIGZvciBhIE1JTUUgbWVzc2FnZSBmcm9tIFNURElOLi4uDQo9 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT0NCkNvbnRlbnQtdHlwZTogbXVsdGlwYXJ0L21peGVk DQpCb2R5LWZpbGU6IE5PTkUNClN1YmplY3Q6IEEgY29tcGxleCBuZXN0ZWQg bXVsdGlwYXJ0IGV4YW1wbGUNCk51bS1wYXJ0czogMw0KLS0NCiAgICBDb250 ZW50LXR5cGU6IHRleHQvcGxhaW4NCiAgICBCb2R5LWZpbGU6IC4vdGVzdG91 dC9tc2ctMzUzOC0xLmRvYw0KICAgIC0tDQogICAgQ29udGVudC10eXBlOiB0 ZXh0L3BsYWluDQogICAgQm9keS1maWxlOiAuL3Rlc3RvdXQvbXNnLTM1Mzgt Mi5kb2MNCiAgICAtLQ0KICAgIENvbnRlbnQtdHlwZTogbXVsdGlwYXJ0L3Bh cmFsbGVsDQogICAgQm9keS1maWxlOiBOT05FDQogICAgU3ViamVjdDogUGFy dCAzIG9mIHRoZSBvdXRlciBtZXNzYWdlIGlzIG11bHRpcGFydCENCiAgICBO dW0tcGFydHM6IDINCiAgICAtLQ0KICAgICAgICBDb250ZW50LXR5cGU6IGlt YWdlL2dpZg0KICAgICAgICBCb2R5LWZpbGU6IC4vdGVzdG91dC8zZC1jb21w cmVzcy5naWYNCiAgICAgICAgU3ViamVjdDogUGFydCAxIG9mIHRoZSBpbm5l ciBtZXNzYWdlIGlzIGEgR0lGLCAiM2QtY29tcHJlc3MuZ2lmIg0KICAgICAg ICAtLQ0KICAgICAgICBDb250ZW50LXR5cGU6IGltYWdlL2dpZg0KICAgICAg ICBCb2R5LWZpbGU6IC4vdGVzdG91dC8zZC1leWUuZ2lmDQogICAgICAgIFN1 YmplY3Q6IFBhcnQgMiBvZiB0aGUgaW5uZXIgbWVzc2FnZSBpcyBhbm90aGVy IEdJRiwgIjNkLWV5ZS5naWYiDQogICAgICAgIC0tDQo9PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT0NCg0K ---490585488-806670346-834061839=:2195-- MIME-tools-5.509/testmsgs/ak-0696.msg0000644000076400007640000001121212541013575015121 0ustar dfsdfsFrom specht@kulturbox.de Thu Jun 20 08:35:23 1996 Date: Thu, 20 Jun 1996 08:35:17 +0200 From: Juergen Specht Organization: KULTURBOX X-Mailer: Mozilla 2.02 (WinNT; I) MIME-Version: 1.0 To: andreas.koenig@mind.de, kun@pop.combox.de, 101762.2307@compuserve.com Subject: [Fwd: Re: 34Mbit/s Netz] Content-Type: MULTIPART/MIXED; boundary="------------70522FC73543" X-Filter: mailagent [version 3.0 PL44] for k@.in-berlin.de This is a multi-part message in MIME format. --------------70522FC73543 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit -- Juergen Specht - KULTURBOX --------------70522FC73543 Content-Type: message/rfc822 Content-Transfer-Encoding: 7bit Content-Disposition: inline X-POP3-Rcpt: specht@trachea Return-Path: hermes Received: (from hermes@localhost) by kulturbox.netmbx.de (8.7.1/8.7.1) id SAA04513 for specht; Wed, 19 Jun 1996 18:30:12 +0200 Received: by netmbx.netmbx.de (/\==/\ Smail3.1.28.1) from mail.cs.tu-berlin.de with smtp id ; Wed, 19 Jun 96 18:12 MES Received: (from nobody@localhost) by mail.cs.tu-berlin.de (8.6.12/8.6.12) id SAA12413; Wed, 19 Jun 1996 18:26:28 +0200 Resent-Date: Wed, 19 Jun 1996 18:26:28 +0200 Resent-Message-Id: <199606191626.SAA12413@mail.cs.tu-berlin.de> Resent-From: nobody@cs.tu-berlin.de Resent-To: kultur@kulturbox.netmbx.de Received: from gatekeeper.telekom.de ([194.25.15.11]) by mail.cs.tu-berlin.de (8.6.12/8.6.12) with SMTP id SAA11678 for ; Wed, 19 Jun 1996 18:11:29 +0200 Received: from ULM02.mnh.telekom.de by gatekeeper.telekom.de; (5.65v3.0/1.1.8.2/02Aug95-0132PM) id AA01376; Wed, 19 Jun 1996 18:11:27 +0200 Received: from ulm02.mnh.telekom.de (deuschle@mnh.telekom.de) by ULM02.mnh.telekom.de (8.6.10/3) with SMTP id SAA30680 for ; Wed, 19 Jun 1996 18:14:40 GMT Message-Id: <199606191814.SAA30680@ULM02.mnh.telekom.de> X-Sender: deuschle@ulm02.mnh.telekom.de X-Mailer: Windows Eudora Version 1.4.4 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Date: Wed, 19 Jun 1996 18:12:02 +0200 To: Juergen Specht From: deuschle@mnh.telekom.de (Guenter Deuschle) Subject: Re: 34Mbit/s Netz X-Mozilla-Status: 0011 Hallo Herr Specht, entschuldigen Sie vorab, dass ich Ihnen nicht telefonisch zur Verfuegung stehe, ich Praesentationen gehalten/ noch zu halten und viele Kundennachfragen zu projektieren. Nach Informationen des Produkt-Managers Temme steht der POP schon zur Verf=FCgung! Standort: voraussichtlich: Winterfeldstr. 21, 10781 Berlin. Der POP hat zur Zeit direkte 34M-Anbindungen zu folgenden Orten: Rostock, Hamburg, Hannover & Leipzig. 4 weitere werden in kuerze in Betrieb gehen. Damit haben Sie einen Besonderen Sicherheitsstandard verfuegbar! Kontakt muessen Sie ueber Ihre oerltliche Vertriebseinheit aufnehmen: entweder den Geschaefts-Kunden-Vertrieb oder das GrossKundenManagement. Diese Vertriebseinheiten greifen auf den oertlichen Technischen Vertriebs-Support zu. Die Informationen werden ueber TVS zur Vertriebseiheit gegeben und dann zu Ihnen. Sie benoetigen eine Standleitung von Ihrer Lokation zum Internet-POP Uebergabepunkt zu Ihrem Info-Server ist ein CISCO 1000-Router. Dann zahlen Sie neben den monatlichen Kosten fuer die Standleitung die Kosten fuer den Internet-Zugang: zB bei 64k: 1500DM bei 2GByte Freivolumen. 128K: 3000 DM bei 5 GB Freivolumen & 2M: 30.000 DM bei 50GB Freivolumen. Freundliche Gruesse=20 Guenter Deuschle >Sehr geehrter Herr Deuschle, >Sie sind mir von Herrn Meyendriesch empfohlen worden. >Ich versuche Informationen ueber das T-eigene 34Mbit/s Netz und den=20 >lokalen Pop-Berlin rauszufinden, bzw. was ein Anschluss kostet und=20 >wo man ihn herbekommt. Laut Herrn Schnick in Berlin gibt es den=20 >T-Pop nicht, laut Traceroute von Herrn Meyendriesch sehrwohl. Auch=20 >ist dies Netz in der IX vom Mai 96 erwaehnt. >Koennen Sie mir helfen? > >MfG >--=20 >Juergen Specht - KULTURBOX > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D Dipl.-Ing. Guenter D E U S C H L E Deutsche Telekom AG Niederlassung 3 Hannover GrossKundenManagement - Techn. Vertriebs-Support: Team-Leiter Internet Online-Dienste --------------------------------------------------- GrKM-TVS-IOD Tel: +49-511-333-2772 Vahrenwalder-Str. 245 FAX: +49-511-333-2751 30179 Hannover eMail: deuschle@mnh.telekom.de=20 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D --------------70522FC73543-- MIME-tools-5.509/MYMETA.json0000644000076400007640000000306313071220710013425 0ustar dfsdfs{ "abstract" : "Tools to manipulate MIME messages", "author" : [ "Eryq , Dianne Skoll , Dave O'Neill " ], "dynamic_config" : 0, "generated_by" : "Module::Install version 1.14, CPAN::Meta::Converter version 2.142690", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "MIME-tools", "no_index" : { "directory" : [ "examples", "inc", "t" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "6.59", "Test::Deep" : "0", "Test::More" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "recommends" : { "Convert::BinHex" : "0", "MIME::Base64" : "3.03" }, "requires" : { "File::Path" : "1", "File::Spec" : "0.6", "File::Temp" : "0.18", "IO::File" : "1.13", "IO::Handle" : "0", "MIME::Base64" : "2.2", "Mail::Field" : "1.05", "Mail::Header" : "1.01", "Mail::Internet" : "1.0203", "perl" : "5.008" } } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ] }, "version" : "5.508", "x_module_name" : "MIME::Tools" } MIME-tools-5.509/lib/0000755000076400007640000000000013071231525012310 5ustar dfsdfsMIME-tools-5.509/lib/MIME/0000755000076400007640000000000013071231525013037 5ustar dfsdfsMIME-tools-5.509/lib/MIME/Body.pm0000644000076400007640000003742613071220635014306 0ustar dfsdfspackage MIME::Body; =head1 NAME MIME::Body - the body of a MIME message =head1 SYNOPSIS Before reading further, you should see L to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait. Ready? Ok... =head2 Obtaining bodies ### Get the bodyhandle of a MIME::Entity object: $body = $entity->bodyhandle; ### Create a body which stores data in a disk file: $body = new MIME::Body::File "/path/to/file"; ### Create a body which stores data in an in-core array: $body = new MIME::Body::InCore \@strings; =head2 Opening, closing, and using IO handles ### Write data to the body: $IO = $body->open("w") || die "open body: $!"; $IO->print($message); $IO->close || die "close I/O handle: $!"; ### Read data from the body (in this case, line by line): $IO = $body->open("r") || die "open body: $!"; while (defined($_ = $IO->getline)) { ### do stuff } $IO->close || die "close I/O handle: $!"; =head2 Other I/O ### Dump the ENCODED body data to a filehandle: $body->print(\*STDOUT); ### Slurp all the UNENCODED data in, and put it in a scalar: $string = $body->as_string; ### Slurp all the UNENCODED data in, and put it in an array of lines: @lines = $body->as_lines; =head2 Working directly with paths to underlying files ### Where's the data? if (defined($body->path)) { ### data is on disk: print "data is stored externally, in ", $body->path; } else { ### data is in core: print "data is already in core, and is...\n", $body->as_string; } ### Get rid of anything on disk: $body->purge; =head1 DESCRIPTION MIME messages can be very long (e.g., tar files, MPEGs, etc.) or very short (short textual notes, as in ordinary mail). Long messages are best stored in files, while short ones are perhaps best stored in core. This class is an attempt to define a common interface for objects which contain message data, regardless of how the data is physically stored. The lifespan of a "body" object usually looks like this: =over 4 =item 1. B It's at this point that the actual MIME::Body subclass is chosen, and new() is invoked. (For example: if the body data is going to a file, then it is at this point that the class MIME::Body::File, and the filename, is chosen). =item 2. B (usually by the MIME parser) like this: The body is opened for writing, via C. This will trash any previous contents, and return an "I/O handle" opened for writing. Data is written to this I/O handle, via print(). Then the I/O handle is closed, via close(). =item 3. B (usually by the user application) like this: The body is opened for reading by a user application, via C. This will return an "I/O handle" opened for reading. Data is read from the I/O handle, via read(), getline(), or getlines(). Then the I/O handle is closed, via close(). =item 4. B =back You can write your own subclasses, as long as they follow the interface described below. Implementers of subclasses should assume that steps 2 and 3 may be repeated any number of times, and in different orders (e.g., 1-2-2-3-2-3-3-3-3-3-2-4). In any case, once a MIME::Body has been created, you ask to open it for reading or writing, which gets you an "i/o handle": you then use the same mechanisms for reading from or writing to that handle, no matter what class it is. Beware: unless you know for certain what kind of body you have, you should I assume that the body has an underlying filehandle. =head1 PUBLIC INTERFACE =over 4 =cut ### Pragmas: use strict; use vars qw($VERSION); ### System modules: use Carp; use IO::File; ### The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; #------------------------------ =item new ARGS... I Create a new body. Any ARGS are sent to init(). =cut sub new { my $self = bless {}, shift; $self->init(@_); $self; } #------------------------------ =item init ARGS... I This is called automatically by C, with the arguments given to C. The arguments are optional, and entirely up to the subclass. The default method does nothing, =cut sub init { 1 } #------------------------------ =item as_lines I Return the contents of the body as an array of lines (each terminated by a newline, with the possible exception of the final one). Returns empty on failure (NB: indistinguishable from an empty body!). Note: the default method gets the data via repeated getline() calls; your subclass might wish to override this. =cut sub as_lines { my $self = shift; my @lines; my $io = $self->open("r") || return (); local $_; push @lines, $_ while (defined($_ = $io->getline())); $io->close; @lines; } #------------------------------ =item as_string I Return the body data as a string (slurping it into core if necessary). Best not to do this unless you're I that the body is reasonably small! Returns empty string for an empty body, and undef on failure. Note: the default method uses print(), which gets the data via repeated read() calls; your subclass might wish to override this. =cut sub as_string { my $self = shift; my $str = ''; my $fh = IO::File->new(\$str, '>:') or croak("Cannot open in-memory file: $!"); $self->print($fh); close($fh); return $str; } *data = \&as_string; ### silently invoke preferred usage #------------------------------ =item binmode [ONOFF] I With argument, flags whether or not open() should return an I/O handle which has binmode() activated. With no argument, just returns the current value. =cut sub binmode { my ($self, $onoff) = @_; $self->{MB_Binmode} = $onoff if (@_ > 1); $self->{MB_Binmode}; } #------------------------------ =item is_encoded [ONOFF] I If set to yes, no decoding is applied on output. This flag is set by MIME::Parser, if the parser runs in decode_bodies(0) mode, so the content is handled unmodified. =cut sub is_encoded { my ($self, $yesno) = @_; $self->{MB_IsEncoded} = $yesno if (@_ > 1); $self->{MB_IsEncoded}; } #------------------------------ =item dup I Duplicate the bodyhandle. I external data in bodyhandles is I copied to new files! Changing the data in one body's data file, or purging that body, I affect its duplicate. Bodies with in-core data probably need not worry. =cut sub dup { my $self = shift; bless { %$self }, ref($self); ### shallow copy ok for ::File and ::Scalar } #------------------------------ =item open READWRITE I This should do whatever is necessary to open the body for either writing (if READWRITE is "w") or reading (if mode is "r"). This method is expected to return an "I/O handle" object on success, and undef on error. An I/O handle can be any object that supports a small set of standard methods for reading/writing data. See the IO::Handle class for an example. =cut sub open { undef; } #------------------------------ =item path [PATH] I If you're storing the body data externally (e.g., in a disk file), you'll want to give applications the ability to get at that data, for cleanup. This method should return the path to the data, or undef if there is none. Where appropriate, the path I be a simple string, like a filename. With argument, sets the PATH, which should be undef if there is none. =cut sub path { my $self = shift; $self->{MB_Path} = shift if @_; $self->{MB_Path}; } #------------------------------ =item print FILEHANDLE I Output the body data to the given filehandle, or to the currently-selected one if none is given. =cut sub print { my ($self, $fh) = @_; my $nread; ### Get output filehandle, and ensure that it's a printable object: $fh ||= select; ### Write it: my $buf = ''; my $io = $self->open("r") || return undef; $fh->print($buf) while ($nread = $io->read($buf, 8192)); $io->close; return defined($nread); ### how'd we do? } #------------------------------ =item purge I Remove any data which resides external to the program (e.g., in disk files). Immediately after a purge(), the path() should return undef to indicate that the external data is no longer available. =cut sub purge { 1; } =back =head1 SUBCLASSES The following built-in classes are provided: Body Stores body When open()ed, class: data in: returns: -------------------------------------------------------- MIME::Body::File disk file IO::Handle MIME::Body::Scalar scalar IO::Handle MIME::Body::InCore scalar array IO::Handle =cut #------------------------------------------------------------ package MIME::Body::File; #------------------------------------------------------------ =head2 MIME::Body::File A body class that stores the data in a disk file. Invoke the constructor as: $body = new MIME::Body::File "/path/to/file"; In this case, the C method would return the given path, so you I say: if (defined($body->path)) { open BODY, $body->path or die "open: $!"; while () { ### do stuff } close BODY; } But you're best off not doing this. =cut ### Pragmas: use vars qw(@ISA); use strict; ### System modules: use IO::File; ### Kit modules: use MIME::Tools qw(whine); @ISA = qw(MIME::Body); #------------------------------ # init PATH #------------------------------ sub init { my ($self, $path) = @_; $self->path($path); ### use it as-is $self; } #------------------------------ # open READWRITE #------------------------------ sub open { my ($self, $mode) = @_; my $path = $self->path; if( $mode ne 'r' && $mode ne 'w' ) { die "bad mode: '$mode'"; } my $IO = IO::File->new($path, $mode) || die "MIME::Body::File->open $path: $!"; $IO->binmode() if $self->binmode; return $IO; } #------------------------------ # purge #------------------------------ # Unlink the path (and undefine it). # sub purge { my $self = shift; if (defined($self->path)) { unlink $self->path or whine "couldn't unlink ".$self->path.": $!"; $self->path(undef); } 1; } #------------------------------------------------------------ package MIME::Body::Scalar; #------------------------------------------------------------ =head2 MIME::Body::Scalar A body class that stores the data in-core, in a simple scalar. Invoke the constructor as: $body = new MIME::Body::Scalar \$string; A single scalar argument sets the body to that value, exactly as though you'd opened for the body for writing, written the value, and closed the body again: $body = new MIME::Body::Scalar "Line 1\nLine 2\nLine 3"; A single array reference sets the body to the result of joining all the elements of that array together: $body = new MIME::Body::Scalar ["Line 1\n", "Line 2\n", "Line 3"]; =cut use vars qw(@ISA); use strict; use Carp; @ISA = qw(MIME::Body); #------------------------------ # init DATA #------------------------------ sub init { my ($self, $data) = @_; $data = join('', @$data) if (ref($data) && (ref($data) eq 'ARRAY')); $self->{MBS_Data} = (defined($data) ? $data : ''); $self; } #------------------------------ # as_string #------------------------------ sub as_string { shift->{MBS_Data}; } #------------------------------ # open READWRITE #------------------------------ sub open { my ($self, $mode) = @_; $self->{MBS_Data} = '' if ($mode eq 'w'); ### writing if ($mode eq 'w') { $mode = '>:'; } elsif ($mode eq 'r') { $mode = '<:'; } else { die "bad mode: $mode"; } return IO::File->new(\ $self->{MBS_Data}, $mode); } #------------------------------------------------------------ package MIME::Body::InCore; #------------------------------------------------------------ =head2 MIME::Body::InCore A body class that stores the data in-core. Invoke the constructor as: $body = new MIME::Body::InCore \$string; $body = new MIME::Body::InCore $string; $body = new MIME::Body::InCore \@stringarray A simple scalar argument sets the body to that value, exactly as though you'd opened for the body for writing, written the value, and closed the body again: $body = new MIME::Body::InCore "Line 1\nLine 2\nLine 3"; A single array reference sets the body to the concatenation of all scalars that it holds: $body = new MIME::Body::InCore ["Line 1\n", "Line 2\n", "Line 3"]; =cut use vars qw(@ISA); use strict; use Carp; @ISA = qw(MIME::Body::Scalar); #------------------------------ # init DATA #------------------------------ sub init { my ($self, $data) = @_; if (!defined($data)) { ### nothing $self->{MBS_Data} = ''; } elsif (!ref($data)) { ### simple scalar $self->{MBS_Data} = $data; } elsif (ref($data) eq 'SCALAR') { $self->{MBS_Data} = $$data; } elsif (ref($data) eq 'ARRAY') { $self->{MBS_Data} = join('', @$data); } else { croak "I can't handle DATA which is a ".ref($data)."\n"; } $self; } 1; __END__ #------------------------------ =head2 Defining your own subclasses So you're not happy with files and scalar-arrays? No problem: just define your own MIME::Body subclass, and make a subclass of MIME::Parser or MIME::ParserBase which returns an instance of your body class whenever appropriate in the C method. Your "body" class must inherit from MIME::Body (or some subclass of it), and it must either provide (or inherit the default for) the following methods... The default inherited method I for all these: new binmode [ONOFF] path The default inherited method I for these, but perhaps there's a better implementation for your subclass. init ARGS... as_lines as_string dup print purge The default inherited method I for these: open =head1 NOTES One reason I didn't just use IO::Handle objects for message bodies was that I wanted a "body" object to be a form of completely encapsulated program-persistent storage; that is, I wanted users to be able to write code like this... ### Get body handle from this MIME message, and read its data: $body = $entity->bodyhandle; $IO = $body->open("r"); while (defined($_ = $IO->getline)) { print STDOUT $_; } $IO->close; ...without requiring that they know anything more about how the $body object is actually storing its data (disk file, scalar variable, array variable, or whatever). Storing the body of each MIME message in a persistently-open IO::Handle was a possibility, but it seemed like a bad idea, considering that a single multipart MIME message could easily suck up all the available file descriptors on some systems. This risk increases if the user application is processing more than one MIME entity at a time. =head1 SEE ALSO L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). David F. Skoll (dfs@roaringpenguin.com) http://www.roaringpenguin.com All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Thanks to Achim Bohnet for suggesting that MIME::Parser not be restricted to the use of FileHandles. #------------------------------ 1; MIME-tools-5.509/lib/MIME/Head.pm0000644000076400007640000006216213071225410014241 0ustar dfsdfspackage MIME::Head; use MIME::WordDecoder; =head1 NAME MIME::Head - MIME message header (a subclass of Mail::Header) =head1 SYNOPSIS Before reading further, you should see L to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait. Ready? Ok... =head2 Construction ### Create a new, empty header, and populate it manually: $head = MIME::Head->new; $head->replace('content-type', 'text/plain; charset=US-ASCII'); $head->replace('content-length', $len); ### Parse a new header from a filehandle: $head = MIME::Head->read(\*STDIN); ### Parse a new header from a file, or a readable pipe: $testhead = MIME::Head->from_file("/tmp/test.hdr"); $a_b_head = MIME::Head->from_file("cat a.hdr b.hdr |"); =head2 Output ### Output to filehandle: $head->print(\*STDOUT); ### Output as string: print STDOUT $head->as_string; print STDOUT $head->stringify; =head2 Getting field contents ### Is this a reply? $is_reply = 1 if ($head->get('Subject') =~ /^Re: /); ### Get receipt information: print "Last received from: ", $head->get('Received', 0); @all_received = $head->get('Received'); ### Print the subject, or the empty string if none: print "Subject: ", $head->get('Subject',0); ### Too many hops? Count 'em and see! if ($head->count('Received') > 5) { ... ### Test whether a given field exists warn "missing subject!" if (! $head->count('subject')); =head2 Setting field contents ### Declare this to be an HTML header: $head->replace('Content-type', 'text/html'); =head2 Manipulating field contents ### Get rid of internal newlines in fields: $head->unfold; ### Decode any Q- or B-encoded-text in fields (DEPRECATED): $head->decode; =head2 Getting high-level MIME information ### Get/set a given MIME attribute: unless ($charset = $head->mime_attr('content-type.charset')) { $head->mime_attr("content-type.charset" => "US-ASCII"); } ### The content type (e.g., "text/html"): $mime_type = $head->mime_type; ### The content transfer encoding (e.g., "quoted-printable"): $mime_encoding = $head->mime_encoding; ### The recommended name when extracted: $file_name = $head->recommended_filename; ### The boundary text, for multipart messages: $boundary = $head->multipart_boundary; =head1 DESCRIPTION A class for parsing in and manipulating RFC-822 message headers, with some methods geared towards standard (and not so standard) MIME fields as specified in the various I RFCs (starting with RFC 2045) =head1 PUBLIC INTERFACE =cut #------------------------------ require 5.002; ### Pragmas: use strict; use vars qw($VERSION @ISA @EXPORT_OK); ### System modules: use IO::File; ### Other modules: use Mail::Header 1.09 (); use Mail::Field 1.05 (); ### Kit modules: use MIME::Words qw(:all); use MIME::Tools qw(:config :msgs); use MIME::Field::ParamVal; use MIME::Field::ConTraEnc; use MIME::Field::ContDisp; use MIME::Field::ContType; @ISA = qw(Mail::Header); #------------------------------ # # Public globals... # #------------------------------ ### The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; ### Sanity (we put this test after our own version, for CPAN::): use Mail::Header 1.06 (); #------------------------------ =head2 Creation, input, and output =over 4 =cut #------------------------------ #------------------------------ =item new [ARG],[OPTIONS] I Creates a new header object. Arguments are the same as those in the superclass. =cut sub new { my $class = shift; bless Mail::Header->new(@_), $class; } #------------------------------ =item from_file EXPR,OPTIONS I. For convenience, you can use this to parse a header object in from EXPR, which may actually be any expression that can be sent to open() so as to return a readable filehandle. The "file" will be opened, read, and then closed: ### Create a new header by parsing in a file: my $head = MIME::Head->from_file("/tmp/test.hdr"); Since this method can function as either a class constructor I an instance initializer, the above is exactly equivalent to: ### Create a new header by parsing in a file: my $head = MIME::Head->new->from_file("/tmp/test.hdr"); On success, the object will be returned; on failure, the undefined value. The OPTIONS are the same as in new(), and are passed into new() if this is invoked as a class method. B This is really just a convenience front-end onto C, provided mostly for backwards-compatibility with MIME-parser 1.0. =cut sub from_file { my ($self, $file, @opts) = @_; ### at this point, $self is inst. or class! my $class = ref($self) ? ref($self) : $self; ### Parse: my $fh = IO::File->new($file, '<') or return error("open $file: $!"); $fh->binmode() or return error("binmode $file: $!"); # we expect to have \r\n at line ends, and want to keep 'em. $self = $class->new($fh, @opts); ### now, $self is instance or undef $fh->close or return error("close $file: $!"); $self; } #------------------------------ =item read FILEHANDLE I This initializes a header object by reading it in from a FILEHANDLE, until the terminating blank line is encountered. A syntax error or end-of-stream will also halt processing. Supply this routine with a reference to a filehandle glob; e.g., C<\*STDIN>: ### Create a new header by parsing in STDIN: $head->read(\*STDIN); On success, the self object will be returned; on failure, a false value. B in the MIME world, it is perfectly legal for a header to be empty, consisting of nothing but the terminating blank line. Thus, we can't just use the formula that "no tags equals error". B as of the time of this writing, Mail::Header::read did not flag either syntax errors or unexpected end-of-file conditions (an EOF before the terminating blank line). MIME::ParserBase takes this into account. =cut sub read { my $self = shift; ### either instance or class! ref($self) or $self = $self->new; ### if used as class method, make new $self->SUPER::read(@_); } #------------------------------ =back =head2 Getting/setting fields The following are methods related to retrieving and modifying the header fields. Some are inherited from Mail::Header, but I've kept the documentation around for convenience. =over 4 =cut #------------------------------ #------------------------------ =item add TAG,TEXT,[INDEX] I Add a new occurrence of the field named TAG, given by TEXT: ### Add the trace information: $head->add('Received', 'from eryq.pr.mcs.net by gonzo.net with smtp'); Normally, the new occurrence will be I to the existing occurrences. However, if the optional INDEX argument is 0, then the new occurrence will be I. If you want to be I about appending, specify an INDEX of -1. B: this method always adds new occurrences; it doesn't overwrite any existing occurrences... so if you just want to I the value of a field (creating it if necessary), then you probably B want to use this method: consider using C instead. =cut ### Inherited. #------------------------------ # # copy # # Instance method, DEPRECATED. # Duplicate the object. # sub copy { usage "deprecated: use dup() instead."; shift->dup(@_); } #------------------------------ =item count TAG I Returns the number of occurrences of a field; in a boolean context, this tells you whether a given field exists: ### Was a "Subject:" field given? $subject_was_given = $head->count('subject'); The TAG is treated in a case-insensitive manner. This method returns some false value if the field doesn't exist, and some true value if it does. =cut ### Inherited. #------------------------------ =item decode [FORCE] I Go through all the header fields, looking for RFC 1522 / RFC 2047 style "Q" (quoted-printable, sort of) or "B" (base64) encoding, and decode them in-place. Fellow Americans, you probably don't know what the hell I'm talking about. Europeans, Russians, et al, you probably do. C<:-)>. B See L for the full reasons. If you absolutely must use it and don't like the warning, then provide a FORCE: "I_NEED_TO_FIX_THIS" Just shut up and do it. Not recommended. Provided only for those who need to keep old scripts functioning. "I_KNOW_WHAT_I_AM_DOING" Just shut up and do it. Not recommended. Provided for those who REALLY know what they are doing. B For an example, let's consider a valid email header you might get: From: =?US-ASCII?Q?Keith_Moore?= To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= CC: =?ISO-8859-1?Q?Andr=E9_?= Pirard Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?= =?US-ASCII?Q?.._cool!?= That basically decodes to (sorry, I can only approximate the Latin characters with 7 bit sequences /o and 'e): From: Keith Moore To: Keld J/orn Simonsen CC: Andr'e Pirard Subject: If you can read this you understand the example... cool! B currently, the decodings are done without regard to the character set: thus, the Q-encoding C<=F8> is simply translated to the octet (hexadecimal C), period. For piece-by-piece decoding of a given field, you want the array context of C. B the CRLF+SPACE separator that splits up long encoded words into shorter sequences (see the Subject: example above) gets lost when the field is unfolded, and so decoding after unfolding causes a spurious space to be left in the field. I This method returns the self object. I =cut sub decode { my $self = shift; ### Warn if necessary: my $force = shift || 0; unless (($force eq "I_NEED_TO_FIX_THIS") || ($force eq "I_KNOW_WHAT_I_AM_DOING")) { usage "decode is deprecated for safety"; } my ($tag, $i, @decoded); foreach $tag ($self->tags) { @decoded = map { scalar(decode_mimewords($_, Field=>$tag)) } $self->get_all($tag); for ($i = 0; $i < @decoded; $i++) { $self->replace($tag, $decoded[$i], $i); } } $self->{MH_Decoded} = 1; $self; } #------------------------------ =item delete TAG,[INDEX] I Delete all occurrences of the field named TAG. ### Remove some MIME information: $head->delete('MIME-Version'); $head->delete('Content-type'); =cut ### Inherited #------------------------------ # # exists # sub exists { usage "deprecated; use count() instead"; shift->count(@_); } #------------------------------ # # fields # sub fields { usage "deprecated: use tags() instead", shift->tags(@_); } #------------------------------ =item get TAG,[INDEX] I Get the contents of field TAG. If a B is given, returns the occurrence at that index, or undef if not present: ### Print the first and last 'Received:' entries (explicitly): print "First, or most recent: ", $head->get('received', 0); print "Last, or least recent: ", $head->get('received',-1); If B is given, but invoked in a B context, then INDEX simply defaults to 0: ### Get the first 'Received:' entry (implicitly): my $most_recent = $head->get('received'); If B is given, and invoked in an B context, then I occurrences of the field are returned: ### Get all 'Received:' entries: my @all_received = $head->get('received'); B: The header(s) returned may end with a newline. If you don't want this, then B the return value. =cut ### Inherited. #------------------------------ =item get_all FIELD I Returns the list of I occurrences of the field, or the empty list if the field is not present: ### How did it get here? @history = $head->get_all('Received'); B I had originally experimented with having C return all occurrences when invoked in an array context... but that causes a lot of accidents when you get careless and do stuff like this: print "\u$field: ", $head->get($field); It also made the intuitive behaviour unclear if the INDEX argument was given in an array context. So I opted for an explicit approach to asking for all occurrences. =cut sub get_all { my ($self, $tag) = @_; $self->count($tag) or return (); ### empty if doesn't exist ($self->get($tag)); } #------------------------------ # # original_text # # Instance method, DEPRECATED. # Return an approximation of the original text. # sub original_text { usage "deprecated: use stringify() instead"; shift->stringify(@_); } #------------------------------ =item print [OUTSTREAM] I Print the header out to the given OUTSTREAM, or the currently-selected filehandle if none. The OUTSTREAM may be a filehandle, or any object that responds to a print() message. The override actually lets you print to any object that responds to a print() method. This is vital for outputting MIME entities to scalars. Also, it defaults to the I filehandle if none is given (not STDOUT!), so I supply a filehandle to prevent confusion. =cut sub print { my ($self, $fh) = @_; $fh ||= select; $fh->print($self->as_string); } #------------------------------ # # set TAG,TEXT # # Instance method, DEPRECATED. # Set the field named TAG to [the single occurrence given by the TEXT. # sub set { my $self = shift; usage "deprecated: use the replace() method instead."; $self->replace(@_); } #------------------------------ =item stringify I Return the header as a string. You can also invoke it as C. If you set the variable $MIME::Entity::BOUNDARY_DELIMITER to a string, that string will be used as line-end delimiter. If it is not set, the line ending will be a newline character (\n) =cut sub stringify { my $self = shift; ### build clean header, and output... my @header = grep {defined($_) ? $_ : ()} @{$self->header}; my $header_delimiter = $MIME::Entity::BOUNDARY_DELIMITER || "\n"; join "", map { /\n$/ ? substr($_, 0, -1) . $header_delimiter : $_ . $header_delimiter } @header; } sub as_string { shift->stringify(@_) } #------------------------------ =item unfold [FIELD] I Unfold (remove newlines in) the text of all occurrences of the given FIELD. If the FIELD is omitted, I fields are unfolded. Returns the "self" object. =cut ### Inherited #------------------------------ =back =head2 MIME-specific methods All of the following methods extract information from the following fields: Content-type Content-transfer-encoding Content-disposition Be aware that they do not just return the raw contents of those fields, and in some cases they will fill in sensible (I hope) default values. Use C or C if you need to grab and process the raw field text. B some of these methods are provided both as a convenience and for backwards-compatibility only, while others (like recommended_filename()) I since they look for their value in more than one field. However, if you know that a value is restricted to a single field, you should really use the Mail::Field interface to get it. =over 4 =cut #------------------------------ #------------------------------ # # params TAG # # Instance method, DEPRECATED. # Extract parameter info from a structured field, and return # it as a hash reference. Provided for 1.0 compatibility only! # Use the new MIME::Field interface classes (subclasses of Mail::Field). sub params { my ($self, $tag) = @_; usage "deprecated: use the MIME::Field interface classes from now on!"; return MIME::Field::ParamVal->parse_params($self->get($tag,0)); } #------------------------------ =item mime_attr ATTR,[VALUE] A quick-and-easy interface to set/get the attributes in structured MIME fields: $head->mime_attr("content-type" => "text/html"); $head->mime_attr("content-type.charset" => "US-ASCII"); $head->mime_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. B will cause the contents of the named subfield to be deleted: $head->mime_attr("content-type.charset" => undef); B just returns the attribute's value, or undefined if it isn't there: $type = $head->mime_attr("content-type"); ### text/html $name = $head->mime_attr("content-type.name"); ### homepage.html In all cases, the new/current value is returned. =cut sub mime_attr { my ($self, $attr, $value) = @_; ### Break attribute name up: my ($tag, $subtag) = split /\./, $attr; $subtag ||= '_'; ### Set or get? my $field = MIME::Field::ParamVal->parse($self->get($tag, 0)); if (@_ > 2) { ### set it: $field->param($subtag, $value); ### set subfield $self->replace($tag, $field->stringify); ### replace! return $value; } else { ### get it: return $field->param($subtag); } } #------------------------------ =item mime_encoding I Try I to determine the content transfer encoding (e.g., C<"base64">, C<"binary">), which is returned in all-lowercase. If no encoding could be found, the default of C<"7bit"> is returned I quote from RFC 2045 section 6.1: This is the default value -- that is, "Content-Transfer-Encoding: 7BIT" is assumed if the Content-Transfer-Encoding header field is not present. I do one other form of fixup: "7_bit", "7-bit", and "7 bit" are corrected to "7bit"; likewise for "8bit". =cut sub mime_encoding { my $self = shift; my $enc = lc($self->mime_attr('content-transfer-encoding') || '7bit'); $enc =~ s{^([78])[ _-]bit\Z}{$1bit}; $enc; } #------------------------------ =item mime_type [DEFAULT] I Try C to determine the content type (e.g., C<"text/plain">, C<"image/gif">, C<"x-weird-type">, which is returned in all-lowercase. "Real hard" means that if no content type could be found, the default (usually C<"text/plain">) is returned. From RFC 2045 section 5.2: Default RFC 822 messages without a MIME Content-Type header are taken by this protocol to be plain text in the US-ASCII character set, which can be explicitly specified as: Content-type: text/plain; charset=us-ascii This default is assumed if no Content-Type header field is specified. Unless this is a part of a "multipart/digest", in which case "message/rfc822" is the default. Note that you can also I the default, but you shouldn't: normally only the MIME parser uses this feature. =cut sub mime_type { my ($self, $default) = @_; $self->{MIH_DefaultType} = $default if @_ > 1; my $s = $self->mime_attr('content-type') || $self->{MIH_DefaultType} || 'text/plain'; # avoid [perl #87336] bug, lc laundering tainted data return lc($s) if $] <= 5.008 || $] >= 5.014; $s =~ tr/A-Z/a-z/; $s; } #------------------------------ =item multipart_boundary I If this is a header for a multipart message, return the "encapsulation boundary" used to separate the parts. The boundary is returned exactly as given in the C field; that is, the leading double-hyphen (C<-->) is I prepended. Well, I exactly... this passage from RFC 2046 dictates that we remove any trailing spaces: If a boundary appears to end with white space, the white space must be presumed to have been added by a gateway, and must be deleted. Returns undef (B the empty string) if either the message is not multipart or if there is no specified boundary. =cut sub multipart_boundary { my $self = shift; my $value = $self->mime_attr('content-type.boundary'); (!defined($value)) ? undef : $value; } #------------------------------ =item recommended_filename I Return the recommended external filename. This is used when extracting the data from the MIME stream. The filename is always returned as a string in Perl's internal format (the UTF8 flag may be on!) Returns undef if no filename could be suggested. =cut sub recommended_filename { my $self = shift; # Try these headers in order, taking the first defined, # non-blank one we find. my $wd = supported MIME::WordDecoder 'UTF-8'; foreach my $attr_name ( qw( content-disposition.filename content-type.name ) ) { my $value = $self->mime_attr( $attr_name ); if ( defined $value && $value ne '' && $value =~ /\S/ ) { return $wd->decode($value); } } return undef; } #------------------------------ =back =cut #------------------------------ # # tweak_FROM_parsing # # DEPRECATED. Use the inherited mail_from() class method now. sub tweak_FROM_parsing { my $self = shift; usage "deprecated. Use mail_from() instead."; $self->mail_from(@_); } __END__ #------------------------------ =head1 NOTES =over 4 =item Why have separate objects for the entity, head, and body? See the documentation for the MIME-tools distribution for the rationale behind this decision. =item Why assume that MIME headers are email headers? I quote from Achim Bohnet, who gave feedback on v.1.9 (I think he's using the word "header" where I would use "field"; e.g., to refer to "Subject:", "Content-type:", etc.): There is also IMHO no requirement [for] MIME::Heads to look like [email] headers; so to speak, the MIME::Head [simply stores] the attributes of a complex object, e.g.: new MIME::Head type => "text/plain", charset => ..., disposition => ..., ... ; I agree in principle, but (alas and dammit) RFC 2045 says otherwise. RFC 2045 [MIME] headers are a syntactic subset of RFC-822 [email] headers. In my mind's eye, I see an abstract class, call it MIME::Attrs, which does what Achim suggests... so you could say: my $attrs = new MIME::Attrs type => "text/plain", charset => ..., disposition => ..., ... ; We could even make it a superclass of MIME::Head: that way, MIME::Head would have to implement its interface, I allow itself to be initialized from a MIME::Attrs object. However, when you read RFC 2045, you begin to see how much MIME information is organized by its presence in particular fields. I imagine that we'd begin to mirror the structure of RFC 2045 fields and subfields to such a degree that this might not give us a tremendous gain over just having MIME::Head. =item Why all this "occurrence" and "index" jazz? Isn't every field unique? Aaaaaaaaaahh....no. Looking at a typical mail message header, it is sooooooo tempting to just store the fields as a hash of strings, one string per hash entry. Unfortunately, there's the little matter of the C field, which (unlike C, C, etc.) will often have multiple occurrences; e.g.: Received: from gsfc.nasa.gov by eryq.pr.mcs.net with smtp (Linux Smail3.1.28.1 #5) id m0tStZ7-0007X4C; Thu, 21 Dec 95 16:34 CST Received: from rhine.gsfc.nasa.gov by gsfc.nasa.gov (5.65/Ultrix3.0-C) id AA13596; Thu, 21 Dec 95 17:20:38 -0500 Received: (from eryq@localhost) by rhine.gsfc.nasa.gov (8.6.12/8.6.12) id RAA28069; Thu, 21 Dec 1995 17:27:54 -0500 Date: Thu, 21 Dec 1995 17:27:54 -0500 From: Eryq Message-Id: <199512212227.RAA28069@rhine.gsfc.nasa.gov> To: eryq@eryq.pr.mcs.net Subject: Stuff and things The C field is used for tracing message routes, and although it's not generally used for anything other than human debugging, I didn't want to inconvenience anyone who actually wanted to get at that information. I also didn't want to make this a special case; after all, who knows what other fields could have multiple occurrences in the future? So, clearly, multiple entries had to somehow be stored multiple times... and the different occurrences had to be retrievable. =back =head1 SEE ALSO L, L, L, L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). Dianne Skoll (dfs@roaringpenguin.com) http://www.roaringpenguin.com All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The more-comprehensive filename extraction is courtesy of Lee E. Brotzman, Advanced Data Solutions. =cut 1; MIME-tools-5.509/lib/MIME/Decoder.pm0000644000076400007640000003766713071220635014765 0ustar dfsdfspackage MIME::Decoder; =head1 NAME MIME::Decoder - an object for decoding the body part of a MIME stream =head1 SYNOPSIS Before reading further, you should see L to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait. Ready? Ok... =head2 Decoding a data stream Here's a simple filter program to read quoted-printable data from STDIN (until EOF) and write the decoded data to STDOUT: use MIME::Decoder; $decoder = new MIME::Decoder 'quoted-printable' or die "unsupported"; $decoder->decode(\*STDIN, \*STDOUT); =head2 Encoding a data stream Here's a simple filter program to read binary data from STDIN (until EOF) and write base64-encoded data to STDOUT: use MIME::Decoder; $decoder = new MIME::Decoder 'base64' or die "unsupported"; $decoder->encode(\*STDIN, \*STDOUT); =head2 Non-standard encodings You can B your own decoders so that MIME::Decoder will know about them: use MyBase64Decoder; install MyBase64Decoder 'base64'; You can also B if a given encoding is supported: if (supported MIME::Decoder 'x-uuencode') { ### we can uuencode! } =head1 DESCRIPTION This abstract class, and its private concrete subclasses (see below) provide an OO front end to the actions of... =over 4 =item * Decoding a MIME-encoded stream =item * Encoding a raw data stream into a MIME-encoded stream. =back The constructor for MIME::Decoder takes the name of an encoding (C, C<7bit>, etc.), and returns an instance of a I of MIME::Decoder whose C method will perform the appropriate decoding action, and whose C method will perform the appropriate encoding action. =cut ### Pragmas: use strict; use vars qw($VERSION %DecoderFor); ### System modules: use IPC::Open2; use IO::Select; use FileHandle; ### Kit modules: use MIME::Tools qw(:config :msgs); use Carp; #------------------------------ # # Globals # #------------------------------ ### The stream decoders: %DecoderFor = ( ### Standard... '7bit' => 'MIME::Decoder::NBit', '8bit' => 'MIME::Decoder::NBit', 'base64' => 'MIME::Decoder::Base64', 'binary' => 'MIME::Decoder::Binary', 'none' => 'MIME::Decoder::Binary', 'quoted-printable' => 'MIME::Decoder::QuotedPrint', ### Non-standard... 'binhex' => 'MIME::Decoder::BinHex', 'binhex40' => 'MIME::Decoder::BinHex', 'mac-binhex40' => 'MIME::Decoder::BinHex', 'mac-binhex' => 'MIME::Decoder::BinHex', 'x-uu' => 'MIME::Decoder::UU', 'x-uuencode' => 'MIME::Decoder::UU', ### This was removed, since I fear that x-gzip != x-gzip64... ### 'x-gzip' => 'MIME::Decoder::Gzip64', ### This is no longer installed by default, since not all folks have gzip: ### 'x-gzip64' => 'MIME::Decoder::Gzip64', ); ### The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; ### Me: my $ME = 'MIME::Decoder'; #------------------------------ =head1 PUBLIC INTERFACE =head2 Standard interface If all you are doing is I this class, here's all you'll need... =over 4 =cut #------------------------------ =item new ENCODING I Create and return a new decoder object which can handle the given ENCODING. my $decoder = new MIME::Decoder "7bit"; Returns the undefined value if no known decoders are appropriate. =cut sub new { my ($class, @args) = @_; my ($encoding) = @args; ### Coerce the type to be legit: $encoding = lc($encoding || ''); ### Get the class: my $concrete_name = $DecoderFor{$encoding}; if( ! $concrete_name ) { carp "no decoder for $encoding"; return undef; } ### Create the new object (if we can): my $self = { MD_Encoding => lc($encoding) }; unless (eval "require $concrete_name;") { carp $@; return undef; } bless $self, $concrete_name; $self->init(@args); } #------------------------------ =item best ENCODING I Exactly like new(), except that this defaults any unsupported encoding to "binary", after raising a suitable warning (it's a fatal error if there's no binary decoder). my $decoder = best MIME::Decoder "x-gzip64"; Will either return a decoder, or a raise a fatal exception. =cut sub best { my ($class, $enc, @args) = @_; my $self = $class->new($enc, @args); if (!$self) { usage "unsupported encoding '$enc': using 'binary'"; $self = $class->new('binary') || croak "ack! no binary decoder!"; } $self; } #------------------------------ =item decode INSTREAM,OUTSTREAM I Decode the document waiting in the input handle INSTREAM, writing the decoded information to the output handle OUTSTREAM. Read the section in this document on I/O handles for more information about the arguments. Note that you can still supply old-style unblessed filehandles for INSTREAM and OUTSTREAM. Returns true on success, throws exception on failure. =cut sub decode { my ($self, $in, $out) = @_; ### Set up the default input record separator to be CRLF: ### $in->input_record_separator("\012\015"); ### Invoke back-end method to do the work: $self->decode_it($in, $out) || die "$ME: ".$self->encoding." decoding failed\n"; 1; } #------------------------------ =item encode INSTREAM,OUTSTREAM I Encode the document waiting in the input filehandle INSTREAM, writing the encoded information to the output stream OUTSTREAM. Read the section in this document on I/O handles for more information about the arguments. Note that you can still supply old-style unblessed filehandles for INSTREAM and OUTSTREAM. Returns true on success, throws exception on failure. =cut sub encode { my ($self, $in, $out, $textual_type) = @_; ### Invoke back-end method to do the work: $self->encode_it($in, $out, $self->encoding eq 'quoted-printable' ? ($textual_type) : ()) || die "$ME: ".$self->encoding." encoding failed\n"; } #------------------------------ =item encoding I Return the encoding that this object was created to handle, coerced to all lowercase (e.g., C<"base64">). =cut sub encoding { shift->{MD_Encoding}; } #------------------------------ =item head [HEAD] I Completely optional: some decoders need to know a little about the file they are encoding/decoding; e.g., x-uu likes to have the filename. The HEAD is any object which responds to messages like: $head->mime_attr('content-disposition.filename'); =cut sub head { my ($self, $head) = @_; $self->{MD_Head} = $head if @_ > 1; $self->{MD_Head}; } #------------------------------ =item supported [ENCODING] I With one arg (an ENCODING name), returns truth if that encoding is currently handled, and falsity otherwise. The ENCODING will be automatically coerced to lowercase: if (supported MIME::Decoder '7BIT') { ### yes, we can handle it... } else { ### drop back six and punt... } With no args, returns a reference to a hash of all available decoders, where the key is the encoding name (all lowercase, like '7bit'), and the value is true (it happens to be the name of the class that handles the decoding, but you probably shouldn't rely on that). You may safely modify this hash; it will I change the way the module performs its lookups. Only C can do that. I =cut sub supported { my ($class, $decoder) = @_; defined($decoder) ? $DecoderFor{lc($decoder)}: { %DecoderFor }; } #------------------------------ =back =head2 Subclass interface If you are writing (or installing) a new decoder subclass, there are some other methods you'll need to know about: =over 4 =item decode_it INSTREAM,OUTSTREAM I The back-end of the B method. It takes an input handle opened for reading (INSTREAM), and an output handle opened for writing (OUTSTREAM). If you are writing your own decoder subclass, you must override this method in your class. Your method should read from the input handle via C or C, decode this input, and print the decoded data to the output handle via C. You may do this however you see fit, so long as the end result is the same. Note that unblessed references and globrefs are automatically turned into I/O handles for you by C, so you don't need to worry about it. Your method must return either C (to indicate failure), or C<1> (to indicate success). It may also throw an exception to indicate failure. =cut sub decode_it { die "attempted to use abstract 'decode_it' method!"; } =item encode_it INSTREAM,OUTSTREAM I The back-end of the B method. It takes an input handle opened for reading (INSTREAM), and an output handle opened for writing (OUTSTREAM). If you are writing your own decoder subclass, you must override this method in your class. Your method should read from the input handle via C or C, encode this input, and print the encoded data to the output handle via C. You may do this however you see fit, so long as the end result is the same. Note that unblessed references and globrefs are automatically turned into I/O handles for you by C, so you don't need to worry about it. Your method must return either C (to indicate failure), or C<1> (to indicate success). It may also throw an exception to indicate failure. =cut sub encode_it { die "attempted to use abstract 'encode_it' method!"; } =item filter IN, OUT, COMMAND... I If your decoder involves an external program, you can invoke them easily through this method. The command must be a "filter": a command that reads input from its STDIN (which will come from the IN argument) and writes output to its STDOUT (which will go to the OUT argument). For example, here's a decoder that un-gzips its data: sub decode_it { my ($self, $in, $out) = @_; $self->filter($in, $out, "gzip -d -"); } The usage is similar to IPC::Open2::open2 (which it uses internally), so you can specify COMMAND as a single argument or as an array. =cut sub filter { my ($self, $in, $out, @cmd) = @_; my $buf = ''; ### Open pipe: STDOUT->flush; ### very important, or else we get duplicate output! my $kidpid = open2(my $child_out, my $child_in, @cmd) || die "@cmd: open2 failed: $!"; ### We have to use select() for doing both reading and writing. my $rsel = IO::Select->new( $child_out ); my $wsel = IO::Select->new( $child_in ); while (1) { ### Wait for one hour; if that fails, it's too bad. my ($read, $write) = IO::Select->select( $rsel, $wsel, undef, 3600); if( !defined $read && !defined $write ) { kill 1, $kidpid; waitpid $kidpid, 0; die "@cmd: select failed: $!"; } ### If can read from child: if( my $fh = shift @$read ) { if( $fh->sysread(my $buf, 1024) ) { $out->print($buf); } else { $rsel->remove($fh); $fh->close(); } } ### If can write to child: if( my $fh = shift @$write ) { if($in->read(my $buf, 1024)) { local $SIG{PIPE} = sub { warn "got SIGPIPE from @cmd"; $wsel->remove($fh); $fh->close(); }; $fh->syswrite( $buf ); } else { $wsel->remove($fh); $fh->close(); } } ### If both $child_out and $child_in are done: last unless ($rsel->count() || $wsel->count()); } ### Wait for it: waitpid($kidpid, 0) == $kidpid or die "@cmd: couldn't reap child $kidpid"; ### Check if it failed: $? == 0 or die "@cmd: bad exit status: \$? = $?"; 1; } #------------------------------ =item init ARGS... I Do any necessary initialization of the new instance, taking whatever arguments were given to C. Should return the self object on success, undef on failure. =cut sub init { $_[0]; } #------------------------------ =item install ENCODINGS... I. Install this class so that each encoding in ENCODINGS is handled by it: install MyBase64Decoder 'base64', 'x-base64super'; You should not override this method. =cut sub install { my $class = shift; $DecoderFor{lc(shift @_)} = $class while (@_); } #------------------------------ =item uninstall ENCODINGS... I. Uninstall support for encodings. This is a way to turn off the decoding of "experimental" encodings. For safety, always use MIME::Decoder directly: uninstall MIME::Decoder 'x-uu', 'x-uuencode'; You should not override this method. =cut sub uninstall { shift; $DecoderFor{lc(shift @_)} = undef while (@_); } 1; __END__ #------------------------------ =back =head1 DECODER SUBCLASSES You don't need to C<"use"> any other Perl modules; the following "standard" subclasses are included as part of MIME::Decoder: Class: Handles encodings: ------------------------------------------------------------ MIME::Decoder::Binary binary MIME::Decoder::NBit 7bit, 8bit MIME::Decoder::Base64 base64 MIME::Decoder::QuotedPrint quoted-printable The following "non-standard" subclasses are also included: Class: Handles encodings: ------------------------------------------------------------ MIME::Decoder::UU x-uu, x-uuencode MIME::Decoder::Gzip64 x-gzip64 ** requires gzip! =head1 NOTES =head2 Input/Output handles As of MIME-tools 2.0, this class has to play nice with the new MIME::Body class... which means that input and output routines cannot just assume that they are dealing with filehandles. Therefore, all that MIME::Decoder and its subclasses require (and, thus, all that they can assume) is that INSTREAMs and OUTSTREAMs are objects which respond to a subset of the messages defined in the IO::Handle interface; minimally: print getline read(BUF,NBYTES) I =head2 Writing a decoder If you're experimenting with your own encodings, you'll probably want to write a decoder. Here are the basics: =over 4 =item 1. Create a module, like "MyDecoder::", for your decoder. Declare it to be a subclass of MIME::Decoder. =item 2. Create the following instance methods in your class, as described above: decode_it encode_it init =item 3. In your application program, activate your decoder for one or more encodings like this: require MyDecoder; install MyDecoder "7bit"; ### use MyDecoder to decode "7bit" install MyDecoder "x-foo"; ### also use MyDecoder to decode "x-foo" =back To illustrate, here's a custom decoder class for the C encoding: package MyQPDecoder; @ISA = qw(MIME::Decoder); use MIME::Decoder; use MIME::QuotedPrint; ### decode_it - the private decoding method sub decode_it { my ($self, $in, $out) = @_; local $_; while (defined($_ = $in->getline)) { my $decoded = decode_qp($_); $out->print($decoded); } 1; } ### encode_it - the private encoding method sub encode_it { my ($self, $in, $out) = @_; my ($buf, $nread) = ('', 0); while ($in->read($buf, 60)) { my $encoded = encode_qp($buf); $out->print($encoded); } 1; } That's it. The task was pretty simple because the C<"quoted-printable"> encoding can easily be converted line-by-line... as can even C<"7bit"> and C<"8bit"> (since all these encodings guarantee short lines, with a max of 1000 characters). The good news is: it is very likely that it will be similarly-easy to write a MIME::Decoder for any future standard encodings. The C<"binary"> decoder, however, really required block reads and writes: see L<"MIME::Decoder::Binary"> for details. =head1 SEE ALSO L, other MIME::Decoder subclasses. =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. 1; MIME-tools-5.509/lib/MIME/Parser.pm0000644000076400007640000015243613071220635014644 0ustar dfsdfspackage MIME::Parser; =head1 NAME MIME::Parser - experimental class for parsing MIME streams =head1 SYNOPSIS Before reading further, you should see L to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait. Ready? Ok... =head2 Basic usage examples ### Create a new parser object: my $parser = new MIME::Parser; ### Tell it where to put things: $parser->output_under("/tmp"); ### Parse an input filehandle: $entity = $parser->parse(\*STDIN); ### Congratulations: you now have a (possibly multipart) MIME entity! $entity->dump_skeleton; # for debugging =head2 Examples of input ### Parse from filehandles: $entity = $parser->parse(\*STDIN); $entity = $parser->parse(IO::File->new("some command|"); ### Parse from any object that supports getline() and read(): $entity = $parser->parse($myHandle); ### Parse an in-core MIME message: $entity = $parser->parse_data($message); ### Parse an MIME message in a file: $entity = $parser->parse_open("/some/file.msg"); ### Parse an MIME message out of a pipeline: $entity = $parser->parse_open("gunzip - < file.msg.gz |"); ### Parse already-split input (as "deliver" would give it to you): $entity = $parser->parse_two("msg.head", "msg.body"); =head2 Examples of output control ### Keep parsed message bodies in core (default outputs to disk): $parser->output_to_core(1); ### Output each message body to a one-per-message directory: $parser->output_under("/tmp"); ### Output each message body to the same directory: $parser->output_dir("/tmp"); ### Change how nameless message-component files are named: $parser->output_prefix("msg"); ### Put temporary files somewhere else $parser->tmp_dir("/var/tmp/mytmpdir"); =head2 Examples of error recovery ### Normal mechanism: eval { $entity = $parser->parse(\*STDIN) }; if ($@) { $results = $parser->results; $decapitated = $parser->last_head; ### get last top-level head } ### Ultra-tolerant mechanism: $parser->ignore_errors(1); $entity = eval { $parser->parse(\*STDIN) }; $error = ($@ || $parser->last_error); ### Cleanup all files created by the parse: eval { $entity = $parser->parse(\*STDIN) }; ... $parser->filer->purge; =head2 Examples of parser options ### Automatically attempt to RFC 2047-decode the MIME headers? $parser->decode_headers(1); ### default is false ### Parse contained "message/rfc822" objects as nested MIME streams? $parser->extract_nested_messages(0); ### default is true ### Look for uuencode in "text" messages, and extract it? $parser->extract_uuencode(1); ### default is false ### Should we forgive normally-fatal errors? $parser->ignore_errors(0); ### default is true =head2 Miscellaneous examples ### Convert a Mail::Internet object to a MIME::Entity: my $data = join('', (@{$mail->header}, "\n", @{$mail->body})); $entity = $parser->parse_data(\$data); =head1 DESCRIPTION You can inherit from this class to create your own subclasses that parse MIME streams into MIME::Entity objects. =head1 PUBLIC INTERFACE =cut #------------------------------ require 5.004; ### Pragmas: use strict; use vars (qw($VERSION $CAT $CRLF)); ### core Perl modules use IO::File; use File::Spec; use File::Path; use Config qw(%Config); use Carp; ### Kit modules: use MIME::Tools qw(:config :utils :msgtypes usage tmpopen ); use MIME::Head; use MIME::Body; use MIME::Entity; use MIME::Decoder; use MIME::Parser::Reader; use MIME::Parser::Filer; use MIME::Parser::Results; #------------------------------ # # Globals # #------------------------------ ### The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; ### How to catenate: $CAT = '/bin/cat'; ### The CRLF sequence: $CRLF = "\015\012"; ### Who am I? my $ME = 'MIME::Parser'; #------------------------------------------------------------ =head2 Construction =over 4 =cut #------------------------------ =item new ARGS... I Create a new parser object. Once you do this, you can then set up various parameters before doing the actual parsing. For example: my $parser = new MIME::Parser; $parser->output_dir("/tmp"); $parser->output_prefix("msg1"); my $entity = $parser->parse(\*STDIN); Any arguments are passed into C. Don't override this in your subclasses; override init() instead. =cut sub new { my $self = bless {}, shift; $self->init(@_); } #------------------------------ =item init ARGS... I Initiallize a new MIME::Parser object. This is automatically sent to a new object; you may want to override it. If you override this, be sure to invoke the inherited method. =cut sub init { my $self = shift; $self->{MP5_DecodeHeaders} = 0; $self->{MP5_DecodeBodies} = 1; $self->{MP5_Interface} = {}; $self->{MP5_ParseNested} = 'NEST'; $self->{MP5_TmpToCore} = 0; $self->{MP5_IgnoreErrors} = 1; $self->{MP5_UUDecode} = 0; $self->{MP5_MaxParts} = -1; $self->{MP5_TmpDir} = undef; $self->interface(ENTITY_CLASS => 'MIME::Entity'); $self->interface(HEAD_CLASS => 'MIME::Head'); $self->output_dir("."); $self; } #------------------------------ =item init_parse I Invoked automatically whenever one of the top-level parse() methods is called, to reset the parser to a "ready" state. =cut sub init_parse { my $self = shift; $self->{MP5_Results} = new MIME::Parser::Results; $self->{MP5_Filer}->results($self->{MP5_Results}); $self->{MP5_Filer}->purgeable([]); $self->{MP5_Filer}->init_parse(); $self->{MP5_NumParts} = 0; 1; } =back =cut #------------------------------------------------------------ =head2 Altering how messages are parsed =over 4 =cut #------------------------------ =item decode_headers [YESNO] I Controls whether the parser will attempt to decode all the MIME headers (as per RFC 2047) the moment it sees them. B =over =item * B If you fully decode the headers into bytes, you can inadvertently transform a parseable MIME header like this: Content-type: text/plain; filename="=?ISO-8859-1?Q?Hi=22Ho?=" into unparseable gobbledygook; in this case: Content-type: text/plain; filename="Hi"Ho" =item * B An encoded string which contains both Latin-1 and Cyrillic characters will be turned into a binary mishmosh which simply can't be rendered. =back B This method was once the only out-of-the-box way to deal with attachments whose filenames had non-ASCII characters. However, since MIME-tools 5.4xx this is no longer necessary. B If YESNO is true, decoding is done. However, you will get a warning unless you use one of the special "true" values: "I_NEED_TO_FIX_THIS" Just shut up and do it. Not recommended. Provided only for those who need to keep old scripts functioning. "I_KNOW_WHAT_I_AM_DOING" Just shut up and do it. Not recommended. Provided for those who REALLY know what they are doing. If YESNO is false (the default), no attempt at decoding will be done. With no argument, just returns the current setting. B you can always decode the headers I the parsing has completed (see L), or decode the words on demand (see L). =cut sub decode_headers { my ($self, $yesno) = @_; if (@_ > 1) { $self->{MP5_DecodeHeaders} = $yesno; if ($yesno) { if (($yesno eq "I_KNOW_WHAT_I_AM_DOING") || ($yesno eq "I_NEED_TO_FIX_THIS")) { ### ok } else { $self->whine("as of 5.4xx, decode_headers() should NOT be ". "set true... if you are doing this to make sure ". "that non-ASCII filenames are translated, ". "that's now done automatically; for all else, ". "use MIME::Words."); } } } $self->{MP5_DecodeHeaders}; } #------------------------------ =item extract_nested_messages OPTION I Some MIME messages will contain a part of type C ,C or C: literally, the text of an embedded mail/news/whatever message. This option controls whether (and how) we parse that embedded message. If the OPTION is false, we treat such a message just as if it were a C document, without attempting to decode its contents. If the OPTION is true (the default), the body of the C or C part is parsed by this parser, creating an entity object. What happens then is determined by the actual OPTION: =over 4 =item NEST or 1 The default setting. The contained message becomes the sole "part" of the C entity (as if the containing message were a special kind of "multipart" message). You can recover the sub-entity by invoking the L method on the C entity. =item REPLACE The contained message replaces the C entity, as though the C "container" never existed. B notice that, with this option, all the header information in the C header is lost. This might seriously bother you if you're dealing with a top-level message, and you've just lost the sender's address and the subject line. C<:-/>. =back I =cut sub extract_nested_messages { my ($self, $option) = @_; $self->{MP5_ParseNested} = $option if (@_ > 1); $self->{MP5_ParseNested}; } sub parse_nested_messages { usage "parse_nested_messages() is now extract_nested_messages()"; shift->extract_nested_messages(@_); } #------------------------------ =item extract_uuencode [YESNO] I If set true, then whenever we are confronted with a message whose effective content-type is "text/plain" and whose encoding is 7bit/8bit/binary, we scan the encoded body to see if it contains uuencoded data (generally given away by a "begin XXX" line). If it does, we explode the uuencoded message into a multipart, where the text before the first "begin XXX" becomes the first part, and all "begin...end" sections following become the subsequent parts. The filename (if given) is accessible through the normal means. =cut sub extract_uuencode { my ($self, $yesno) = @_; $self->{MP5_UUDecode} = $yesno if @_ > 1; $self->{MP5_UUDecode}; } #------------------------------ =item ignore_errors [YESNO] I Controls whether the parser will attempt to ignore normally-fatal errors, treating them as warnings and continuing with the parse. If YESNO is true (the default), many syntax errors are tolerated. If YESNO is false, fatal errors throw exceptions. With no argument, just returns the current setting. =cut sub ignore_errors { my ($self, $yesno) = @_; $self->{MP5_IgnoreErrors} = $yesno if (@_ > 1); $self->{MP5_IgnoreErrors}; } #------------------------------ =item decode_bodies [YESNO] I Controls whether the parser should decode entity bodies or not. If this is set to a false value (default is true), all entity bodies will be kept as-is in the original content-transfer encoding. To prevent double encoding on the output side MIME::Body->is_encoded is set, which tells MIME::Body not to encode the data again, if encoded data was requested. This is in particular useful, when it's important that the content B be modified, e.g. if you want to calculate OpenPGP signatures from it. B: the semantics change significantly if you parse MIME messages with this option set, because MIME::Entity resp. MIME::Body *always* see encoded data now, while the default behaviour is working with *decoded* data (and encoding it only if you request it). You need to decode the data yourself, if you want to have it decoded. So use this option only if you exactly know, what you're doing, and that you're sure, that you really need it. =cut sub decode_bodies { my ($self, $yesno) = @_; $self->{MP5_DecodeBodies} = $yesno if (@_ > 1); $self->{MP5_DecodeBodies}; } #------------------------------ # # MESSAGES... # #------------------------------ # # debug MESSAGE... # sub debug { my $self = shift; if (MIME::Tools->debugging()) { if (my $r = $self->{MP5_Results}) { unshift @_, $r->indent; $r->msg($M_DEBUG, @_); } MIME::Tools::debug(@_); } } #------------------------------ # # whine PROBLEM... # sub whine { my $self = shift; if (my $r = $self->{MP5_Results}) { unshift @_, $r->indent; $r->msg($M_WARNING, @_); } &MIME::Tools::whine(@_); } #------------------------------ # # error PROBLEM... # # Possibly-forgivable parse error occurred. # Raises a fatal exception unless we are ignoring errors. # sub error { my $self = shift; if (my $r = $self->{MP5_Results}) { unshift @_, $r->indent; $r->msg($M_ERROR, @_); } &MIME::Tools::error(@_); $self->{MP5_IgnoreErrors} ? return undef : die @_; } #------------------------------ # # PARSING... # #------------------------------ # # process_preamble IN, READER, ENTITY # # I # Dispose of a multipart message's preamble. # sub process_preamble { my ($self, $in, $rdr, $ent) = @_; ### Sanity: ($rdr->depth > 0) or die "$ME: internal logic error"; ### Parse preamble: my @saved; my $data = ''; open(my $fh, '>', \$data) or die $!; $rdr->read_chunk($in, $fh, 1); close $fh; # Ugh. Horrible. If the preamble consists only of CRLF, squash it down # to the empty string. Else, remove the trailing CRLF. if( $data =~ m/^[\r\n]\z/ ) { @saved = (''); } else { $data =~ s/[\r\n]\z//; @saved = split(/^/, $data); } $ent->preamble(\@saved); 1; } #------------------------------ # # process_epilogue IN, READER, ENTITY # # I # Dispose of a multipart message's epilogue. # sub process_epilogue { my ($self, $in, $rdr, $ent) = @_; $self->debug("process_epilogue"); ### Parse epilogue: my @saved; $rdr->read_lines($in, \@saved); $ent->epilogue(\@saved); 1; } #------------------------------ # # process_to_bound IN, READER, OUT # # I # Dispose of the next chunk into the given output stream OUT. # sub process_to_bound { my ($self, $in, $rdr, $out) = @_; ### Parse: $rdr->read_chunk($in, $out); 1; } #------------------------------ # # process_header IN, READER # # I # Process and return the next header. # Return undef if, instead of a header, the encapsulation boundary is found. # Fatal exception on failure. # sub process_header { my ($self, $in, $rdr) = @_; $self->debug("process_header"); ### Parse and save the (possibly empty) header, up to and including the ### blank line that terminates it: my $head = $self->interface('HEAD_CLASS')->new; ### Read the lines of the header. ### We localize IO inside here, so that we can support the IO:: interface my @headlines; my $hdr_rdr = $rdr->spawn; $hdr_rdr->add_terminator(""); $hdr_rdr->add_terminator("\r"); ### sigh my $headstr = ''; open(my $outfh, '>:scalar', \$headstr) or die $!; $hdr_rdr->read_chunk($in, $outfh, 0, 1); close $outfh; ### How did we do? if ($hdr_rdr->eos_type eq 'DELIM') { $self->whine("bogus part, without CRLF before body"); return undef; } ($hdr_rdr->eos_type eq 'DONE') or $self->error("unexpected end of header\n"); ### Extract the header (note that zero-size headers are admissible!): open(my $readfh, '<:scalar', \$headstr) or die $!; $head->read( $readfh ); unless( $readfh->eof() ) { # Not entirely correct, since ->read consumes the line it gives up on. # it's actually the line /before/ the one we get with ->getline $self->error("couldn't parse head; error near:\n", $readfh->getline()); } ### If desired, auto-decode the header as per RFC 2047 ### This shouldn't affect non-encoded headers; however, it will decode ### headers with international characters. WARNING: currently, the ### character-set information is LOST after decoding. $head->decode($self->{MP5_DecodeHeaders}) if $self->{MP5_DecodeHeaders}; ### If this is the top-level head, save it: $self->results->top_head($head) if !$self->results->top_head; return $head; } #------------------------------ # # process_multipart IN, READER, ENTITY # # I # Process the multipart body, and return the state. # Fatal exception on failure. # Invoked by process_part(). # sub process_multipart { my ($self, $in, $rdr, $ent) = @_; my $head = $ent->head; $self->debug("process_multipart..."); ### Get actual type and subtype from the header: my ($type, $subtype) = (split('/', $head->mime_type, -1), ''); ### If this was a type "multipart/digest", then the RFCs say we ### should default the parts to have type "message/rfc822". ### Thanks to Carsten Heyl for suggesting this... my $retype = (($subtype eq 'digest') ? 'message/rfc822' : ''); ### Get the boundaries for the parts: my $bound = $head->multipart_boundary; if (!defined($bound) || ($bound =~ /[\r\n]/)) { $self->error("multipart boundary is missing, or contains CR or LF\n"); $ent->effective_type("application/x-unparseable-multipart"); return $self->process_singlepart($in, $rdr, $ent); } my $part_rdr = $rdr->spawn->add_boundary($bound); ### Prepare to parse: my $eos_type; my $more_parts; ### Parse preamble... $self->process_preamble($in, $part_rdr, $ent); ### ...and look at how we finished up: $eos_type = $part_rdr->eos_type; if ($eos_type eq 'DELIM'){ $more_parts = 1 } elsif ($eos_type eq 'CLOSE'){ $self->whine("empty multipart message\n"); $more_parts = 0; } else { $self->error("unexpected end of preamble\n"); return 1; } ### Parse parts: my $partno = 0; my $part; while ($more_parts) { ++$partno; $self->debug("parsing part $partno..."); ### Parse the next part, and add it to the entity... my $part = $self->process_part($in, $part_rdr, Retype=>$retype); return undef unless defined($part); $ent->add_part($part); ### ...and look at how we finished up: $eos_type = $part_rdr->eos_type; if ($eos_type eq 'DELIM') { $more_parts = 1 } elsif ($eos_type eq 'CLOSE') { $more_parts = 0; } else { $self->error("unexpected end of parts ". "before epilogue\n"); return 1; } } ### Parse epilogue... ### (note that we use the *parent's* reader here, which does not ### know about the boundaries in this multipart!) $self->process_epilogue($in, $rdr, $ent); ### ...and there's no need to look at how we finished up! 1; } #------------------------------ # # process_singlepart IN, READER, ENTITY # # I # Process the singlepart body. Returns true. # Fatal exception on failure. # Invoked by process_part(). # sub process_singlepart { my ($self, $in, $rdr, $ent) = @_; my $head = $ent->head; $self->debug("process_singlepart..."); ### Obtain a filehandle for reading the encoded information: ### We have two different approaches, based on whether or not we ### have to contend with boundaries. my $ENCODED; ### handle my $can_shortcut = (!$rdr->has_bounds and !$self->{MP5_UUDecode}); if ($can_shortcut) { $self->debug("taking shortcut"); $ENCODED = $in; $rdr->eos('EOF'); ### be sure to bogus-up the reader state to EOF: } else { $self->debug("using temp file"); $ENCODED = $self->new_tmpfile(); ### Read encoded body until boundary (or EOF)... $self->process_to_bound($in, $rdr, $ENCODED); ### ...and look at how we finished up. ### If we have bounds, we want DELIM or CLOSE. ### Otherwise, we want EOF (and that's all we'd get, anyway!). if ($rdr->has_bounds) { ($rdr->eos_type =~ /^(DELIM|CLOSE)$/) or $self->error("part did not end with expected boundary\n"); } ### Flush and rewind encoded buffer, so we can read it: $ENCODED->flush or die "$ME: can't flush: $!"; $ENCODED->seek(0, 0) or die "$ME: can't seek: $!"; } ### Get a content-decoder to decode this part's encoding: my $encoding = $head->mime_encoding; my $decoder = new MIME::Decoder $encoding; if (!$decoder) { $self->whine("Unsupported encoding '$encoding': using 'binary'... \n". "The entity will have an effective MIME type of \n". "application/octet-stream."); ### as per RFC-2045 $ent->effective_type('application/octet-stream'); $decoder = new MIME::Decoder 'binary'; $encoding = 'binary'; } ### Data should be stored encoded / as-is? if ( !$self->decode_bodies ) { $decoder = new MIME::Decoder 'binary'; $encoding = 'binary'; } ### If desired, sidetrack to troll for UUENCODE: $self->debug("extract uuencode? ", $self->extract_uuencode); $self->debug("encoding? ", $encoding); $self->debug("effective type? ", $ent->effective_type); if ($self->extract_uuencode and ($encoding =~ /^(7bit|8bit|binary)\Z/) and ($ent->effective_type =~ m{^(?:text/plain|application/mac-binhex40|application/mac-binhex)\Z})) { ### Hunt for it: my $uu_ent = eval { $self->hunt_for_uuencode($ENCODED, $ent) }; if ($uu_ent) { ### snark %$ent = %$uu_ent; return 1; } else { ### boojum $self->whine("while hunting for uuencode: $@"); $ENCODED->seek(0,0) or die "$ME: can't seek: $!"; } } ### Open a new bodyhandle for outputting the data: my $body = $self->new_body_for($head) or die "$ME: no body"; # gotta die $body->binmode(1) or die "$ME: can't set to binmode: $!" unless textual_type($ent->effective_type) or !$self->decode_bodies; $body->is_encoded(1) if !$self->decode_bodies; ### Decode and save the body (using the decoder): my $DECODED = $body->open("w") or die "$ME: body not opened: $!"; eval { $decoder->decode($ENCODED, $DECODED); }; $@ and $self->error($@); $DECODED->close or die "$ME: can't close: $!"; ### Success! Remember where we put stuff: $ent->bodyhandle($body); ### Done! 1; } #------------------------------ # # hunt_for_uuencode ENCODED, ENTITY # # I # Try to detect and dispatch embedded uuencode as a fake multipart message. # Returns new entity or undef. # sub hunt_for_uuencode { my ($self, $ENCODED, $ent) = @_; my ($good, $how_encoded); local $_; $self->debug("sniffing around for UUENCODE"); ### Heuristic: $ENCODED->seek(0,0) or die "$ME: can't seek: $!"; while (defined($_ = $ENCODED->getline)) { if ($good = /^begin [0-7]{3}/) { $how_encoded = 'uu'; last; } if ($good = /^\(This file must be converted with/i) { $how_encoded = 'binhex'; last; } } $good or do { $self->debug("no one made the cut"); return 0 }; # If a decoder doesn't exist for this type, forget it! my $decoder = MIME::Decoder->new(($how_encoded eq 'uu')?'x-uuencode' :'binhex'); unless (defined($decoder)) { $self->debug("No decoder for $how_encoded attachments"); return 0; } ### New entity: my $top_ent = $ent->dup; ### no data yet $top_ent->make_multipart; my @parts; ### Made the first cut; on to the real stuff: $ENCODED->seek(0,0) or die "$ME: can't seek: $!"; $self->whine("Found a $how_encoded attachment"); my $pre; while (1) { my $bin_data = ''; ### Try next part: my $out = IO::File->new(\$bin_data, '>:'); eval { $decoder->decode($ENCODED, $out) }; last if $@; my $preamble = $decoder->last_preamble; my $filename = $decoder->last_filename; my $mode = $decoder->last_mode; ### Get probable type: my $type = 'application/octet-stream'; my ($ext) = $filename =~ /\.(\w+)\Z/; $ext = lc($ext || ''); if ($ext =~ /^(gif|jpe?g|xbm|xpm|png)\Z/) { $type = "image/$1" } ### If we got our first preamble, create the text portion: if (@$preamble and (grep /\S/, @$preamble) and !@parts) { my $txt_ent = $self->interface('ENTITY_CLASS')->new; MIME::Entity->build(Type => "text/plain", Data => ""); $txt_ent->bodyhandle($self->new_body_for($txt_ent->head)); my $io = $txt_ent->bodyhandle->open("w") or die "$ME: can't create: $!"; $io->print(@$preamble) or die "$ME: can't print: $!"; $io->close or die "$ME: can't close: $!"; push @parts, $txt_ent; } ### Create the attachment: ### We use the x-unix-mode convention from "dtmail 1.2.1 SunOS 5.6". if (1) { my $bin_ent = MIME::Entity->build(Type=>$type, Filename=>$filename, Data=>""); $bin_ent->head->mime_attr('Content-type.x-unix-mode' => "0$mode"); $bin_ent->bodyhandle($self->new_body_for($bin_ent->head)); $bin_ent->bodyhandle->binmode(1) or die "$ME: can't set to binmode: $!"; my $io = $bin_ent->bodyhandle->open("w") or die "$ME: can't create: $!"; $io->print($bin_data) or die "$ME: can't print: $!"; $io->close or die "$ME: can't close: $!"; push @parts, $bin_ent; } } ### Did we get anything? @parts or return undef; ### Set the parts and a nice preamble: $top_ent->parts(\@parts); $top_ent->preamble (["The following is a multipart MIME message which was extracted\n", "from a $how_encoded-encoded message.\n"]); $top_ent; } #------------------------------ # # process_message IN, READER, ENTITY # # I # Process the singlepart body, and return true. # Fatal exception on failure. # Invoked by process_part(). # sub process_message { my ($self, $in, $rdr, $ent) = @_; my $head = $ent->head; $self->debug("process_message"); ### Verify the encoding restrictions: my $encoding = $head->mime_encoding; if ($encoding !~ /^(7bit|8bit|binary)$/) { $self->error("illegal encoding [$encoding] for MIME type ". $head->mime_type."\n"); $encoding = 'binary'; } ### Parse the message: my $msg = $self->process_part($in, $rdr); return undef unless defined($msg); ### How to handle nested messages? if ($self->extract_nested_messages eq 'REPLACE') { %$ent = %$msg; ### shallow replace %$msg = (); } else { ### "NEST" or generic 1: $ent->bodyhandle(undef); $ent->add_part($msg); } 1; } #------------------------------ # # process_part IN, READER, [OPTSHASH...] # # I # The real back-end engine. # See the documentation up top for the overview of the algorithm. # The OPTSHASH can contain: # # Retype => retype this part to the given content-type # # Return the entity. # Fatal exception on failure. Returns undef if message to complex # sub process_part { my ($self, $in, $rdr, %p) = @_; if ($self->{MP5_MaxParts} > 0) { $self->{MP5_NumParts}++; if ($self->{MP5_NumParts} > $self->{MP5_MaxParts}) { # Return UNDEF if msg too complex return undef; } } $rdr ||= MIME::Parser::Reader->new; #debug "process_part"; $self->results->level(+1); ### Create a new entity: my $ent = $self->interface('ENTITY_CLASS')->new; ### Parse and add the header: my $head = $self->process_header($in, $rdr); if (not defined $head) { $self->debug("bogus empty part"); $head = $self->interface('HEAD_CLASS')->new; $head->mime_type('text/plain'); $ent->head($head); $ent->bodyhandle($self->new_body_for($head)); $ent->bodyhandle->open("w")->close or die "$ME: can't close: $!"; $self->results->level(-1); return $ent; } $ent->head($head); ### Tweak the content-type based on context from our parent... ### For example, multipart/digest messages default to type message/rfc822: $head->mime_type($p{Retype}) if $p{Retype}; ### Get the MIME type and subtype: my ($type, $subtype) = (split('/', $head->mime_type, -1), ''); $self->debug("type = $type, subtype = $subtype"); ### Handle, according to the MIME type: if ($type eq 'multipart') { return undef unless defined($self->process_multipart($in, $rdr, $ent)); } elsif (("$type/$subtype" eq "message/rfc822" || "$type/$subtype" eq "message/external-body" || ("$type/$subtype" eq "message/partial" && defined($head->mime_attr("content-type.number")) && $head->mime_attr("content-type.number") == 1)) && $self->extract_nested_messages) { $self->debug("attempting to process a nested message"); return undef unless defined($self->process_message($in, $rdr, $ent)); } else { $self->process_singlepart($in, $rdr, $ent); } ### Done (we hope!): $self->results->level(-1); return $ent; } =back =head2 Parsing an input source =over 4 =cut #------------------------------ =item parse_data DATA I Parse a MIME message that's already in core. This internally creates an "in memory" filehandle on a Perl scalar value using PerlIO You may supply the DATA in any of a number of ways... =over 4 =item * B which holds the message. A reference to this scalar will be used internally. =item * B which holds the message. This reference will be used internally. =item * B B The array is internally concatenated into a temporary string, and a reference to the new string is used internally. It is much more efficient to pass in a scalar reference, so please consider refactoring your code to use that interface instead. If you absolutely MUST pass an array, you may be better off using IO::ScalarArray in the calling code to generate a filehandle, and passing that filehandle to I =back Returns the parsed MIME::Entity on success. =cut sub parse_data { my ($self, $data) = @_; if (!defined($data)) { croak "parse_data: No data passed"; } ### Get data as a scalar: my $io; if (! ref $data ) { $io = IO::File->new(\$data, '<:'); } elsif( ref $data eq 'SCALAR' ) { $io = IO::File->new($data, '<:'); } elsif( ref $data eq 'ARRAY' ) { # Passing arrays is deprecated now that we've nuked IO::ScalarArray # but for backwards compatibility we still support it by joining the # array lines to a scalar and doing scalar IO on it. my $tmp_data = join('', @$data); $io = IO::File->new(\$tmp_data, '<:'); } else { croak "parse_data: wrong argument ref type: ", ref($data); } if (!$io) { croak "parse_data: unable to open in-memory file handle"; } ### Parse! return $self->parse($io); } #------------------------------ =item parse INSTREAM I Takes a MIME-stream and splits it into its component entities. The INSTREAM can be given as an IO::File, a globref filehandle (like C<\*STDIN>), or as I blessed object conforming to the IO:: interface (which minimally implements getline() and read()). Returns the parsed MIME::Entity on success. Throws exception on failure. If the message contained too many parts (as set by I), returns undef. =cut sub parse { my $self = shift; my $in = shift; my $entity; local $/ = "\n"; ### just to be safe local $\ = undef; # CPAN ticket #71041 $self->init_parse; $entity = $self->process_part($in, undef); ### parse! $entity; } ### Backcompat: sub read { shift->parse(@_); } sub parse_FH { shift->parse(@_); } #------------------------------ =item parse_open EXPR I Convenience front-end onto C. Simply give this method any expression that may be sent as the second argument to open() to open a filehandle for reading. Returns the parsed MIME::Entity on success. Throws exception on failure. =cut sub parse_open { my ($self, $expr) = @_; my $ent; my $io = IO::File->new($expr) or die "$ME: couldn't open $expr: $!"; $ent = $self->parse($io); $io->close or die "$ME: can't close: $!"; $ent; } ### Backcompat: sub parse_in { usage "parse_in() is now parse_open()"; shift->parse_open(@_); } #------------------------------ =item parse_two HEADFILE, BODYFILE I Convenience front-end onto C, intended for programs running under mail-handlers like B, which splits the incoming mail message into a header file and a body file. Simply give this method the paths to the respective files. B it is assumed that, once the files are cat'ed together, there will be a blank line separating the head part and the body part. B new implementation slurps files into line array for portability, instead of using 'cat'. May be an issue if your messages are large. Returns the parsed MIME::Entity on success. Throws exception on failure. =cut sub parse_two { my ($self, $headfile, $bodyfile) = @_; my $data; foreach ($headfile, $bodyfile) { open IN, "<$_" or die "$ME: open $_: $!"; $data .= do { local $/; }; close IN or die "$ME: can't close: $!"; } return $self->parse_data($data); } =back =cut #------------------------------------------------------------ =head2 Specifying output destination B in 5.212 and before, this was done by methods of MIME::Parser. However, since many users have requested fine-tuned control over how this is done, the logic has been split off from the parser into its own class, MIME::Parser::Filer Every MIME::Parser maintains an instance of a MIME::Parser::Filer subclass to manage disk output (see L for details.) The benefit to this is that the MIME::Parser code won't be confounded with a lot of garbage related to disk output. The drawback is that the way you override the default behavior will change. For now, all the normal public-interface methods are still provided, but many are only stubs which create or delegate to the underlying MIME::Parser::Filer object. =over 4 =cut #------------------------------ =item filer [FILER] I Get/set the FILER object used to manage the output of files to disk. This will be some subclass of L. =cut sub filer { my ($self, $filer) = @_; if (@_ > 1) { $self->{MP5_Filer} = $filer; $filer->results($self->results); ### but we still need in init_parse } $self->{MP5_Filer}; } #------------------------------ =item output_dir DIRECTORY I Causes messages to be filed directly into the given DIRECTORY. It does this by setting the underlying L to a new instance of MIME::Parser::FileInto, and passing the arguments into that class' new() method. B Since this method replaces the underlying filer, you must invoke it I doing changing any attributes of the filer, like the output prefix; otherwise those changes will be lost. =cut sub output_dir { my ($self, @init) = @_; if (@_ > 1) { $self->filer(MIME::Parser::FileInto->new(@init)); } else { &MIME::Tools::whine("0-arg form of output_dir is deprecated."); return $self->filer->output_dir; } } #------------------------------ =item output_under BASEDIR, OPTS... I Causes messages to be filed directly into subdirectories of the given BASEDIR, one subdirectory per message. It does this by setting the underlying L to a new instance of MIME::Parser::FileUnder, and passing the arguments into that class' new() method. B Since this method replaces the underlying filer, you must invoke it I doing changing any attributes of the filer, like the output prefix; otherwise those changes will be lost. =cut sub output_under { my ($self, @init) = @_; if (@_ > 1) { $self->filer(MIME::Parser::FileUnder->new(@init)); } else { &MIME::Tools::whine("0-arg form of output_under is deprecated."); return $self->filer->output_dir; } } #------------------------------ =item output_path HEAD I Given a MIME head for a file to be extracted, come up with a good output pathname for the extracted file. Identical to the preferred form: $parser->filer->output_path(...args...); We just delegate this to the underlying L object. =cut sub output_path { my $self = shift; ### We use it, so don't warn! ### &MIME::Tools::whine("output_path deprecated in MIME::Parser"); $self->filer->output_path(@_); } #------------------------------ =item output_prefix [PREFIX] I Get/set the short string that all filenames for extracted body-parts will begin with (assuming that there is no better "recommended filename"). Identical to the preferred form: $parser->filer->output_prefix(...args...); We just delegate this to the underlying L object. =cut sub output_prefix { my $self = shift; &MIME::Tools::whine("output_prefix deprecated in MIME::Parser"); $self->filer->output_prefix(@_); } #------------------------------ =item evil_filename NAME I Identical to the preferred form: $parser->filer->evil_filename(...args...); We just delegate this to the underlying L object. =cut sub evil_filename { my $self = shift; &MIME::Tools::whine("evil_filename deprecated in MIME::Parser"); $self->filer->evil_filename(@_); } #------------------------------ =item max_parts NUM I Limits the number of MIME parts we will parse. Normally, instances of this class parse a message to the bitter end. Messages with many MIME parts can cause excessive memory consumption. If you invoke this method, parsing will abort with a die() if a message contains more than NUM parts. If NUM is set to -1 (the default), then no maximum limit is enforced. With no argument, returns the current setting as an integer =cut sub max_parts { my($self, $num) = @_; if (@_ > 1) { $self->{MP5_MaxParts} = $num; } return $self->{MP5_MaxParts}; } #------------------------------ =item output_to_core YESNO I Normally, instances of this class output all their decoded body data to disk files (via MIME::Body::File). However, you can change this behaviour by invoking this method before parsing: If YESNO is false (the default), then all body data goes to disk files. If YESNO is true, then all body data goes to in-core data structures This is a little risky (what if someone emails you an MPEG or a tar file, hmmm?) but people seem to want this bit of noose-shaped rope, so I'm providing it. Note that setting this attribute true I mean that parser-internal temporary files are avoided! Use L for that. With no argument, returns the current setting as a boolean. =cut sub output_to_core { my ($self, $yesno) = @_; if (@_ > 1) { $yesno = 0 if ($yesno and $yesno eq 'NONE'); $self->{MP5_FilerToCore} = $yesno; } $self->{MP5_FilerToCore}; } =item tmp_recycling I This method is a no-op to preserve the pre-5.421 API. The tmp_recycling() feature was removed in 5.421 because it had never actually worked. Please update your code to stop using it. =cut sub tmp_recycling { return; } #------------------------------ =item tmp_to_core [YESNO] I Should L create real temp files, or use fake in-core ones? Normally we allow the creation of temporary disk files, since this allows us to handle huge attachments even when core is limited. If YESNO is true, we implement new_tmpfile() via in-core handles. If YESNO is false (the default), we use real tmpfiles. With no argument, just returns the current setting. =cut sub tmp_to_core { my ($self, $yesno) = @_; $self->{MP5_TmpToCore} = $yesno if (@_ > 1); $self->{MP5_TmpToCore}; } #------------------------------ =item use_inner_files [YESNO] I. I MIME::Parser no longer supports IO::InnerFile, but this method is retained for backwards compatibility. It does nothing. The original reasoning for IO::InnerFile was that inner files were faster than "in-core" temp files. At the time, the "in-core" tempfile support was implemented with IO::Scalar from the IO-Stringy distribution, which used the tie() interface to wrap a scalar with the appropriate IO::Handle operations. The penalty for this was fairly hefty, and IO::InnerFile actually was faster. Nowadays, MIME::Parser uses Perl's built in ability to open a filehandle on an in-memory scalar variable via PerlIO. Benchmarking shows that IO::InnerFile is slightly slower than using in-memory temporary files, and is slightly faster than on-disk temporary files. Both measurements are within a few percent of each other. Since there's no real benefit, and since the IO::InnerFile abuse was fairly hairy and evil ("writes" to it were faked by extending the size of the inner file with the assumption that the only data you'd ever ->print() to it would be the line from the "outer" file, for example) it's been removed. =cut sub use_inner_files { return 0; } =back =cut #------------------------------------------------------------ =head2 Specifying classes to be instantiated =over 4 =cut #------------------------------ =item interface ROLE,[VALUE] I During parsing, the parser normally creates instances of certain classes, like MIME::Entity. However, you may want to create a parser subclass that uses your own experimental head, entity, etc. classes (for example, your "head" class may provide some additional MIME-field-oriented methods). If so, then this is the method that your subclass should invoke during init. Use it like this: package MyParser; @ISA = qw(MIME::Parser); ... sub init { my $self = shift; $self->SUPER::init(@_); ### do my parent's init $self->interface(ENTITY_CLASS => 'MIME::MyEntity'); $self->interface(HEAD_CLASS => 'MIME::MyHead'); $self; ### return } With no VALUE, returns the VALUE currently associated with that ROLE. =cut sub interface { my ($self, $role, $value) = @_; $self->{MP5_Interface}{$role} = $value if (defined($value)); $self->{MP5_Interface}{$role}; } #------------------------------ =item new_body_for HEAD I Based on the HEAD of a part we are parsing, return a new body object (any desirable subclass of MIME::Body) for receiving that part's data. If you set the C option to false before parsing (the default), then we call C and create a new MIME::Body::File on that filename. If you set the C option to true before parsing, then you get a MIME::Body::InCore instead. If you want the parser to do something else entirely, you can override this method in a subclass. =cut sub new_body_for { my ($self, $head) = @_; if ($self->output_to_core) { $self->debug("outputting body to core"); return (new MIME::Body::InCore); } else { my $outpath = $self->output_path($head); $self->debug("outputting body to disk file: $outpath"); $self->filer->purgeable($outpath); ### we plan to use it return (new MIME::Body::File $outpath); } } #------------------------------ =pod =back =head2 Temporary File Creation =over =item tmp_dir DIRECTORY I Causes any temporary files created by this parser to be created in the given DIRECTORY. If called without arguments, returns current value. The default value is undef, which will cause new_tmpfile() to use the system default temporary directory. =cut sub tmp_dir { my ($self, $dirname) = @_; if ( $dirname ) { $self->{MP5_TmpDir} = $dirname; } return $self->{MP5_TmpDir}; } =item new_tmpfile I Return an IO handle to be used to hold temporary data during a parse. The default uses MIME::Tools::tmpopen() to create a new temporary file, unless L dictates otherwise, but you can override this. You shouldn't need to. The location for temporary files can be changed on a per-parser basis with L. If you do override this, make certain that the object you return is set for binmode(), and is able to handle the following methods: read(BUF, NBYTES) getline() getlines() print(@ARGS) flush() seek(0, 0) Fatal exception if the stream could not be established. =cut sub new_tmpfile { my ($self) = @_; my $io; if ($self->{MP5_TmpToCore}) { my $var; $io = IO::File->new(\$var, '+>:') or die "$ME: Can't open in-core tmpfile: $!"; } else { my $args = {}; if( $self->tmp_dir ) { $args->{DIR} = $self->tmp_dir; } $io = tmpopen( $args ) or die "$ME: can't open tmpfile: $!\n"; binmode($io) or die "$ME: can't set to binmode: $!"; } return $io; } =back =cut #------------------------------------------------------------ =head2 Parse results and error recovery =over 4 =cut #------------------------------ =item last_error I Return the error (if any) that we ignored in the last parse. =cut sub last_error { join '', shift->results->errors; } #------------------------------ =item last_head I Return the top-level MIME header of the last stream we attempted to parse. This is useful for replying to people who sent us bad MIME messages. ### Parse an input stream: eval { $entity = $parser->parse(\*STDIN) }; if (!$entity) { ### parse failed! my $decapitated = $parser->last_head; ... } =cut sub last_head { shift->results->top_head; } #------------------------------ =item results I Return an object containing lots of info from the last entity parsed. This will be an instance of class L. =cut sub results { shift->{MP5_Results}; } =back =cut #------------------------------ 1; __END__ =head1 OPTIMIZING YOUR PARSER =head2 Maximizing speed Optimum input mechanisms: parse() YES (if you give it a globref or a subclass of IO::File) parse_open() YES parse_data() NO (see below) parse_two() NO (see below) Optimum settings: decode_headers() *** (no real difference; 0 is slightly faster) extract_nested_messages() 0 (may be slightly faster, but in general you want it set to 1) output_to_core() 0 (will be MUCH faster) tmp_to_core() 0 (will be MUCH faster) B It's much faster to use E$fooE than $foo-Egetline. For backwards compatibility, this module must continue to use object-oriented I/O in most places, but if you use L with a "real" filehandle (string, globref, or subclass of IO::File) then MIME::Parser is able to perform some crucial optimizations. B Currently this is just a front-end onto parse_data(). If your OS supports it, you're I better off doing something like: $parser->parse_open("/bin/cat msg.head msg.body |"); =head2 Minimizing memory Optimum input mechanisms: parse() YES parse_open() YES parse_data() NO (in-core I/O will burn core) parse_two() NO (in-core I/O will burn core) Optimum settings: decode_headers() *** (no real difference) extract_nested_messages() *** (no real difference) output_to_core() 0 (will use MUCH less memory) tmp_to_core is 1) tmp_to_core() 0 (will use MUCH less memory) =head2 Maximizing tolerance of bad MIME Optimum input mechanisms: parse() *** (doesn't matter) parse_open() *** (doesn't matter) parse_data() *** (doesn't matter) parse_two() *** (doesn't matter) Optimum settings: decode_headers() 0 (sidesteps problem of bad hdr encodings) extract_nested_messages() 0 (sidesteps problems of bad nested messages, but often you want it set to 1 anyway). output_to_core() *** (doesn't matter) tmp_to_core() *** (doesn't matter) =head2 Avoiding disk-based temporary files Optimum input mechanisms: parse() YES (if you give it a seekable handle) parse_open() YES (becomes a seekable handle) parse_data() NO (unless you set tmp_to_core(1)) parse_two() NO (unless you set tmp_to_core(1)) Optimum settings: decode_headers() *** (doesn't matter) extract_nested_messages() *** (doesn't matter) output_to_core() *** (doesn't matter) tmp_to_core() 1 B You can set L true: this will always use in-core I/O for the buffering (B this will slow down the parsing of messages with large attachments). B You can always override L in a subclass. =head1 WARNINGS =over 4 =item Multipart messages are always read line-by-line Multipart document parts are read line-by-line, so that the encapsulation boundaries may easily be detected. However, bad MIME composition agents (for example, naive CGI scripts) might return multipart documents where the parts are, say, unencoded bitmap files... and, consequently, where such "lines" might be veeeeeeeeery long indeed. A better solution for this case would be to set up some form of state machine for input processing. This will be left for future versions. =item Multipart parts read into temp files before decoding In my original implementation, the MIME::Decoder classes had to be aware of encapsulation boundaries in multipart MIME documents. While this decode-while-parsing approach obviated the need for temporary files, it resulted in inflexible and complex decoder implementations. The revised implementation uses a temporary file (a la C) during parsing to hold the I portion of the current MIME document or part. This file is deleted automatically after the current part is decoded and the data is written to the "body stream" object; you'll never see it, and should never need to worry about it. Some folks have asked for the ability to bypass this temp-file mechanism, I suppose because they assume it would slow down their application. I considered accommodating this wish, but the temp-file approach solves a lot of thorny problems in parsing, and it also protects against hidden bugs in user applications (what if you've directed the encoded part into a scalar, and someone unexpectedly sends you a 6 MB tar file?). Finally, I'm just not convinced that the temp-file use adds significant overhead. =item Fuzzing of CRLF and newline on input RFC 2045 dictates that MIME streams have lines terminated by CRLF (C<"\r\n">). However, it is extremely likely that folks will want to parse MIME streams where each line ends in the local newline character C<"\n"> instead. An attempt has been made to allow the parser to handle both CRLF and newline-terminated input. =item Fuzzing of CRLF and newline on output The C<"7bit"> and C<"8bit"> decoders will decode both a C<"\n"> and a C<"\r\n"> end-of-line sequence into a C<"\n">. The C<"binary"> decoder (default if no encoding specified) still outputs stuff verbatim... so a MIME message with CRLFs and no explicit encoding will be output as a text file that, on many systems, will have an annoying ^M at the end of each line... I. =item Inability to handle multipart boundaries that contain newlines First, let's get something straight: I and is incompatible with RFC 2046... hence, it's not valid MIME. If your mailer creates multipart boundary strings that contain newlines I give it two weeks notice and find another one. If your mail robot receives MIME mail like this, regard it as syntactically incorrect MIME, which it is. Why do I say that? Well, in RFC 2046, the syntax of a boundary is given quite clearly: boundary := 0*69 bcharsnospace bchars := bcharsnospace / " " bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" /"_" / "," / "-" / "." / "/" / ":" / "=" / "?" All of which means that a valid boundary string I have newlines in it, and any newlines in such a string in the message header are expected to be solely the result of I the string (i.e., inserting to-be-removed newlines for readability and line-shortening I). Yet, there is at least one brain-damaged user agent out there that composes mail like this: MIME-Version: 1.0 Content-type: multipart/mixed; boundary="----ABC- 123----" Subject: Hi... I'm a dork! This is a multipart MIME message (yeah, right...) ----ABC- 123---- Hi there! We have I to discourage practices like this (and the recent file upload idiocy where binary files that are part of a multipart MIME message aren't base64-encoded) if we want MIME to stay relatively simple, and MIME parsers to be relatively robust. I =back =head1 SEE ALSO L, L, L, L, L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). Dianne Skoll (dfs@roaringpenguin.com) http://www.roaringpenguin.com All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut MIME-tools-5.509/lib/MIME/Parser/0000755000076400007640000000000013071231525014273 5ustar dfsdfsMIME-tools-5.509/lib/MIME/Parser/Filer.pm0000644000076400007640000006157412202447135015710 0ustar dfsdfspackage MIME::Parser::Filer; =head1 NAME MIME::Parser::Filer - manage file-output of the parser =head1 SYNOPSIS Before reading further, you should see L to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait. Ready? Ok... now read L<"DESCRIPTION"> below, and everything else should make sense. =head2 Public interface ### Create a "filer" of the desired class: my $filer = MIME::Parser::FileInto->new($dir); my $filer = MIME::Parser::FileUnder->new($basedir); ... ### Want added security? Don't let outsiders name your files: $filer->ignore_filename(1); ### Prepare for the parsing of a new top-level message: $filer->init_parse; ### Return the path where this message's data should be placed: $path = $filer->output_path($head); =head2 Semi-public interface These methods might be overridden or ignored in some subclasses, so they don't all make sense in all circumstances: ### Tweak the mapping from content-type to extension: $emap = $filer->output_extension_map; $emap->{"text/html"} = ".htm"; =head1 DESCRIPTION =head2 How this class is used when parsing When a MIME::Parser decides that it wants to output a file to disk, it uses its "Filer" object -- an instance of a MIME::Parser::Filer subclass -- to determine where to put the file. Every parser has a single Filer object, which it uses for all parsing. You can get the Filer for a given $parser like this: $filer = $parser->filer; At the beginning of each C, the filer's internal state is reset by the parser: $parser->filer->init_parse; The parser can then get a path for each entity in the message by handing that entity's header (a MIME::Head) to the filer and having it do the work, like this: $new_file = $parser->filer->output_path($head); Since it's nice to be able to clean up after a parse (especially a failed parse), the parser tells the filer when it has actually used a path: $parser->filer->purgeable($new_file); Then, if you want to clean up the files which were created for a particular parse (and also any directories that the Filer created), you would do this: $parser->filer->purge; =head2 Writing your own subclasses There are two standard "Filer" subclasses (see below): B, which throws all files from all parses into the same directory, and B (preferred), which creates a subdirectory for each message. Hopefully, these will be sufficient for most uses, but just in case... The only method you have to override is L: $filer->output_path($head); This method is invoked by MIME::Parser when it wants to put a decoded message body in an output file. The method should return a path to the file to create. Failure is indicated by throwing an exception. The path returned by C should be "ready for open()": any necessary parent directories need to exist at that point. These directories can be created by the Filer, if course, and they should be marked as B if a purge should delete them. Actually, if your issue is more I the files go than what they're named, you can use the default L method and just override one of its components: $dir = $filer->output_dir($head); $name = $filer->output_filename($head); ... =head1 PUBLIC INTERFACE =head2 MIME::Parser::Filer This is the abstract superclass of all "filer" objects. =over 4 =cut use strict; ### Kit modules: use MIME::Tools qw(:msgtypes); use File::Spec; use File::Path qw(rmtree); use MIME::WordDecoder; ### Output path uniquifiers: my $GFileNo = 0; my $GSubdirNo = 0; ### Map content-type to extension. ### If we can't map "major/minor", we try "major/*", then use "*/*". my %DefaultTypeToExt = qw( application/andrew-inset .ez application/octet-stream .bin application/oda .oda application/pdf .pdf application/pgp .pgp application/postscript .ps application/rtf .rtf application/x-bcpio .bcpio application/x-chess-pgn .pgn application/x-cpio .cpio application/x-csh .csh application/x-dvi .dvi application/x-gtar .gtar application/x-gunzip .gz application/x-hdf .hdf application/x-latex .latex application/x-mif .mif application/x-netcdf .cdf application/x-netcdf .nc application/x-sh .sh application/x-shar .shar application/x-sv4cpio .sv4cpio application/x-sv4crc .sv4crc application/x-tar .tar application/x-tcl .tcl application/x-tex .tex application/x-texinfo .texi application/x-troff .roff application/x-troff .tr application/x-troff-man .man application/x-troff-me .me application/x-troff-ms .ms application/x-ustar .ustar application/x-wais-source .src application/zip .zip audio/basic .snd audio/ulaw .au audio/x-aiff .aiff audio/x-wav .wav image/gif .gif image/ief .ief image/jpeg .jpg image/png .png image/xbm .xbm image/tiff .tif image/x-cmu-raster .ras image/x-portable-anymap .pnm image/x-portable-bitmap .pbm image/x-portable-graymap .pgm image/x-portable-pixmap .ppm image/x-rgb .rgb image/x-xbitmap .xbm image/x-xpixmap .xpm image/x-xwindowdump .xwd text/* .txt text/html .html text/plain .txt text/richtext .rtx text/tab-separated-values .tsv text/x-setext .etx text/x-vcard .vcf video/mpeg .mpg video/quicktime .mov video/x-msvideo .avi video/x-sgi-movie .movie message/* .msg */* .dat ); #------------------------------ =item new INITARGS... I Create a new outputter for the given parser. Any subsequent arguments are given to init(), which subclasses should override for their own use (the default init does nothing). =cut sub new { my ($class, @initargs) = @_; my $self = bless { MPF_Prefix => "msg", MPF_Dir => ".", MPF_Ext => { %DefaultTypeToExt }, MPF_Purgeable => [], ### files created by the last parse MPF_MaxName => 80, ### max filename before treated as evil MPF_TrimRoot => 14, ### trim root to this length MPF_TrimExt => 3, ### trim extension to this length }, $class; $self->init(@initargs); $self; } sub init { ### no-op } #------------------------------ # # cleanup_dir # # Instance method, private. # Cleanup a directory, defaulting empty to "." # sub cleanup_dir { my ($self, $dir) = @_; $dir = '.' if (!defined($dir) || ($dir eq '')); # coerce empty to "." $dir = '/.' if ($dir eq '/'); # coerce "/" so "$dir/$filename" works $dir =~ s|/$||; # be nice: get rid of any trailing "/" $dir; } #------------------------------ =item results RESULTS I Link this filer to a MIME::Parser::Results object which will tally the messages. Notice that we avoid linking it to the parser to avoid circular reference! =cut sub results { my ($self, $results) = @_; $self->{MPF_Results} = $results if (@_ > 1); $self->{MPF_Results}; } ### Log debug messages: sub debug { my $self = shift; if (MIME::Tools->debugging()) { if ($self->{MPF_Results}) { unshift @_, $self->{MPF_Results}->indent; $self->{MPF_Results}->msg($M_DEBUG, @_); } MIME::Tools::debug(@_); } } ### Log warning messages: sub whine { my $self = shift; if ($self->{MPF_Results}) { unshift @_, $self->{MPF_Results}->indent; $self->{MPF_Results}->msg($M_WARNING, @_); } MIME::Tools::whine(@_); } #------------------------------ =item init_parse I Prepare to start parsing a new message. Subclasses should always be sure to invoke the inherited method. =cut sub init_parse { my $self = shift; $self->{MPF_Purgeable} = []; } #------------------------------ =item evil_filename FILENAME I Is this an evil filename; i.e., one which should not be used in generating a disk file name? It is if any of these are true: * it is empty or entirely whitespace * it contains leading or trailing whitespace * it is a string of dots: ".", "..", etc. * it contains characters not in the set: "A" - "Z", "a" - "z", "0" - "9", "-", "_", "+", "=", ".", ",", "@", "#", "$", and " ". * it is too long If you just want to change this behavior, you should override this method in the subclass of MIME::Parser::Filer that you use. B at the time this method is invoked, the FILENAME has already been unmime'd into the local character set. If you're using any character set other than ASCII, ISO-8859-*, or UTF-8, the interpretation of the "path" characters might be very different, and you will probably need to override this method. See L for more details. B subclasses of MIME::Parser::Filer which override output_path() might not consult this method; note, however, that the built-in subclasses do consult it. I =cut sub evil_filename { my ($self, $name) = @_; $self->debug("is this evil? '$name'"); return 1 if (!defined($name) or ($name eq '')); ### empty return 1 if ($name =~ m{(^\s)|(\s+\Z)}); ### leading/trailing whitespace return 1 if ($name =~ m{^\.+\Z}); ### dots return 1 if ($name =~ /[^-A-Z0-9_+=.,@\#\$\% ]/i); # Only allow good chars return 1 if ($self->{MPF_MaxName} and (length($name) > $self->{MPF_MaxName})); $self->debug("it's ok"); 0; } #------------------------------ =item exorcise_filename FILENAME I If a given filename is evil (see L) we try to rescue it by performing some basic operations: shortening it, removing bad characters, etc., and checking each against evil_filename(). Returns the exorcised filename (which is guaranteed to not be evil), or undef if it could not be salvaged. B at the time this method is invoked, the FILENAME has already been unmime'd into the local character set. If you're using anything character set other than ASCII, ISO-8859-*, or UTF-8, the interpretation of the "path" characters might be very very different, and you will probably need to override this method. See L for more details. =cut sub exorcise_filename { my ($self, $fname) = @_; ### Isolate to last path element: my $last = $fname; ### Path separators are / or \ $last =~ s{^.*[/\\]}{}; ### Convert semi-evil characters to underscores $last =~ s/[\/\\\[\]:]/_/g; if ($last and !$self->evil_filename($last)) { $self->debug("looks like I can use the last path element"); return $last; } ### Break last element into root and extension, and truncate: my ($root, $ext) = (($last =~ /^(.*)\.([^\.]+)\Z/) ? ($1, $2) : ($last, '')); ### Delete leading and trailing whitespace $root =~ s/^\s+//; $ext =~ s/\s+$//; $root = substr($root, 0, ($self->{MPF_TrimRoot} || 14)); $ext = substr($ext, 0, ($self->{MPF_TrimExt} || 3)); $ext =~ /^\w+$/ or $ext = "dat"; my $trunc = $root . ($ext ? ".$ext" : ''); if (!$self->evil_filename($trunc)) { $self->debug("looks like I can use the truncated last path element"); return $trunc; } ### Remove all bad characters $trunc =~ s/([^-A-Z0-9_+=.,@\#\$ ])/sprintf("%%%02X", unpack("C", $1))/ige; if (!$self->evil_filename($trunc)) { $self->debug("looks like I can use a munged version of the truncated last path element"); return $trunc; } ### Hope that works: undef; } #------------------------------ =item find_unused_path DIR, FILENAME I We have decided on an output directory and tentative filename, but there is a chance that it might already exist. Keep adding a numeric suffix "-1", "-2", etc. to the filename until an unused path is found, and then return that path. The suffix is actually added before the first "." in the filename is there is one; for example: picture.gif archive.tar.gz readme picture-1.gif archive-1.tar.gz readme-1 picture-2.gif archive-2.tar.gz readme-2 ... ... ... picture-10.gif ... This can be a costly operation, and risky if you don't want files renamed, so it is in your best interest to minimize situations where these kinds of collisions occur. Unfortunately, if a multipart message gives all of its parts the same recommended filename, and you are placing them all in the same directory, this method might be unavoidable. =cut sub find_unused_path { my ($self, $dir, $fname) = @_; my $i = 0; while (1) { ### Create suffixed name (from filename), and see if we can use it: my $suffix = ($i ? "-$i" : ""); my $sname = $fname; $sname =~ s/^(.*?)(\.|\Z)/$1$suffix$2/; my $path = File::Spec->catfile($dir, $sname); if (! -e $path) { ### it's good! $i and $self->whine("collision with $fname in $dir: using $path"); return $path; } $self->debug("$path already taken"); } continue { ++$i; } } #------------------------------ =item ignore_filename [YESNO] I Return true if we should always ignore recommended filenames in messages, choosing instead to always generate our own filenames. With argument, sets this value. B subclasses of MIME::Parser::Filer which override output_path() might not honor this setting; note, however, that the built-in subclasses honor it. =cut sub ignore_filename { my $self = shift; $self->{MPF_IgnoreFilename} = $_[0] if @_; $self->{MPF_IgnoreFilename}; } #------------------------------ =item output_dir HEAD I Return the output directory for the given header. The default method returns ".". =cut sub output_dir { my ($self, $head) = @_; return "."; } #------------------------------ =item output_filename HEAD I A given recommended filename was either not given, or it was judged to be evil. Return a fake name, possibly using information in the message HEADer. Note that this is just the filename, not the full path. Used by L. If you're using the default C, you probably don't need to worry about avoiding collisions with existing files; we take care of that in L. =cut sub output_filename { my ($self, $head) = @_; ### Get the recommended name: my $recommended = $head->recommended_filename; ### Get content type: my ($type, $subtype) = split m{/}, $head->mime_type; $subtype ||= ''; ### Get recommended extension, being quite conservative: my $recommended_ext = (($recommended and ($recommended =~ m{(\.\w+)\Z})) ? $1 : undef); ### Try and get an extension, honoring a given one first: my $ext = ($recommended_ext || $self->{MPF_Ext}{"$type/$subtype"} || $self->{MPF_Ext}{"$type/*"} || $self->{MPF_Ext}{"*/*"} || ".dat"); ### Get a prefix: ++$GFileNo; return ($self->output_prefix . "-$$-$GFileNo$ext"); } #------------------------------ =item output_prefix [PREFIX] I Get the short string that all filenames for extracted body-parts will begin with (assuming that there is no better "recommended filename"). The default is F<"msg">. If PREFIX I given, the current output prefix is returned. If PREFIX I given, the output prefix is set to the new value, and the previous value is returned. Used by L. B subclasses of MIME::Parser::Filer which override output_path() or output_filename() might not honor this setting; note, however, that the built-in subclasses honor it. =cut sub output_prefix { my ($self, $prefix) = @_; $self->{MPF_Prefix} = $prefix if (@_ > 1); $self->{MPF_Prefix}; } #------------------------------ =item output_type_ext I Return a reference to the hash used by the default L for mapping from content-types to extensions when there is no default extension to use. $emap = $filer->output_typemap; $emap->{'text/plain'} = '.txt'; $emap->{'text/html'} = '.html'; $emap->{'text/*'} = '.txt'; $emap->{'*/*'} = '.dat'; B subclasses of MIME::Parser::Filer which override output_path() or output_filename() might not consult this hash; note, however, that the built-in subclasses consult it. =cut sub output_type_ext { my $self = shift; return $self->{MPF_Ext}; } #------------------------------ =item output_path HEAD I Given a MIME head for a file to be extracted, come up with a good output pathname for the extracted file. This is the only method you need to worry about if you are building a custom filer. The default implementation does a lot of work; subclass implementers I should try to just override its components instead of the whole thing. It works basically as follows: $directory = $self->output_dir($head); $filename = $head->recommended_filename(); if (!$filename or $self->ignore_filename() or $self->evil_filename($filename)) { $filename = $self->output_filename($head); } return $self->find_unused_path($directory, $filename); B There are many, many, many ways you might want to control the naming of files, based on your application. If you don't like the behavior of this function, you can easily define your own subclass of MIME::Parser::Filer and override it there. B Nickolay Saukh pointed out that, given the subjective nature of what is "evil", this function really shouldn't I about an evil filename, but maybe just issue a I message. I considered that, but then I thought: if debugging were off, people wouldn't know why (or even if) a given filename had been ignored. In mail robots that depend on externally-provided filenames, this could cause hard-to-diagnose problems. So, the message is still a warning. I =cut sub output_path { my ($self, $head) = @_; ### Get the output directory: my $dir = $self->output_dir($head); ### Get the output filename as UTF-8 my $fname = $head->recommended_filename; ### Can we use it: if (!defined($fname)) { $self->debug("no filename recommended: synthesizing our own"); $fname = $self->output_filename($head); } elsif ($self->ignore_filename) { $self->debug("ignoring all external filenames: synthesizing our own"); $fname = $self->output_filename($head); } elsif ($self->evil_filename($fname)) { ### Can we save it by just taking the last element? my $ex = $self->exorcise_filename($fname); if (defined($ex) and !$self->evil_filename($ex)) { $self->whine("Provided filename '$fname' is regarded as evil, ", "but I was able to exorcise it and get something ", "usable."); $fname = $ex; } else { $self->whine("Provided filename '$fname' is regarded as evil; ", "I'm ignoring it and supplying my own."); $fname = $self->output_filename($head); } } $self->debug("planning to use '$fname'"); ### Resolve collisions and return final path: return $self->find_unused_path($dir, $fname); } #------------------------------ =item purge I Purge all files/directories created by the last parse. This method simply goes through the purgeable list in reverse order (see L) and removes all existing files/directories in it. You should not need to override this method. =cut sub purge { my ($self) = @_; foreach my $path (reverse @{$self->{MPF_Purgeable}}) { (-e $path) or next; ### must check: might delete DIR before DIR/FILE rmtree($path, 0, 1); (-e $path) and $self->whine("unable to purge: $path"); } 1; } #------------------------------ =item purgeable [FILE] I Add FILE to the list of "purgeable" files/directories (those which will be removed if you do a C). You should not need to override this method. If FILE is not given, the "purgeable" list is returned. This may be used for more-sophisticated purging. As a special case, invoking this method with a FILE that is an arrayref will replace the purgeable list with a copy of the array's contents, so [] may be used to clear the list. Note that the "purgeable" list is cleared when a parser begins a new parse; therefore, if you want to use purge() to do cleanup, you I do so I starting a new parse! =cut sub purgeable { my ($self, $path) = @_; return @{$self->{MPF_Purgeable}} if (@_ == 1); if (ref($path)) { $self->{MPF_Purgeable} = [ @$path ]; } else { push @{$self->{MPF_Purgeable}}, $path; } 1; } =back =cut #------------------------------------------------------------ #------------------------------------------------------------ =head2 MIME::Parser::FileInto This concrete subclass of MIME::Parser::Filer supports filing into a given directory. =over 4 =cut package MIME::Parser::FileInto; use strict; use vars qw(@ISA); @ISA = qw(MIME::Parser::Filer); #------------------------------ =item init DIRECTORY I Set the directory where all files will go. =cut sub init { my ($self, $dir) = @_; $self->{MPFI_Dir} = $self->cleanup_dir($dir); } #------------------------------ # # output_dir HEAD # # I # Return the output directory where the files go. # sub output_dir { shift->{MPFI_Dir}; } =back =cut #------------------------------------------------------------ #------------------------------------------------------------ =head2 MIME::Parser::FileUnder This concrete subclass of MIME::Parser::Filer supports filing under a given directory, using one subdirectory per message, but with all message parts in the same directory. =over 4 =cut package MIME::Parser::FileUnder; use strict; use vars qw(@ISA); @ISA = qw(MIME::Parser::Filer); #------------------------------ =item init BASEDIR, OPTSHASH... I Set the base directory which will contain the message directories. If used, then each parse of begins by creating a new subdirectory of BASEDIR where the actual parts of the message are placed. OPTSHASH can contain the following: =over 4 =item DirName Explicitly set the name of the subdirectory which is created. The default is to use the time, process id, and a sequence number, but you might want a predictable directory. =item Purge Automatically purge the contents of the directory (including all subdirectories) before each parse. This is really only needed if using an explicit DirName, and is provided as a convenience only. Currently we use the 1-arg form of File::Path::rmtree; you should familiarize yourself with the caveats therein. =back The output_dir() will return the path to this message-specific directory until the next parse is begun, so you can do this: use File::Path; $parser->output_under("/tmp"); $ent = eval { $parser->parse_open($msg); }; ### parse if (!$ent) { ### parse failed rmtree($parser->output_dir); die "parse failed: $@"; } else { ### parse succeeded ...do stuff... } =cut sub init { my ($self, $basedir, %opts) = @_; $self->{MPFU_Base} = $self->cleanup_dir($basedir); $self->{MPFU_DirName} = $opts{DirName}; $self->{MPFU_Purge} = $opts{Purge}; } #------------------------------ # # init_parse # # I # Prepare to start parsing a new message. # sub init_parse { my $self = shift; ### Invoke inherited method first! $self->SUPER::init_parse; ### Determine the subdirectory of their base to use: my $subdir = (defined($self->{MPFU_DirName}) ? $self->{MPFU_DirName} : ("msg-".scalar(time)."-$$-".$GSubdirNo++)); $self->debug("subdir = $subdir"); ### Determine full path to the per-message output directory: $self->{MPFU_Dir} = File::Spec->catfile($self->{MPFU_Base}, $subdir); ### Remove and re-create the per-message output directory: rmtree $self->output_dir if $self->{MPFU_Purge}; (-d $self->output_dir) or mkdir $self->output_dir, 0700 or die "mkdir ".$self->output_dir.": $!\n"; ### Add the per-message output directory to the puregables: $self->purgeable($self->output_dir); 1; } #------------------------------ # # output_dir HEAD # # I # Return the output directory that we used for the last parse. # sub output_dir { shift->{MPFU_Dir}; } =back =cut 1; __END__ =head1 SEE ALSO L, L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. MIME-tools-5.509/lib/MIME/Parser/Results.pm0000644000076400007640000000601212541013575016275 0ustar dfsdfspackage MIME::Parser::Results; =head1 NAME MIME::Parser::Results - results of the last entity parsed =head1 SYNOPSIS Before reading further, you should see L to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait. Ready? Ok... ### Do parse, get results: my $entity = eval { $parser->parse(\*STDIN); }; my $results = $parser->results; ### Get all messages logged: @msgs = $results->msgs; ### Get messages of specific types (also tests if there were problems): $had_errors = $results->errors; $had_warnings = $results->warnings; ### Get outermost header: $top_head = $results->top_head; =head1 DESCRIPTION Results from the last MIME::Parser parse. =head1 PUBLIC INTERFACE =over 4 =cut use strict; ### Kit modules: use MIME::Tools qw(:msgs); #------------------------------ =item new I =cut sub new { bless { MPI_ID => 'MIME-parser', MPI_Msgs => [], MPI_Level => 0, MPI_TopHead => undef, }, shift; } #------------------------------ =item msgs I Return all messages that we logged, in order. Every message is a string beginning with its type followed by C<": ">; the current types are C, C, and C. =cut sub msgs { @{shift->{MPI_Msgs}}; } #------------------------------ =item errors I Return all error messages that we logged, in order. A convenience front-end onto msgs(). =cut sub errors { grep /^error: /, @{shift->{MPI_Msgs}}; } #------------------------------ =item warnings I Return all warning messages that we logged, in order. A convenience front-end onto msgs(). =cut sub warnings { grep /^warning: /, @{shift->{MPI_Msgs}}; } #------------------------------ =item top_head I Return the topmost header, if we were able to read it. This may be useful if the parse fails. =cut sub top_head { my ($self, $head) = @_; $self->{MPI_TopHead} = $head if @_ > 1; $self->{MPI_TopHead}; } #------------------------------ # # PRIVATE: FOR USE DURING PARSING ONLY! # #------------------------------ # # msg TYPE, MESSAGE... # # Take a message. # sub msg { my $self = shift; my $type = shift; my @args = map { defined($_) ? $_ : '<>' } @_; push @{$self->{MPI_Msgs}}, ($type.": ".join('', @args)."\n"); } #------------------------------ # # level [+1|-1] # # Return current parsing level. # sub level { my ($self, $lvl) = @_; $self->{MPI_Level} += $lvl if @_ > 1; $self->{MPI_Level}; } #------------------------------ # # indent # # Return indent for current parsing level. # sub indent { my ($self) = @_; ' ' x $self->{MPI_Level}; } =back =cut 1; __END__ =head1 SEE ALSO L, L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. MIME-tools-5.509/lib/MIME/Parser/Reader.pm0000644000076400007640000002016512541013575016043 0ustar dfsdfspackage MIME::Parser::Reader; =head1 NAME MIME::Parser::Reader - a line-oriented reader for a MIME::Parser =head1 SYNOPSIS This module is used internally by MIME::Parser; you probably don't need to be looking at it at all. But just in case... ### Create a top-level reader, where chunks end at EOF: $rdr = MIME::Parser::Reader->new(); ### Spawn a child reader, where chunks also end at a boundary: $subrdr = $rdr->spawn->add_boundary($bound); ### Spawn a child reader, where chunks also end at a given string: $subrdr = $rdr->spawn->add_terminator($string); ### Read until boundary or terminator: $subrdr->read_chunk($in, $out); =head1 DESCRIPTION A line-oriented reader which can deal with virtual end-of-stream defined by a collection of boundaries. B this is a private class solely for use by MIME::Parser. This class has no official public interface =cut use strict; ### All possible end-of-line sequences. ### Note that "" is included because last line of stream may have no newline! my @EOLs = ("", "\r", "\n", "\r\n", "\n\r"); ### Long line: my $LONGLINE = ' ' x 1000; #------------------------------ # # new # # I # Construct an empty (top-level) reader. # sub new { my ($class) = @_; my $eos; return bless { Bounds => [], BH => {}, TH => {}, EOS => \$eos, }, $class; } #------------------------------ # # spawn # # I # Return a reader which is mostly a duplicate, except that the EOS # accumulator is shared. # sub spawn { my $self = shift; my $dup = bless {}, ref($self); $dup->{Bounds} = [ @{$self->{Bounds}} ]; ### deep copy $dup->{BH} = { %{$self->{BH}} }; ### deep copy $dup->{TH} = { %{$self->{TH}} }; ### deep copy $dup->{EOS} = $self->{EOS}; ### shallow copy; same ref! $dup; } #------------------------------ # # add_boundary BOUND # # I # Let BOUND be the new innermost boundary. Returns self. # sub add_boundary { my ($self, $bound) = @_; unshift @{$self->{Bounds}}, $bound; ### now at index 0 $self->{BH}{"--$bound"} = "DELIM $bound"; $self->{BH}{"--$bound--"} = "CLOSE $bound"; $self; } #------------------------------ # # add_terminator LINE # # I # Let LINE be another terminator. Returns self. # sub add_terminator { my ($self, $line) = @_; foreach (@EOLs) { $self->{TH}{"$line$_"} = "DONE $line"; } $self; } #------------------------------ # # has_bounds # # I # Are there boundaries to contend with? # sub has_bounds { scalar(@{shift->{Bounds}}); } #------------------------------ # # depth # # I # How many levels are there? # sub depth { scalar(@{shift->{Bounds}}); } #------------------------------ # # eos [EOS] # # I # Return the last end-of-stream token seen. # See read_chunk() for what these might be. # sub eos { my $self = shift; ${$self->{EOS}} = $_[0] if @_; ${$self->{EOS}}; } #------------------------------ # # eos_type [EOSTOKEN] # # I # Return the high-level type of the given token (defaults to our token). # # DELIM saw an innermost boundary like --xyz # CLOSE saw an innermost boundary like --xyz-- # DONE callback returned false # EOF end of file # EXT saw boundary of some higher-level # sub eos_type { my ($self, $eos) = @_; $eos = $self->eos if (@_ == 1); if ($eos =~ /^(DONE|EOF)/) { return $1; } elsif ($eos =~ /^(DELIM|CLOSE) (.*)$/) { return (($2 eq $self->{Bounds}[0]) ? $1 : 'EXT'); } else { die("internal error: unable to classify boundary token ($eos)"); } } #------------------------------ # # native_handle HANDLE # # I # Can we do native i/o on HANDLE? If true, returns the handle # that will respond to native I/O calls; else, returns undef. # sub native_handle { my $fh = shift; return $fh if ($fh->isa('IO::File') || $fh->isa('IO::Handle')); return $fh if (ref $fh eq 'GLOB'); undef; } #------------------------------ # # read_chunk INHANDLE, OUTHANDLE # # I # Get lines until end-of-stream. # Returns the terminating-condition token: # # DELIM xyz saw boundary line "--xyz" # CLOSE xyz saw boundary line "--xyz--" # DONE xyz saw terminator line "xyz" # EOF end of file # Parse up to (and including) the boundary, and dump output. # Follows the RFC 2046 specification, that the CRLF immediately preceding # the boundary is part of the boundary, NOT part of the input! # # NOTE: while parsing bodies, we take care to remember the EXACT end-of-line # sequence. This is because we *may* be handling 'binary' encoded data, and # in that case we can't just massage \r\n into \n! Don't worry... if the # data is styled as '7bit' or '8bit', the "decoder" will massage the CRLF # for us. For now, we're just trying to chop up the data stream. # NBK - Oct 12, 1999 # The CRLF at the end of the current line is considered part # of the boundary. I buffer the current line and output the # last. I strip the last CRLF when I hit the boundary. sub read_chunk { my ($self, $in, $out, $keep_newline, $normalize_newlines) = @_; # If we're parsing a preamble or epilogue, we need to keep the blank line # that precedes the boundary line. $keep_newline ||= 0; $normalize_newlines ||= 0; ### Init: my %bh = %{$self->{BH}}; my %th = %{$self->{TH}}; my $thx = keys %th; local $_ = $LONGLINE; my $maybe; my $last = ''; my $eos = ''; ### Determine types: my $n_in = native_handle($in); my $n_out = native_handle($out); ### Handle efficiently by type: if ($n_in) { if ($n_out) { ### native input, native output [fastest] while (<$n_in>) { # Normalize line ending $_ =~ s/(?:\n\r|\r\n|\r)$/\n/ if $normalize_newlines; if (substr($_, 0, 2) eq '--') { ($maybe = $_) =~ s/[ \t\r\n]+\Z//; $bh{$maybe} and do { $eos = $bh{$maybe}; last }; } $thx and $th{$_} and do { $eos = $th{$_}; last }; print $n_out $last; $last = $_; } } else { ### native input, OO output [slower] while (<$n_in>) { # Normalize line ending $_ =~ s/(?:\n\r|\r\n|\r)$/\n/ if $normalize_newlines; if (substr($_, 0, 2) eq '--') { ($maybe = $_) =~ s/[ \t\r\n]+\Z//; $bh{$maybe} and do { $eos = $bh{$maybe}; last }; } $thx and $th{$_} and do { $eos = $th{$_}; last }; $out->print($last); $last = $_; } } } else { if ($n_out) { ### OO input, native output [even slower] while (defined($_ = $in->getline)) { # Normalize line ending $_ =~ s/(?:\n\r|\r\n|\r)$/\n/ if $normalize_newlines; if (substr($_, 0, 2) eq '--') { ($maybe = $_) =~ s/[ \t\r\n]+\Z//; $bh{$maybe} and do { $eos = $bh{$maybe}; last }; } $thx and $th{$_} and do { $eos = $th{$_}; last }; print $n_out $last; $last = $_; } } else { ### OO input, OO output [slowest] while (defined($_ = $in->getline)) { # Normalize line ending $_ =~ s/(?:\n\r|\r\n|\r)$/\n/ if $normalize_newlines; if (substr($_, 0, 2) eq '--') { ($maybe = $_) =~ s/[ \t\r\n]+\Z//; $bh{$maybe} and do { $eos = $bh{$maybe}; last }; } $thx and $th{$_} and do { $eos = $th{$_}; last }; $out->print($last); $last = $_; } } } # Write out last held line, removing terminating CRLF if ended on bound, # unless the line consists only of CRLF and we're wanting to keep the # preceding blank line (as when parsing a preamble) $last =~ s/[\r\n]+\Z// if ($eos =~ /^(DELIM|CLOSE)/ && !($keep_newline && $last =~ m/^[\r\n]\z/)); $out->print($last); ### Save and return what we finished on: ${$self->{EOS}} = ($eos || 'EOF'); 1; } #------------------------------ # # read_lines INHANDLE, \@OUTLINES # # I # Read lines into the given array. # sub read_lines { my ($self, $in, $outlines) = @_; my $data = ''; open(my $fh, '>', \$data) or die $!; $self->read_chunk($in, $fh); @$outlines = split(/^/, $data); close $fh; 1; } 1; __END__ =head1 SEE ALSO L, L MIME-tools-5.509/lib/MIME/Words.pm0000644000076400007640000002347213071220635014503 0ustar dfsdfspackage MIME::Words; =head1 NAME MIME::Words - deal with RFC 2047 encoded words =head1 SYNOPSIS Before reading further, you should see L to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait. Ready? Ok... use MIME::Words qw(:all); ### Decode the string into another string, forgetting the charsets: $decoded = decode_mimewords( 'To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= ', ); ### Split string into array of decoded [DATA,CHARSET] pairs: @decoded = decode_mimewords( 'To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= ', ); ### Encode a single unsafe word: $encoded = encode_mimeword("\xABFran\xE7ois\xBB"); ### Encode a string, trying to find the unsafe words inside it: $encoded = encode_mimewords("Me and \xABFran\xE7ois\xBB in town"); =head1 DESCRIPTION Fellow Americans, you probably won't know what the hell this module is for. Europeans, Russians, et al, you probably do. C<:-)>. For example, here's a valid MIME header you might get: From: =?US-ASCII?Q?Keith_Moore?= To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= CC: =?ISO-8859-1?Q?Andr=E9_?= Pirard Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?= =?US-ASCII?Q?.._cool!?= The fields basically decode to (sorry, I can only approximate the Latin characters with 7 bit sequences /o and 'e): From: Keith Moore To: Keld J/orn Simonsen CC: Andr'e Pirard Subject: If you can read this you understand the example... cool! =head1 PUBLIC INTERFACE =over 4 =cut require 5.001; ### Pragmas: use strict; use re 'taint'; use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS @ISA); ### Exporting: use Exporter; %EXPORT_TAGS = (all => [qw(decode_mimewords encode_mimeword encode_mimewords )]); Exporter::export_ok_tags('all'); ### Inheritance: @ISA = qw(Exporter); ### Other modules: use MIME::Base64; use MIME::QuotedPrint; #------------------------------ # # Globals... # #------------------------------ ### The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; ### Nonprintables (controls + x7F + 8bit): my $NONPRINT = "\\x00-\\x1F\\x7F-\\xFF"; #------------------------------ # _decode_Q STRING # Private: used by _decode_header() to decode "Q" encoding, which is # almost, but not exactly, quoted-printable. :-P sub _decode_Q { my $str = shift; local $1; $str =~ s/_/\x20/g; # RFC-1522, Q rule 2 $str =~ s/=([\da-fA-F]{2})/pack("C", hex($1))/ge; # RFC-1522, Q rule 1 $str; } # _encode_Q STRING # Private: used by _encode_header() to decode "Q" encoding, which is # almost, but not exactly, quoted-printable. :-P sub _encode_Q { my $str = shift; local $1; $str =~ s{([ _\?\=$NONPRINT])}{sprintf("=%02X", ord($1))}eog; $str; } # _decode_B STRING # Private: used by _decode_header() to decode "B" encoding. sub _decode_B { my $str = shift; decode_base64($str); } # _encode_B STRING # Private: used by _decode_header() to decode "B" encoding. sub _encode_B { my $str = shift; encode_base64($str, ''); } #------------------------------ =item decode_mimewords ENCODED I Go through the string looking for RFC 2047-style "Q" (quoted-printable, sort of) or "B" (base64) encoding, and decode them. B splits the ENCODED string into a list of decoded C<[DATA, CHARSET]> pairs, and returns that list. Unencoded data are returned in a 1-element array C<[DATA]>, giving an effective CHARSET of C. $enc = '=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= '; foreach (decode_mimewords($enc)) { print "", ($_->[1] || 'US-ASCII'), ": ", $_->[0], "\n"; } B joins the "data" elements of the above list together, and returns that. I and probably I what you want, but if you know that all charsets in the ENCODED string are identical, it might be useful to you. (Before you use this, please see L, which is probably what you want.) In the event of a syntax error, $@ will be set to a description of the error, but parsing will continue as best as possible (so as to get I back when decoding headers). $@ will be false if no error was detected. Any arguments past the ENCODED string are taken to define a hash of options: =cut sub decode_mimewords { my $encstr = shift; my @tokens; local($1,$2,$3); $@ = ''; ### error-return ### Collapse boundaries between adjacent encoded words: $encstr =~ s{(\?\=)\s*(\=\?)}{$1$2}gs; pos($encstr) = 0; ### print STDOUT "ENC = [", $encstr, "]\n"; ### Decode: my ($charset, $encoding, $enc, $dec); while (1) { last if (pos($encstr) >= length($encstr)); my $pos = pos($encstr); ### save it ### Case 1: are we looking at "=?..?..?="? if ($encstr =~ m{\G # from where we left off.. =\?([^?]*) # "=?" + charset + \?([bq]) # "?" + encoding + \?([^?]+) # "?" + data maybe with spcs + \?= # "?=" }xgi) { ($charset, $encoding, $enc) = ($1, lc($2), $3); $dec = (($encoding eq 'q') ? _decode_Q($enc) : _decode_B($enc)); push @tokens, [$dec, $charset]; next; } ### Case 2: are we looking at a bad "=?..." prefix? ### We need this to detect problems for case 3, which stops at "=?": pos($encstr) = $pos; # reset the pointer. if ($encstr =~ m{\G=\?}xg) { $@ .= qq|unterminated "=?..?..?=" in "$encstr" (pos $pos)\n|; push @tokens, ['=?']; next; } ### Case 3: are we looking at ordinary text? pos($encstr) = $pos; # reset the pointer. if ($encstr =~ m{\G # from where we left off... (.*? # shortest possible string, \n*) # followed by 0 or more NLs, (?=(\Z|=\?)) # terminated by "=?" or EOS }sxg) { length($1) or die "MIME::Words: internal logic err: empty token\n"; push @tokens, [$1]; next; } ### Case 4: bug! die "MIME::Words: unexpected case:\n($encstr) pos $pos\n\t". "Please alert developer.\n"; } return (wantarray ? @tokens : join('',map {$_->[0]} @tokens)); } #------------------------------ =item encode_mimeword RAW, [ENCODING], [CHARSET] I Encode a single RAW "word" that has unsafe characters. The "word" will be encoded in its entirety. ### Encode "<>": $encoded = encode_mimeword("\xABFran\xE7ois\xBB"); You may specify the ENCODING (C<"Q"> or C<"B">), which defaults to C<"Q">. You may specify the CHARSET, which defaults to C. =cut sub encode_mimeword { my $word = shift; my $encoding = uc(shift || 'Q'); my $charset = uc(shift || 'ISO-8859-1'); my $encfunc = (($encoding eq 'Q') ? \&_encode_Q : \&_encode_B); "=?$charset?$encoding?" . &$encfunc($word) . "?="; } #------------------------------ =item encode_mimewords RAW, [OPTS] I Given a RAW string, try to find and encode all "unsafe" sequences of characters: ### Encode a string with some unsafe "words": $encoded = encode_mimewords("Me and \xABFran\xE7ois\xBB"); Returns the encoded string. Any arguments past the RAW string are taken to define a hash of options: =over 4 =item Charset Encode all unsafe stuff with this charset. Default is 'ISO-8859-1', a.k.a. "Latin-1". =item Encoding The encoding to use, C<"q"> or C<"b">. The default is C<"q">. =back B this is a quick-and-dirty solution, intended for character sets which overlap ASCII. B. You may want to roll your own variant, using C, for your application. I =cut sub encode_mimewords { my ($rawstr, %params) = @_; my $charset = $params{Charset} || 'ISO-8859-1'; my $encoding = lc($params{Encoding} || 'q'); ### Encode any "words" with unsafe characters. ### We limit such words to 18 characters, to guarantee that the ### worst-case encoding give us no more than 54 + ~10 < 75 characters my $word; local $1; $rawstr =~ s{([a-zA-Z0-9\x7F-\xFF]+\s*)}{ ### get next "word" $word = $1; (($word !~ /(?:[$NONPRINT])|(?:^\s+$)/o) ? $word ### no unsafe chars : encode_mimeword($word, $encoding, $charset)); ### has unsafe chars }xeg; $rawstr =~ s/\?==\?/?= =?/g; $rawstr; } 1; __END__ =back =head1 SEE ALSO L, L, L For other implementations of this or similar functionality (particularly, ones with proper UTF8 support), see: L, L, L At some future point, one of these implementations will likely replace MIME::Words and MIME::Words will become deprecated. =head1 NOTES Exports its principle functions by default, in keeping with MIME::Base64 and MIME::QuotedPrint. =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). Dianne Skoll (dfs@roaringpenguin.com) http://www.roaringpenguin.com All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Thanks also to... Kent Boortz For providing the idea, and the baseline RFC-1522-decoding code! KJJ at PrimeNet For requesting that this be split into its own module. Stephane Barizien For reporting a nasty bug. MIME-tools-5.509/lib/MIME/Field/0000755000076400007640000000000013071231525014062 5ustar dfsdfsMIME-tools-5.509/lib/MIME/Field/ConTraEnc.pm0000644000076400007640000000251113071220636016234 0ustar dfsdfspackage MIME::Field::ConTraEnc; =head1 NAME MIME::Field::ConTraEnc - a "Content-transfer-encoding" field =head1 DESCRIPTION A subclass of Mail::Field. I Instead, ask Mail::Field for new instances based on the field name! =head1 SYNOPSIS use Mail::Field; use MIME::Head; # Create an instance from some text: $field = Mail::Field->new('Content-transfer-encoding', '7bit'); # Get the encoding. # Possible values: 'binary', '7bit', '8bit', 'quoted-printable', # 'base64' and '' (unspecified). Note that there can't be a # single default for this, since it depends on the content type! $encoding = $field->encoding; =head1 SEE ALSO L, L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). Dianne Skoll (dfs@roaringpenguin.com) http://www.roaringpenguin.com =cut require 5.001; use strict; use MIME::Field::ParamVal; use vars qw($VERSION @ISA); @ISA = qw(MIME::Field::ParamVal); # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; # Install it: bless([])->register('Content-transfer-encoding'); #------------------------------ sub encoding { shift->paramstr('_', @_); } #------------------------------ 1; MIME-tools-5.509/lib/MIME/Field/ParamVal.pm0000644000076400007640000002366613071220636016141 0ustar dfsdfspackage MIME::Field::ParamVal; use MIME::Words; =head1 NAME MIME::Field::ParamVal - subclass of Mail::Field, for structured MIME fields =head1 SYNOPSIS # Create an object for a content-type field: $field = new Mail::Field 'Content-type'; # Set some attributes: $field->param('_' => 'text/html'); $field->param('charset' => 'us-ascii'); $field->param('boundary' => '---ABC---'); # Same: $field->set('_' => 'text/html', 'charset' => 'us-ascii', 'boundary' => '---ABC---'); # Get an attribute, or undefined if not present: print "no id!" if defined($field->param('id')); # Same, but use empty string for missing values: print "no id!" if ($field->paramstr('id') eq ''); # Output as string: print $field->stringify, "\n"; =head1 DESCRIPTION This is an abstract superclass of most MIME fields. It handles fields with a general syntax like this: Content-Type: Message/Partial; number=2; total=3; id="oc=jpbe0M2Yt4s@thumper.bellcore.com" Comments are supported I items, like this: Content-Type: Message/Partial; (a comment) number=2 (another comment) ; (yet another comment) total=3; id="oc=jpbe0M2Yt4s@thumper.bellcore.com" =head1 PUBLIC INTERFACE =over 4 =cut #------------------------------ require 5.001; # Pragmas: use strict; use re 'taint'; use vars qw($VERSION @ISA); # Other modules: use Mail::Field; # Kit modules: use MIME::Tools qw(:config :msgs); @ISA = qw(Mail::Field); #------------------------------ # # Public globals... # #------------------------------ # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; #------------------------------ # # Private globals... # #------------------------------ # Pattern to match parameter names (like fieldnames, but = not allowed): my $PARAMNAME = '[^\x00-\x1f\x80-\xff :=]+'; # Pattern to match the first value on the line: my $FIRST = '[^\s\;\x00-\x1f\x80-\xff]*'; # Pattern to match an RFC 2045 token: # # token = 1* # my $TSPECIAL = '()<>@,;:\VAL,...,KEY=>VAL] I Set this field. The paramhash should contain parameter names in I, with the special C<"_"> parameter name signifying the "default" (unnamed) parameter for the field: # Set up to be... # # Content-type: Message/Partial; number=2; total=3; id="ocj=pbe0M2" # $conttype->set('_' => 'Message/Partial', 'number' => 2, 'total' => 3, 'id' => "ocj=pbe0M2"); Note that a single argument is taken to be a I to a paramhash, while multiple args are taken to be the elements of the paramhash themselves. Supplying undef for a hashref, or an empty set of values, effectively clears the object. The self object is returned. =cut sub set { my $self = shift; my $params = ((@_ == 1) ? (shift || {}) : {@_}); %$self = %$params; # set 'em $self; } #------------------------------ =item parse_params STRING I Extract parameter info from a structured field, and return it as a hash reference. For example, here is a field with parameters: Content-Type: Message/Partial; number=2; total=3; id="oc=jpbe0M2Yt4s@thumper.bellcore.com" Here is how you'd extract them: $params = $class->parse_params('content-type'); if ($$params{'_'} eq 'message/partial') { $number = $$params{'number'}; $total = $$params{'total'}; $id = $$params{'id'}; } Like field names, parameter names are coerced to lowercase. The special '_' parameter means the default parameter for the field. B This has been provided as a public method to support backwards compatibility, but you probably shouldn't use it. =cut sub rfc2231decode { my($val) = @_; my($enc, $lang, $rest); local($1,$2,$3); if ($val =~ m/^([^']*)'([^']*)'(.*)\z/s) { $enc = $1; $lang = $2; $rest = $3; } elsif ($val =~ m/^([^']*)'([^']*)\z/s) { $enc = $1; $rest = $2; } else { $rest = $val; # $enc remains undefined when charset/language info is missing } return ($enc, $lang, $rest); } sub rfc2231percent { # Do percent-substitution my($str) = @_; local $1; $str =~ s/%([0-9a-fA-F]{2})/pack("C", hex($1))/ge; return $str; } sub parse_params { my ($self, $raw) = @_; my %params; my %rfc2231params; my %rfc2231encoding_is_used; my $param; my $val; my $part; # Get raw field, and unfold it: defined($raw) or $raw = ''; $raw =~ s/\n//g; $raw =~ s/\s+\z//; # Strip trailing whitespace local($1,$2,$3,$4,$5); # Extract special first parameter: $raw =~ m/\A$SPCZ($FIRST)$SPCZ/og or return {}; # nada! $params{'_'} = $1; # Extract subsequent parameters. # No, we can't just "split" on semicolons: they're legal in quoted strings! while (1) { # keep chopping away until done... $raw =~ m/\G[^;]*(\;$SPCZ)+/og or last; # skip leading separator $raw =~ m/\G($PARAMNAME)\s*=\s*/og or last; # give up if not a param $param = lc($1); $raw =~ m/\G(?:$QUOTED_STRING|($ENCTOKEN)|($TOKEN)|($BADTOKEN))/g or last; # give up if no value" my ($qstr, $enctoken, $token, $badtoken) = ($1, $2, $3, $4, $5); if (defined($qstr)) { # unescape $qstr =~ s/\\(.)/$1/g; } if (defined($badtoken)) { # Strip leading/trailing whitespace from badtoken $badtoken =~ s/^\s+//; $badtoken =~ s/\s+\z//; # Only keep token parameters in badtoken; # cut it off at the first non-token char. CPAN RT #105455 $badtoken =~ /^($TOKEN)*/; $badtoken = $1; # Cut it off at first whitespace too $badtoken =~ s/\s.*//; } $val = defined($qstr) ? $qstr : (defined($enctoken) ? $enctoken : (defined($badtoken) ? $badtoken : $token)); # Do RFC 2231 processing # Pick out the parts of the parameter if ($param =~ /\*/ && $param =~ /^ ([^*]+) (?: \* ([^*]+) )? (\*)? \z/xs) { # We have param*number* or param*number or param* my($name, $num) = ($1, $2||0); if (defined($3)) { # We have param*number* or param* # RFC 2231: Asterisks ("*") are reused to provide the # indicator that language and character set information # is present and encoding is being used $val = rfc2231percent($val); $rfc2231encoding_is_used{$name} = 1; } $rfc2231params{$name}{$num} .= $val; } else { # Assign non-rfc2231 value directly. If we # did get a mix of rfc2231 and non-rfc2231 values, # the non-rfc2231 will be blown away in the # "extract reconstructed parameters" loop. $params{$param} = $val; } } # Extract reconstructed parameters foreach $param (keys %rfc2231params) { # If we got any rfc-2231 parameters, then # blow away any potential non-rfc-2231 parameter. $params{$param} = ''; foreach $part (sort { $a <=> $b } keys %{$rfc2231params{$param}}) { $params{$param} .= $rfc2231params{$param}{$part}; } if ($rfc2231encoding_is_used{$param}) { my($enc, $lang, $val) = rfc2231decode($params{$param}); if (defined $enc) { # re-encode as QP, preserving charset and language info $val =~ s{([=?_\x00-\x1F\x7F-\xFF])} {sprintf("=%02X", ord($1))}eg; $val =~ tr/ /_/; # RFC 2231 section 5: Language specification in Encoded Words $enc .= '*' . $lang if defined $lang && $lang ne ''; $params{$param} = '=?' . $enc . '?Q?' . $val . '?='; } } debug " field param <$param> = <$params{$param}>"; } # Done: \%params; } #------------------------------ =item parse STRING I Parse the string into the instance. Any previous information is wiped. The self object is returned. May also be used as a constructor. =cut sub parse { my ($self, $string) = @_; # Allow use as constructor, for MIME::Head: ref($self) or $self = bless({}, $self); # Get params, and stuff them into the self object: $self->set($self->parse_params($string)); } #------------------------------ =item param PARAMNAME,[VALUE] I Return the given parameter, or undef if it isn't there. With argument, set the parameter to that VALUE. The PARAMNAME is case-insensitive. A "_" refers to the "default" parameter. =cut sub param { my ($self, $paramname, $value) = @_; $paramname = lc($paramname); $self->{$paramname} = $value if (@_ > 2); $self->{$paramname} } #------------------------------ =item paramstr PARAMNAME,[VALUE] I Like param(): return the given parameter, or I if it isn't there. With argument, set the parameter to that VALUE. The PARAMNAME is case-insensitive. A "_" refers to the "default" parameter. =cut sub paramstr { my $val = shift->param(@_); (defined($val) ? $val : ''); } #------------------------------ =item stringify I Convert the field to a string, and return it. =cut sub stringify { my $self = shift; my ($key, $val); my $str = $self->{'_'}; # default subfield foreach $key (sort keys %$self) { next if ($key !~ /^[a-z][a-z-_0-9]*$/); # only lowercase ones! defined($val = $self->{$key}) or next; $val =~ s/(["\\])/\\$1/g; $str .= qq{; $key="$val"}; } $str; } #------------------------------ =item tag I Return the tag for this field. =cut sub tag { '' } =back =head1 SEE ALSO L =cut #------------------------------ 1; MIME-tools-5.509/lib/MIME/Field/ContDisp.pm0000644000076400007640000000231713071220636016147 0ustar dfsdfspackage MIME::Field::ContDisp; =head1 NAME MIME::Field::ContDisp - a "Content-disposition" field =head1 DESCRIPTION A subclass of Mail::Field. I Instead, ask Mail::Field for new instances based on the field name! =head1 SYNOPSIS use Mail::Field; use MIME::Head; # Create an instance from some text: $field = Mail::Field->new('Content-disposition', $text); # Inline or attachment? $type = $field->type; # Recommended filename? $filename = $field->filename; =head1 SEE ALSO L, L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). Dianne Skoll (dfs@roaringpenguin.com) http://www.roaringpenguin.com =cut require 5.001; use strict; use MIME::Field::ParamVal; use vars qw($VERSION @ISA); @ISA = qw(MIME::Field::ParamVal); # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; # Install it: bless([])->register('Content-disposition'); #------------------------------ sub filename { shift->paramstr('filename', @_); } sub type { shift->paramstr('_', @_); } #------------------------------ 1; MIME-tools-5.509/lib/MIME/Field/ContType.pm0000644000076400007640000001117213071220636016170 0ustar dfsdfspackage MIME::Field::ContType; =head1 NAME MIME::Field::ContType - a "Content-type" field =head1 DESCRIPTION A subclass of Mail::Field. I Instead, ask Mail::Field for new instances based on the field name! =head1 SYNOPSIS use Mail::Field; use MIME::Head; # Create an instance from some text: $field = Mail::Field->new('Content-type', 'text/HTML; charset="US-ASCII"'); # Get the MIME type, like 'text/plain' or 'x-foobar'. # Returns 'text/plain' as default, as per RFC 2045: my ($type, $subtype) = split('/', $field->type); # Get generic information: print $field->name; # Get information related to "message" type: if ($type eq 'message') { print $field->id; print $field->number; print $field->total; } # Get information related to "multipart" type: if ($type eq 'multipart') { print $field->boundary; # the basic value, fixed up print $field->multipart_boundary; # empty if not a multipart message! } # Get information related to "text" type: if ($type eq 'text') { print $field->charset; # returns 'us-ascii' as default } =head1 PUBLIC INTERFACE =over 4 =cut require 5.001; use strict; use MIME::Field::ParamVal; use vars qw($VERSION @ISA); @ISA = qw(MIME::Field::ParamVal); # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; # Install it: bless([])->register('Content-type'); #------------------------------ # # Basic access/storage methods... # sub charset { lc(shift->paramstr('charset', @_)) || 'us-ascii'; # RFC 2045 } sub id { shift->paramstr('id', @_); } sub name { shift->paramstr('name', @_); } sub number { shift->paramstr('number', @_); } sub total { shift->paramstr('total', @_); } #------------------------------ =item boundary Return the boundary field. The boundary is returned exactly as given in the C field; that is, the leading double-hyphen (C<-->) is I prepended. (Well, I exactly... from RFC 2046: (If a boundary appears to end with white space, the white space must be presumed to have been added by a gateway, and must be deleted.) so we oblige and remove any trailing spaces.) Returns the empty string if there is no boundary, or if the boundary is illegal (e.g., if it is empty after all trailing whitespace has been removed). =cut sub boundary { my $value = shift->param('boundary', @_); defined($value) || return ''; $value =~ s/\s+$//; # kill trailing white, per RFC 2046 $value; } #------------------------------ =item multipart_boundary Like C, except that this will also return the empty string if the message is not a multipart message. In other words, there's an automatic sanity check. =cut sub multipart_boundary { my $self = shift; my ($type) = split('/', $self->type); return '' if ($type ne 'multipart'); # not multipart! $self->boundary; # okay, return the boundary } #------------------------------ =item type Try real hard to determine the content type (e.g., C<"text/plain">, C<"image/gif">, C<"x-weird-type">, which is returned in all-lowercase. A happy thing: the following code will work just as you would want, even if there's no subtype (as in C<"x-weird-type">)... in such a case, the $subtype would simply be the empty string: ($type, $subtype) = split('/', $head->mime_type); If the content-type information is missing, it defaults to C<"text/plain">, as per RFC 2045: Default RFC 2822 messages are typed by this protocol as plain text in the US-ASCII character set, which can be explicitly specified as "Content-type: text/plain; charset=us-ascii". If no Content-Type is specified, this default is assumed. B under the "be liberal in what we accept" principle, this routine no longer syntax-checks the content type. If it ain't empty, just downcase and return it. =cut sub type { lc(shift->paramstr('_', @_)) || 'text/plain'; # RFC 2045 } #------------------------------ =back =head1 NOTES Since nearly all (if not all) parameters must have non-empty values to be considered valid, we just return the empty string to signify missing fields. If you need to get the I underlying value, use the inherited C method (which returns undef if the parameter is missing). =head1 SEE ALSO L, L =head1 AUTHOR Eryq (F), ZeeGee Software Inc (F). Dianne Skoll (dfs@roaringpenguin.com) http://www.roaringpenguin.com =cut 1; MIME-tools-5.509/lib/MIME/Tools.pm0000644000076400007640000007542413071220633014507 0ustar dfsdfspackage MIME::Tools; #------------------------------ # Because the POD documentation is pretty extensive, it follows # the __END__ statement below... #------------------------------ use strict; use vars (qw(@ISA %CONFIG @EXPORT_OK %EXPORT_TAGS $VERSION $ME $M_DEBUG $M_WARNING $M_ERROR )); require Exporter; use IO::File; use File::Temp 0.18 (); use Carp; $ME = "MIME-tools"; @ISA = qw(Exporter); # Exporting (importing should only be done by modules in this toolkit!): %EXPORT_TAGS = ( 'config' => [qw(%CONFIG)], 'msgs' => [qw(usage debug whine error)], 'msgtypes'=> [qw($M_DEBUG $M_WARNING $M_ERROR)], 'utils' => [qw(textual_type tmpopen )], ); Exporter::export_ok_tags('config', 'msgs', 'msgtypes', 'utils'); # The TOOLKIT version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "5.509"; # Configuration (do NOT alter this directly)... # All legal CONFIG vars *must* be in here, even if only to be set to undef: %CONFIG = ( DEBUGGING => 0, QUIET => 1, ); # Message-logging constants: $M_DEBUG = 'debug'; $M_WARNING = 'warning'; $M_ERROR = 'error'; #------------------------------ # # CONFIGURATION... (see below) # #------------------------------ sub config { my $class = shift; usage("config() is obsolete"); # No args? Just return list: @_ or return keys %CONFIG; my $method = lc(shift); return $class->$method(@_); } sub debugging { my ($class, $value) = @_; $CONFIG{'DEBUGGING'} = $value if (@_ > 1); return $CONFIG{'DEBUGGING'}; } sub quiet { my ($class, $value) = @_; $CONFIG{'QUIET'} = $value if (@_ > 1); return $CONFIG{'QUIET'}; } sub version { my ($class, $value) = @_; return $VERSION; } #------------------------------ # # MESSAGES... # #------------------------------ #------------------------------ # # debug MESSAGE... # # Function, private. # Output a debug message. # sub debug { print STDERR "$ME: $M_DEBUG: ", @_, "\n" if $CONFIG{DEBUGGING}; } #------------------------------ # # whine MESSAGE... # # Function, private. # Something doesn't look right: issue a warning. # Only output if $^W (-w) is true, and we're not being QUIET. # sub whine { my $msg = "$ME: $M_WARNING: ".join('', @_)."\n"; warn $msg if ($^W && !$CONFIG{QUIET}); return (wantarray ? () : undef); } #------------------------------ # # error MESSAGE... # # Function, private. # Something failed, but not so badly that we want to throw an # exception. Just report our general unhappiness. # Only output if $^W (-w) is true, and we're not being QUIET. # sub error { my $msg = "$ME: $M_ERROR: ".join('', @_)."\n"; warn $msg if ($^W && !$CONFIG{QUIET}); return (wantarray ? () : undef); } #------------------------------ # # usage MESSAGE... # # Register unhappiness about usage. # sub usage { my ( $p, $f, $l, $s) = caller(1); my ($cp, $cf, $cl, $cs) = caller(2); my $msg = join('', (($s =~ /::/) ? "$s() " : "${p}::$s() "), @_, "\n"); my $loc = ($cf ? "\tin code called from $cf l.$cl" : ''); warn "$msg$loc\n" if ($^W && !$CONFIG{QUIET}); return (wantarray ? () : undef); } #------------------------------ # # UTILS... # #------------------------------ #------------------------------ # # textual_type MIMETYPE # # Function. Does the given MIME type indicate a textlike document? # sub textual_type { ($_[0] =~ m{^(text|message)(/|\Z)}i); } #------------------------------ # # tmpopen # # sub tmpopen { my ($args) = @_; $args ||= {}; return File::Temp->new( %{$args} ); } #------------------------------ 1; __END__ =head1 NAME MIME-tools - modules for parsing (and creating!) MIME entities =head1 SYNOPSIS Here's some pretty basic code for B and outputting its decoded components to a given directory: use MIME::Parser; ### Create parser, and set some parsing options: my $parser = new MIME::Parser; $parser->output_under("$ENV{HOME}/mimemail"); ### Parse input: $entity = $parser->parse(\*STDIN) or die "parse failed\n"; ### Take a look at the top-level entity (and any parts it has): $entity->dump_skeleton; Here's some code which B containing three parts: a text file, an attached GIF, and some more text: use MIME::Entity; ### Create the top-level, and set up the mail headers: $top = MIME::Entity->build(Type =>"multipart/mixed", From => "me\@myhost.com", To => "you\@yourhost.com", Subject => "Hello, nurse!"); ### Part #1: a simple text document: $top->attach(Path=>"./testin/short.txt"); ### Part #2: a GIF file: $top->attach(Path => "./docs/mime-sm.gif", Type => "image/gif", Encoding => "base64"); ### Part #3: some literal text: $top->attach(Data=>$message); ### Send it: open MAIL, "| /usr/lib/sendmail -t -oi -oem" or die "open: $!"; $top->print(\*MAIL); close MAIL; For more examples, look at the scripts in the B directory of the MIME-tools distribution. =head1 DESCRIPTION MIME-tools is a collection of Perl5 MIME:: modules for parsing, decoding, I single- or multipart (even nested multipart) MIME messages. (Yes, kids, that means you can send messages with attached GIF files). =head1 REQUIREMENTS You will need the following installed on your system: File::Path File::Spec IPC::Open2 (optional) MIME::Base64 MIME::QuotedPrint Net::SMTP Mail::Internet, ... from the MailTools distribution. See the Makefile.PL in your distribution for the most-comprehensive list of prerequisite modules and their version numbers. =head1 A QUICK TOUR =head2 Overview of the classes Here are the classes you'll generally be dealing with directly: (START HERE) results() .-----------------. \ .-------->| MIME:: | .-----------. / | Parser::Results | | MIME:: |--' `-----------------' | Parser |--. .-----------------. `-----------' \ filer() | MIME:: | | parse() `-------->| Parser::Filer | | gives you `-----------------' | a... | output_path() | | determines | | path() of... | head() .--------. | | returns... | MIME:: | get() | V .-------->| Head | etc... | .--------./ `--------' | .---> | MIME:: | | `-----| Entity | .--------. | parts() `--------'\ | MIME:: | / returns `-------->| Body |<---------' sub-entities bodyhandle() `--------' (if any) returns... | open() | returns... | V .--------. read() | IO:: | getline() | Handle | print() `--------' etc... To illustrate, parsing works this way: =over 4 =item * B A parser is an instance of C. You hand it an input stream (like a filehandle) to parse a message from: if the parse is successful, the result is an "entity". =item * B An entity is an instance of C (a subclass of C). If the message had "parts" (e.g., attachments), then those parts are "entities" as well, contained inside the top-level entity. Each entity has a "head" and a "body". =item * B A "head" is an instance of C (a subclass of C). It contains information from the message header: content type, sender, subject line, etc. =item * B You can ask to "open" this data source for I or I, and you will get back an "I/O handle". =item * B This handle is an object that is basically like an IO::Handle... it can be any class, so long as it supports a small, standard set of methods for reading from or writing to the underlying data source. =back A typical multipart message containing two parts -- a textual greeting and an "attached" GIF file -- would be a tree of MIME::Entity objects, each of which would have its own MIME::Head. Like this: .--------. | MIME:: | Content-type: multipart/mixed | Entity | Subject: Happy Samhaine! `--------' | `----. parts | | .--------. |---| MIME:: | Content-type: text/plain; charset=us-ascii | | Entity | Content-transfer-encoding: 7bit | `--------' | .--------. |---| MIME:: | Content-type: image/gif | Entity | Content-transfer-encoding: base64 `--------' Content-disposition: inline; filename="hs.gif" =head2 Parsing messages You usually start by creating an instance of B and setting up certain parsing parameters: what directory to save extracted files to, how to name the files, etc. You then give that instance a readable filehandle on which waits a MIME message. If all goes well, you will get back a B object (a subclass of B), which consists of... =over 4 =item * A B (a subclass of B) which holds the MIME header data. =item * A B, which is a object that knows where the body data is. You ask this object to "open" itself for reading, and it will hand you back an "I/O handle" for reading the data: this could be of any class, so long as it conforms to a subset of the B interface. =back If the original message was a multipart document, the MIME::Entity object will have a non-empty list of "parts", each of which is in turn a MIME::Entity (which might also be a multipart entity, etc, etc...). Internally, the parser (in MIME::Parser) asks for instances of B whenever it needs to decode an encoded file. MIME::Decoder has a mapping from supported encodings (e.g., 'base64') to classes whose instances can decode them. You can add to this mapping to try out new/experiment encodings. You can also use MIME::Decoder by itself. =head2 Composing messages All message composition is done via the B class. For single-part messages, you can use the B constructor to create MIME entities very easily. For multipart messages, you can start by creating a top-level C entity with B, and then use the similar B method to attach parts to that message. I what most people think of as "a text message with an attached GIF file" is I a multipart message with 2 parts: the first being the text message, and the second being the GIF file. When building MIME a entity, you'll have to provide two very important pieces of information: the I and the I. The type is usually easy, as it is directly determined by the file format; e.g., an HTML file is C. The encoding, however, is trickier... for example, some HTML files are C<7bit>-compliant, but others might have very long lines and would need to be sent C for reliability. See the section on encoding/decoding for more details, as well as L<"A MIME PRIMER"> below. =head2 Sending email Since MIME::Entity inherits directly from Mail::Internet, you can use the normal Mail::Internet mechanisms to send email. For example, $entity->smtpsend; =head2 Encoding/decoding support The B class can be used to I as well; this is done when printing MIME entities. All the standard encodings are supported (see L<"A MIME PRIMER"> below for details): Encoding: | Normally used when message contents are: ------------------------------------------------------------------- 7bit | 7-bit data with under 1000 chars/line, or multipart. 8bit | 8-bit data with under 1000 chars/line. binary | 8-bit data with some long lines (or no line breaks). quoted-printable | Text files with some 8-bit chars (e.g., Latin-1 text). base64 | Binary files. Which encoding you choose for a given document depends largely on (1) what you know about the document's contents (text vs binary), and (2) whether you need the resulting message to have a reliable encoding for 7-bit Internet email transport. In general, only C and C guarantee reliable transport of all data; the other three "no-encoding" encodings simply pass the data through, and are only reliable if that data is 7bit ASCII with under 1000 characters per line, and has no conflicts with the multipart boundaries. I've considered making it so that the content-type and encoding can be automatically inferred from the file's path, but that seems to be asking for trouble... or at least, for Mail::Cap... =head2 Message-logging MIME-tools is a large and complex toolkit which tries to deal with a wide variety of external input. It's sometimes helpful to see what's really going on behind the scenes. There are several kinds of messages logged by the toolkit itself: =over 4 =item Debug messages These are printed directly to the STDERR, with a prefix of C<"MIME-tools: debug">. Debug message are only logged if you have turned L on in the MIME::Tools configuration. =item Warning messages These are logged by the standard Perl warn() mechanism to indicate an unusual situation. They all have a prefix of C<"MIME-tools: warning">. Warning messages are only logged if C<$^W> is set true and MIME::Tools is not configured to be L. =item Error messages These are logged by the standard Perl warn() mechanism to indicate that something actually failed. They all have a prefix of C<"MIME-tools: error">. Error messages are only logged if C<$^W> is set true and MIME::Tools is not configured to be L. =item Usage messages Unlike "typical" warnings above, which warn about problems processing data, usage-warnings are for alerting developers of deprecated methods and suspicious invocations. Usage messages are currently only logged if C<$^W> is set true and MIME::Tools is not configured to be L. =back When a MIME::Parser (or one of its internal helper classes) wants to report a message, it generally does so by recording the message to the B object immediately before invoking the appropriate function above. That means each parsing run has its own trace-log which can be examined for problems. =head2 Configuring the toolkit If you want to tweak the way this toolkit works (for example, to turn on debugging), use the routines in the B module. =over =item debugging Turn debugging on or off. Default is false (off). MIME::Tools->debugging(1); =item quiet Turn the reporting of warning/error messages on or off. Default is true, meaning that these message are silenced. MIME::Tools->quiet(1); =item version Return the toolkit version. print MIME::Tools->version, "\n"; =back =head1 THINGS YOU SHOULD DO =head2 Take a look at the examples The MIME-Tools distribution comes with an "examples" directory. The scripts in there are basically just tossed-together, but they'll give you some ideas of how to use the parser. =head2 Run with warnings enabled I run your Perl script with C<-w>. If you see a warning about a deprecated method, change your code ASAP. This will ease upgrades tremendously. =head2 Avoid non-standard encodings Don't try to MIME-encode using the non-standard MIME encodings. It's just not a good practice if you want people to be able to read your messages. =head2 Plan for thrown exceptions For example, if your mail-handling code absolutely must not die, then perform mail parsing like this: $entity = eval { $parser->parse(\*INPUT) }; Parsing is a complex process, and some components may throw exceptions if seriously-bad things happen. Since "seriously-bad" is in the eye of the beholder, you're better off I possible exceptions instead of asking me to propagate C up the stack. Use of exceptions in reusable modules is one of those religious issues we're never all going to agree upon; thankfully, that's what C is good for. =head2 Check the parser results for warnings/errors As of 5.3xx, the parser tries extremely hard to give you a MIME::Entity. If there were any problems, it logs warnings/errors to the underlying "results" object (see L). Look at that object after each parse. Print out the warnings and errors, I if messages don't parse the way you thought they would. =head2 Don't plan on printing exactly what you parsed! I Because of things like ambiguities in base64-encoding, the following is I going to spit out its input unchanged in all cases: $entity = $parser->parse(\*STDIN); $entity->print(\*STDOUT); If you're using MIME::Tools to process email, remember to save the data you parse if you want to send it on unchanged. This is vital for things like PGP-signed email. =head2 Understand how international characters are represented The MIME standard allows for text strings in headers to contain characters from any character set, by using special sequences which look like this: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= To be consistent with the existing Mail::Field classes, MIME::Tools does I automatically unencode these strings, since doing so would lose the character-set information and interfere with the parsing of fields (see L for a full explanation). That means you should be prepared to deal with these encoded strings. The most common question then is, B The answer depends on what you want to decode them I: ASCII, Latin1, UTF-8, etc. Be aware that your "target" representation may not support all possible character sets you might encounter; for example, Latin1 (ISO-8859-1) has no way of representing Big5 (Chinese) characters. A common practice is to represent "untranslateable" characters as "?"s, or to ignore them completely. To unencode the strings into some of the more-popular Western byte representations (e.g., Latin1, Latin2, etc.), you can use the decoders in MIME::WordDecoder (see L). The simplest way is by using C, a function wrapped around your "default" decoder, as follows: use MIME::WordDecoder; ... $subject = unmime $entity->head->get('subject'); One place this I done automatically is in extracting the recommended filename for a part while parsing. That's why you should start by setting up the best "default" decoder if the default target of Latin1 isn't to your liking. =head1 THINGS I DO THAT YOU SHOULD KNOW ABOUT =head2 Fuzzing of CRLF and newline on input RFC 2045 dictates that MIME streams have lines terminated by CRLF (C<"\r\n">). However, it is extremely likely that folks will want to parse MIME streams where each line ends in the local newline character C<"\n"> instead. An attempt has been made to allow the parser to handle both CRLF and newline-terminated input. =head2 Fuzzing of CRLF and newline when decoding The C<"7bit"> and C<"8bit"> decoders will decode both a C<"\n"> and a C<"\r\n"> end-of-line sequence into a C<"\n">. The C<"binary"> decoder (default if no encoding specified) still outputs stuff verbatim... so a MIME message with CRLFs and no explicit encoding will be output as a text file that, on many systems, will have an annoying ^M at the end of each line... I. =head2 Fuzzing of CRLF and newline when encoding/composing TODO FIXME All encoders currently output the end-of-line sequence as a C<"\n">, with the assumption that the local mail agent will perform the conversion from newline to CRLF when sending the mail. However, there probably should be an option to output CRLF as per RFC 2045 =head2 Inability to handle multipart boundaries with embedded newlines Let's get something straight: this is an evil, EVIL practice. If your mailer creates multipart boundary strings that contain newlines, give it two weeks notice and find another one. If your mail robot receives MIME mail like this, regard it as syntactically incorrect, which it is. =head2 Ignoring non-header headers People like to hand the parser raw messages straight from POP3 or from a mailbox. There is often predictable non-header information in front of the real headers; e.g., the initial "From" line in the following message: From - Wed Mar 22 02:13:18 2000 Return-Path: Subject: Hello The parser simply ignores such stuff quietly. Perhaps it shouldn't, but most people seem to want that behavior. =head2 Fuzzing of empty multipart preambles Please note that there is currently an ambiguity in the way preambles are parsed in. The following message fragments I are regarded as having an empty preamble (where C<\n> indicates a newline character): Content-type: multipart/mixed; boundary="xyz"\n Subject: This message (#1) has an empty preamble\n \n --xyz\n ... Content-type: multipart/mixed; boundary="xyz"\n Subject: This message (#2) also has an empty preamble\n \n \n --xyz\n ... In both cases, the I completely-empty line (after the "Subject") marks the end of the header. But we should clearly ignore the I empty line in message #2, since it fills the role of I<"the newline which is only there to make sure that the boundary is at the beginning of a line">. Such newlines are I part of the content preceding the boundary; thus, there is no preamble "content" in message #2. However, it seems clear that message #1 I has no preamble "content", and is in fact merely a compact representation of an empty preamble. =head2 Use of a temp file during parsing I Although the amount of core available on even a modest home system continues to grow, the size of attachments continues to grow with it. I wanted to make sure that even users with small systems could deal with decoding multi-megabyte sounds and movie files. That means not being core-bound. As of the released 5.3xx, MIME::Parser gets by with only one temp file open per parser. This temp file provides a sort of infinite scratch space for dealing with the current message part. It's fast and lightweight, but you should know about it anyway. =head2 Why do I assume that MIME objects are email objects? Achim Bohnet once pointed out that MIME headers do nothing more than store a collection of attributes, and thus could be represented as objects which don't inherit from Mail::Header. I agree in principle, but RFC 2045 says otherwise. RFC 2045 [MIME] headers are a syntactic subset of RFC-822 [email] headers. Perhaps a better name for these modules would have been RFC1521:: instead of MIME::, but we're a little beyond that stage now. When I originally wrote these modules for the CPAN, I agonized for a long time about whether or not they really should subclass from B (then at version 1.17). Thanks to Graham Barr, who graciously evolved MailTools 1.06 to be more MIME-friendly, unification was achieved at MIME-tools release 2.0. The benefits in reuse alone have been substantial. =head1 A MIME PRIMER So you need to parse (or create) MIME, but you're not quite up on the specifics? No problem... =head2 Glossary Here are some definitions adapted from RFC 1521 (predecessor of the current RFC 204[56789] defining MIME) explaining the terminology we use; each is accompanied by the equivalent in MIME:: module terms... =over 4 =item attachment An "attachment" is common slang for any part of a multipart message -- except, perhaps, for the first part, which normally carries a user message describing the attachments that follow (e.g.: "Hey dude, here's that GIF file I promised you."). In our system, an attachment is just a B under the top-level entity, probably one of its L. =item body The "body" of an L is that portion of the entity which follows the L and which contains the real message content. For example, if your MIME message has a GIF file attachment, then the body of that attachment is the base64-encoded GIF file itself. A body is represented by an instance of B. You get the body of an entity by sending it a L message. =item body part One of the parts of the body of a multipart B. A body part has a B and a B, so it makes sense to speak about the body of a body part. Since a body part is just a kind of entity, it's represented by an instance of B. =item entity An "entity" means either a B or a B. All entities have a B and a B. An entity is represented by an instance of B. There are instance methods for recovering the L (a B) and the L (a B). =item header This is the top portion of the MIME message, which contains the "Content-type", "Content-transfer-encoding", etc. Every MIME entity has a header, represented by an instance of B. You get the header of an entity by sending it a head() message. =item message A "message" generally means the complete (or "top-level") message being transferred on a network. There currently is no explicit package for "messages"; under MIME::, messages are streams of data which may be read in from files or filehandles. You can think of the B returned by the B as representing the full message. =back =head2 Content types This indicates what kind of data is in the MIME message, usually as I. The standard major types are shown below. 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