greenmail icon indicating copy to clipboard operation
greenmail copied to clipboard

Custom Message-Id header

Open anton-johansson opened this issue 1 year ago • 7 comments

Hi! I want to use a custom Message-Id when I send mails with greenmail. This makes it easier to unit test my flows. Whenever I set a Message-Id, it seems to get overwritten with something else when I run the deliver method. Some time stamp and my computers host name. Any ideas?

I use 1.6.8 (also tried 1.6.14).

anton-johansson avatar Jul 03 '23 15:07 anton-johansson

Spring does this before sending. Maybe try that. https://github.com/spring-projects/spring-framework/blob/main/spring-context-support/src/main/java/org/springframework/mail/javamail/JavaMailSenderImpl.java#L458-L463

apinske avatar Jul 03 '23 15:07 apinske

Spring does this before sending. Maybe try that. https://github.com/spring-projects/spring-framework/blob/main/spring-context-support/src/main/java/org/springframework/mail/javamail/JavaMailSenderImpl.java#L458-L463

Hmm, could you elaborate? Do you mean that I should do this before calling Greenmails deliver method, or that Greenmail should be adapted with something similar?

I think it's currently out of my control. I think it's somewhere around here:
https://github.com/greenmail-mail-test/greenmail/blob/release-1.6.8/greenmail-core/src/main/java/com/icegreen/greenmail/store/StoredMessage.java#L72

I can't say exactly where. But the Message-Id header gets overridden by some automated value here.

anton-johansson avatar Jul 04 '23 07:07 anton-johansson

Digging a bit deeper, it's actually here:
https://github.com/greenmail-mail-test/greenmail/blob/release-1.6.8/greenmail-core/src/main/java/com/icegreen/greenmail/store/StoredMessage.java#L40

The super(source) call leads to a source.writeTo(bos), which in turns runs MimeMessage#saveChanges, which in turns runs MimeMessage#updateHeaders, which in turn generates a new "random" Message-Id.

I think Greenmail would need similar code as Spring has in your link, @apinske. Would you agree? I can't see another easy workaround either. :/

anton-johansson avatar Jul 04 '23 07:07 anton-johansson

Can you try doing the spring-workaround before calling greenmail. Does that help? Maybe we should have the code in greenmail, I'll need to analyse that.

apinske avatar Jul 04 '23 07:07 apinske

Can you try doing the spring-workaround before calling greenmail. Does that help? Maybe we should have the code in greenmail, I'll need to analyse that.

Yeah, I've been trying to do that, no success. I've also tried to create my own custom extension of MimeMessage that overrides updateHeaders, but it does not matter, since Greenmails StoredMessage creates a new UidAwareMimeMessage. So I think Greenmail would need this something like you mentioned within StoredMessage constructor`:

     StoredMessage(MimeMessage mimeMessage,
             Date receivedDate, long uid) {
         this.receivedDate = receivedDate;
         this.uid = uid;
         try {
+            String messageId = this.mimeMessage.getMessageID();
             this.mimeMessage = new UidAwareMimeMessage(mimeMessage, uid, receivedDate);
+            if (messageId != null) {
+                this.mimeMessage.setHeader(HEADER_MESSAGE_ID, messageId);
+            }
             this.attributes = new SimpleMessageAttributes(mimeMessage, receivedDate);
         } catch (MessagingException e) {
             throw new IllegalStateException("Could not parse mime message " + mimeMessage + " with uid " + uid, e);
         }
     }

anton-johansson avatar Jul 04 '23 08:07 anton-johansson

That would probably work. But you should be able to accomplish the same in the meantime by doing the "spring-dance" (saveChanges, setHeader). The subsequent saveChanges during writeTo should not update the Message-ID again.

apinske avatar Jul 04 '23 08:07 apinske

That's the problem. Since Greenmail is wrapping the MimeMessage in its own class, UidAwareMimeMessage, the default implementation of updateMessageID is always called:

    /**
     * Update the Message-ID header.  This method is called
     * by the <code>updateHeaders</code> and allows a subclass
     * to override only the algorithm for choosing a Message-ID.
     *
     * @exception  	MessagingException for failures
     * @since		JavaMail 1.4
     */
    protected void updateMessageID() throws MessagingException {
	setHeader("Message-ID", 
		  "<" + UniqueValue.getUniqueMessageIDValue(session) + ">");
          
    }	

I'm finding no ways around this. :/

anton-johansson avatar Jul 04 '23 08:07 anton-johansson