'''[http://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/mime/mime.html%|%MIME]''', a [Tcllib] module, provides commands to create and manipulate [MIME] body parts. ** Synopsis ** ====== package require mime ====== ** Documentation ** [http://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/mime/mime.html%|%official reference for development release]: [http://tcllib.sourceforge.net/doc/mime.html%|%official reference] for latest release: ** Description ** Based upon the [MIME] package from [Marshal T. Rose], which has a hard dependency upon [Trf]. [Tcllib]'s variatn converts that into a soft dependency. It tries to use [Trf] to gain performance but falls back to pure tcl if that package is not present. ** Example: Basic ** The distribution documentation deserves ''many'' more examples. Until [CL] makes the time to update it, we'll keep several of them here. In this example, individual mail items might well have originated as return values from the [pop3] [package]. ====== package require mime set item {From claird@starbase.neosoft.com Tue May 29 11:49:26 EDT 2001 Date: Tue, 29 May 2001 11:03:02 -0500 From: Cameron Laird To: someone@somewhere.com,other@other.org Subject: some subject Message-ID: <20010529110302.A47592@starbase.neosoft.com> This is only a test.} # A production version deserves exception-handling. set token [mime::initialize -string $item] puts "The subject is '[mime::getheader $token Subject]'." ====== Address parsing is an area where many, MANY square wheels have been reinvented, in part because RFC 822 (and updates ... []) are so poorly understood. Here's an example of a correct usage: ====== # Take $item from above. set token [mime::initialize -string $item] set to [mime::getheader $token To] puts "The (unparsed) recipients are '$to'." set parsed [mime::parseaddress $to] foreach element $parsed { array set array $element puts "One deliverable address is $array(address)." } ====== This prints ======none The (unparsed) recipients are 'someone@somewhere.com,other@other.org'. One deliverable address is someone@somewhere.com. One deliverable address is other@other.org. ====== ---- In the above example, `$to` is set as the result of ====== mime::getheader $token To ====== . This value is a list. However, in mime 1.5.4, `mime::parseaddress` wants a string so the that line should be: ====== set parsed [mime::parsedaddress [lindex $to 0]] ====== The curly braces were being treated as part of the string. That gave almost correct results. :) ** Mail with special characters ** It took me quite some time to come up with a version that can send an email with special characters (german Umlaute) and is correctly displayed in windows and unix. ====== package require smtp set text {some text with 8 special characters äöü ÄÖÜ ß €} set tok [mime::initialize -canonical text/plain -param {charset "utf-8"} \ -encoding 8bit -string [encoding convertto utf-8 $text] set erg [smtp::sendmessage $tok \ -servers localhost \ -recipients myself@localhost \ -usetls 1 \ -username myself \ -password password \ -header [ list Subject [mime::word_encode utf-8 quoted-printable $text]] \ -header [list From myself@localhost] \ -header [list To myself@localhost] \ ] ====== another version was ====== set tok [mime::initialize -canonical text/plain -param {charset "iso8859-1"} \ -encoding 8bit -string $text] ====== but this doesn't show the Euro-Symbol. Using iso8859-16 doesn't work with windows mail program outlook. There are lots of versions and combinations to try. An additional joy are ancient versions of tcllib used by colleagues. ** Misc ** Things to explain: performance issues (large messages: headers, split, buffering); package (including fix-up); examples; exception-(mis)handling; magic arrays; ... [CL] has found two principal difficulties in trying to use mime with 8.0 or early 8.1: the "format %c ..." change (explain) and the incompatibility in interpretation of "\n" vs. {\n} to regsub (explain). ---- One of the difficulties in explaining mime is its flexibility. It can do many, many things, and it's hard to know where to begin explaining it. In a case like this, I like a few examples--feel free to think of them as a cookbook of recipes for starting points. How, for instance, can you use Tcl to automate emission of a message which includes an [attachment]? ---- One definite fault of 0.8 is that it only reports some of the filenames of attachments it detects (explain Content-Disposition alternative). [CL] has code that repairs this, but has yet to check it in. ---- As this is noted nowhere, use `mime::word_encode` to encode your headers according to your needs. As an example we are using ====== set subject_encoded [mime::word_encode "iso8859-1" base64 $subject] ====== to make sure the subject is encoded as well . OpenACS has a complex_send procedure that makes use of a lot of the mime functionality. It is contained in [http://cvs.openacs.org/cvs/openacs-4/packages/acs-mail-lite/tcl/complex-send-procs.tcl?rev=1.1&view=log]. ** See Also ** [A Message User Agent]: an example of generating multi-part MIME messages [Sorting mail into Maildirs]: [Reading messages that might be MIME-encoded]: [Email Authentication with MIME], by [Jeff Gosnell]: an example and functional script. It is an SMTP email authenticator. It turns out that to authenticate a user in SMTP requires MIME format. The script will display a GUI asking for the username, password, and server (port will always be 25, unless the programmer changes that or modifies the script for their own use). After receiving this information (and pressing the "Ok" button or ) the script attempts to authenticate the user. [JMN] 2006-03-30 Actually the above statement re MIME & SMTP-AUTH is a little misleading. It's more correctly stated that SMTP-AUTH uses base64 encoding for the AUTH types LOGIN and PLAIN. You don't need a MIME package to do SMTP Authentication. In fact if you happen to have a message on disk that is already in MIME format - you still don't necessarily need a MIME package to submit it to an SMTP server. This might be the case for example when using Tcl to pick up a maildrop file and forward it somewhere. The MIME package has some useful features such as `mime::parseaddress` that can help when handling mail - but if you care about memory consumption and performance don't run the whole message text through the MIME parser unnecessarily. ** Historical: `mime::initialize` ** In earlier versions of MIME, ====== mime::initialize ... -string ... ====== could be slow. See [https://groups.google.com/d/msg/comp.lang.tcl/Z50YYngYlok/bjeRwY7_bHoJ%|%ime::initialize has to perform better], [Cameron Laird], [comp.lang.tcl], 2001-11-08. That is probably not the best way to process a message of unknown size anyway. There is an example of a different approach in [Sorting mail into Maildirs]. [Andreas Kupries]: One issue with performance (splitting a '''large''' string at each character created thousands of [Tcl_Obj]'s containing all the same character, gobbling up memory like mad) was solved for Tcl 8.4a3, by [Donal Fellows]. This performance improvement was also one of the [Changes in Tcl/Tk 8.3.3]. <> MIME | Tcllib