开发者

Problem sending email with image attachment from app engine using java mail api

First of all,I would like to thank everyone for the answers posted.This site is great. Second of all, I am having a problem and after searching a few days I still can't figure it out.I found a lot of people with the same problem, but no answer. I am trying to upload an image to a application running on app engine and to send an email with the image as an attachment. I am also using org.apache.commons.fileupload to upload the image. I successfully sent the email, but I am having trouble with the attachment. My html form looks like this:

<form id="contact" action="/sign" method="post" enctype="multipart/form-data">
                            <fieldset>
                                <label>Nume / Prenume</label>
                                <input type="text" name="nume" />
                                <label>Telefon</label>
                                <input type="text" name="telefon" />
                                <label>E-mail</label>
                                <input type="text" name="email"/>                                    
                            </fieldset>
                            <fieldset>
                                <label>Textul sesizarii</label>
                                <textarea name="textulses"></textarea>
                                <div class="upload-fix-wrap">
                                    <input size="35" class="upload" type="file"         name=myFile />
                                    <input type="text" />
                                    <button>Incarca poze</button>
                                </div>
                                <button class="send" type="submit">Trimite </button>
                            </fieldset>
                        </form>

My web.xml file where I choose wich servlet should answer looks like this:

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
    <servlet-name>sign</servlet-name>
    <servlet-class>com.campiacareiului.CampiaCareiuluiServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>sign</servlet-name>
    <url-pattern>/sign</url-pattern>
</servlet-mapping>
<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>

So, by now I have a html form and a servlet to respond. First, I tried by using javax.mail:

public class CampiaCareiuluiServlet extends HttpServlet {
private String nume=null;
private String telefon=null;
private String email=null;
private String textulses=null;
private String attname=null;
private  byte[] buffer = new byte[8192000];
private boolean att=false;
private int size=0;
private static final Logger log =
          Logger.getLogger(CampiaCareiuluiServlet.class.getName());
public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    try {

        ServletFileUpload upload=new ServletFileUpload();
        FileItemIterator it = upload.getItemIterator(req);
        while(it.hasNext()){
            FileItemStream item = it.next();
            String name = item.getFieldName();
            InputStream stream = item.openStream();
            if (item.isFormField()) {
    if(name.equals("nume")) nume=Streams.asString(stream);
        else if(name.equals("telefon")) telefon=Streams.asString(stream);
        else if(name.equals("email")) email=Streams.asString(stream);
        else if(name.equals("textulses")) textulses=Streams.asString(stream);开发者_如何学运维
            } else {
                att=true;
                attname=item.getName();

                int len;
                size=0;
               while ((len = stream.read(buffer, 0, buffer.length)) != -1){
                    size+=len;

                 }

            }

        }
          Properties props = new Properties();
            Session session = Session.getDefaultInstance(props, null);

  String msgBody = "Nume/Prenume: "+nume+" Telefon: "+telefon+" Mail:"+email+"Textul  Sesizarii: "+textulses;
  Message msg = new MimeMessage(session);
                msg.setFrom(new     InternetAddress("myAdministratorAccount@gmail.com", ""));
                msg.addRecipient(Message.RecipientType.TO,
                                 new InternetAddress("aUser@yahoo.com", "Mr. User"));
                msg.setSubject("Mail Sesizare Campia Careiului");
                msg.setText(msgBody);
   if(att){
         byte[] bufferTemp = new byte[size];
         for(int i=0;i<=size;i++)
             bufferTemp[i]=buffer[i];
             Multipart mp=new MimeMultipart();
                   MimeBodyPart attachment= new MimeBodyPart();

                   DataSource src = new ByteArrayDataSource 
                           (bufferTemp,"image/jpeg"); 
                   attachment.setFileName(attname);
                   attachment.setContent(src,"image/jpeg"); 
                   mp.addBodyPart(attachment);
                   msg.setContent(mp);

         }
     Transport.send(msg);
     resp.sendRedirect("/contact.html");
    } catch (Exception ex) {
          try {
            throw new ServletException(ex);
        } catch (ServletException e) {

            e.printStackTrace();
}
      }

}
}

When I debugged the application it showed that it had uploaded the image to the buffer, but it failed sending the mail (no exception was thrown) .( I uploaded the app to app engine because you cannot send an email if you are running the application locally). Next I tried using the low level api. The changes I made were:

                    Properties props = new Properties();
            Session session = Session.getDefaultInstance(props, null);

            String msgBody = "Nume/Prenume: "+nume+" Telefon: "+telefon+" Mail: "+email+" Textul Sesizarii: "+textulses;

            MailService service = MailServiceFactory.getMailService(); 
            MailService.Message msg = new MailService.Message(); 
                    msg.setSender("myAdminAccount@gmail.com"); 
                    msg.setTo("aUser@yahoo.com"); 
                    msg.setSubject("Mail Sesizare Campia Careiului"); 
                    msg.setTextBody(msgBody); 
     if(att){
         byte[] bufferTemp = new byte[size];
         for(int i=0;i<=size;i++)
             bufferTemp[i]=buffer[i];

            MailService.Attachment attachment=new MailService.Attachment("picture.pdf",
                   bufferTemp);
            msg.setAttachments(attachment);
             }
            service.send(msg);
                            resp.sendRedirect("/contact.html");

Now, it sends the email, with the attachment, but when I try to download the attachment from my email account(either a pdf or a image) it doesn't recognize it.It just says that the file may have been corrupted. When I tried to send an image I put "image/jpeg" and when I tried to send a pdf I put "application/pdf". I searched everywhere and I found other people with this problem but no solution. If someone could help me I would be grateful. ( I apologize for my spelling errors) My imports are:

import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.activation.DataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import javax.mail.Multipart;
import javax.servlet.http.*;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.io.IOUtils;

import com.google.appengine.api.mail.MailService;
import com.google.appengine.api.mail.MailServiceFactory;

I successfully sent the email with the attachment with the below code.But my problem is that when I try to download the attachment, or when I try to view it, it says that it is corrupted and it doesn't recognize it. I think that the problem lies in uploading the image. To upload the image I use org.apache.commons.fileupload. Here I upload the image to a byte array:

    while ((len = stream.read(buffer, 0, buffer.length)) != -1)
           {
                size+=len;
            }

I also track the size of the uploaded image in "size" Here, I move the image in another buffer of apropriate dimensions:

            byte[] bufferTemp = new byte[size];
            for(int i=0;i<size;i++)
                bufferTemp[i]=buffer[i];

The image from the attachment has the same dimension as the one uploaded, but is corrupted somehow.If anyone can help. The source code is:

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import javax.mail.Multipart;
import javax.servlet.http.*;

import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;


@SuppressWarnings("serial")
public class CampiaCareiuluiServlet extends HttpServlet {
private String nume=null;
private String telefon=null;
private String email=null;
private String textulses=null;
private String attname=null;
private  byte[] buffer = new byte[8192000];
private boolean att=false;
private int size=0;
private static final Logger log =
        Logger.getLogger(CampiaCareiuluiServlet.class.getName());
public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    try {

        ServletFileUpload upload=new ServletFileUpload();
        FileItemIterator it = upload.getItemIterator(req);
        while(it.hasNext()){
            FileItemStream item = it.next();
            String name = item.getFieldName();
            InputStream stream = item.openStream();
            if (item.isFormField()) {
                if(name.equals("nume")) nume=Streams.asString(stream);
                else if(name.equals("telefon")) telefon=Streams.asString(stream);
                else if(name.equals("email")) email=Streams.asString(stream);
                else if(name.equals("textulses")) textulses=Streams.asString(stream);
            } else {
                att=true;
                attname=item.getName();

                int len;
                size=0;
                while ((len = stream.read(buffer, 0, buffer.length)) != -1){
                    size+=len;

                }

            }

        }
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        String msgBody = "Nume/Prenume: "+nume+" Telefon: "+telefon+" Mail: "+email+" Textul Sesizarii: "+textulses;

        Message msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress("ursu.adrian88@gmail.com", "gmail.com Adrian Ursu"));
        msg.addRecipient(Message.RecipientType.TO,
                new InternetAddress("ursu.adrian88@gmail.com", "Mr. User"));
        msg.setSubject("Mail Sesizare Campia Careiului");

        if(!att){
            msg.setText(msgBody);      
        }
        else{
            byte[] bufferTemp = new byte[size];
            for(int i=0;i<size;i++)
                bufferTemp[i]=buffer[i];

            Multipart mp=new MimeMultipart();

            MimeBodyPart textPart = new MimeBodyPart();
            textPart.setContent(msgBody, "text/plain");

            mp.addBodyPart(textPart);

            MimeBodyPart attachment= new MimeBodyPart();
            DataSource src = new ByteArrayDataSource 
                    (bufferTemp, "image/jpeg"); 
            attachment.setFileName(attname);    
            attachment.setDataHandler(new DataHandler 
                    (src));
            mp.addBodyPart(attachment);
            msg.setContent(mp);
            msg.saveChanges();



        }
        Transport.send(msg);

        resp.sendRedirect("/contact.html");
    } catch (Exception ex) {
        try {
            throw new ServletException(ex);
        } catch (ServletException e) {

            e.printStackTrace();
        }
    }

}
}


I think the problem in example #1 may be that you are setting a text body and then trying to add a multipart. That isn't correct. A message can be of Content-Type: text/plain or Content-Type: multipart/mixed but not both. If there is an attachment, you need to add the text body as one of the multiparts. Something like this (untested):

   if (!att) {
         msg.setText(msgBody);
   } else {

         //first build and add the text part
         MimeBodyPart textPart = new MimeBodyPart();
         textPart.setContent(msgBody, "text/plain");

         Multipart mp=new MimeMultipart();
         mp.addBodyPart(textPart));

         //now read/buffer the image data (?)
         byte[] bufferTemp = new byte[size];
         for(int i=0;i<=size;i++)
             bufferTemp[i]=buffer[i];
             // YOU NEED TO FIX THIS!!
         }

         // now add the attachment part.
         // the attachment data must be added all together, not in pieces
         MimeBodyPart attachment= new MimeBodyPart();

         // YOU NEED TO FIX THIS!!
         attachment.setFileName(attname);
         attachment.setContent(bufferTemp,"image/jpeg"); 
         mp.addBodyPart(attachment);
         msg.setContent(mp);

There is also a problem with the way you are reading in your image data but you haven't provided enough of your code for me to tell you how to correct it. You'll need to read the ENTIRE image data into some object (array, buffer, etc) before adding it into the body part content. And you can't add src as the content for attachment - you have to use the actual data - either a String or a byte[] etc.

To help understand the concept of body parts, try and visualize the structure of the message. The email headers list a header of Content-type: multipart/mixed, with enclosed parts of Content-type: text/plain and Content-type: image/jpeg.

To: testuser@test.com
From: testuser2@test.com
Date: Aug 19, 2011
Content-Type: multipart/mixed; boundary="aswevb323f23f3f"

This is a message with multiple parts in MIME format.
--aswevb323f23f3f
Content-Type: text/plain

This is the body of the message.
--aswevb323f23f3f
Content-Type: image/jpeg
Content-Transfer-Encoding: base64

ZQs0bWw+CiAgPGhlYWQ+CiAgP49oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg
Ym9keSBvZiB0aGUgbWVzc2FnZa48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==
--aswevb323f23f3f


I finally got it to work. the problem (of course) uploading the image. I was overwriting the same bytes in buffer, I didn't take the offset into account. The right way is:

        int len=0;
        size=0;
        while ((len = stream.read(buffer, size,buffer.length)) != -1)
                {
                    size+=len;
                }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜