mail-api icon indicating copy to clipboard operation
mail-api copied to clipboard

Optional of update messageId and sentDate

Open valenpo opened this issue 4 years ago • 2 comments

If where is no messageId, and sentDate when saveChanges() called, MimeMessage always generate new messageId and set sentDate if it is not exist.

This is confusing, as when changed only one header like "Message-ID" it will be rewritten on saveChanges() call. This can broke data consistency.

Is it possible save only updated values? Or make set those headers (Message-ID, Date) optionally updatable?

   protected synchronized void updateHeaders() throws MessagingException {
        MimeBodyPart.updateHeaders(this);
        setHeader("MIME-Version", "1.0");
        if (getHeader("Date") == null)
            setSentDate(new Date());
        updateMessageID();

        if (cachedContent != null) {
            dh = new DataHandler(cachedContent, getContentType());
            cachedContent = null;
            content = null;
            if (contentStream != null) {
                try {
                    contentStream.close();
                } catch (IOException ioex) { }	// nothing to do
            }
            contentStream = null;
        }
    }

valenpo avatar Oct 06 '21 12:10 valenpo

There are a few ways to patch this to make it so we don't cache the sent date if not set but they are all kind of gross to implement and don't really improve things. It is really tricky to get consistency between writeTo and getHeaders to work correctly if we are not doing what we are doing today.

The history of this comes from https://github.com/eclipse-ee4j/mail/issues/77

To be RFC 822 compliant, a message must have a Date header. RFC 822 compliance is a shared responsibility between JavaMail and the application, but JavaMail could help by setting the Date header (if not already set) when updating the headers for a message.

Why we unconditionally update the message header is covered in: Use user provided message-id

I understand why you might want this behavior, but I fear that this change in behavior will break other use cases. For example, if you create a MimeMessage object, send it, then change the recipients and send it again, you want the Message-Id to be updated, but with this change it would not be updated.

So we have to unconditionally update the message id so each message sent is unique.

The logic to update the sent date is only there handle the case where the application is faulty and doesn't provide a sent date for RFC 822 compliance. The accuracy of that date is the responsibility of the caller and not the MimeMessage class. Some applications may want to use now as the sent date but other applications may want to use an older date (like when the message was written to a cache).

Bottom line is that before you call MimeMessage::saveChanges or Transport::send the application should set the date header.

I'll leave this open for a few days but I think we'll have to close it as will not fix.

jmehrens avatar Oct 07 '21 22:10 jmehrens

@jmehrens thanks for reply.

It is possible to fix, if MimeMessage provide not package access to methods on update headers and etc... involved on such process.

For my situation I can extent MimeMessage and use mine implementation, but plenty of methods Like MimeBodyPart.updateHeaders (package private). Maybe make access to such methods more public ?

Thanks.

valenpo avatar Oct 08 '21 06:10 valenpo