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.
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.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to send email using Java code. I am using smtp.gmail.com for sending the mail and it's working fine. Now I want to send email on particular day of every month say 1st of every month. I have searched a lot but not working for me.
Below is my code for sending mail.
public class sendMailUsingTimeInterval{
public static void main(String[] args) throws IOException{
String[] to={"to#gmail.com"};
String[] cc={"cc#gmail.com"};
String subject = "hello";
String body = "Thanks , this is test.....!!";
//This is for google
sendMail("from#gmail.com","password","smtp.gmail.com","465","true",
"true",true,"javax.net.ssl.SSLSocketFactory","false",to,cc,
subject,body);
}
public synchronized static boolean sendMail(String userName,String passWord,String host,String port,String starttls,String auth,boolean debug,String socketFactoryClass,String fallback,String[] to,String[] cc,String subject,String text)
{
Properties props = new Properties();
//Properties props=System.getProperties();
props.put("mail.smtp.user", userName);
props.put("mail.smtp.host", host);
if(!"".equals(port))
props.put("mail.smtp.port", port);
if(!"".equals(starttls))
props.put("mail.smtp.starttls.enable",starttls);
props.put("mail.smtp.auth", auth);
if(debug){
props.put("mail.smtp.debug", "true");
}
else
{
props.put("mail.smtp.debug", "false");
}
if(!"".equals(port))
props.put("mail.smtp.socketFactory.port", port);
if(!"".equals(socketFactoryClass))
props.put("mail.smtp.socketFactory.class",socketFactoryClass);
if(!"".equals(fallback))
props.put("mail.smtp.socketFactory.fallback", fallback);
try
{
Session session = Session.getDefaultInstance(props, null);
session.setDebug(debug);
MimeMessage msg = new MimeMessage(session);
msg.setContent(text,"text/html");
msg.setSubject(subject);
msg.setFrom(new InternetAddress("from#gmail.com"));
for(int i=0;i<to.length;i++)
{
msg.addRecipient(Message.RecipientType.TO, new InternetAddress(to[i]));
}
for(int i=0;i<cc.length;i++)
{
msg.addRecipient(Message.RecipientType.CC, new InternetAddress(cc[i]));
}
msg.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(host, userName, passWord);
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();
return true;
}
catch (Exception mex)
{
mex.printStackTrace();
return false;
}
}
The code is working when this class is called. Would really appreciate if someone could tell me how to implement it in such a way that message is sent automatically on 1st of every month.
You can do this using the Quartz scheduler.
You can use "Annotation Type Schedule"
#Target(value=METHOD)
#Retention(value=RUNTIME)
public #interface Schedule
Schedule a timer for automatic creation with a timeout schedule based on a cron-like time expression. The annotated method is used as the timeout callback method.
All elements of this annotation are optional. If none are specified a persistent timer will be created with callbacks occuring every day at midnight in the default time zone associated with the container in which the application is executing...
Documentation - http://docs.oracle.com/javaee/6/api/javax/ejb/Schedule.html
Example - https://stackoverflow.com/a/7499769/1490962
https://stackoverflow.com/a/5357856/1490962
http://ci.apache.org/projects/openejb/examples-generated/schedule-methods/
This isn't something that you can do through the mail APIs directly, you'd have to use some sort of scheduling tool (Quartz, Spring #Scheduled, or similar) to call sendMail at the appropriate times with the appropriate parameters.
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)
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...
I need to send simple html-message with JavaMail. And when I tried to find some nice examples with explanations in the Internet, each next example made me more angry and angry.
All those silly examples contain copied and pasted Java code which differs only in comments and a nice disclaimer that first you should config your smtp and pop3 server.
I understand that nobody wants to make an advertise for some concrete products but configuring the server is imho the hardest part. So, can anyone give me some really useful information (without java code) about configuring concrete server (Kerio, for example, or any other one)?
What I have now is the next exception:
250 2.0.0 Reset state
javax.mail.SendFailedException: Invalid Addresses;
nested exception is:
com.sun.mail.smtp.SMTPAddressFailedException: 550 5.7.1 Relaying to <mymail#mycompany.com> denied (authentication required)
UPD. Simple reformulation of all previous text is: imagine that you have Windows, jdk, and nothing else. And you want to make java program and run it on your machine. And this program should send "Hello world!" to your gmail account. List your steps.
UPD2. Here is the code:
Properties props = new Properties ();
props.setProperty ("mail.transport.protocol", "smtp");
props.setProperty ("mail.host", "smtp.gmail.com");
props.setProperty ("mail.user", "my_real_address_1#gmail.com");
props.setProperty ("mail.password", "password_from_email_above");
Session mailSession = Session.getDefaultInstance (props, null);
mailSession.setDebug (true);
Transport transport = mailSession.getTransport ();
MimeMessage message = new MimeMessage (mailSession);
message.setSubject ("HTML mail with images");
message.setFrom (new InternetAddress ("my_real_address_1#gmail.com"));
message.setContent ("<h1>Hello world</h1>", "text/html");
message.addRecipient (Message.RecipientType.TO,
new InternetAddress ("my_real_address_2#gmail.com"));
transport.connect ();
transport.sendMessage (message,
message.getRecipients (Message.RecipientType.TO));
And exception is:
RSET
250 2.1.5 Flushed 3sm23455365fge.10
com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. 3sm23455365fge.10
at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1829)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1368)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:886)
at com.teamdev.imgmail.MailSender.main(MailSender.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
...
If you're looking for a tutorial to configure an SMTP server, you shouldn't be looking for JavaMail. Simply look for a tutorial on your server of choice (Kerio, for example ... or Exim, SendMail, Apache James, Postfix) or ask on Serverfault. Any SMTP-compliant server will play nicely with JavaMail.
Alternatively, you may even use any "standard" mail provider's infrastructure. For example, I use a Google Apps account along with Google's SMTP infrastructure to send mail from our Java applications. Using a Gmail account is a good starting point anyway if you don't want to setup your own SMTP server in order to simply testdrive JavaMail.
As a last option, you might even lookup the MX Records for a domain and deliver your mails directly to the SMTP server of the recipient. There are some common gotchas to workaround tough.
As a last point, you'll have to look into how to avoid that your mails be filtered as spam - which is a huge topic itself. Here it helps to rely on standard providers that will deal with some of the issues you might encounter when hosting your own server.
Btw: Regarding the error message you posted: the SMTP server is denying relaying of messages. This is if your SMTP server (thinks that it) is running on example.com and you're sending as bob#example.net to alice#example.org, you're asking the SMTP server to act as a relay. This was common practice several years ago, until it was - you guessed it - abused by spammers. Since those days, postmasters are encouraged to deny relaying. You have two choices: authenticate before sending mail or send to accounts hosted at your server only (i.e. on example.com, e.g. alice#example.com).
Edit:
Here is some code to get you started with authenticationg (works with Gmail accounts but should do for your own server as well)
private Session createSmtpSession() {
final Properties props = new Properties();
props.setProperty("mail.smtp.host", "smtp.gmail.com");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.port", "" + 587);
props.setProperty("mail.smtp.starttls.enable", "true");
// props.setProperty("mail.debug", "true");
return Session.getDefaultInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("john.doe#gmail.com", "mypassword");
}
});
}
I can see part of your problem. It's adequately explained in the error message.
The SMTP server you are sending your mail to (i.e. one of the addresses you've configured in your JavaMail configuration) is refusing to forward mail to mymail#company.com. Looks like a configuration issue in your SMTP server. As sfussenegger indicated, it has nothing to do with javamail.
So you're not debugging on all fronts at the same time, it might be a good idea to try addressing your SMTP server from a known working SMTP client. Thunderbird would do fine, for example. If you can send mail through it from Thunderbird, there should be little problem from JavaMail.
Update:
The correct address for Google's SMTP server is: smtp.gmail.com . Is this the server you have configured in JavaMail? Can you show us the matching error message?
A working example combining the above answers, using activation-1.1.jar and mail-1.4.1.jar and the SMTP host is Gmail.
Replace user#gmail.com and user_pw in line return new PasswordAuthentication("user#gmail.com", "user_pw");
Also, you want to replace myRecipientAddress#gmail.com by the email address where you want to receive the email.
package com.test.sendEmail;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
public class sendEmailTest {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
sendEmailTest emailer = new sendEmailTest();
//the domains of these email addresses should be valid,
//or the example will fail:
emailer.sendEmail();
}
/**
* Send a single email.
*/
public void sendEmail(){
Session mailSession = createSmtpSession();
mailSession.setDebug (true);
try {
Transport transport = mailSession.getTransport ();
MimeMessage message = new MimeMessage (mailSession);
message.setSubject ("HTML mail with images");
message.setFrom (new InternetAddress ("myJavaEmailSender#gmail.com"));
message.setContent ("<h1>Hello world</h1>", "text/html");
message.addRecipient (Message.RecipientType.TO, new InternetAddress ("myRecipientAddress#gmail.com"));
transport.connect ();
transport.sendMessage (message, message.getRecipients (Message.RecipientType.TO));
}
catch (MessagingException e) {
System.err.println("Cannot Send email");
e.printStackTrace();
}
}
private Session createSmtpSession() {
final Properties props = new Properties();
props.setProperty ("mail.host", "smtp.gmail.com");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.port", "" + 587);
props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty ("mail.transport.protocol", "smtp");
// props.setProperty("mail.debug", "true");
return Session.getDefaultInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("user#gmail.com", "user_pw");
}
});
}
}
This should work:
import java.text.MessageFormat;
import java.util.List;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class Emailer {
public static void main(String[] args) {
String hostname = args[0];
final String userName = args[1];
final String passWord = args[2];
String toEmail = args[3];
String fromEmail = args[4];
String subject = args[5];
String body = "";
// add rest of args as one body text for convenience
for (int i = 6; i < args.length; i++) {
body += args[i] + " ";
}
Properties props = System.getProperties();
props.put("mail.smtp.host", hostname);
Session session = Session.getInstance(props, new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, passWord);
}
});
MimeMessage message = new MimeMessage(session);
try {
message.setFrom(new InternetAddress(fromEmail));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
message.setSubject(subject);
message.setText(body);
Transport.send(message);
} catch (MessagingException e) {
System.out.println("Cannot send email " + e);
}
}
}
You need to put the JavaMail mail.jar on your classpath for the javax.mail dependencies.
I'm not sure if Google lets you send email like you want to. How about trying another email provider, like your ISP's?