2013/2/13 Thomas Delafosse <[email protected]> > On Wed, Feb 13, 2013 at 2:40 PM, Jeremie BOUSQUET < > [email protected]> wrote: > > > Hi, > > > > Reviving this thread, because I wonder how multiparts are managed ... > > More precisely, nowhere in current mailsender API do we choose the type > of > > multipart to manage (ie, multipart/mixed, multipart/alternative...). From > > what is said above, and the api signatures, it seems that by default the > > component will generate mails with multipart/alternative content, which > may > > be most common use-case. > > > > Yes, this is multipart/alternative content I create > > > > > > If it's multipart/alternative, then calling: > > $mail.addContent("text1", "plain/text") > > $mail.addContent("text2", "plain/text") > > $mail.addContent("text3", "plain/html") > > ... has very little meaning. A multipart alternative is supposed to > present > > alternative representations of the same information, most usual use-case > > being to provide text and html parts. The client is supposed to display > the > > last part he can handle (ie, pure text client would display the text > part, > > and html capable client will display the html part). > > > > Indeed with what I have implemented so far, this has very little meaning. I > considered that people that were going to use addContent and not directly > one of the method like $services.mailSender.sendMail(to, html, alternative > text) would be aware of that (of course this should be explicitly said in > the doc). But I agree that we could perhaps consider letting them choose > between multipart/alternative and multipart/mixed for example. I'm just > afraid that it would make the component harder to understand and to use. > > I agree with you, most important is to know what to expect. Managing all multiparts types would make the component very complex I believe, for little added-value.
> > > > When there are several calls to addContent(...) for the same content > type, > > is provided text appended to content already present in existing part ? > > Ie, in sample above, I would get an email with a plain/text part > containing > > "text1text2" and an html part with "text3" ? > > If text/plain parts are added instead of concatenated, then in sample > > below, it would mean that "text2" would obliterate "text1" added before, > as > > it will maybe never be displayed by the client (depending on how the > client > > interprets this case). > > > > Another thing, when you add html content to an email, it's usually for > its > > better formatting features compared to plain text. A common use-case (for > > example, if you want to send a newsletter), is to include some images in > > the html page sent. > > To do that, you can't just provide the html content, then some attached > > images. Doing that you can only send an html page (without inline images) > > and images attached. To send an html document with inline image, you need > > to send a multipart/related, instead of a "text/html" part, and generate > > content-ids for each image/attachment. > > Is it managed by the mail sender ? > > > > When I have a text/html mime part, I parse it for finding things like src > :cid and create a multipart/related part in order to embed the image in the > HTML. So I guess it's fine from this point of view. > By the way, I've just put my current mailSender code on a contrib repo : > https://github.com/xwiki-contrib/xwiki-platform-mail. I should still clear > up a few things in it (had to make some strange thing to get rid of class > fan out issues... I would take care of it as soon as I have time to, > hopefully next week) before it is publishable but it is supposed to work (I > tested it locally) and it would at least enable you to see how things are > done. Don't hesitate to comment it, and let me know what you think should > be changed ! > > No pb, even if I'm not an email expert in any way ;-) But I think I will use your component as client when I'll implement the reply feature in Mail Archive app, at that time it will be easier to challenge it against my own use-cases. What I just saw very quickly: - I wonder if DefaultMailSenderUtils#getDocumentRef(String docName) is not the same as DocumentReferenceResolver#resolve() ? - from MimePartCreator#createAttachmentPart(), you create a temporary file in order to create the MimeBodyPart, maybe you could use a BufferedDataSource to avoid that ? - from MimePartCreator#createHtmlPart(), you use a pattern to find inline-d attachments ("cid:") : src=('|\")cid:([^'\"]*)('|\") ...but in HTML nothing prevents from having "src = 'cid:...'" (with white spaces), that would not be match by that pattern. Also, I'm not sure I understand well, but it seems to consider that file name is what is in the "cid:*" value, but it's usually not the case (usually, content-id is a unique id built from filename, both values being provided as Content-Id and filename headers). - you call MimePartCreator#createAttachmentPart() for both types of attachments ("embedded images", and all other attachments), but "INLINE_DISPOSITION" is used as disposition for all of them. I think non-embedded attachments should have a disposition of ATTACHMENT. It's not so important though as anyway clients do whatever they like with your attachments. - currently it seems not to manage possibility to send a mail with a "Sender:" different than "From:" header. It is sometimes useful, for example in mailing-lists, usually "From:" is the human person who is sending the mail, and "Sender:" is the mailing-list server that effectively sends it to mailing-list recipients. For SMTP servers that allow that, it is then possible to send mails from a unique account (the sender) "on behalf of" the real users (in from/to), if it has the rights to do so of course. > > By the way it would be quite nice, to be able to round-trip between an > > XWiki page content (html) and a multipart/related part. I wonder how it > is > > managed by Newsletter Application... > > > > Using mail Templates enables you to include some Wiki content in it. > Perhaps it is what the Newsletter application uses ? > > Cheers, > Thomas > > > > > > Note: concerning the "mail parser" implemented in Mail Archive app, > > currently, it does not differentiate multipart/related, > > multipart/alternative and multipart/mixed. The same process applies: all > > "text/html" parts are parsed into a unique concatenated html content, all > > "text/plain" parts are parsed into a unique concatenated pure text > content. > > If some attachments have content-ids, their reference are replaced in the > > html content by a link to proper attached file. This almost respects > > RFC1341, in that it almost considers all multiparts as "mixed" (but not > in > > sequence, as text and html are grouped together). The resulting display > is > > fine in 99,99% of cases, as far as I tested. > > > > > > BR, > > Jeremie > > > > > > > > > > > > > > > > > > 2013/1/7 Thomas Mortagne <[email protected]> > > > > > On Mon, Jan 7, 2013 at 12:12 AM, Vincent Massol <[email protected]> > > > wrote: > > > > > > > > On Jan 6, 2013, at 10:54 PM, Thomas Delafosse < > > > [email protected]> wrote: > > > > > > > >> The advantage of jSoup is that it handles the problems I could have > if > > > the > > > >> html part is not well written, > > > > > > > > Actually this is exactly what the XWiki HTML parser does too :) > > > > > > > > I really think you should use our parser. > > > > > > Plus de HTML parser is very important so the more we test it the > better. > > > > > > > > > > > Thanks > > > > -Vincent > > > > > > > >> so I was thinking it was more secure to use > > > >> it than just parsing the "<>" in the html part . But I must admit > > that I > > > >> haven't had a close look on the xwiki renderers, and if there are > some > > > that > > > >> do it well, I should probably rather use them... I will give it a > > closer > > > >> look tomorrow. > > > > > > > >> > > > >> Cheers, > > > >> > > > >> Thomas > > > >> > > > >> On Sun, Jan 6, 2013 at 8:53 AM, Jeremie BOUSQUET < > > > [email protected] > > > >>> wrote: > > > >> > > > >>> Le 2 janv. 2013 18:44, "Thomas Delafosse" < > > [email protected]> > > > a > > > >>> écrit : > > > >>>> > > > >>>> On Fri, Dec 28, 2012 at 9:01 PM, Sergiu Dumitriu < > [email protected]> > > > >>> wrote: > > > >>>> > > > >>>>> On 12/26/2012 10:18 AM, Vincent Massol wrote: > > > >>>>>> > > > >>>>>> On Dec 26, 2012, at 4:01 PM, Thomas Delafosse < > > > >>>>> [email protected]> wrote: > > > >>>>>> > > > >>>>>>> On Wed, Dec 26, 2012 at 3:23 PM, Vincent Massol < > > > [email protected] > > > >>>> > > > >>>>> wrote: > > > >>>>>>> > > > >>>>>>>> > > > >>>>>>>> On Dec 26, 2012, at 3:15 PM, Thomas Delafosse < > > > >>>>> [email protected]> > > > >>>>>>>> wrote: > > > >>>>>>>> > > > >>>>>>>>> Ok, so I would rather have a component API like > > > >>>>>>>>> > > > >>>>>>>>> - Mail prepareMail(from, to, cc, bcc, subject) > > > >>>>>>>> > > > >>>>>>>> createMail is better than prepareMail IMO. > > > >>>>>>>> > > > >>>>>>>> I'd make the cc and bcc not part of the constructor and > instead > > > >>> move > > > >>>>> them > > > >>>>>>>> as setters since they're optional. > > > >>>>>>>> > > > >>>>>>>>> - int sendMail(Mail mail) > > > >>>>>>>> > > > >>>>>>>> Either that or add a send() method in Mail. > > > >>>>>>>> > > > >>>>>>>>> while the methods addToContent, addHtml, addAttachment, > etc... > > > >>> would > > > >>>>> be > > > >>>>>>>>> directly used from the Mail class. > > > >>>>>>>> > > > >>>>>>>> I don't understand what addToContent is and what different it > > has > > > >>> to > > > >>>>>>>> addHtml. > > > >>>>>>>> > > > >>>>>>> > > > >>>>>>> addToContent (String mimeType, String partToAdd) is more > generic > > : > > > >>> you > > > >>>>>>> specify the Mime Type of the part you want to add. So > > > addHtml(String > > > >>> s) > > > >>>>> is > > > >>>>>>> just the same as addToContent("text/html", s). But as most of > the > > > >>> time > > > >>>>> you > > > >>>>>>> add only Html or text, I was thinking it was better to have a > > > >>> specific > > > >>>>>>> method to add an Html part in the scripting API. I can do the > > same > > > >>> with > > > >>>>> a > > > >>>>>>> addTextContent method. > > > >>>>>> > > > >>>>>> I think I prefer addContent instead of addToContent. > > > >>>>>> > > > >>>>>> So just to be sure, doing the following will work: > > > >>>>>> > > > >>>>>> addContent("content1", "text") > > > >>>>>> addContent("content2", "text") > > > >>>>>> addContent("content3", "html") > > > >>>>>> > > > >>>>>> right? > > > >>>>>> > > > >>>>>> It's going to create a multipart email? > > > >>>>>> > > > >>>>>> I think a single addContent method is good enough, passing an > enum > > > as > > > >>>>> the second parameter (the mimetype). Enums are magically > > constructed > > > >>> from > > > >>>>> velocity with our custom uberspector. > > > >>>>> > > > >>>>> -1 for enums. That limits the possible content types we can add. > > > >>>>> > > > >>>> > > > >>>> I agree on that point : there are simpler methods such as > > > >>>> $services.mailSender.sendHtmlMail(from, to, subject, html, > > > alternative) > > > >>> for > > > >>>> people who don't know much about mimeTypes, so it would be a shame > > to > > > >>> limit > > > >>>> this method. > > > >>>> > > > >>>>> > > > >>>>> I prefer: > > > >>>>> > > > >>>>> addMimePart(String content, string mimeType) > > > >>>>> > > > >>>>> > > > >>>> So far it's exactly the way my addContent method works. But I can > > > change > > > >>>> its name to addMimePart if you prefer. > > > >>>> > > > >>>> > > > >>>>> There's also a MimePart in the standard javax.mail library, and > we > > > >>> could > > > >>>>> actually use this one, since it's more standard, and more > flexible: > > > >>>>> > > > >>>>> > > > >>> > > > > > > http://javamail.kenai.com/nonav/javadocs/javax/mail/internet/MimePart.html > > > >>>>> > > > >>>>> > > > >>>>> > > > >>> > > > >>> > > > > > > http://javamail.kenai.com/nonav/javadocs/javax/mail/internet/MimeBodyPart.html > > > >>>>> > > > >>>>> But this might be a bit too verbose and complex to use. > > > >>>>> > > > >>>>> I hope that the implementation will be smart enough to send a > plain > > > >>>>> message when only one body part (of type text or html) is > present. > > > >>>>> > > > >>>>> > > > >>>> If there is only a text or html part to the mail, I add an > > alternative > > > >>>> text/plain part to the mail, using jSoup to convert the html > content > > > into > > > >>>> text, if it's what you mean. > > > >>> > > > >>> On mail reader side, I used xwiki parsers/renderers to convert html > > to > > > >>> plain text. What is added value of jsoup ? > > > >>> > > > >>>> > > > >>>>>>> Can I call addContent several times? > > > >>>>>>>> > > > >>>>>>> > > > >>>>>>> Yes, so for example if you want to have an email with an html > > part > > > >>> and a > > > >>>>>>> calendar part, you call addToContent("text/html", html Text) > and > > > >>> then > > > >>>>>>> addToContent("text/calendar", calendar Code). > > > >>>>>>> > > > >>>>>>> > > > >>>>>>>> > > > >>>>>>>>> So a use-case would rather be : > > > >>>>>>>>> {{velocity}} > > > >>>>>>>>> $mail = $services.mailSender.prepareMail(from, to,...) > > > >>>>>>>>> $mail.addHtml('<p>Blabla</p>') > > > >>>>>>>> > > > >>>>>>>> addHTMLContent would be nicer. So you need also a > > addTextContent? > > > >>>>>>>> why not have an addContent(String, boolean isHTML) > > > >>>>>>>> or a more generic addContent(String, String mimeType) > > > >>>>>>>> or both > > > >>>>>>>> > > > >>>>>>>>> $mail.addCalendar() > > > >>>>>>>> > > > >>>>>>>> What is a calendar? > > > >>>>>>>> > > > >>>>>>> > > > >>>>>>> It is either a vCalendar or an iCalendar (it is used by Gmail > to > > > >>> send > > > >>>>>>> invitations). It corresponds to the Mime Type "text/calendar". > > Here > > > >>>>> again > > > >>>>>>> addCalendar(String calendar) is just the same as > > > >>>>>>> addToContent("text/calendar", calendar). It's just to make it > > > easier > > > >>> to > > > >>>>>>> use. > > > >>>>>> > > > >>>>>> ok. So I think in the future we could add some calendar helper > > that > > > >>> will > > > >>>>> create the calendar string information. > > > >>>>> > > > >>>>> -1 for a specific addCalendar method. Why not addVCard, addImage, > > > >>>>> addPDF, addDoc and so on? This makes a stuffed API, where > anything > > > that > > > >>>>> doesn't have a dedicated API method will feel like a second-class > > > >>>>> citizen. > > > >>>> > > > >>>> > > > >>>>>> For now this is good enough IMO: > > > >>>>>> addContent("calendar info content as per RFC 2445", "calendar") > > > >>>>>> > > > >>>>>> And then later on something like: > > > >>>>>> > > > >>>>>> addContent($mailsender.createCalendarMimeTypeData(param1, > param2, > > > >>> ….), > > > >>>>> "calendar") > > > >>>>>> > > > >>>>>>>> You should also show an example when using the Java API. > > > >>>>>>>> > > > >>>>>>> > > > >>>>>>> On Java it would give something like : > > > >>>>>>> > > > >>>>>>> @Inject > > > >>>>>>> private MailSender mailSender > > > >>>>>>> > > > >>>>>>> Mail mail = this.mailSender.newMail(from,to,subject) ; > > > >>>>>> > > > >>>>>> I don't like this too much. Why not use a constructor on the > Mail > > > >>> object? > > > >>>>> > > > >>>>> Constructors are bad, in a component-based world. I'd rather have > > the > > > >>>>> Mail object an interface, with an internal implementation used by > > the > > > >>>>> MailSender implementation. > > > >>>>> > > > >>>>>> (The other option is a perlookup component is you really need to > > > have > > > >>>>> some other components injected in the Mail object; in that case > > > you'll > > > >>> need > > > >>>>> setters to from/to/subject since we currently don't support > > > constructor > > > >>>>> injection). > > > >>>>>> > > > >>>>>>> String htmlCode = "<p>Blabla</p>" ; > > > >>>>>>> String calendar = "BEGIN VCALENDAR... END VCALENDAR" ; > > > >>>>>>> mail.addToContent("text/html", htmlCode) ; > > > >>>>>>> mail.addToContent("text/calendar", calendar) ; > > > >>>>>>> this.mailSender.sendMail(mail) ; > > > >>>>>> > > > >>>>>> why sendMail and not send? We're in a MailSender component so we > > > know > > > >>>>> we're sending mail already ;) > > > >>>>> > > > >>>>> +1 for send. > > > >>>>> > > > >>>>> By the way, I've put a first version of my component on github : > > > >>>> https://github.com/tdelafosse/mailSender. Feel free to have a > look > > > and > > > >>> to > > > >>>> tell me if there's things to change / add / enhance. > > > >>>> > > > >>>> Cheers, > > > >>>> > > > >>>> Thomas > > > > _______________________________________________ > > > > devs mailing list > > > > [email protected] > > > > http://lists.xwiki.org/mailman/listinfo/devs > > > > > > > > > > > > -- > > > Thomas Mortagne > > > _______________________________________________ > > > devs mailing list > > > [email protected] > > > http://lists.xwiki.org/mailman/listinfo/devs > > > > > _______________________________________________ > > devs mailing list > > [email protected] > > http://lists.xwiki.org/mailman/listinfo/devs > > > _______________________________________________ > devs mailing list > [email protected] > http://lists.xwiki.org/mailman/listinfo/devs > _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs

