A question about sending email from java program - java

I need to send email from java program. I am first trying to understand basics. I found a snippet at:
https://www.javatpoint.com/example-of-sending-email-using-java-mail-api
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
public class SendEmail
{
public static void main(String [] args){
String to = "sonoojaiswal1988#gmail.com";//change accordingly
String from = "sonoojaiswal1987#gmail.com";change accordingly
String host = "localhost";//or IP address
//Get the session object
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host", host);
Session session = Session.getDefaultInstance(properties);
//compose the message
try{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,new InternetAddress(to));
message.setSubject("Ping");
message.setText("Hello, this is example of sending email ");
// Send message
Transport.send(message);
System.out.println("message sent successfully....");
}catch (MessagingException mex) {mex.printStackTrace();}
}
}
My question is that as per the code, it looks like anyone can use any sender email address string and send infinite emails to any receiver email address. I am missing something in my understanding, which will prevent such scenario to happen. Please help.
I understand that this is not a programming question, but guess, it will not take too much time to answer this basic question and don't know any other equally active forum.

This example works for servers which don't need authentication. And this is usually not applicable to the smtp servers used in production. Such servers are used mostly for testing purposes where they are not exposed over the internet. Hence, although its possible to send infinite number of mails as mentioned by you, no one would be interested in doing the same.
For the servers where authentication is necessary, credentials need to be provided. And this is explained in detail in the blog mentioned by you.

Related

Automating existing web application and email generated report

I do have a java web application that is used for storing data about issues we faces daily.
There are many users and each user will be inserting data into it daily and by the end of day we'll gather that particular days data and then mail it to everyone.
We are using the web app to do this. But as of now web app generates consolidated data for one day when I trigger it using a button press.
And the code written to create excel sheet drafts a excel sheet and this one i mail to everyone. This web application is being run on a server.
I wish to automate this process i.e. each night at some specified time it should automatically trigger the function and generate the excel sheet and it should mail it to everyone.
I don't have much idea about how to go forward so I thought first I'll write java code to send mail and later think about triggering the function at a particular time.
I would like to know whether is there any other better way to deal with my requirement. I'am open to suggestions.
Also, the code I have written to send the mail is not working. It is giving me exception and I tried almost everything I could find but nothing is working. Could someone help me in sorting out the error.
Here's the code :
package com.email;
import java.util.Properties;
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 SendEmail {
public static void main(String[] args) {
// Recipient's email ID needs to be mentioned.
String to = "toemail#gmail.com";
// Sender's email ID needs to be mentioned
String from = "fromemail#gmail.com";
final String username = "username";//change accordingly
final String password = "password";//change accordingly
String host = "smtp.gmail.com";
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", "587");
// Get the Session object.
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
// Create a default MimeMessage object.
Message message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(from));
// Set To: header field of the header.
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(to));
// Set Subject: header field
message.setSubject("Testing Subject");
// Now set the actual message
message.setText("Hello, this is sample for to check send " +
"email using JavaMailAPI ");
// Send message
Transport.send(message);
System.out.println("Sent message successfully....");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}
Exception that I am receiving is :
Exception in thread "main" java.lang.RuntimeException: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 587; timeout -1;
nested exception is:
java.net.UnknownHostException: smtp.gmail.com
at com.tutorialspoint.SendEmail.main(SendEmail.java:62)
Caused by: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 465; timeout -1;
nested exception is:
java.net.UnknownHostException: smtp.gmail.com
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2209)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:740)
at javax.mail.Service.connect(Service.java:388)
at javax.mail.Service.connect(Service.java:246)
at javax.mail.Service.connect(Service.java:195)
at javax.mail.Transport.send0(Transport.java:254)
at javax.mail.Transport.send(Transport.java:124)
at com.email.SendEmail.main(SendEmail.java:57)
Caused by: java.net.UnknownHostException: smtp.gmail.com
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:178)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:353)
at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:239)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2175)
... 7 more
According to the logs you cannot reach the gmail smtp. Are you maybe behind a proxy/firewall? Did you try pinging the smtp?
For running the tasks automatically you just need to add a scheduling framework to run the code at a certain time.
You could use quartz for example

Java email received from standalone class, but not when executed within a servlet

Using Java, I can send email from a toy standalone class (with hard-coded data) perfectly fine, and I receive the email within seconds.
When the exact same code is called in the context of a servlet, however, the code executes without failure, but I don't actually receive the email.
How could that be? Is there something special about the servlet environment?
I'm running Tomcat 6, JRE 1.5.
Here is the code (I have edited my data):
public void sendEmail(String aSubject, String aBody){
Properties props = new Properties();
props.put("mail.host", "smtp.blah.ca");
props.put("mail.from", "from-blah#blah.ca");
Session session = Session.getDefaultInstance(props, null /*no authenticator*/);
System.out.println("JRE" + System.getProperty("java.version"));
System.out.println(session.getProperties());
MimeMessage message = new MimeMessage(session);
try {
message.addRecipient(
Message.RecipientType.TO, new InternetAddress("to-blah#blah.com")
);
message.setSubject(aSubject);
message.setText(aBody);
Transport.send(message);
}
catch (MessagingException ex){
System.err.println("Cannot send email. " + ex);
}
}
Edit: the email is recieved when the content (email body) is small. When the content is large, it's not recieved.
This is not java-related at all.
I tested a large email with a normal email client. The same behavior was seen: the email is sent fine, but I'm not receiving it in a timely manner, for some reason. (I haven't seen this kind of behavior before, but there it is...)

Email sending not working using Apache James

I am trying to send email using apache james but the emails are not getting delievered. Below is my code.
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
public class test {
public static void main(String args[]) throws Exception {
String user = "test";
String password = "test";
String fromAddress = "test#localhost";
String toAddress = "test#gmail.com";
Properties properties = new Properties();
properties.put("mail.smtp.host", "localhost");
properties.put("mail.smtp.port", "25");
properties.put("mail.smtp.username", user);
properties.put("mail.smtp.password", password);
properties.put("mail.transport.protocol", "smtp");
Session session = Session.getDefaultInstance(properties, null);
try
{
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromAddress));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toAddress));
message.setSubject("Email from our JAMEs");
message.setText("hiiiiii!!");
Transport.send(message);
System.out.println("Email sent");
}
catch (MessagingException e)
{
e.printStackTrace();
}
}
}
Also test user is added in apache james having password test. Requesting you to kindly help me out in the same.
I think problem caused by this:
Email servers before accepting any mail do a reverse dns query. They check the ip for domain that the email came from and the ip that email is really came from.
If ip of domain and ip of email sender does not match, mail servers think that email is junk or spam.
Here since your domain (localhost) is not a valid address when Email server send a reverse dns query does not get an IP and think your mail is junk or spam.
For more information check this: http://wiki.junkemailfilter.com/index.php/Fixing_Reverse_DNS
I faced the same problem. What I did:
Go to the path : \apps\james\conf
Open for edit the filename 'james-fetchmail.xml'
Change "fetchmail" from false to true as:
Restart the Apache James Server.
You would see the following messages printed on the console after you start the server:
James Mail Server 2.3.2
Remote Manager Service started plain:4555
POP3 Service started plain:110
SMTP Service started plain:25
NNTP Service started plain:119
FetchMail Started
Now, run your program. It should work!
Did you added the domain "localhost"?
If not, add the domain first, and after create the users.
$ james-cli AddDomain -h 127.0.0.1 localhost
check if domain exists
$ james-cli ListDomains -h 127.0.0.1
And, how do you started james? Using james.bat?

Appengine not sending email

I am trying to use the Appengine Mail API to send mail from my application. I'm running the code below which executes fine without exceptions but no mail is actually sent. Here's the code:
public static void sendNotificationEmail(String subject, String message, String emailAddress) {
System.err.println("Sending mail: " + emailAddress);
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try {
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("a#b.com", "Name"));
msg.addRecipient(Message.RecipientType.TO, new InternetAddress(emailAddress));
msg.setSubject(subject);
msg.setText(message);
Transport.send(msg);
System.err.println("done");
}
catch (Exception e) {
System.err.println(e);
}
}
a#b.com is a registered owner of the app (but not the billing administrator). Looking at the logs, "done" is printed but no email is sent.
Any ideas?
UPDATE:
Found out the emails are actually getting through but are in the spam folder. Any way to give my app more (reputation) to not be marked as spam. Our app sends out notification emails to users when something has changed in the system.
Maybe you email marked as spam because it was sent from different host, I mean that maybe it's not GMail-connected domain.
At this case, to prevent it from being marked as spam, it's very helpful to configure SPF for your domain, see google help: Creating an SPF record. It has helped me some time ago

Getting Invalid Address with javax.mail when the addresses are fine

I'm using the javax.mail system, and having problems with "Invalid Address" exceptions. Here's the basics of the code:
// Get system properties
Properties props = System.getProperties();
// Setup mail server
props.put("mail.smtp.host", m_sending_host);
// Get session
Session session = Session.getDefaultInstance(props, new Authenticator(){
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(m_sending_user, m_sending_pass);
}
});
// Define message
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(m_sending_from));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(vcea.get(i).emailaddr));
message.setSubject( replaceEnvVars(subject) );
message.setText(replaceEnvVars(body));
// Send message
try {
Transport.send(message);
} catch (Exception e){
Log.Error("Error sending e-mail to addr (%s): %s",
vcea.get(i).emailaddr, e.getLocalizedMessage() );
}
The issue is that the above code does work, sometimes. But for some e-mail addresses that I know to be valid (because I can send to them via a standard e-mail client), the above code will throw an "Invalid Address" exception when trying to send.
Any clues or hints would be greatly appreciated.
--Update: problem with authentication.
Ok, here's what I've discovered was going on. When receiving e-mail, the code above correctly sets up authentication and the Authenticator.getPasswordAuthentication() callback is actually invoked.
Not so when sending e-mail. You have to do a bit more. Add this:
// Setup mail server
props.put("mail.smtp.host", m_sending_host);
props.put("mail.smtp.auth", "true");
which will force the javax.mail API to do the login authentication. And then use an actual Transport instance instead of the static .send() method:
Transport t = session.getTransport(m_sending_protocol);
t.connect(m_sending_user, m_sending_pass);
...
// Send message
try {
t.sendMessage(message, message.getAllRecipients());
} catch (Exception e){
Without forcing the authentication, the mail server saw me as an unauthorized relay, and just shut me down. The difference between the addresses that "worked" and the addresses that didn't was that the ones that "worked" were all local to the mail server. Therefore, it simply accepted them. But for any non-local "relay" addresses, it would reject the message because my authentication information hadn't been presented by the javax.mail API when I thought it would have.
Thanks for the clues to prompt me to look at the mail server side of things as well.
--Update: problem with authentication.
Ok, here's what I've discovered was going on. When receiving e-mail, the code above correctly sets up authentication and the Authenticator.getPasswordAuthentication() callback is actually invoked.
Not so when sending e-mail. You have to do a bit more. Add this:
// Setup mail server
props.put("mail.smtp.host", m_sending_host);
props.put("mail.smtp.auth", "true");
which will force the javax.mail API to do the login authentication. And then use an actual Transport instance instead of the static .send() method:
Transport t = session.getTransport(m_sending_protocol);
t.connect(m_sending_user, m_sending_pass);
...
// Send message
try {
t.sendMessage(message, message.getAllRecipients());
} catch (Exception e){
Without forcing the authentication, the mail server saw me as an unauthorized relay, and just shut me down. The difference between the addresses that "worked" and the addresses that didn't was that the ones that "worked" were all local to the mail server. Therefore, it simply accepted them. But for any non-local "relay" addresses, it would reject the message because my authentication information hadn't been presented by the javax.mail API when I thought it would have.
Thanks for the clues to prompt me to look at the mail server side of things as well.
I would change the call to InternetAddress to use the "strict" interpretation and see if you get further errors on the addresses you are having trouble with.
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(vcea.get(i).emailaddr, true ));
// ^^^^ turns on strict interpretation
Javadoc for InternetAddress constructor
If this fails, it will throw an AddressException which has a method called getPos() which returns the position of the failure (Javadoc)
A good hint for those using the ssl encryption in the smtp configuration, you should enable it by specifying the property mail.smtp.ssl.enable, as shown below:
props.put("mail.smtp.ssl.enable", "true");
Otherwise it can lead to similar problems as described above.
Try this:
String to="stackoverflow#so.com";
String cc="one#mail.com,two#mail.com"; //The separator ',' works good
message.setRecipients(Message.RecipientType.TO,new InternetAddress[] {
new InternetAddress(to) }); // This is only one mail
InternetAddress[] addr = parseAddressList(cc); //Here add all the rest of the mails
message.setRecipients(Message.RecipientType.CC,addr);
Sorry for my english. It's not good.
This seems to me like a problem that happened at my work.
If the code you are showing is being concurrent, then using directly System.getProperties
could be a problem, because the host value you put on them can be overwritten by next request, while still keeping the user and password from the overwritten host.
In our case, we solved that using a clone of the System.getProperties() hashtable.
Hope that helps (this problem was really hard to track).

Categories

Resources