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);
}
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.
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.
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.
Plz compare two methods of Session class: Session.getDefaultInstance(Properties, Authenticator) and Session.getInstance(Properties, Authenticator)
Related
I am working with JavaMail for my plugin, within this plugin I am trying to send an email but my issue lies around the client. The client can't handle the plugin connecting to the email server and sending an email it either crashes the entire server or the client gets kicked out. My fix for this was instead of constantly connecting to the email server and sending an email why not simply keep one connection open when the plugin starts and grab that connection when I am wanting to send an email hopefully this will help in allowing the client and server to stay stable without any crashes. If anyone can help me I am just curious on how I can go about keeping a a single connection open and grabbing it when it is needed and then closing it when the plugin gets disabled.
What I have tried:
private Session session;
public void connect() {
String provider = plugin.getConfig().getString("EmailProvider");
String email = plugin.getConfig().getString("Email");
String password = plugin.getConfig().getString("Password");
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", provider);
props.put("mail.smtp.port", "25");
session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(email, password);
}
});
}
private boolean checkSession() {
try {
if (session != null) {
return true;
} else {
return false;
}
}
return false;
}
public void sendEmail(String to, String from, String subject, String text) {
if (!checkSession()) {
connect();
System.out.println("connecting");
}
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject(subject);
message.setText(text);
Transport.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
The simple answer is, you can't.
There's no way to force a connection to remain open. Connections can be closed for all sorts of reasons and your program needs to be prepared for that.
You can, however, cache an open connection and reuse it as long as it's still connected. But without knowing what your plugin plugs in to, it's hard to describe the best strategy for that.
Note also that mail servers really don't want you to keep a connection open if you're not using it, which is why they'll close it out from under you if you leave it open but idle for too long. And artificially keeping the connection active won't win you any points with the mail server either.
If your mail server crashes when you connect to it, it's probably time to get a new mail server.
I want to program a "Contact Us" form in my desktop application (Swing in Netbeans), just like what we find in some websites.
The problem that I faced is the smtp server name. Actually, I want that the user could send me a message without giving his address mail and without requiring that he connects to his account either.
Here a screen shot:
And this is my Submit button action:
#Override
public void actionPerformed(ActionEvent e) {
boolean isSent = true;
try {
//Properties properties = new Properties();
Properties properties = System.getProperties();
// properties.setProperty("mail.smtp.submitter", contactUs.getMailField().getText());
//properties.setProperty("mail.smtp.auth", "false");
properties.setProperty("mail.smtp.host", "localhost");
//properties.put("mail.smtp.user", txtfrom.getText());
//properties.put("mail.smtp.port", txtPort.getText());
//properties.put("mail.smtp.socketFactory.port", txtPort.getText());
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.socketFactory.fallback", "false");
//Authenticator mailAuthenticator = new MailAuthenticator();
Session mailSession = Session.getDefaultInstance(properties);
Message message = new MimeMessage(mailSession);
InternetAddress fromAddress = new InternetAddress(contactUs.getMailField().getText());
InternetAddress toAddress = new InternetAddress("mancha#gmail.com");
message.setFrom(fromAddress);
message.setRecipient(Message.RecipientType.TO, toAddress);
message.setSubject(contactUs.getSubjectField().getText());
message.setText(contactUs.getMsgField().getText());
Transport.send(message);
} catch (Exception ex) {
contactUs.getErrorMsg().setText("ERROR:" + ex.getMessage());
isSent = false;
}
if (isSent == true) {
contactUs.getSubmitBtn().setEnabled(false);
contactUs.getErrorMsg().setText("Your e-mail has been sent.");
}
}
Of course I google and I found that simple example which causes always problem of connection to smtp server.
First of all, make sure that your smtp server listens on port 25.
you can check it via telnet.
telnet localhost 25
if you do not have any, install a smtp service to your system.
if you have, check your smtp services security settings to connect it
Firstly check that your mail server is up and running by running
telnet localhost 25
Secondly you don't want to set the fromAddress as the users 'prescribed' email as that would require the account exists on your local mail server (As often people contacting you wouldn't already be on your system). Instead, temporarily hard code the fromAddress to an email address you know exists on your mail server and just append the users email address to the email.
An example of what you might want to do
final String FROM_EMAIL_ADDRESS = yourexistingemail#mailserver.com;
InternetAddress fromAddress = new InternetAddress(FROM_EMAIL_ADDRESS);
message.setText(contactUs.getMsgField().getText(), "\nFrom: " + contactUs.getMailField().getText());
This is my entire java code. If I comment the line:
objCon = DriverManager.getConnection(props.getString("url")); the mail is sending correctly. Else, its throwing the error - Could not connect to SMTP host: mail.companyname.com, port: 25;
public class PullRec {
private static final Logger LOG_TRACE = Logger.getLogger("debugLogger");
public static void main(String[] args) throws Exception {
Connection objCon = null;
PropertyResourceBundle props;
props = (PropertyResourceBundle) ResourceBundle.getBundle("com.cts.properties.config");
try {
Class.forName(props.getString("dbdriver"));
// If I comment the below line, the sendmail function works perfectly..!!
objCon = DriverManager.getConnection(props.getString("url"));
}
catch(Exception e) {
LOG_TRACE.info("DBConnection.java FILE ERROR: Disconnected due to "+e);
}
sendmail("Test");
}
public static void sendmail(String strBody) {
String to = "sarath#companyname.com";
String from = "sarath#companyname.com";
String host = "mail.companyname.com";
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host", host);
properties.setProperty("java.net.preferIPv4Stack","true");
Session session = Session.getDefaultInstance(properties);
try{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject("CTS Monitor");
message.setContent(strBody,"text/html" );
Transport.send(message);
System.out.println("Sent message successfully....");
}
catch (MessagingException e) {
e.printStackTrace();
}
}
}
Your mail method is clearly setting the SMTP server hostname to "<hostname>". That is never going to work. You need to replace that with the real DNS hostname of the SMTP server you are attempting to use.
(Your from and to addresses are unlikely to work either ...)
If you have done that and it still isn't working, then check that you have got the (real) hostname and port correct, and that the SMTP server on that host / port are alive.
I notice that you have commented out the call to mail(String) which configures the mail server, and I'm not sure what your Mail object is, or what the sendmail method is actually doing.
(Note: this is NOT all of your Java code, because if it was, it doesn't compile!)
I am using javaMail API for Sending mails my code is working fine but the Problem is that while sending mail it is taking time to send mails(delaying time is nearly 15 to 20 seconds), this is the reason my application is going down.I want to send mails with out taking any time while sending mails .Please give an idea
here is my code:
public class sendMail {
public static void main(String[] args) {
Properties props = new Properties();
props=System.getProperties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "587");
String mail="XYZ#gmail.com";
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("abc#gmail.com","********");
}
});
try {
String emails="xyz#gmail.com"+","+"xyz.kannoju#vxyz.com";
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("xyz.rajender#gmail.com"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(emails));
message.setSubject("Testing Subject");
message.setText("Dear Rejender," +
"\n\n Please find the like!");
//Transport.send(message);
Transport tr=session.getTransport("smtp");
//tr.sendMessage(message, message.getRecipients(message.));
tr.send(message);
tr.close();
//Transport
System.out.println("Done");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
You could run the method that takes too much time in its own thread, allowing your main program to continue doing other things:
new Thread(new Runnable() {
public void run() {
tr.send(message);
tr.close();
}
}).start();
ps: you need to make tr and message final and you need to add some error handling in the run method.
Sending email does not offer any guarantee or expectation regarding delivery-time. The JavaMail API does not impose or add any delays to the process, it immediately sends the email to the SMTP server indicated. How long it takes from there to the email having been relayed to the actual recipient's mailbox is out of your control. Depending on circumstances, the message may have to pass several intermediary servers and may or may not be processed at several points during the transit (virus-checking etc).
If you have specific requirements that your message has to be delivered within a certain time, email is a very bad choice of transport. My advice, rethink your architecture to either accept a variable, non-deterministic delivery-time or look into possible using some other messaging method that offers synchronous communication.
I am using Java mail API to send email through my java application. But I want to send it automatically on future date i.e. any specific date of every month/year. I have used my ISP's SMTP server to send email on mentioned id.I have referred the below available example on net. How to set any specific date here.I have tried SimpleDateFormat and set it here but it still sends mail immediately but set its sent date as mentioned specific date. Is there any other way to send automatic email on mentioned date and time?
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
// Send a simple, single part, text/plain e-mail
public class TestEmail {
public static void main(String[] args) {
// SUBSTITUTE YOUR EMAIL ADDRESSES HERE!!!
String to = "abc#abc.com";
String from = "abc#abc.com";
// SUBSTITUTE YOUR ISP'S MAIL SERVER HERE!!!
String host = "smtp.yourisp.net";
// Create properties, get Session
Properties props = new Properties();
// If using static Transport.send(),
// need to specify which host to send it to
props.put("mail.smtp.host", host);
// To see what is going on behind the scene
props.put("mail.debug", "true");
Session session = Session.getInstance(props);
try {
// Instantiatee a message
Message msg = new MimeMessage(session);
//Set message attributes
msg.setFrom(new InternetAddress(from));
InternetAddress[] address = {new InternetAddress(to)};
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject("Test E-Mail through Java");
msg.setSentDate(new Date());
// Set message content
msg.setText("This is a test of sending a " +
"plain text e-mail through Java.\n" +
"Here is line 2.");
//Send the message
Transport.send(msg);
}
catch (MessagingException mex) {
// Prints all nested (chained) exceptions as well
mex.printStackTrace();
}
}
}//End of class
Configure Quartz Job for it. Use cron trigger to specify the execution event
If you're using an EJB 3.0+ container, you could easily use the timer service.
You need to make a session bean, and either implement the TimedObject interface or annotate a method with #Timeout. You can get an instance of the TimerService from the InitialContext via getTimerService(), then create a timer with one of the createTimer() variants. It can take an interval, or a Date object specifying when it expires...