I'm trying to send an email using javamail inside a web application using TomEE. My problem is that when I attach a file such as a PDF, the file that I recive is named "noname". Also I don't recieve the body text.
As an observation, if I execute my code from a "main" program (in an other project), the email is sent perfectly. Here is the code:
public class EnviaCorreo{
static Properties mailServerProperties;
static Session getMailSession;
static MimeMessage generateMailMessage;
public void generateAndSendEmail() throws AddressException, MessagingException {
System.out.println("\n 1st ===> setup Mail Server Properties..");
mailServerProperties = System.getProperties();
mailServerProperties.put("mail.smtp.port", "587");
mailServerProperties.put("mail.smtp.auth", "true");
mailServerProperties.put("mail.smtp.starttls.enable", "true");
System.out.println("Mail Server Properties have been setup successfully..");
System.out.println("\n\n 2nd ===> get Mail Session..");
getMailSession = Session.getDefaultInstance(mailServerProperties, null);
generateMailMessage = new MimeMessage(getMailSession);
generateMailMessage.addRecipient(Message.RecipientType.TO, new InternetAddress("xxx#gmail.com"));
generateMailMessage.addRecipient(Message.RecipientType.CC, new InternetAddress("yyy#gmail.com"));
generateMailMessage.setSubject("Foo store has bought strawberries");
MimeMultipart multiParte = new MimeMultipart();
BodyPart adjunto = new MimeBodyPart();
adjunto.setDataHandler(new DataHandler(new FileDataSource("/home/foo/Desktop/FooProject/src/main/resources/fruit/6781430324446945.pdf")));
adjunto.setFileName("readme.pdf");
BodyPart texto = new MimeBodyPart();
texto.setText("Success!!");
multiParte.addBodyPart(texto);
multiParte.addBodyPart(adjunto);
generateMailMessage.setContent(multiParte, "text/html");
System.out.println("Mail Session has been created successfully..");
System.out.println("\n\n 3rd ===> Get Session and Send mail");
Transport transport = getMailSession.getTransport("smtp");
transport.connect("smtp.gmail.com", "yyy#gmail.com", "foopsswd123()");
transport.sendMessage(generateMailMessage, generateMailMessage.getAllRecipients());
transport.close();
}
Bonus
I'm working with TomEE and iText for PDF generation. Where should I put the folder where I save dynamically generated PDFs to?
TomEE uses geronimo javamail (in tomee lib) by default. You can replace it by the version you used in your main and add geronimo-locator and geronimo-registry
http://repo1.maven.org/maven2/org/apache/geronimo/specs/geronimo-osgi-locator/1.1/geronimo-osgi-locator-1.1.jar
and http://repo1.maven.org/maven2/org/apache/geronimo/specs/geronimo-osgi-registry/1.1/geronimo-osgi-registry-1.1.jar as well in libs
If you dont want to change the version maybe use tomee.xml session to get your session injected. I know for gmail you have to provide an authenticator for instance with geronimo javamail
Related
So i am trying to send a pdf through mail using Gmail smtp port 465 but it keeps on throwing this error,
googled it but couldn't solve this.
i don't understand whats wrong? help me on this?
thanks in advance
tried:
1.changing ports
2.tried to correct something on certificates didn't work
error:
Exception in thread "main" java.lang.RuntimeException: javax.mail.MessagingException: Exception reading response;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sample.pdf.PDFMailing.pdfMail(PDFMailing.java:72)
at com.sample.pdf.GeneratePdf.addDataToPdf(GeneratePdf.java:42)
at com.sample.pdf.Report.main(Report.java:47)
PDFMailing.java
public static void pdfMail(String file){
//Sender email-ID and Password.
final String senderEmail="xxxxxx";//Sender Mail ID
final String password="xxxxx";//Sender Mail ID Password.
//setting the Properties.
Properties props=new Properties();
props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
props.put("mail.smtp.socketFactory.port", "465"); //SSL Port
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory"); //SSL Factory Class
props.put("mail.smtp.auth", "true"); //Enabling SMTP Authentication
props.put("mail.smtp.port", "465"); //SMTP Port
//Authenticating the mailID of the sender.
Authenticator auth = new Authenticator() {
//override the getPasswordAuthentication method
protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
return new javax.mail.PasswordAuthentication(senderEmail, password);
}
};
//Creating and getting the Session Object.
Session session=Session.getInstance(props, auth);
//Setting the From, To, Subject, MessageBody.
try{
Message message=new MimeMessage(session);
message.setFrom(new InternetAddress(senderEmail));//Sender Mail ID
message.setRecipients(Message.RecipientType.TO,InternetAddress.parse("harshapirate#gmail.com"));//Receiver Mail ID
message.setSubject("Sample ECO PDF file");
message.setText("This a Sample ECO PDF file.");
MimeBodyPart bodyPart=new MimeBodyPart();
Multipart multipart=new MimeMultipart();
bodyPart.setText("This is multipart Text.");
//Attachments for any file.
MimeBodyPart pdfAttachment=new MimeBodyPart();
pdfAttachment.attachFile(file);
//Attach the Body part to the Multipart.
multipart.addBodyPart(bodyPart);
multipart.addBodyPart(pdfAttachment);
//Associate multipart to the message.
message.setContent(multipart);
System.out.println("Sending mail is in process.......");
//sending the message to-address mail.
Transport.send(message);
System.out.println("Mail has been sent sucessfully.");
}
catch(Exception e){
throw new RuntimeException(e);
}
}
I presume that is Java 8.0.251. Since you have the latest Java 8 release then this should not be happening:
The root certificates in a 8.0.251 keystore should all be current.
The real smtp.google.com should be using well-known root certificates.
The real smtp.google.com would not be presenting the cert chain in the wrong order.
So I think that something is else "getting in the way". Likely explanations include:
Something that is sending outgoing email connections through an SMTP proxy; e.g. a firewall or anti-virus product.
You are running on an application server that has overridden the set of trusted certificates provided by the JDK.
It is also possible that something has subverted your DNS or IP routing and you are talking to a spoofed "smtp.gmail.com" server.
Check the following:
Check if latest JDK is installed (Command: java -version) so that it has latest
certificates and updated CA's.
Check if there are multiple JDKs or JREs installed: If so remove them.
Check if JAVA_HOME is pointing to the latest JDK you installed.
(Command: echo $JAVA_HOME in linux Or echo %JAVA_HOME% in Windows command prompt)
Check if your system date and time are correct.
If above is verified then your Java installation is fine.
Code:
I see a missing property in your code: props.put("mail.smtp.starttls.enable", "true").
Add it and try.
Hope you are able to access Gmail from your browser at least. This confirms that your machine is able to access Gmail servers - Though not an exact test for SMTP, but it is still good to test.
If you are running inside Tomcat, then ensure you have the latest version and hope it has its certificate store not customized or altered in some way.
If everything above is OK, then either you are behind some proxy or you are hacked.
Maybe check for a system property or other way that someone has defined a different trust store e.g. with: -Djavax.net.ssl.trustStore=somefilename.jks
See: https://www.baeldung.com/java-keystore-truststore-difference
But the default truststore should be $JAVA_HOME/jre/lib/security/cacerts (but its contents vary between the Oracle JDK and OpenJDK - this was later fixed, see: https://openjdk.java.net/jeps/319 )
Inspecting/modifying the contents of the store can be done with the command line tool: keytool or a GUI like: https://keystore-explorer.org/
Before you go crazy try starting your application with the following extra System Property for java (-Dsystempropertyname=value):
-Djavax.net.debug=all
Then you will exactly see all details of the used trust store and offered certificates from the server, details of the SSL/TLS handshake and even all data encrypted/decrypted.
For all the information there is on this subject see the JSSE Reference Guide for your Java version, e.g.: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html
The same kind of code, I have written earlier and is in working state. Could you please give a try on using this code below:
Also, check the proper version of Java installed 8+ in your system, with all the Environment variables properly set and required for your project. If any proxy settings exists in your system, try to remove it and then again running the code.
//this will work only for gmail.
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import com.[MyProjectRelatedImports].pojo.EmployeeDetails;
public class SendEmail {
public static void sendMail(List<EmployeeDetails> emplDetails) {
Address[] to = new Address[emplDetails.size()];
try {
for (int i = 0; i < to.length; i++) {
to[i] = new InternetAddress(emplDetails.get(i).getEmail());
}
} catch (MessagingException e) {
e.printStackTrace();
}
// Recipient's email ID needs to be mentioned.
String tom = "xyz#gmail.com";// address of recipient
// Sender's email ID needs to be mentioned
String from = "abc#gmail.com"; //address of sender
// Assuming you are sending email from localhost
String host = "smtp.gmail.com";
// Get system properties
Properties properties = System.getProperties();
// Setup mail server
properties.setProperty("mail.smtp.host", host);
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.user", "emailID"); // User name
properties.put("mail.smtp.password", "password"); // password
properties.put("mail.smtp.port", "587");// default mail submission port
properties.put("mail.smtp.auth", "true");
// Get the default Session object.
Session session = Session.getDefaultInstance(properties, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("emailID", "password"); // username will be your email address and password same as your Gmail account.
// And if your account is protected with 2 step verification then you need to generate the app password from the link provided
//https://security.google.com/settings/security/apppasswords
}
});
try {
// Create a default MimeMessage object.
MimeMessage message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(from));
// Set To: header field of the header. //message.addRecipient(Message.RecipientType.TO, new InternetAddress(tom));
//Send Email to multiple recipients
message.addRecipients(Message.RecipientType.TO, to);
// Set Subject: header field
message.setSubject("Subject text via Java Class");
// Now set the actual message
message.setText("Message Content should be written here!!! Regards: Pratishtha Sharma ");
// Send message
Transport.send(message);
System.out.println("Sent message successfully....");
} catch (MessagingException mEx){
mEx.printStackTrace();}
}
}
We are moving some old code to java11.We are creating a smtp client. The coe compilation fails when we use java11.
error: package sun.net.smtp is not visible
[javac] sun.net.smtp.SmtpClient SMTP = new sun.net.smtp.SmtpClient(SMTP_SERVER);
[javac] ^
[javac] (package sun.net.smtp is declared in module java.base, which
does not export it)
looks like smtp package support is removed from the java11. Any suggestions will be helpful.
Regards,
Akj
You can use JavaMail API to send email to get this sorted. Go to below link and download the .jar file and add to your project. If not you can add it as a maven dependency.
https://mvnrepository.com/artifact/javax.mail/mail/1.4.7
A sample code to talk to SMTP server and send email as per below.
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("abc#abcmail.com"));
message.setRecipients(
Message.RecipientType.TO, InternetAddress.parse("to#abcmail.com"));
message.setSubject("Mail Subject");
String msg = "This is a sample email ";
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(msg, "text/html");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
message.setContent(multipart);
Transport.send(message);
Your configurations can be done with a Java Properties object
Properties prop = new Properties();
prop.put("mail.smtp.auth", true);
prop.put("mail.smtp.starttls.enable", "true");
prop.put("mail.smtp.host", "smtp.abcmail.com");
prop.put("mail.smtp.port", "25");
prop.put("mail.smtp.ssl.trust", "smtp.abcmail.com");
You should use JavaMail, a Java API for sending and receiving emails via SMTP, POP3, and IMAP.
First, have a look at Oracle docs about sending mail in Java here
The sample code below is extracted from the Oracle docs and illustrate how you should send email using the JavaMail API.
Properties props = new Properties();
props.put("mail.smtp.host", "my-mail-server");
Session session = Session.getInstance(props, null);
try {
MimeMessage msg = new MimeMessage(session);
msg.setFrom("me#example.com");
msg.setRecipients(Message.RecipientType.TO,
"you#example.com");
msg.setSubject("JavaMail hello world example");
msg.setSentDate(new Date());
msg.setText("Hello, world!\n");
Transport.send(msg, "me#example.com", "my-password");
} catch (MessagingException mex) {
System.out.println("send failed, exception: " + mex);
}
Also, note that to send a mail with Java Mail you need a valid SMTP server and an account in that server.
I'm trying to figure it out of how to open an email using javax.mail. My goal is to provide a feature where a user clicks on a button and a default email will open with an attachment. So far, I'm using javax.mail and what it does is just sending the email right when the button is click. Is there a way to just open the email without direct sending? If so, how? I'm using Java 8.
I can't use the 'mailto:' because I need to attach a png file when a user opens an email. Also I'm not sure if I should use ProcessBuilder to open outlook because every user's machine will have a different userName within the C Drive or I'm not sure how to use that.
Here's my code just in case if you need it
String result;
String to = "....gov";
String from = "....gov";
String host = "....gov";
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host", host);
Session mailSession = Session.getDefaultInstance(properties);
try{
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress(emailFrom));
message.addRecipient(Message.RecipientType.TO,new InternetAddress(emailTo));
message.setSubject("meh!");
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("text body mehmehmehmeh");
// Create a multipar message
Multipart multipart = new MimeMultipart();
// Set text message part
multipart.addBodyPart(messageBodyPart);
// Part two is attachment
messageBodyPart = new MimeBodyPart();
String filename = "testing.png";
DataSource source = new FileDataSource(filename);
String imageString = toDataURL.substring("data:image/png;base64," .length());
byte[] contentdata = imageString.getBytes();
ByteArrayDataSource ds = new ByteArrayDataSource(contentdata, "image/png");
messageBodyPart.setDataHandler(new DataHandler(ds));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart); //
// Send the complete message parts
message.setContent(multipart);
Transport.send(message);
result = "Sent message successfully....";
}catch (MessagingException mex) {
mex.printStackTrace();
result = "Error: unable to send message....";
}
Is there a way to just open the email without direct sending? If so, how?
Don't call Transport.send. Then follow the steps in this answer. and start with msg.saveChanges(). There is an X-Unsent header in that answer that can be used to toggle some outlook features.
Also I'm not sure if I should use ProcessBuilder to open outlook because every user's machine will have a different userName within the C Drive or I'm not sure how to use that.
You use File.createTempFile​ as this will account for user names. If you need to save in a different location you can read from System.getProperty​ or if you are only targeting Windows machines you can read from System.getenv. To list all the environment vars you can type set in the command window.
Currently I am using Commons Email to send email messages, but I have not been able to find a way to share smtp connections between emails sent. I have code like the following:
Email email = new SimpleEmail();
email.setFrom("example#example.com");
email.addTo("example#example.com");
email.setSubject("Hello Example");
email.setMsg("Hello Example");
email.setSmtpPort(25);
email.setHostName("localhost");
email.send();
Which is very readable, but is slow when I do a large amount of messages, which I believe is the overhead of reconnecting for each message. So I profiled it with the following code and have found that using the reusing the Transport makes things about three times faster.
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
Session mailSession = Session.getDefaultInstance(props, null);
Transport transport = mailSession.getTransport("smtp");
transport.connect("localhost", 25, null, null);
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress("example#example.com"));
message.addRecipient(Message.RecipientType.TO, new InternetAddress("example#example.com"));
message.setSubject("Hello Example");
message.setContent("Hello Example", "text/html; charset=ISO-8859-1");
transport.sendMessage(message, message.getAllRecipients());
So I was wondering if there was a way to make Commons Email reuse an SMTP connection for multiple email sendings? I like the Commons Email API better, but the performance is kind of painful.
Thanks,
Ransom
I came up with the following solution after digging into the commons source itself. This should work, but there may be better solutions I do not know of
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
Session mailSession = Session.getDefaultInstance(props, null);
Transport transport = mailSession.getTransport("smtp");
transport.connect("localhost", 25, null, null);
Email email = new SimpleEmail();
email.setFrom("example#example.com");
email.addTo("example#example.com");
email.setSubject("Hello Example");
email.setMsg("Hello Example");
email.setHostName("localhost"); // buildMimeMessage call below freaks out without this
// dug into the internals of commons email
// basically send() is buildMimeMessage() + Transport.send(message)
// so rather than using Transport, reuse the one that I already have
email.buildMimeMessage();
Message m = email.getMimeMessage();
transport.sendMessage(m, m.getAllRecipients());
Could we not achieve this easier by getting the mail session from the first email using getMailSession() and putting it to all subsequent messages using setMailSession() ?
Not 100% sure what the
Please note that passing a username and password (in the case of mail authentication) will create a new mail session with a DefaultAuthenticator. This is a convience but might come unexpected. If mail authentication is used but NO username and password is supplied the implementation assumes that you have set a authenticator and will use the existing mail session (as expected).
from the javadoc means, though :-/
http://commons.apache.org/email/api-release/org/apache/commons/mail/Email.html#setMailSession%28javax.mail.Session%29
see also:
https://issues.apache.org/jira/browse/EMAIL-96
not sure how to continue here...
i have using the following code for sending mail within a domain.
public void sendMail(String mailServer, String from, String to,
String subject, String messageBody, String[] attachments)
throws MessagingException, AddressException {
// Setup mail server
Properties props = System.getProperties();
props.put("mail.smtp.host", mailServer);
// Get a mail session
Session session = Session.getDefaultInstance(props, null);
// Define a new mail message
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
// Create a message part to represent the body text
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(messageBody);
// use a MimeMultipart as we need to handle the file attachments
Multipart multipart = new MimeMultipart();
// add the message body to the mime message
multipart.addBodyPart(messageBodyPart);
// add any file attachments to the message
addAtachments(attachments, multipart);
// Put all message parts in the message
message.setContent(multipart);
// Send the message
Transport.send(message);
System.err.println("Message Send");
}
protected void addAtachments(String[] attachments, Multipart multipart)
throws MessagingException, AddressException {
for (int i = 0; i < attachments.length ; i++) {
String filename = attachments[i];
MimeBodyPart attachmentBodyPart = new MimeBodyPart();
// use a JAF FileDataSource as it does MIME type detection
DataSource source = new FileDataSource(filename);
attachmentBodyPart.setDataHandler(new DataHandler(source));
// assume that the filename you want to send is the same as the
// actual file name - could alter this to remove the file path
attachmentBodyPart.setFileName(filename);
// add the attachment
multipart.addBodyPart(attachmentBodyPart);
}
}
but if with the same code i try to send an email outside the domain, say i am sending email from mjsharma#domain.com to mhsharma#gmail,com then it fails and gives me the following error. 550 5.7.1 Rcpt command failed: Mail denied due to site's policy
Am i missing something in the above code.
Please help me
I suspect that's not a problem in your code, but in your mail server (sendmail?) configuration. I would talk to whoever administers your mail infrastructure.
It's likely that your local mail server requires you to authenticate before sending mail out into the world. This is a common policy to prevent spammers from relaying their mail through it.
Assuming your machine has Outlook installed... have you tried using moyosoft's java outlook connector? it's pretty simple to use and passes through network restrictions because it connects to your Outlook application and then sends the mail, so any restriction on smtp ports or servers/proxy policies will be ignored if your Outlook client is working fine.
if you are doing it with command line server-side then i guess this answer is useless for you.
Source: i had similar problem (not same error code, more like an intranet restriction) and using this library solved my problem because of the posted above.