Проблема отправки электронной почты с вложенным изображением из движка приложения с помощью Java Mail API - PullRequest
0 голосов
/ 19 августа 2011

Прежде всего, я хотел бы поблагодарить всех за опубликованные ответы. Этот сайт великолепен. Во-вторых, у меня возникла проблема, и после нескольких дней поиска я все еще не могу ее решить. Я нашел много людей с такой же проблемой, но ответа не было. Я пытаюсь загрузить изображение в приложение, работающее на ядре приложения, и отправить электронное письмо с изображением в виде вложения. Я также использую org.apache.commons.fileupload для загрузки изображения. Я успешно отправил электронное письмо, но у меня возникли проблемы с вложением. Моя HTML-форма выглядит так:

<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>

Мой файл web.xml, в котором я выбираю, какой сервлет должен отвечать, выглядит следующим образом:

<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>

Итак, теперь у меня есть HTML-форма и сервлет для ответа. Сначала я попытался с помощью 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();
}
      }

}
}

Когда я отлаживал приложение, оно показывало, что оно загрузило изображение в буфер, но не смогло отправить почту (исключение не было выдано). (Я загрузил приложение в механизм приложений, потому что вы не можете отправить электронное письмо, если вы запуск приложения локально). Затем я попытался использовать API низкого уровня. Я сделал следующие изменения:

                    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");

Теперь он отправляет электронное письмо с вложением, но когда я пытаюсь загрузить вложение из своей учетной записи электронной почты (в формате PDF или изображения), оно не распознает его. Оно просто говорит, что файл мог быть поврежден. Когда я пытался отправить изображение, я помещал «image / jpeg», а когда я пытался отправить PDF, я помещал «application / pdf». Я искал везде, и я нашел других людей с этой проблемой, но не нашел решения. Если бы кто-то мог помочь мне, я был бы благодарен. (Я прошу прощения за мои орфографические ошибки) Мой импорт:

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;

Я успешно отправил электронное письмо с приложением с приведенным ниже кодом. Но моя проблема в том, что когда я пытаюсь загрузить вложение или когда я пытаюсь его просмотреть, он говорит, что он поврежден и не распознает его. , Я думаю, что проблема заключается в загрузке изображения. Для загрузки изображения я использую org.apache.commons.fileupload. Здесь я загружаю изображение в байтовый массив:

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

Я также отслеживаю размер загружаемого изображения в «размере» Здесь я перемещаю изображение в другой буфер соответствующих размеров:

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

Изображение из вложения имеет тот же размер, что и загруженное, но каким-то образом повреждено. Если кто-то может помочь. Исходный код:

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();
        }
    }

}
}

Ответы [ 2 ]

2 голосов
/ 19 августа 2011

Я думаю, что проблема в примере # 1 может заключаться в том, что вы устанавливаете текстовое тело, а затем пытаетесь добавить составную часть.Это не правильно.Сообщение может быть Content-Type: text/plain или Content-Type: multipart/mixed, но не одновременно.Если есть вложение, вам нужно добавить текстовое тело как одно из нескольких.Примерно так (не проверено):

   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);

Существует также проблема с тем, как вы читаете данные своего изображения, но вы не предоставили достаточно кода, чтобы я мог рассказать вам, как его исправить.,Вам нужно будет прочитать ВСЕ данные изображения в некоторый объект (массив, буфер и т. Д.), Прежде чем добавлять их в содержимое части тела.И вы не можете добавить src в качестве содержимого для attachment - вы должны использовать фактические данные - либо строку, либо байт [] и т. Д.

Чтобы помочь понять концепцию частей тела,попробуйте визуализировать структуру сообщения.Заголовки электронной почты содержат заголовок Content-type: multipart/mixed, с вложенными частями Content-type: text/plain и 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
1 голос
/ 19 августа 2011

Я наконец получил его на работу. проблема (конечно) загрузки изображения. Я перезаписывал одни и те же байты в буфере, я не учел смещение. Правильный путь:

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