Email.getMailSession() is a mess
--------------------------------

                 Key: EMAIL-96
                 URL: https://issues.apache.org/jira/browse/EMAIL-96
             Project: Commons Email
          Issue Type: Bug
    Affects Versions: 1.2
            Reporter: NC


Email.getMailSession() is a mess

This bug initially was going to address only the excessive permissions required 
by Email.getMailSession().  My examination of how this might best be remedied 
led me to the revelation that the problems with this method, and their effects 
on the entire class are quite extraordinary.  (To be fair, some of the blame 
should be placed squarely upon other members of this class.)

Excess permission requirements
--------------------------------------------

The Email.getMailSession() method, when running under a SecurityManager, 
requires permission to be granted to read and write ALL permissions 
(java.util.PropertyPermission * read, write).  This, despite the fact that only 
a handful of permissions are applicable to sending mail.

The permission requirement stems from the following line:

        Properties properties = new Properties(System.getProperties());

As far as I can tell, Commons-Email reads only "mail.smtp.from" and 
"mail.smtp.host" from the system properties for use as default values.  
Commons-Email does not appear to write any system properties.

Therefore, something along these lines would greatly reduce the permissions 
required to send mail using Commons-Email:

        Properties properties = new Properties();
        properties.setProperty(MAIL_SMTP_FROM, 
System.getProperty(MAIL_SMTP_FROM));
        properties.setProperty(MAIL_HOST, System.getProperty(MAIL_HOST));

On top of all of this, getMailSession() does not use 
AccessController.doPrivileged() to isolate the code requiring the permission 
grants.

My thought was to submit a patch refactoring the class, adding a 
createDefaultProperties() method to do all of this.

But then...
--------------

During my examination of the code, I noticed that getMailSession() is 
documented with the following JavaDoc comment:

        Initialise a mailsession object

That would be an appropriate description for an initMailSession() method.  For 
getMailSession(), I would have expected something more along the lines of:

   Determines the Session used when sending this Email, creating the Session if 
necessary.

(I would also refactor the class such that getMailSession() delegates creation 
and initialization of a mail Session to a createMailSession() method.)

However, buildMimeMessage() *does* treat getMailSession() as though it is 
initMailSession(), e.g.:

        this.getMailSession();
        this.message = this.createMimeMessage(this.session);

One might have expected a simple createMimeMessage(getMailSession()), rather 
than using getMailSession() for its side effect and then accessing the data 
member directly.  A bit confusing, but it got me thinking.

Suppose I do something like this:

        System.getProperties().setProperty("mail.smtp.host", 
"smtp.example.com");
        Email email =new SimpleEmail();
        email.getMailSession();
        email.setHostName("mail.example.com");
        email.setSmtpPort(26);
        email.setSsl(true);
        email.addTo("[email protected]", "Someone");
        email.setFrom("[email protected]", "Me");
        email.setSubject("Test");
        email.setMsg("This is a test.");
        email.send();

Q. What SMTP server is contacted to relay the mail?
A. smtp.example.com

Q. On what port is the SMTP server contacted?
A. 25

Q. Is SSL used when communicating with the SMTP server?
A. No.

Q. What mail host and port will be reported in any error message?
A. mail.example.com: 26

The problems here are:
 a) The call to getMailSession() initializes the Session used by Email
 b) subsequent setXxxx() calls don't write through to the already-initialized 
Session
 c) any EmailException thrown by sendMimeMessage() uses values obtained from 
the getter methods, which prefer local data members rather than Session 
properties

I suppose one could argue that getMailSession(), despite its misleading name, 
clearly states that it initializes the Session, thereby sealing the attributes 
despite subsequent setXxxx() calls.  In that case the JavaDoc comments should 
clearly note this.  That would leave Commons Email with a confusing and stinky 
API.  Problem 'c' listed above would still need to be addressed.

How truly fixable this class is without breaking the API is probably dependent 
upon whether javax.mail.Session accepts changes written to the Properties 
object returned by its getProperties() method.  The JavaMail API does not seem 
to specify that behavior.

I will cheerfully accept any corrections, major or minor.  I imagine anyone 
reading this has spent far more time with the code involved than I have.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to