TODO IMMEDIATELY: Is it possible to provide names/filenames for text/* sections? If so, move set/get_name() to LAFmessage_MIME. Fix Header to canonicalize headers according to RFC 822 section 3 and enforce format rules (email addresses, dates, illegal character sequences, etc). Make line wrapping attempt to break lines at whitespace instead of the middle of words. Finish the documentation! TODO LATER: Consider adding something to monitor the worker threads on an asynchronous queue to ensure they don't all exit before the work is done. Fix the avl_compare() and avl_find() function in Attachment, Header, Text and Message to somehow return an error code if the passed objects' values turn out to be invalid for some reason. Change Text to allow the charset to be set by the user. Change Text::get_mime_section() to specify the charset. Add a "Precendence" header type for "Bulk", "Junk", etc. Add a filesystem mail store object (LAFCMS?). Add a database mail store object (LAFCMS). Add an IMAP4 interface object. Make additional_error_text get passed around so it can retrieve SMTP and POP3 protocol error messages. Consider making the POP3, SMTP and IMAP4 classes derive from a common base. VERSION 1.0.1.0 - 3/2/2005 Removed some debugging code from java_Message.cpp and java_SMTP.cpp. VERSION 1.0.0.0 - 2/23/2005 Changed the license from the LAF LGPL to the GNU GPL. Incorporated the changes from LAFcommon version 8.0.0.0. VERSION 0.0.27.0 - 12/8/2004 Fixed a bug in Java_com_lookandfeel_lafmessage_Message_cmd_1add_1attachment() (the JNI version of LAFmessage_Message::cmd_add_attachment()) that was returning LAFMESSAGE_error_invalid_value if the parameter encoding was given but the parameter inline_flag was not. Fixed a bug in Java_com_lookandfeel_lafmessage_SMTP_finalize() that was calling global_attachment_init() instead of global_smtp_init(). VERSION 0.0.26.0 - 8/25/2004 Incorporated the updates from LAFcommon version 7.1.1.0. Fixed a number of small syntactic items to allow LAFmessage to compile on Mac OS X. VERSION 0.0.25.0 - 8/20/2003 Fixed every JNI function that accepts a String object or an array of objects to gracefully fail when those parameters are NULL. Incorporated the changes from LAFcommon version 7.0.0.0. Changed LAFmessage_data_store::LAFmessage_data_store() to use the new features of CMutexQueue correctly. VERSION 0.0.24.0 - 4/17/2003 Fixed Java_com_lookandfeel_lafmessage_POP3_set_1id() and Java_com_lookandfeel_lafmessage_SMTP_set_1id() to allow the caller to set the object's ID to a previously unused value instead of returning LAFMESSAGE_error_not_found. VERSION 0.0.23.0 - 4/10/2003 Incorporated the changes from LAFcommon version 6.8.0.0. Fixed LAFmessage_SMTP::queue_run() to deliver a message to every recipient when failure_retries is 0 instead of just the first one. VERSION 0.0.22.0 - 2/11/2003 Incorporated the changes from LAFcommon version 6.6.1.0. Fixed LAFmessage_SMTP::smtp_script_generate to correctly replace periods at the beginning of a line with an additional period. This was causing problems in production with HTML emails containing lots of URLs. VERSION 0.0.21.0 - 1/6/2003 Added the copyright header to the top of java_Attachment.cpp, java_globals.cpp, java_globals.h, java_Header.cpp, java_Message.cpp, java_POP3.cpp, java_SMTP.cpp, java_Text.cpp. Removed the declaration for global_empty() from java_globals.h as it was never defined or used. Changed lafmail to send its mail synchronously so delivery errors can be returned. VERSION 0.0.20.0 - 9/27/2002 Changed LAFmessage_SMTP::smtp_script_execute() to place sent recipient addresses in a separate list until the entire transaction is successful. LAFmessage_SMTP::smtp_script_cleanup() will then move the addresses to the appropriate list. This is necessary because a network error in the middle of a large list of recipients would leave the processed recipient addresses on the sent_recipient_addresses list, even though the message was not delivered. VERSION 0.0.19.0 - 9/25/2002 Incorporated the changes from LAFcommon version 6.5.7.0. Fixed LAFmessage_SMTP::queue_run() so the failure retry mechanism will work as advertised. Fixed new/free mismatches in com_Attachment::AddHeader(), com_Message::AddAttachment(), com_Message::AddHeader(), com_Message::AddText() and com_Text::AddHeader(). Fixed thinkos in LAFmessage_SMTP::cmd_remove(), LAFmessage_SMTP::cmd_remove_all() and LAFmessage_SMTP::internal_empty() that were not allowing for NULL message objects in the processed messages list and could leak memory. Fixed a small typo in lafmail.asp. VERSION 0.0.18.0 - 9/3/2002 Fixed identical logic errors in com_SMTP::get_RejectedRecipientAddresses(), com_SMTP::get_SentRecipientAddresses(), com_SMTP::get_QueuedRecipientAddresses() and com_SMTP::get_RecipientAddresses() that were preventing the functions from detecting array manipulation errors. Fixed identical VARIANT-handling errors in com_SMTP::get_RejectedRecipientAddresses(), com_SMTP::get_SentRecipientAddresses(), com_SMTP::get_QueuedRecipientAddresses() and com_SMTP::get_RecipientAddresses() that were preventing the functions from creating VARIANTs of type VT_BSTR. VERSION 0.0.17.0 - 8/30/2002 Removed an extraneous response code from the macro LAFMESSAGE_SMTP_EXPECTED_RESPONSES that was preventing LAFmessage_SMTP::smtp_script_execute() from completing successfully. This bug has existed for a long time but only now became evident because of the fix in 0.0.16.0 that allowed LAFmessage_SMTP::smtp_script_execute() to report errors. VERSION 0.0.16.0 - 8/26/2002 Incorporated the changes from LAFcommon version 6.5.3.0. Changed the parameter list of com_SMTP::get_QueuedMessages() and com_SMTP::put_QueuedMessages() to use a single VARIANT instead of a VARIANT and a long that are each ignored at different times. This change breaks backwards compatibility. Fixed the Makefile and lots of other little details so LAFmessage will now compile down into libLAFmessage.so on Linux systems and will load correctly into programs that attempt to link to it (e.g. java). Added JNI/GNUmakefile so the Java files will also compile under Linux. Fixed some of the #include directives so LAFmessage's reusables files will compile in a non-MFC Win32 project. Fixed LAFmessage_SMTP::smtp_script_execute() so it would correctly report protocol errors. VERSION 0.0.15.0 - 7/9/2002 Changed LAFmessage_SMTP::cmd_wait_until_empty() to wait until all messages are completely processed before returning a success code. Changed LAFmessage_SMTP::queue_run() to start or kill threads as appropriate if max_worker_threads changes during an asynchronous run. Fixed all the uses of get_internal_object() in the COM interface -- none of them were using the reference counting system. Fixed numerous places in LAFmessage_SMTP and the COM classes where the wrong return code was being returned, either because an error that generated a return code was being overwritten with a different one or because the return code was unconditionally set to a success before the function exited. Changed the COM interface to expose the address-checking functionality introduced in version 0.0.14.0. VERSION 0.0.14.0 - 7/9/2002 Incorporated the changes from LAFcommon version 6.5.2.0. Removed unused variables and such so the java_* files will compile cleanly under Linux. Found the TOFRODOS package to make moving files from Windows to Linux easier. Finished the Makefile so compiling a shared object under Linux is now possible. Added header types for Reply-By and Importance so Outlook-style flags are now possible. Changed the Makefiles to make compiling a shared object under Linux possible. Added the ability to check addresses without delivering messages by adding NULL message objects to an SMTP queue. NOTE: This depends on using a mail server that will verify the recipient addresses. By default, sendmail won't do that -- it takes some hacking. The COM interface still needs some work to expose this feature, though the JNI interface can use it. VERSION 0.0.13.0 - 6/3/2002 Incorporated the changes from LAFcommon version 6.5.0.0. Fixed a bug in LAFMESSAGE_display_string() that would set *strlen_return to an uninitialized value if input_string was NULL. Renamed LAFmessage_POP3::get_count() to LAFmessage_POP3::get_num_messages(). Fixed some uninitialized variable errors spotted by g++ (Linux). Added a JNI interface. Now there's even more stuff to document (woohoo). VERSION 0.0.12.0 - 4/8/2002 Removed LAFmessage_enum::is_valid_reserved_header_type() and changed LAFmessage_enum::is_valid_header_type() to allow any header type to be set by any caller. VERSION 0.0.11.0 - 4/3/2002 Incorporated the changes from LAFcommon version 6.3.0.0. Changed LAFmessage_Attachment and LAFmessage_Text to use LAFmessage_Header objects internally to hold their header information. Removed get_mime_section_content() and get_mime_section_header() from LAFmessage_Attachment and LAFmessage_Text. Removed the MIMESectionContent and MIMESectionHeader properties from LAFmessage.Attachment and LAFmessage.Text. Renamed LAFmessage_Message::set_mime_message() and LAFmessage_Message::get_mime_message() to LAFmessage_Message::set_mime_section() and LAFmessage_Message::get_mime_section(), respectively. Renamed the MIMEMessage property on LAFmessage.Message to MIMESection. Moved the per-class declarations of get_object() and put_object() into LAFmessage_MIME. Overloaded LAFmessage_MIME::set_type() and LAFmessage_MIME::set_encoding() to allow them to be called when the object has already been locked. Changed the constructor and destructor of LAFmessage_Attachment, LAFmessage_Header, LAFmessage_Text and LAFmessage_Message to be private. Added get_content_id() and set_content_id() to LAFmessage_Attachment. Changed cmd_clone(LAFmessage_MIME **) in LAFmessage_Attachment, LAFmessage_Header, LAFmessage_Text, LAFmessage_Message and LAFmessage_MIME to be private. Changed all uses of SafeArrayCreate() to SafeArrayCreateVector() since no SaveArrayCreateVector() is advertised as being faster and no multi- dimensional SAFEARRAYs are being created anyway. Added LAFMESSAGE_DISPLAY_quoted_printable and LAFMESSAGE_DISPLAY_base64 as valid display enumeration values. Changed the COM property Attachment.Content to accept two new optional parameters: the first parameter controls the returned data type -- an array of unsigned bytes or a string. The second parameter allows the caller to canonicalize the data if the desired return type is a string. Fixed identical bugs in LAFmessage_Attachment::cmd_clone(), LAFmessage_Header::cmd_clone() and LAFmessage_Text::cmd_clone() that were not cloning the type_index member variable. Changed the minimum encoding level for a new LAFmessage_Attachment object to 7BIT instead of BASE64. Added is_valid_reserved_header_type() to LAFmessage_enum to filter on all header types, even ones the caller is not allowed to create. VERSION 0.0.10.0 - 3/14/2002 Incorporated the changes from LAFcommon version 6.1.1.0. After a discovery by Eric Beane, added the MIME type "text/x-aol" to encode HTML-like messages for AOL clients prior to version 6.0. Apparently, older AOL clients support the HTML tags BR, FONT, B, I, U, SUB, SUP, BIG, SMALL, H1, H2, H3, P, BODY, A, CENTER and STRONG when encoded as "text/x-aol". Added the return code LAFMESSAGE_error_missing_content to address a bug located by Lonnie Pryor: rendering a section whose content is NULL throws an access violation. VERSION 0.0.9.0 - 2/21/2002 Incorporated the changes from LAFcommon version 6.0.0.0. Fixed LAFmessage_SMTP::set_smtp_server() and LAFmessage_POP3::set_pop3_server() to accept IP addresses with octets of 0 and/or 255. Changed com_Message::put_Attachments(), com_Message::put_Headers(), com_Message::put_Texts(), com_SMTP::put_QueuedMessages() and global_get_display() to accept SAFEARRAYs that contain 0 elements and treat them the same as a VARIANT of type VT_EMPTY. Changed the SMTP network timeout limit from 2 minutes to 15 minutes. VERSION 0.0.8.0 - 1/10/2002 Fixed LAFmessage_SMTP::set_smtp_server() and LAFmessage_POP3::set_pop3_server() so they would not always return LAFmessage_enum::LAFMESSAGE_success. Fixed LAFmessage_SMTP and LAFmessage_POP3 to initialize the Windows Sockets library in their constructors and shut it down in their destructors. Fixed LAFmessage_SMTP::get_processed_messages() to return a NULL-terminated array of LAFmessage_Message*s instead of an array of NULLs. Fixed LAFMESSAGE_word_wrap_content() to correctly terminate zero-length strings. Began work on an IMAP4 object: LAFmessage_IMAP4. VERSION 0.0.7.0 - 12/18/2001 Incorporated the changes from LAFcommon version 5.4.3.0. Fixed a set of serious thinkos in com_POP3::put_ID() and com_SMTP::put_ID() that were preventing them from ever working properly. Added "=20" to the list of unbreakable sequences in LAFmessage_MIME::encode_quoted_printable(). Changed LAFmessage_MIME::update_ref_count(), LAFmessage_POP3::update_ref_count() and LAFmessage_SMTP::update_ref_count() to use timeouts in their lock attempts. Fixed LAFmessage_POP3::set_id() and LAFmessage_SMTP::set_id() to handle the object locking correctly and to re-insert the object into the object cache if the ID change was unsuccessful. Fixed most occurances of GetBSTRFromString() to pass the string through LAFMESSAGE_NULL_STRING_FILTER() first. VERSION 0.0.6.0 - 12/18/2001 Changed LAFmessage_SMTP::~LAFmessage_SMTP() and LAFmessage_POP3::~LAFmessage_POP3() to unconditionally lock the object and disable the mutex for destruction before calling internal_empty(). Changed LAFmessage_SMTP::init(), LAFmessage_SMTP::empty(), LAFmessage_POP3::init() and LAFmessage_POP3::empty() to use a timeout value when attempting to lock the object and to return LAFmessage_enum::LAFMESSAGE_error_mutex_timeout if the lock attempt times out. Fixed LAFmessage_MIME::encode_quoted_printable() to include all of the possible hex-encoded values as unbreakable sequences when word-wrapping lines. Changed LAFMESSAGE_word_wrap_content() to not allow unbreakable sequences to be substrings of other unbreakable sequences -- all possible sequences must be given and those that contain others must be listed first. VERSION 0.0.5.0 - 12/12/2001 Incorporated the changes from LAFcommon version 5.4.2.0. Changed com_Attachment::get_Content() to return a SAFEARRAY VARIANT that contains unsigned char VARIANTs instead of a BSTR VARIANT. This brings it in line with the API documentation and makes it much more useful -- binary attachments often contain embedded null characters. Changed com_Attachment::put_Content() to accept a SAFEARRAY VARIANT that contains unsigned char VARIANTs instead of just BSTR VARIANTs. Changed com_Attachment::put_Content() to accept a SAFEARRAY VARIANT that contains unsigned chars instead of VARIANTS so it can be used with output from C++ COM objects like SAFileUp. Changed com_Message::AddAttachment() to accept a SAFEARRAY VARIANT that contains unsigned char VARIANTs instead of just BSTR VARIANTs. The following bugs were discovered by Lonnie Pryor. Fixed com_Message::get_HeaderContents() to only return LAFMESSAGE_error_internal when an internal error occurs. VERSION 0.0.4.0 - 12/11/2001 Fixed a set of thinkos in LAFmessage_SMTP::cmd_pause(), LAFmessage_SMTP::cmd_unpause() and LAFmessage_SMTP::queue_run() that assumed pause and unpause commands would not occur within the same second. Now, a queue is considered unpaused when the current time is equal to or greater than the unpause time, not when the current time is greater than the unpause time. VERSION 0.0.3.0 - 12/10/2001 Removed all of the "helpstring" entries from the IDL file. The typelib is a stupid place to store documentation and comments like "property Name" and "method Save" don't help anyone anyway. Added overridden get_object(), put_object() and cmd_clone() functions to LAFmessage_Attachment, LAFmessage_Header, LAFmessage_Text and LAFmessage_Message that do not require casting the object pointer to LAFmessage_MIME**. Changed the content type of LAFmessage_Attachment from char* to unsigned char*. Fixed LAFmessage.rc to use the version numbers from version.h. VERSION 0.0.2.0 - 11/26/2001 Incorporated the changes from LAFcommon version 5.4.0.0. Cleaned up all the LAFmessage_*.* files so they will compile and work under Linux. Moved assignment and storage of recipient addresses for Messages to SMTP where it belongs. SMTP::set_queued_messages() and SMTP::cmd_add() now accept arrays of recipient addresses. Added SMTP::get_queued_recipient_addresses() and SMTP::get_recipient_addresses() to make working with a queued Message easier. Added LAFMESSAGE_copy_arrays_of_strings(char***,char***,long*,long,int, LAFMESSAGE_ENUM::display_types*) to merge multiple arrays of strings together as they are copied. Added a Makefile to make compiling the project under Linux a bit easier. Renamed Attachment to LAFmessage_Attachment. Renamed Header to LAFmessage_Header. Renamed Message to LAFmessage_Message. Renamed POP3 to LAFmessage_POP3. Renamed SMTP to LAFmessage_SMTP. Renamed Text to LAFmessage_Text. Renamed LAFMESSAGE_ENUM to LAFmessage_enum. Changed LAFmessage_SMTP::set_queued_messages() and LAFmessage_SMTP::cmd_add() to check smtp_server and sender_address before queueing messages for delivery. LAFmessage_SMTP::smtp_script_execute() checks these values as well in case they are changed during the queueing process but hopefully this will prevent sloppy errors. Changed LAFmessage_SMTP::queue_handle_update() not to start more worker threads than queued messages, no matter what the maximum is set to. This should prevent starting a dozen worker threads when a single message is queued. Added get_min_delivery_secs() and set_min_delivery_secs() to LAFmessage_SMTP to allow the caller to specify the minimum number of seconds between SMTP server transactions. This can be used to slow down batch message delivery so as not to overload a remote server. Fixed all of the COM interface objects to be completely thread-safe. Overloaded LAFmessage_POP3::get_message() and LAFmessage_POP3::get_all_messages() to return the message as downloaded from the POP3 server (before being passed to LAFmessage_Message::set_mime_message()) as a char*. Added get_ItemText() to com_POP3 to expose LAFmessage_POP3::get_message(long,char*,LAFmessage_enum::display_types*) through COM. Fixed LAFmessage_SMTP::smtp_script_execute() so multiline responses are always handled correctly. Moved the MIME Content-Type names into an array within LAFmessage_globals.h to make it easier to add new content types later. Fixed a sundry of potential bugs where variables could be used without having been initialized (caught by GCC). Created LAFmessage_MIME as a base class for LAFmessage_Message, LAFmessage_Attachment, LAFmessage_Header and LAFmessage_Text. This allowed the consolidation of the object pools as well as the inheritance of a number of functions -- the LAFmessage_Message.* files are much smaller now. Replaced all of the calls to AfxBeginThread() with _beginthread(). Changed all of the worker thread functions to wait on a mutex queue variable instead of periodically checking an int to determine if they should exit. This will mean that, when the process is exiting, the mutex queue will be unlocked and the worker threads will immediately wake up. Significantly reworked all of the set_mime_content() functions to be more flexible and more correct in their parsings of MIME messages. Changed the way cached object idle time is tracked -- there is no point in updating last_accessed in every member function because the object will not be discarded until its reference count reaches zero. last_accessed is now only updated when the reference count is updated. Changed the LAFmessage_SMTP object cache not to remove objects with queued messages, regardless of their reference counts or idle times. Changed LAFmessage_POP3 not to immediately construct LAFmessage_Message objects from the downloaded message text but to wait until the objects are needed. Overloaded LAFmessage_POP3::get_message() and LAFmessage_POP3::get_all_messages() to return the text downloaded from the POP3 server without passing it through LAFmessage_Message. Added the ReturnObjects property to the POP3 COM object to determine whether IMessage objects or BSTRs are returned by get_Item() and get__NewEnum(). Fixed innumerable bugs of innumerable types in innumerable places. Many other fixes and changes that didn't get logged. VERSION 0.0.1.0 - 10/17/2001 Initial version. Version 1.0.0.0 will be complete when the documentation has been written and a good testing script has been created. This project is being released as free software in its first version! Wahoo!