I'm having an issue with sending attachments via email in java using the java mail (1.4.6). It seems that when I attach a document of any sort and send it, the recipient gets the file in plain text format in the body. Rather than, you guessed it, sending the whole file like you would expect and the body not interfered with.
Code
try
{
// Create a message
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(Compose.to));
message.setSubject(Compose.subject);
//message.setText(Compose.body);
//If there are no CC's then skip it. This if seemed to decrease send time.
if(Compose.cc != null)
{
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(Compose.cc));
message.saveChanges();
}
else
message.saveChanges();
/*
* For adding the attached file to the email. This time the if
* statement is used to stop the email attachment process if there
* is none. Other wise due to the way I've set it up it'll try to
* send file path and file name as null, and we fail an otherwise valid email.
*/
if(Compose.filename != null)
{
String file = Compose.filepath;
String fileName = Compose.filename;
Multipart multipart = new MimeMultipart();
BodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(file);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(fileName);
multipart.addBodyPart(messageBodyPart);
BodyPart messageBodyPart2 = new MimeBodyPart();
messageBodyPart2.setText(Compose.body);
multipart.addBodyPart(messageBodyPart2);
message.setContent(multipart);
}
else
{
message.setText(Compose.body);
message.saveChanges();
}
//Send the message by javax.mail.Transport .
Transport tr = session.getTransport("smtp"); // Get Transport object from session
tr.connect(smtphost, username, password); // We need to connect
tr.sendMessage(message, message.getAllRecipients()); // Send message
//Notify the user everything functioned fine.
JOptionPane.showMessageDialog(null, "Your mail has been sent.");
}
Thinking over this I remembered how FileDataSource() is an overloaded statement taking a string or a file type as a parameter, trying both I got the same result but I will experiment more with the the file type now.
EDIT: After more testing I noticed that sometimes the file will not appear along with whatever was in the body at the time of sending.
For each part you have to set disposition to Part.INLINE for the body and Part.ATTACHMENT for the attachment. The attachFile methods will do that for you. Avoid JavaMail 1.4.6 in favor of the latest release or at least use JavaMail 1.4.7 which contains fixes for known issues with JavaMail 1.4.6.
You're setting the attachment as the first body part. It needs to be the second body part.
Also, consider upgrading to JavaMail 1.5.4 and using the MimeBodyPart.attachFile method to attach the file.
Related
I'm trying to embed a link in email for a file attached in email message using JavaMail APi like here.
This is my code:
MimeMultipart multipart = new MimeMultipart("related");
BodyPart messageBodyPart = new MimeBodyPart();
String attachment = "/path/test.pdf";
File fAtachh = new File(attachment);
String htmlText = "<a href='cid:file'>test.pdf</a>";
messageBodyPart.setContent(htmlText, "text/html");
multipart.addBodyPart(messageBodyPart);
MimeBodyPart messageBodyPartAttach = new MimeBodyPart();
try {
messageBodyPartAttach.attachFile(fAtachh);
} catch (IOException e) {
logger.info("Exception" + e.getMessage());
}
messageBodyPartAttach.setContentID("<file>");
multipart.addBodyPart(messageBodyPartAttach);
message.setContent(multipart);
The problem is that link doesn't work:
ErrorLink
If change the last code by:
MimeMultipart multipart = new MimeMultipart("related");
MimeBodyPart messageBodyPart = new MimeBodyPart();
String attachment = "/path/test.pdf";
String htmlText = "<a href='cid:file'>test.pdf</a>";
messageBodyPart.setContent(htmlText, "text/html");
multipart.addBodyPart(messageBodyPart);
MimeBodyPart messageBodyPartAttach = new MimeBodyPart();
DataSource fds = new FileDataSource
(attachment);
messageBodyPartAttach.setDataHandler(new DataHandler(fds));
messageBodyPartAttach.setHeader("Content-ID","<file>");
multipart.addBodyPart(messageBodyPartAttach);
message.setContent(multipart);
The link Works but the file name and extension are wrong:
WrongFileName
I've tried to change the file name by method:
messageBodyPartAttach.setFileName("test.pdf");
but if I set the file name, the link doesn´t work like in the first code.
Any suggestion?
Thanks!
The attachFile method sets the filename and sets the Content-Disposition to ATTACHMENT. In a multipart/related message you probably don't want those set, although it likely depends on what mail reader you're using to display the message.
There should be no functional different between using the setContentID method and using the setHeader method with "Content-ID".
Normally multipart/related messages are used to allow the html part to reference an image part also included in the message, and displayed along with the html part. Probably no mail readers are going to display a pdf file inline with the html.
Maybe the question to ask is, what exactly are you trying to accomplish?
If you just want the pdf file to appear as an attachment with a correct filename that the user can then click on to save or view, you should use the (default) multipart/mixed instead of multipart/related. I'm not sure there's a good way to embed the link to the attached file in the html text. If you're able to create such a message with some other mailer, you can examine the structure of that message and replicate it using JavaMail.
i am sending the inline image with email with mime message. Here is the brief code for the same. This is working fine. My
question is i am not setting the MimeMessage content-type as multipart/related (Also not setting
multipart subtype as related)still my code is working fine and iam able to get the inline image at expected postion.
Should i really care about setting the Content-Type as multipart/related when i am referring the image part with cid
or server takes care of that?
MimeMessage msg = new MimeMessage(mailSession);
MimeMultipart mpart = new MimeMultipart();
MimeBodyPart bp = new MimeBodyPart();
bp.setText("plain text and here is html image refering image part <img src="cid:Unique-ContentId" />", CHARSET_UTF_8, MESSAGE_HTML_CONTENT_TYPE);
// add message body
mpart.addBodyPart(bp);
// adding inline image part
MimeBodyPart bodyPart1 = new MimeBodyPart();
bodyPart1.setFileName("inline image");
file1 = new File("image1");
DataSource source1 = new FileDataSource(file);
bodyPart1.setDataHandler(new DataHandler(source));
bodyPart1.setDisposition(MimeBodyPart.INLINE);
bodyPart1.setHeader("Content-ID", "Unique-ContentId");
bodyPart1.setHeader("Content-Type", "image/jpeg");
mpart.addBodyPart(bodyPart1);
// At last setting multipart In MimeMessage
msg.setContent(mpart);
Just for information my email client can be outlook,lotusnotes,yahoo,gmail,thunderbird
That's what we call "luck". :-)
Apparently the email clients you're using are being very generous in the way they interpret the message you're sending. There's nothing in the email specs that suggest they should interpret such messages in this way.
I have been trying to get a solution but I am not able to. Here is the whole thing. I wrote the following code
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
message.setSentDate(new Date());
MimeBodyPart messagePart = new MimeBodyPart();
messagePart.setContent(messageContent, "text/html");
Multipart multipart = new MimeMultipart("mixed");
multipart.addBodyPart(messagePart);
MimeBodyPart attachmentPart = new MimeBodyPart();
DataSource source = new ByteArrayDataSource(attachment.getBytes(), "text/plain");
attachmentPart.setDataHandler(new DataHandler(source));
attachmentPart.setFileName(attachmentFileName);
multipart.addBodyPart(attachmentPart);
message.setContent(multipart);
try {
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
The code is pretty much self explanatory. messagePart is the mail and attachmentPart is the attachment. But messagePart here is not plain text. It is HTML. So the problem is if I run this code mail is sent successfully but the attachment does not come attached to the mail. So my question boils down to this. Is it possible to send html content and attach something to a mail at the same time. I am stuck here. Could anyone help please.
I don't see anything obviously wrong with your code.
How are you determining that the message has no attachment?
You can see exactly what JavaMail would send by adding "message.writeTo(System.out);" just before you call Transport.send.
What version of JavaMail are you using? What mail server are you using? Some mail servers (I'm looking at you, Exchange) will reformat the message to what they think it should be, even if it's different than what you intended.
If you are running on Google App Engine and you add a dummy text part it works great. I have no idea why the dummy text part makes it work, but I was having the exact same problem and adding a dummy text part worked for me too.
You want to add
attachmentPart.setDisposition(Part.ATTACHMENT);
Part.ATTACHMENT means the part should be showed as an attachment.
Part.INLINE means you want to show the attachment as part of the message.
I have a MailMessage class I've written to manage sending email from my application. It works fine for plain text messages, and the attachment logic works when I compile and run it manually on the command line, but it fails to include my attachments when I'm running it within Glassfish 3.1. I'm assuming there must be some subtle class loading problem that I'm clobbering on the command line by having my CLASSPATH environment set, but I haven't been able to figure out what application server setting I need to change. Here's the code I use to create and send my mail message when running on the command line:
public static void main(String[] args) throws Exception {
String[] toAddr = new String[] {"steve.ferguson#epsilon.com"};
String subject = "This is a test";
String data = "This is a message body";
MailMessage mailMessage = new MailMessage(toAddr, subject, data);
mailMessage.addAttachment(new File("/etc/hosts"), "text/plain");
mailMessage.send();
}
If I change this function to a method called by my servlet, with debugging enabled, the resulting mail message looks like this:
[#|2011-11-17T11:21:37.710-0500|INFO|glassfish3.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-1;|Date: Thu, 17 Nov 2011 11:21:37 -0500 (EST)
From: sender#mydomain.com
To: steve.ferguson#mydomain.com
Message-ID: <9116840.7.1321546897580.JavaMail...>
Subject: This is a test
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_6_16232037.1321546897569"
.
|#]
By comparison, when I run the same code on the command line, it shows all of the attachments, each with the separate message boundary. This is the function I'm using to add the attachments to the underlying MimeMessage:
private Multipart buildMultipartMessage(String messageBody)
throws MessagingException {
MimeBodyPart messagePart = new MimeBodyPart();
messagePart.setText(messageBody.toString());
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messagePart);
// Attach each of our files
for (File part : attachment.keySet()) {
BodyPart attachmentPart = new MimeBodyPart();
attachmentPart.setDataHandler(new DataHandler(new FileDataSource(part)));
attachmentPart.setFileName(part.getName() + ".txt");
attachmentPart.setHeader("Content-Type", attachment.get(part));
attachmentPart.setHeader("Content-ID", part.getName());
attachmentPart.setDisposition(Part.ATTACHMENT);
multipart.addBodyPart(attachmentPart);
}
return multipart;
}
Which is called and used like this by my MailMessage class:
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("sender#mydomain.com"));
InternetAddress[] addresses = new InternetAddress[mailTo.length];
for (int i = 0; i < mailTo.length; i++)
addresses[i] = new InternetAddress(mailTo[i]);
message.setRecipients(Message.RecipientType.TO, addresses);
message.setSubject(subject);
message.setSentDate(new Date());
Multipart multipart = buildMultipartMessage(messageBody.toString());
message.setContent(multipart);
Again, all of this code, exactly as is, compiles, runs, and produces a valid email with attachments when run on the command line. It's only when I do the same thing within Glassfish that I get an empty message.
Any suggestions on how to diagnose this would be most appreciated.
Steve
UPDATE:
If I add this code after the call to buildMultipartMessage(), but before message.setContent(multipart), I can see that the content is correct:
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("/var/tmp/stf"));
multipart.writeTo(bos);
bos.close();
} catch (Exception ex) { }
The /var/tmp/stf file contains the full message body with attachments and separators. I'm still confused as to why this works from the command line, but not within Glassfish, but the information may be useful in resolving the problem.
It turned out that my solution to this problem caused the current problem. Having javax.mail.jar in my boot classpath and activation.jar in my endorsed directory was the only way I could get email handling working with the logger, but then they didn't work for normal usage. I have no idea why this is, but I found that eliminating the -Xbootclasspath option and removing activation.jar from my endorsed directory fixed the problem. If anyone has any speculation as to why, I'd be glad to do some more testing and report back. For now, I guess I have to live without email logging, because the attachments are a requirement for my application.
Perhaps if I switch to log4j instead of using the native Java EE 6 logging, I can have the best of both worlds.
why mail content is sent as attachment when I send it to Hotmail account?
When I send mail to a Hotmail account the body of the mail is sent as attachment. But when sent to other accounts like yahoomail, gmail it is not creating any problem.
I want to know why I am getting problem with Hotmail accounts.
Please give me a solution for this.
MimeMessage msg = createMimeMessage(sender, emsg,session,mail.companyName); Transport.send(msg);
Multipart multipart = new MimeMultipart();
// This is the template Attachment part
if (emsg.getAttachment() != null) {
for (File file : emsg.getAttachment()) {
MimeBodyPart messageAttachmentBodyPart = new MimeBodyPart();
messageAttachmentBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(file);
messageAttachmentBodyPart.setDataHandler(new DataHandler(source));
messageAttachmentBodyPart.setFileName(file.getName());
multipart.addBodyPart(messageAttachmentBodyPart);
}
}
Right. So, what happens if you send a file from a gmail account to a hotmail account, does it get attached? Or is it displayed just as you want? My guess is that attaching the file is a security measure to prevent malicious code from being activated on display. This mechanism might also be selective, meaning that it depends on the sender (an interesting post to read on this matter is this one).
Another thought: why is that a problem anyway?
Might help if you add
messageAttachmentBodyPart.setDisposition(Part.INLINE);