|
After a careful review of the current codebase (HtmlEmail.java rev 511673, MultiPartEmail.java rev 517714), I have discovered, that the MIME layout generated is not quite as described in my previous posting.
In many circumstances both HtmlEmail and MultiPartEmail generates MIME structures that do not conform to MIME recommendations. Below, I have listed the MIME structures generated, as well as how I believe they should have been. Example 1: Should have been: Example 2: Should have been: Example 3: should have been: Example 4: should have been: Example 5: This one is well-structured! Conclusion: With regards to the automatically generated text/html part, based on the text/plain part, I concede that this is part of the API contract (specified in JavaDoc of HtmlEmail.setMsg(String) ), although I still believe that generating redundant data is silly. It is fairly easy to show email clients choking on the above MIME structures, one example being embedded images being displayed as attachments by virtually any clients. I agree that the current codebase is an improvement on version 1.0, but I think making the 1.1 release at this stage with MIME structures that violates even the most basic MIME recommendations (see examples above) would be wrong. One alternative possibility would be planning a version 1.2 with a (thoroughly tested) restructuring of the MIME generation.
Morten Hattesen made changes - 13/Mar/07 11:16 PM
What clients, specifically, do you see choking? I'll take a closer look. Your MIME structures also look correct in the examples you give.
Regarding a 1.1 release: when I started working on this, I noticed quickly that there were some design choices that I didn't agree with. For example, I'm not particularly happy with the inheritance hierarchy; I see no reason for HtmlEmail to extend MultiPartEmail, since the former does not have an is-a relationship with the latter. However, I figured that it could be made to work in the current incarnation, and since there are already people using this library, maintaining the API contract and avoiding breaking changes wherever possible was the most important consideration. Unfortunately, this makes it tricky to address situations like this where the objectively best solution is to refactor. I hope it's easier to see where I'm coming from now... In Examples 1 and 4, if you just want to send a plaintext email, then use SimpleEmail; that's what it's for. While you could certainly argue that HtmlEmail should know how to reshape its MIME structure to handle a plaintext email, you could also make the same argument that MultiPartEmail should know how to handle HTML text without attachments in the same way. And also for SimpleEmail to handle HTML text, and so on. Suddenly there are three classes that have the exact same functionality, so naturally you refactor them into one class or start abstracting out interfaces and concrete classes... but doing that breaks the API contract, and you're back to square one. The least evil solution I can see is getting the existing classes to work as well as possible while maintaining the contracts and then helping users to understand that they need to use the right class for the right task. To that end, it's probably a good idea to try to fix examples 2 and 3. I'll take a look this week and see what I can do. I have a couple of comments...
The API contract for HtmlEmail http://jakarta.apache.org/commons/email/api-release/org/apache/commons/mail/HtmlEmail.html If HtmlEmail does not support generating messages with a single text/plain MIME part, by gracefully degrading to content resembling that generated by SimpleEmail/MultiPartEmail, then it should throw an IllegalStateException (possibly wrapped in an EmailException), rather than generating a fundamentally flawed MIME structure. With regards to my example 3, the argument is that the currently generated MIME structure, with attachments inside a multipart/related container does not follow MIME recommendations nor does it resemble the structure generated by other popular smtp clients. Attachments should be contained in a multipart/mixed container. I may not be able to provide concrete proof of email clients that will choke on the current MIME structure (although I will do my best to do so), but that should not be used as an excuse to continue to generate flawed MIME structure. I do, however recognise the need for thorough testing prior to any major change being made, as well as the "if it ain't broke, don't fix it" paradigm. My final argument is, that since the principal role of commons-email is to provide a simple API facade on top of the complex JavaMail API, it should always generate MIME structures that adapts to the actual contents. In other words, the client-programmer need not concern himself with having to choose a "lesser" Email subclass just because a certain email instance does not contain one of the allowed content types. In other words, I feel that the only reason not to always choose HtmlEmail to generate emails, is when the client programmer never requires facilities offered by HtmlEmail, and wishes a simpler API (MultiPartEmail or SimpleEmail).
I will be happy to contribute code, and/or testing effort on this issue, please let me know if I can be of any assistance. For a thorough (although non-authoritative) explanation of MIME multipart subtypes, see http://en.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions#Multipart_Subtypes
The current plan is to try to implement and test cases 2 and 3 above. Hopefully I'll get to it soon – this is the last thing blocking a 1.1 release.
I can't really do any of these cases without rewriting HtmlEmail and I really don't see the need to get this into 1.1. Pushing back to 2.0 for revisiting then.
Ben Speakmon made changes - 12/Sep/07 11:11 PM
I'm pretty sure I'm jumping the gun here and I shouldn't be posting this here, but after a morning with Google searches I've been unable to find any real solution for the messed up mime types.
So, my afternoon has been spent writing something that at least fixes the issues I've been facing with the MIME types mentioned above. As far as I can tell, my abuse of the standard HtmlEmail class should work for variations of: text + html + attachment + inline Example #3 The only significant changes are in the build() method, but I'm still pretty sure I would've broken something else (time limitations mean I can't really give it a good going over - it works for my use cases), but this might help someone else who has the same problem...
Martin Lau made changes - 23/Oct/07 09:14 AM
Since this has not been solved, I was wondering if I could put forth some code for evaluation and feedback. Martin is right, only the build() method in HtmlEmail must be fixed to properly handle text/html, inline images, and attachments. The quick solution would be to rewrite it so that the multiparts look something like this:
Content-Type: multipart/mixed; boundary="attachment" --attachment --html-inline --text-andor-html --text-andor-html - --html-inline --html-inline - --attachment Content-Type: [some type]; name=file1.zip --attachment Content-Type: [some type]; name=fileN.zip - Ken See the HtmlEmail.java attachment
Kenneth Gendron made changes - 29/Nov/08 06:11 PM
Kenneth, I'm currently integrating your patch .... do you have some more regression tests by accident?
Siegfried Goeschl made changes - 29/Dec/08 02:51 PM
Siegfried Goeschl made changes - 29/Dec/08 02:55 PM
Used Kenneth's implementation of HtmlEmail.buildMimeMessage() and did some field testing (Outlook, Outlook WebAccess, GMX WebMail, Apple Mail, Thunderbird) - it looks good. The other guys are much more knowledgeable regarding mail spec ...
Siegfried Goeschl made changes - 29/Dec/08 05:47 PM
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
I'm not aware of any popular email client that handles the current structure incorrectly, and without a clear breakage the amount of testing required to prove this change seems onerous. If you can show me a test case for one, I'd be happy to work with you to figure out what's going on; otherwise, in the interest of getting the important 1.1 fixes out the door ASAP, I view this as more of an enhancement request. (Disclaimer: I'm not a committer and only a committer's opinion is binding on release issues.)
Creating an HTML part (when none is explicitly specified) is expected behavior. If you want plaintext only or plaintext with attachments, I'd say you should use SimpleEmail or MultiPartEmail directly. Changing this would mean changing the API contract, and I don't think that's something we should do for this release. (See previous disclaimer.)