Java Network Programming (3rd ed) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java Network Programming (3rd ed) [Electronic resources] - نسخه متنی

Harold, Elliotte Rusty

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








19.9 Multipart Messages and File Attachments


The way all the different text and
binary file types are encoded into raw text that can be passed
through 7-bit email gateways is fairly ingenious and rather detailed.
Fortunately, the JavaMail API shields you from those details,
interesting as they are. To send a multipart message using the
JavaMail API, all you have to do is add the parts to a
MimeMultipart object, then pass that object to the
Message's setContent(
)
method. To receive a multipart message, you simply
process each of the parts individually.

Most of the
methods for building and deconstructing multipart messages are in the
abstract javax.mail.Multipart class:

public abstract class Multipart extends Object

However, since this class is abstract, you'll
generally start with a
javax.mail.internet.MimeMultipart object instead:

public class MimeMultipart extends Multipart

Each part you add to a Multipart is an instance of
the abstract javax.mail.BodyPart class that
implements the Part interface of the last section:

public abstract class BodyPart extends Object implements Part

In Internet email, the concrete subclass of
BodyPart you'll use is
javax.mail.internet.MimeBodyPart:

public class MimeBodyPart extends BodyPart implements MimePart

Most of the methods you need in the MimeBodyPart
and BodyPart classes are the ones
you're already familiar with from the
Part interface, methods such as
setContent( ) and setDataHandler(
)
. There are also three methods to read the contents of a
Multipart object:

public String   getContentType( )
public int getCount( ) throws MessagingException
public BodyPart getBodyPart(int index)
throws IndexOutOfBoundsException, MessagingException

The getContentType()
method returns the MIME media type of the entire
Multipart, which is typically something like
multipart/mixed or
multipart/alternative. This is not the same as the
MIME types of the individual parts, which are something like
text/plain or image/gif.

The getCount( ) method returns the
number of parts in this Multipart. The
getBodyPart( ) method returns a particular part.
Parts are numbered starting at 0, like the components of an array.
Example 19-11, AllHeaderClient. However,
Example 19-12 adds the necessary code to handle the
body of the message. If the message is a single-part message,
it's simply printed on
System.out. However, if the message has multiple
parts, each part is handled separately. If the part has a multipart
content type itself, processMultipart() is called recursively. If the part has
no filename, does not have the disposition
Part.ATTACHMENT, and has MIME type
text/plain, it's assumed to be an
inline message and is printed on System.out.
Otherwise, it's assumed to be an attachment and is
saved into an appropriate file. If necessary, the static
File.createTempFile( ) method generates a
reasonable name for the file.


Example 19-12. A mail client that handles multipart messages with attached files


import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;
import java.io.*;
public class AllPartsClient {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println(
"Usage: java AllPartsClient protocol://username@host:port/foldername");
return;
}
URLName server = new URLName(args[0]);
try {
Session session = Session.getDefaultInstance(new Properties( ),
new MailAuthenticator(server.getUsername( )));
// Connect to the server and open the folder
Folder folder = session.getFolder(server);
if (folder == null) {
System.out.println("Folder " + server.getFile( ) + " not found.");
System.exit(1);
}
folder.open(Folder.READ_ONLY);
// Get the messages from the server
Message[] messages = folder.getMessages( );
for (int i = 0; i < messages.length; i++) {
System.out.println("------------ Message " + (i+1)
+ " ------------");
// Print message headers
Enumeration headers = messages[i].getAllHeaders( );
while (headers.hasMoreElements( )) {
Header h = (Header) headers.nextElement( );
System.out.println(h.getName( ) + ": " + h.getValue( ));
}
System.out.println( );
// Enumerate parts
Object body = messages[i].getContent( );
if (body instanceof Multipart) {
processMultipart((Multipart) body);
}
else { // ordinary message
processPart(messages[i]);
}
System.out.println( );
}
// Close the connection
// but don't remove the messages from the server
folder.close(false);
}
catch (Exception ex) {
ex.printStackTrace( );
}
// Since we may have brought up a GUI to authenticate,
// we can't rely on returning from main( ) to exit
System.exit(0);
}
public static void processMultipart(Multipart mp)
throws MessagingException {
for (int i = 0; i < mp.getCount( ); i++) {
processPart(mp.getBodyPart(i));
}
}
public static void processPart(Part p) {
try {
String fileName = p.getFileName( );
String disposition = p.getDisposition( );
String contentType = p.getContentType( );
if (contentType.toLowerCase( ).startsWith("multipart/")) {
processMultipart((Multipart) p.getContent( ) );
}
else if (fileName == null
&& (Part.ATTACHMENT.equalsIgnoreCase(disposition)
|| !contentType.equalsIgnoreCase("text/plain"))) {
// pick a random file name. This requires Java 1.2 or later.
fileName = File.createTempFile("attachment", ".txt").getName( );
}
if (fileName == null) { // likely inline
p.writeTo(System.out);
}
else {
File f = new File(fileName);
// find a file that does not yet exist
for (int i = 1; f.exists( ); i++) {
String newName = fileName + " " + i;
f = new File(newName);
}
OutputStream out = new BufferedOutputStream(new FileOutputStream(f));
// We can't just use p.writeTo( ) here because it doesn't
// decode the attachment. Instead we copy the input stream
// onto the output stream which does automatically decode
// Base-64, quoted printable, and a variety of other formats.
InputStream in = new BufferedInputStream(p.getInputStream( ));
int b;
while ((b = in.read( )) != -1) out.write(b);
out.flush( );
out.close( );
in.close( );
}
}
catch (Exception ex) {
System.err.println(e);
ex.printStackTrace( );
}
}
}

You can also get a part from a multipart message by passing an
OutputStream to the
part's
writeTo( ) method:

public abstract void writeTo(OutputStream out) 
throws IOException, MessagingException

However, this differs from the approach taken in Example 19-12 in
that it does not decode the part before writing it. It leaves
whatever Base64, BinHex, or quoted-printable encoding the sender
applied to the attachment alone. Instead, it simply writes the raw
data.

Attaching files (or other documents) to messages you send is more
complicated. To attach a file to a message, you first have to wrap
the data in a BodyPart object and add it to the
Multipart using one of the two
addBodyPart( ) methods:

public void addBodyPart(BodyPart part) 
throws IllegalWriteException, MessagingException
public void addBodyPart(BodyPart part, int index)
throws IllegalWriteException, MessagingException

The first variant simply appends the part to the end of the message.
The second variant adds the given part at the specified position. If
the position is greater than the number of parts in the message, the
part is simply added to the end. If it's added
somewhere in the middle, this may cause the positions of other parts
to change. If the message can't be changed, an
IllegalWriteException is thrown.

The tricky part is creating the BodyPart object.
You first need to guess a reasonable MIME content type for the file
(text/plain and
application/octet-stream are the most common
types). Next, read the file and convert it into some class of Java
object. Then install a
javax.activation.DataHandler class that knows how
to convert your data class according to your chosen MIME type. Once
you've done all this, you can create a new
MimeBodyPart object and use the various methods of
the Part interface to set attributes such as the
filename and the content disposition.

There are also two removeBodyPart() methods that delete a specified part
from the message, although these aren't as commonly
used:

public boolean removeBodyPart(BodyPart part) 
throws IllegalWriteException, MessagingException
public void removeBodyPart(int index)
throws IndexOutOfBoundsException, MessagingException

If the message can't be changed, an
IllegalWriteException is thrown. If the specified
index doesn't identify a part, an
IndexOutOfBoundsException is thrown. If the
specified part isn't present in the message, a
MessagingException is thrown.


/ 164