How to change JavaMail port

2020-02-12 02:04发布

问题:

I'm writing a small Java app using JavaMail that sends the user an automated email. They can choose between (for now) two ports: 25 and 587. The port can be selected via a radio button on the GUI.

I added a test button to allow the user to test the email settings (including port). However, for some reason, once the user tries to send a test email, the port can't be changed. Javamail will always use the port of the original test email.

Example: User tries to send an email on port 25 and JavaMail says it can not connect on port 25 (for example, the SMTP host uses another port). User clicks port 587, and tries to send a new email. JavaMail throws an error saying it can not connect on port 25, again.

I'm kind of stumped as to why. Every time a new test email is sent an entirely new SendMailUsingAuthentication object is created. Within that class the properties are always reset to the proper port. Whenever I debug, as far as I can see, all variables are correct and associated with the correct port. Is there something going on inside of Transport that I'm missing?

In the front end GUI:

private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           

    int port = port25RadioButton.isSelected() ? PORT_25 : PORT_587;
    notifier = new SendMailUsingAuthentication(hostNameTextField.getText(),
            userTextField.getText(), getPassword(), emailTextField.getText().split(","),port);


    Thread wait = new Thread(new Runnable() {

        public void run() {
            try {
                changeStatusText("Sending test email...");
                notifier.postTestMail();
                changeStatusText("Test email sent.");
            } catch (AddressException ex) {
                changeStatusText("Error.  Invalid email address name.");
            } catch (MessagingException ex) {
                changeStatusText("SMTP host connection refused.");
                System.err.println(ex.getMessage());
            } catch (Exception ex) {
                System.err.println(ex);
            }
        }
    });

    wait.start();
}

In the email sender class:

public void postTestMail() throws MessagingException, AddressException{
    String[] testReciever = new String[1];
    testReciever[0] = emailList[0];
    postMail(testReciever, "Test email.", "Your email settings are successfully set up.", emailFromAddress);
}

private void postMail(String recipients[], String subject,
        String message, String from) throws MessagingException, AddressException {

    //Set the host smtp address
    Properties props = new Properties();
    props.put("mail.smtp.port", smtpPort);
    props.put("mail.smtp.host", smtpHostName);
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", true);
    Authenticator auth = new SMTPAuthenticator();
    Session session = Session.getDefaultInstance(props, auth);
    session.setDebug(false);

    // create a message
    Message msg = new MimeMessage(session);

    // set the from and to address
    InternetAddress addressFrom = new InternetAddress(from);
    msg.setFrom(addressFrom);

    InternetAddress[] addressTo = new InternetAddress[recipients.length];
    for (int i = 0; i < recipients.length; i++) {
        addressTo[i] = new InternetAddress(recipients[i]);
    }
    msg.setRecipients(Message.RecipientType.TO, addressTo);

    // Setting the Subject and Content Type
    msg.setSubject(subject);
    msg.setContent(message, "text/plain");
    Transport.send(msg);
}

回答1:

This happens because you're using getDefaultInstance() which says:

Get the default Session object. If a default has not yet been setup, a new Session object is created and installed as the default.

And that the Properties argument is "used only if a new Session object is created."

So the first time you invoke getDefaultInstance it uses your specified port. After that, the Session has already been created, and subsequent calls to getDefaultInstance will return that same session, and ignore the changed properties.

Try using Session.getInstance() instead of getDefaultInstance(), which creates a new Session each time, using the supplied properties.

It pays to read the javadocs very carefully.



回答2:

I think "Transport.send(msg)" wont be taking into account the connection details that you are providing in your properties. It will use its connection that is defined by default.

The java doc says

"Note that send is a static method that creates and manages its own connection. **Any connection associated with any Transport instance used to invoke this method is ignored and not used. This method should only be invoked using the form Transport.send(msg);, and should never be invoked using an instance variable. "**

Instead, I have tried with Transport.connect(smtphost,smtpport,user,password) and it works pretty well.



回答3:

Plz compare two methods of Session class: Session.getDefaultInstance(Properties, Authenticator) and Session.getInstance(Properties, Authenticator)



回答4:

Tip for anyone else still having issues, we were using Session.getInstance and the port was still defaulting to 25.

Turns out, we were setting the prop value as a Long when it needs to be a String

It didn't error, warn or log, just defaulted to 25.