3

I am developing an application that needs to send an email via JavaMail with a specific Message ID.

I have extended the Java MimeMessage class to override the updateMessageID method so that I can set the message ID myself. The problem is that when I call the Transport.send(msg) method it is not calling the updateMessageID method. I thought perhaps I needed to call the saveChanges() method prior to calling Transport.send(msg). Even when I explicitly call msg.saveChanges() this does not trigger the updateMessageID method to be called.

What makes this all the more wacky is the fact that when I convert my test application to a JSP and run it, the Transport.send(msg) method DOES call the updateMessageID method.

Both my server and my webserver that I tested on are running jdk1.7.0_71.

Extended MimeMessage Class

package com.my.framework;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class MYMimeMessage extends MimeMessage {
Session session;
private static int id = 0;
private static String messageID = null;

public MyMimeMessage(Session session) {
    super(session);
    this.session=session;
}

protected void updateMessageID() throws MessagingException {
    System.out.println("Calling updateMessageID()");
    setHeader("Message-ID", "<" + getUniqueMessageIDValue(session) + ">");
}

/* Added to pass message id in */
public static void setMessageID(String cid) 
{
   messageID = cid;
}

public static String getUniqueMessageIDValue(Session ssn) {
    String suffix = null;

    InternetAddress addr = InternetAddress.getLocalAddress(ssn);
    if (addr != null)
        suffix = addr.getAddress();
    else {
        suffix = "javamailuser@localhost"; // worst-case default
    }
 
    if(messageID == null)
    {
      messageID = "987654321";
    }
    StringBuffer s = new StringBuffer();
 
    // Unique string is <messageID>.<id>.<currentTime>.FDDMail.<suffix>
    s.append(messageID).append('.').append(getUniqueId()).append('.').
      append(System.currentTimeMillis()).append('.').
      append("FDDMail.").
      append(suffix);
    System.out.println("RETURNING THE new ID: " + s.toString()");
    return s.toString();
}

private static synchronized int getUniqueId() {
 return id++;
}
}

I call this MimeMessageClass from a mail wrapper called SimpleEmail. It is mostly a bunch of get/set functions. All of the meat is in the sendEmail method...

public String sendEmail()
{
   String msgText1 = this.getBody();
   // Create some properties and get the default Session
   Properties props = System.getProperties();
   props.put("mail.smtp.host", this.getSmtpClient());
   props.put("mail.from", "");

   Session session = Session.getDefaultInstance(props, null);

   try
   {
      // Create a message
      MyMimeMessage msg = new MyMimeMessage(session);

      if (null != sender && sender.length() > 0)
      {
         msg.setSender(new InternetAddress(sender));
      }

      if((this.getReply_to() != null) && (this.getReply_to().length() > 0))
      {
         Address emailReplyTo[] = new Address[1];
         emailReplyTo[0] = new InternetAddress(this.getReply_to());
         msg.setReplyTo(emailReplyTo);
      }

      msg.setFrom(new InternetAddress(this.getFrom()));

      if(this.to == null || this.to.size() <= 0)
      {
         return "Error: No To to send";
      }

      int toIndex = 0;
      InternetAddress [] address = new InternetAddress [this.to.size()];
      while(this.HasNextTo())
      {
         address[toIndex] = new InternetAddress(this.nextTo());
         toIndex++;
      }

      msg.setRecipients(Message.RecipientType.TO, address);

      if(this.subject == null)
      {
         this.subject = "<no subject>";
      }
      msg.setSubject(this.subject);
      if(!useTextHeader)
      {
         //Create and fill the first message part
         MimeBodyPart mbp1 = new MimeBodyPart();
         mbp1.setDataHandler(new DataHandler(new HTMLDataSource(msgText1)));

         Multipart mp = new MimeMultipart();
         mp.addBodyPart(mbp1);
         // Create the second message part
         MimeBodyPart mbp2;
         FileDataSource fds;
         String filename;
         if(this.attachments != null) {
            Set attachmentPathAndNames = this.attachments.keySet();
            Iterator attachmentIterator = attachmentPathAndNames.iterator();
            while(attachmentIterator.hasNext()) {
               String attachmentPathAndName = (String)attachmentIterator.next();
               filename = (String)this.attachments.get(attachmentPathAndName);
               if(filename == null) {
                  String[] dirs = attachmentPathAndName.split("\\/");
                  filename = dirs[dirs.length - 1];
               }

               mbp2 = new MimeBodyPart();
               fds = new FileDataSource(attachmentPathAndName);
               mbp2.setDataHandler(new DataHandler(fds));
               mbp2.setFileName(filename);
               //Create the Multipart and its parts to it
               mp.addBodyPart(mbp2);
            }
         }

         //add the Multipart to the message
         msg.setContent(mp);
      }
      else
      {
         msg.setText(msgText1);
      }

      //set the Date: header
      msg.setSentDate(new Date());

      //set the MessageID Header
      msg.setMessageID(this.messageID);
      //send the message
      try
      {
         Transport.send(msg);
      }
      catch(Exception e)
      {
         System.out.println("STOP WE THREW AN ERROR!!!!!!!!!!!!!!!");
      }
   }
   catch (MessagingException mex)
   {
      mex.printStackTrace();
      System.out.println("Error: SimpleEmail.SendEmail() = Caught MessagingException: " + mex.toString());
      return "Error: SimpleEmail.SendEmail() = Caught MessagingException: " + mex.toString();
   }
   return this.SUCESS_MESSAGE;
}

So, when I call from a JSP I can see the two print statements from MyMimeMessage class

<%@ page import="com.ifx.framework.SimpleEmail" %>
<%
      String toAddr = request.getParameter("emailAddr");
      String mid = request.getParameter("customID");
      String SMTP_CLIENT = "myserver.mydomain.com";

      String body = "Hi " + toAddr + "!<br>Today we are testing to see if the setting messageID to " + mid + " works!";

      String sendResult = "No Email Sent";
      if(toAddr != null)
      {
         SimpleEmail se = new SimpleEmail();
         se.addTo(toAddr);
         se.setSubject("Testing Headers");
         se.setSmtpClient(SMTP_CLIENT);
         se.setFrom("cms_zippylube@gointranet.com");
         se.setBody(body);
         se.setMessageID(mid);
         sendResult = se.sendEmail();
      }
%>
<!DOCTYPE html>
<html>
   <head>
      <title>
         Test Page
      </title>
      <style>
         label {
            width: 200px;
            display: inline-block;
            margin-bottom: 5px;
         }
      </style>
   </head>
   <body>
      <p style="background-color: #ADD8E6; border: solid 2px #000080;">
         <%=sendResult%>
      </p>
      <form action="#" method="post">
         <label for=emailAddr>Email Address:</label><input id="emailAddr" name="emailAddr" type="email"/> <br>
         <label for=customValue>Custom Message ID:</label><input id="customID" name="customID" type="text"/> <br>
         <input type="submit" value="Submit"/>
      </form>
   </body>
</html>

In my logs I see:

Calling updateMessage()
RETURNING THE new ID: 8675309.0.1430500125923.FDDMail.javamailuser@localhost

When I check the resulting email, the Message-ID in the header matches what was set.

Here is where my problem is, when I run a standalone version it still sends out the email but doesn't call the updateMessageID method and does not print out the debugging statements.

import com.ifx.framework.SimpleEmail;

public class headerTest
{
   public static void main(String args[])
   {
      String toAddr = args[0];
      String mid = args[1];
      String SMTP_CLIENT = "myserver.mydomain.com";

      String body = "Hi " + toAddr + "!<br>Today we are testing to see if the header message id is retained";

      String sendResult = "No Email Sent";
      if(toAddr != null)
      {
         SimpleEmail se = new SimpleEmail();
         se.addTo(toAddr);
         se.setSubject("Testing Headers");
         se.setSmtpClient(SMTP_CLIENT);
         se.setFrom("dummy@test.com");
         se.setBody(body);
         se.setMessageID(mid);
         sendResult = se.sendEmail();
      }
      System.out.println("Done!");
   }
}

The only output that I get when I run this is:

Done!

whereas I am expecting

Calling updateMessage()
RETURNING THE new ID: 8675309.0.1430500125923.FDDMail.javamailuser@localhost
Done!

I've got my entire team (including sysadmin) stumped on this issue. Any and All suggestions would be greatly appreciated!

Kirs10
  • 31
  • 1

1 Answers1

0

It sounds like you're testing with two different servers so I'm guessing that they're using different versions of JavaMail. What versions are they using? What does the JavaMail debug output show?

Bill Shannon
  • 29,579
  • 6
  • 38
  • 40