basZero
basZero

Reputation: 4284

JavaMail: MessagingException: Got bad greeting from SMTP host — Error Code 250

Requirements:
- Only 1 connection to mail server allowed (restriction from my customer) - Don't close connection after sending a mail, resend mails over existing connection (better performance as transport.connect() is not needed for each mail)
- Send all mails over that connection
- If connection fails, reconnect, send mail
- Java 1.6

My code works well, but sometimes I get the javax.mail.MessagingException with error code 250: Got bad greeting from SMTP host. The nested exception is java.net.SocketException: Socket closed:

Here is my client code, the line is marked, where the exception is thrown:

// the mail service is a singleton and has one property to store the transport
// object that gets initialized when the singleton instance gets created:
private Transport transport = null;

// props, authU, authP and msg are all passed as a parameter to the sending method:
if (transport == null) {
    Session session = Session.getInstance(props, null);
    transport = session.getTransport("smtp");
}
if(!transport.isConnected()) {
    transport.connect(authU, authP); // <<<<< This line throws the exception !
}
transport.sendMessage(msg, msg.getAllRecipients());

Obviously transport.isConnected() detects no connection, but the connection() does not reopen or recreate a socket. My assumption was that it would do all the necessary stuff for me.

Is there a proper client solution to make sure that exception does not get thrown? A workaround would be to catch the exception and resend the mail, but I don't like workarounds...

Upvotes: 2

Views: 12883

Answers (2)

Ran Adler
Ran Adler

Reputation: 3711

Try this solution :

public static void mail(Reporter report) {
    
 
        if(!sendEmail.trim().equalsIgnoreCase("true")){
            return;
        }
        
 
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.port", "587");
 
        Session session = Session.getInstance(props,
          new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
          });
 
        try {     
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("[email protected]"));
            if(!bccEmail.trim().isEmpty()){
                message.addRecipient(Message.RecipientType.CC, new InternetAddress(bccEmail));
            }
            message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse(toEmail));
            message.setSubject(" Testing ");
            message.setText("automatic email  ,"+report);
            Transport.send(message);
 
            System.out.println("Email Done");
 
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }
}

Upvotes: 0

Bill Shannon
Bill Shannon

Reputation: 29961

What you describe as a workaround is actually the right way to do it.

There's nothing preventing the server from dropping the connection between the time you call the isConnected method and the time you call the sendMessage method, so in the worst case you always have to be prepared to handle the exception.

Upvotes: 2

Related Questions