JavaMail-1 6
JavaMail-1 6
JavaMailTM API
Design Specification
Version 1.6
1. License for Evaluation Purposes. Specification Lead hereby grants you a fully-paid, non-exclusive, non-transferable, worldwide, limited license (without the right to
sublicense), under Specification Lead’s applicable intellectual property rights to view, download, use and reproduce the Specification only for the purpose of internal
evaluation. This includes (i) developing applications intended to run on an implementation of the Specification, provided that such applications do not themselves implement
any portion(s) of the Specification, and (ii) discussing the Specification with any third party; and (iii) excerpting brief portions of the Specification in oral or written
communications which discuss the Specification provided that such excerpts do not in the aggregate constitute a significant portion of the Specification.
2. License for the Distribution of Compliant Implementations. Specification Lead also grants you a perpetual, non-exclusive, non-transferable, worldwide, fully paid-up,
royalty free, limited license (without the right to sublicense) under any applicable copyrights or, subject to the provisions of subsection 4 below, patent rights it may have
covering the Specification to create and/or distribute an Independent Implementation of the Specification that: (a) fully implements the Specification including all its required
interfaces and functionality; (b) does not modify, subset, superset or otherwise extend the Licensor Name Space, or include any public or protected packages, classes, Java
interfaces, fields or methods within the Licensor Name Space other than those required/authorized by the Specification or Specifications being implemented; and (c) passes
the Technology Compatibility Kit (including satisfying the requirements of the applicable TCK Users Guide) for such Specification ("Compliant Implementation"). In
addition, the foregoing license is expressly conditioned on your not acting outside its scope. No license is granted hereunder for any other purpose (including, for example,
modifying the Specification, other than to the extent of your fair use rights, or distributing the Specification to third parties). Also, no right, title, or interest in or to any
trademarks, service marks, or trade names of Specification Lead or Specification Lead’s licensors is granted hereunder. Java, and Java-related logos, marks and names are
trademarks or registered trademarks of Oracle America, Inc. in the U.S. and other countries.
3. Pass-through Conditions. You need not include limitations (a)-(c) from the previous paragraph or any other particular "pass through" requirements in any license You grant
concerning the use of your Independent Implementation or products derived from it. However, except with respect to Independent Implementations (and products derived
from them) that satisfy limitations (a)-(c) from the previous paragraph, You may neither: (a) grant or otherwise pass through to your licensees any licenses under
Specification Lead’s applicable intellectual property rights; nor (b) authorize your licensees to make any claims concerning their implementation’s compliance with the
Specification in question.
a. With respect to any patent claims covered by the license granted under subparagraph 2 above that would be infringed by all technically feasible implementations of the
Specification, such license is conditioned upon your offering on fair, reasonable and non-discriminatory terms, to any party seeking it from You, a perpetual, non-exclusive,
non-transferable, worldwide license under Your patent rights which are or would be infringed by all technically feasible implementations of the Specification to develop,
distribute and use a Compliant Implementation.
b With respect to any patent claims owned by Specification Lead and covered by the license granted under subparagraph 2, whether or not their infringement can be avoided
in a technically feasible manner when implementing the Specification, such license shall terminate with respect to such claims if You initiate a claim against Specification
Lead that it has, in the course of performing its responsibilities as the Specification Lead, induced any other entity to infringe Your patent rights.
c Also with respect to any patent claims owned by Specification Lead and covered by the license granted under subparagraph 2 above, where the infringement of such claims
can be avoided in a technically feasible manner when implementing the Specification such license, with respect to such claims, shall terminate if You initiate a claim against
Specification Lead that its making, having made, using, offering to sell, selling or importing a Compliant Implementation infringes Your patent rights.
5. Definitions. For the purposes of this Agreement: "Independent Implementation" shall mean an implementation of the Specification that neither derives from any of
Specification Lead’s source code or binary code materials nor, except with an appropriate and separate license from Specification Lead, includes any of Specification Lead’s
source code or binary code materials; "Licensor Name Space" shall mean the public class or interface declarations whose names begin with "java", "javax", "com.oracle",
"com.sun" or their equivalents in any subsequent naming convention adopted by Oracle through the Java Community Process, or any recognized successors or replacements
thereof; and "Technology Compatibility Kit" or "TCK" shall mean the test suite and accompanying TCK User’s Guide provided by Specification Lead which corresponds to
the Specification and that was available either (i) from Specification Lead’s 120 days before the first release of Your Independent Implementation that allows its use for
commercial purposes, or (ii) more recently than 120 days from such release but against which You elect to test Your implementation of the Specification.
This Agreement will terminate immediately without notice from Specification Lead if you breach the Agreement or act outside the scope of the licenses granted above.
August 2017
DISCLAIMER OF WARRANTIES
THE SPECIFICATION IS PROVIDED "AS IS". SPECIFICATION LEAD MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT (INCLUDING
AS A CONSEQUENCE OF ANY PRACTICE OR IMPLEMENTATION OF THE SPECIFICATION), OR THAT THE CONTENTS OF THE SPECIFICATION ARE
SUITABLE FOR ANY PURPOSE. This document does not represent any commitment to release or implement any portion of the Specification in any product. In addition,
the Specification could include technical inaccuracies or typographical errors.
LIMITATION OF LIABILITY
TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SPECIFICATION LEAD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING
WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED IN ANY WAY TO YOUR HAVING, IMPLEMENTING
OR OTHERWISE USING THE SPECIFICATION, EVEN IF SPECIFICATION LEAD AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
You will indemnify, hold harmless, and defend Specification Lead and its licensors from any claims arising or resulting from: (i) your use of the Specification; (ii) the use or
distribution of your Java application, applet and/or implementation; and/or (iii) any claims that later versions or releases of any Specification furnished to you are
incompatible with the Specification provided to you under this license.
U.S. Government: If this Specification is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then
the Government’s rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through
227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions).
REPORT
If you provide Specification Lead with any comments or suggestions concerning the Specification ("Feedback"), you hereby: (i) agree that such Feedback is provided on a
non-proprietary and non-confidential basis, and (ii) grant Specification Lead a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable license, with the right to
sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedback for any purpose.
GENERAL TERMS
Any action related to this Agreement will be governed by California law and controlling U.S. federal law. The U.N. Convention for the International Sale of Goods and the
choice of law rules of any jurisdiction will not apply.
The Specification is subject to U.S. export control laws and may be subject to export or import regulations in other countries. Licensee agrees to comply strictly with all such
laws and regulations and acknowledges that it has the responsibility to obtain such licenses to export, re-export or import as may be required after delivery to Licensee.
This Agreement is the parties’ entire agreement relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, conditions,
representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties
relating to its subject matter during the term of this Agreement. No modification to this Agreement will be binding, unless in writing and signed by an authorized
representative of each party.
August 2017
August 2017
Contents iii
Contents
Chapter 1:
Introduction 1
Target Audience 1
Acknowledgments 1
Chapter 2:
Goals and Design Principles 3
Chapter 3:
Architectural Overview 5
JavaMail Layered Architecture 5
JavaMail Class Hierarchy 7
The JavaMail Framework 8
Major JavaMail API Components 10
The Message Class 10
Message Storage and Retrieval 10
Message Composition and Transport 11
The Session Class 11
The JavaMail Event Model 11
Using the JavaMail API 12
Chapter 4:
The Message Class 13
The Part Interface 16
Message Attributes 16
The ContentType Attribute 16
The Address Class 18
The BodyPart Class 18
The Multipart Class 19
The Flags Class 22
Message Creation And Transmission 23
Chapter 5:
The Mail Session 25
Chapter 6:
Message Storage And Retrieval 33
The Store Class 33
Store Events 34
The Folder Class 34
The FetchProfile Method 35
Folder Events 36
The Expunge Process 37
The Search Process 39
Chapter 7:
The JavaBeans Activation Framework 41
Accessing the Content 41
Example: Message Output 42
Operating on the Content 43
Example: Viewing a Message 43
Example: Showing Attachments 43
Adding Support for Content Types 44
Chapter 8:
Message Composition 45
Building a Message Object 45
Message Creation 45
Setting Message Attributes 46
Setting Message Content 47
Building a MIME Multipart Message 48
Chapter 9:
Transport Protocols and Mechanisms 51
Obtaining the Transport Object 51
Transport Methods 51
Transport Events 52
ConnectionEvent 52
TransportEvent 53
Using The Transport Class 54
Chapter 10:
Internet Mail 55
The MimeMessage Class 56
The MimeBodyPart Class 57
The MimeMultipart Class 58
The MimeUtility Class 58
Content Encoding and Decoding 59
Header Encoding and Decoding 59
The ContentType Class 60
Appendix A:
Environment Properties 61
Appendix B:
Examples Using the JavaMail API 63
Example: Showing a Message 63
Example: Listing Folders 71
Example: Search a Folder for a Message 74
Example: Monitoring a Mailbox 79
Example: Sending a Message 80
Appendix C:
Message Security 83
Overview 83
Displaying an Encrypted/Signed Message 83
MultiPartEncrypted/Signed Classes 83
Reading the Contents 84
Verifying Signatures 84
Creating a Message 85
Appendix D:
Part and Multipart Class Diagram 87
Appendix E:
MimeMessage Object Hierarchy 89
Appendix F:
Features Added in JavaMail 1.1 91
The MessageContext Class and MessageAware Interface 91
Appendix G:
Features Added in JavaMail 1.2 95
Additions to the MimeMessage Class 95
Additions to the MimeMultipart Class 96
The getRawInputStream method 96
Additions to the InternetAddress Class 96
The MailDateFormat Class 97
Additions to Exceptions and Events 97
Additions to the Session Class 97
Additions to the MimeUtility Class 98
Additions for serializable javax.mail.search terms 98
Additions to the Store Class 99
New ContentDisposition Class 99
New performance improvements 99
Additions to the ParameterList class 100
Appendix H:
Features Added in JavaMail 1.3 101
Add setSender and getSender methods to MimeMessage (4405115) 101
Add setContentID method to MimeBodyPart (4377720) 102
Add mail.mime.charset property (4377731) 102
Add getDeletedMesageCount method to Folder (4388730) 102
Support parsing illegal Internet addresses (4650940) 103
Add mail.mime.address.strict property (4650940) 104
Add mail.mime.decodetext.strict property (4201203) 105
Add mail.mime.encodeeol.strict property (4650949) 105
Add isGroup and getGroup methods to InternetAddress (4650952) 105
Support per-session debug output stream (4517686) 106
Appendix I:
Features Added in JavaMail 1.4 107
Add MimePart.setText(text, charset, subtype) method (6300765) 107
Add mail.mime.encodefilename and decodefilename properties (6300768) 108
Appendix J:
Features Added in JavaMail 1.5 129
Add FetchProfile.Item.SIZE (37) 129
Fix protected fields in final classes in javax.mail.search (38) 129
Add MimeMultipart(String subtype, BodyPart... bps) constructor (39) 130
Exceptions should support exception chaining (40) 130
ParameterList needs to support use by IMAP (41) 133
ContentType and ContentDisposition toString should never return null (42) 133
Add Transport.send(msg, username, password) method (44) 134
Add MimeMessage.setFrom(String) method (45) 135
Add Message.getSesssion() method (46) 135
MimeBodyPart.attachFile should set the disposition to ATTACHMENT (47) 136
Add MimeMessage.reply(replyToAll, setAnswered) method (48) 137
Add additional “next” methods to HeaderTokenizer (49) 137
Add @MailSessionDefinition and @MailSessionDefinitions for Java EE 7 (51) 138
Make cachedContent field protected in MimeMessage and MimeBodyPart (52) 140
Make MimeMultipart fields protected to allow subclassing (53) 141
Need simple way to override MIME type and encoding of attachment (55) 143
Enable RFC 2231 support by default (56) 144
Appendix K:
Features Added in JavaMail 1.6 147
MailSessionDefinition should use Repeatable annotation for Java EE 8 (226) 147
MimeMessage.updateHeaders should set Date header if not already set (77) 147
Update public API to use generics (232) 148
MailDateFormat changes for version 1.6 (174) 151
Store, Transport, and Folder should implement AutoCloseable (159) 153
The UIDFolder interface should have a getter for UIDNEXT (104) 154
The UIDFolder interface should have a MAXUID constant (244) 155
MimeMultipart should throw ParseException for parsing errors (75) 155
Support addressing i18n via RFC 6530/6531/6532 (93) 156
Look for resource files in <java.home>/conf on JDK 1.9 (247) 158
Flags convenience methods (249) 159
Chapter 1:
Introduction
In the years since its first release, the JavaTM programming language has matured to become a
platform. The Java platform has added functionality, including distributed computing with
RMI and CORBA, and a component architecture (JavaBeansTM). Java applications have also
matured, and many need an addition to the Java platform: a mail and messaging framework.
The JavaMailTM API described in this specification satisfies that need.
The JavaMail API provides a set of abstract classes defining objects that comprise a mail
system. The API defines classes like Message, Store and Transport. The API can be extended
and can be subclassed to provide new protocols and to add functionality when necessary.
In addition, the API provides concrete subclasses of the abstract classes. These subclasses,
including MimeMessage and MimeBodyPart, implement widely used Internet mail protocols
and conform to specifications RFC822 and RFC2045. They are ready to be used in application
development.
Target Audience
The JavaMail API is designed to serve several audiences:
? Client, server, or middleware developers interested in building mail and messaging
applications using the Java programming language.
? Application developers who need to “mail-enable” their applications.
? Service Providers who need to implement specific access and transfer protocols. For
example; a telecommunications company can use the JavaMail API to implement a
PAGER Transport protocol that sends mail messages to alphanumeric pagers.
Acknowledgments
The authors of this specification are John Mani, Bill Shannon, Max Spivak, Kapono Carter and
Chris Cotton.
We would like to acknowledge the following people for their comments and feedback on the
initial drafts of this document:
? Terry Cline, John Russo, Bill Yeager and Monica Gaines: Sun Microsystems.
? Arn Perkins and John Ragan: Novell, Inc.
Chapter 2:
Chapter 3:
Architectural Overview
This section describes the JavaMail architecture, defines major classes and interfaces
comprising that architecture, and lists major functions that the architecture implements.
JavaMail provides elements that are used to construct an interface to a messaging system,
including system components and interfaces. While this specification does not define any
specific implementation, JavaMail does include several classes that implement RFC822 and
MIME Internet messaging standards. These classes are delivered as part of the JavaMail class
package.
JavaMail clients use the JavaMail API and Service Providers implement the JavaMail API.
The layered design architecture allows clients to use the same JavaMail API calls to send,
receive and store a variety of messages using different data-types from different message
stores and using different message transport protocols.
FIGURE 3-1
Mail-enabled Application
JavaMail
API JavaMail
Abstract Class Layer
Internet Mail
Implementation Class Layer
FIGURE 3-2
Legend
Interface Implements
Part Class Extends
Container Class
Message MimeMessage
MimePart
MimeBodyPart
Bodypart
MimeMultipart
Multipart Container
Container Class
Class
Note – The JavaMail framework does not define mechanisms that support message delivery,
security, disconnected operation, directory services or filter functionality.
FIGURE 3-3
MESSAGE
Send a MESSAGE
Message
Submit a Contains
TRANSPORT
Message Messages FOLDERS
FOLDERS
Network Receive a
Infrastructure STORE
Message
Chapter 4:
FIGURE 4-1
Message Class
Part interface Header Attributes
Attributes defined by the
Part interface, including
Content-Type.
Content Body
DataHandler Object
Contains data that conforms
to the Content-Type attri-
JavaBean bute, together with methods
queries the that provide access to that
DataHandler data.
object in order to
view and handle
content body.
The Message object has no direct knowledge of the nature or semantics of its content. This
separation of structure from content allows the message object to contain any arbitrary content.
Message objects are either retrieved from a Folder object or constructed by instantiating a
new Message object of the appropriate subclass. Messages stored within a Folder object
are sequentially numbered, starting at one. An assigned message number can change when the
folder is expunged, since the expunge operation removes deleted messages from the folder and
also renumbers the remaining messages.
A Message object can contain multiple parts, where each part contains its own set of
attributes and content. The content of a multipart message is a Multipart object that
contains BodyPart objects representing each individual part. The Part interface defines the
structural and semantic similarity between the Message class and the BodyPart class.
The figure below illustrates a Message instance hierarchy, where the message contains
attributes, a set of flags, and content. See “MimeMessage Object Hierarchy” on page 89 for an
illustration of the MimeMessage object hierarchy.
FIGURE 4-2
Part
Legend
Interface
Class
Content Contains
Implements
References
This method also ensures that the Message header fields are updated to be consistent with
the changed message contents.
? Generate a bytestream for the Message object.
This byte stream can be used to save the message or send it to a Transport object.
Note – A Message object can not be contained directly in a Multipart object, but must be
embedded in a BodyPart first.
Message Attributes
The Message class adds its own set of standard attributes to those it inherits from the Part
interface. These attributes include the sender and recipient addresses, the subject, flags, and
sent and received dates. The Message class also supports non-standard attributes in the form
of headers. See the JavaMail API (Javadoc) Documentation for the list of standard attributes
defined in the Message class. Not all messaging systems will support arbitrary headers, and
the availability and meaning of particular header names is specific to the messaging system
implementation.
As an input stream The Part interface declares the getInputStream method that
returns an input stream to the content. Note that Part implementations
must decode any mail-specific transfer encoding before providing the
input stream.
As a DataHandler object The Part interface declares the getDataHandler method that
returns a javax.activation.DataHandler object that wraps
around the content. The DataHandler object allows clients to
discover the operations available to perform on the content, and to
instantiate the appropriate component to perform those operations. See
“The JavaBeans Activation Framework” on page 41 for details
describing the data typing framework
As an object in the Java The Part interface declares the getContent method that returns the
programming language content as an object in the Java programming language. The type of the
returned object is dependent on the content’s data type. If the content is
of type multipart, the getContent method returns a Multipart
object, or a Multipart subclass object. The getContent method
returns an input stream for unknown content-types. Note that the
getContent method uses the DataHandler internally to obtain the
native form.
FIGURE 4-3
Note that Multipart objects can be nested to any reasonable depth within a multipart
message, in order to build an appropriate structure for data carried in DataHandler objects.
Therefore, it is important to check the ContentType header for each BodyPart element
stored within a Multipart container. The figure below illustrates a typical nested
Multipart message.
FIGURE 4-4
Message
Object
Carries
addresses for
the entire tree. Multipart Container
Object
Content body
references a Bodypart object
Multipart that carries a
container DataHandler
object holding data.
Bodypart
Bodypart
Typically, the client calls the getContentType method to get the content type of a
message. If getContentType returns a MIME-type whose primary type is multipart, then
the client calls getContent to get the Multipart container object.
The Multipart object supports several methods that get, create, and remove individual
BodyPart objects.
FIGURE 4-5
getContentType()
Message multipart/mixed
getContent() Legend
extends
Multipart
contains
getBodyPart(index)
0... n-1
getContentType()
BodyPart text/plain
getContent()
Text
In this figure, the ContentType attribute of a Message object indicates that it holds a
multipart content. Use the getContent method to obtain the Multipart object.
This code sample below shows the retrieval of a Multipart object. See “Examples Using
the JavaMail API” on page 63 for examples that traverse a multipart message and examples
that create new multipart messages.
Multipart mp = (Multipart)message.getContent();
ANSWERED Clients set this flag to indicate that this message has been answered.
FLAGGED No defined semantics. Clients can use this flag to mark a message in some user-
defined manner.
RECENT This message is newly arrived in this folder. This flag is set when the message is
first delivered into the folder and cleared when the containing folder is closed.
Clients cannot set this flag.
SEEN Marks a message that has been opened. A client sets this flag implicitly when the
message contents are retrieved.
DELETED Allows undoable message deletion. Setting this flag for a message marks it
deleted but does not physically remove the message from its folder. The client
calls the expunge method on a folder to remove all deleted messages in that
folder.
Note that a folder is not guaranteed to support either standard system flags or arbitrary user
flags. The getPermanentFlags method in a folder returns a Flags object that contains
all the system flags supported by that Folder implementation. The presence of the special
USER flag indicates that the client can set arbitrary user-definable flags on any message
belonging to this folder.
Chapter 5:
must be carefully controlled. Applications that create Session objects must restrict access to
those objects appropriately. In addition, the Session class shares some responsibility for
controlling access to the default session object.
The first call to the getDefaultInstance method creates a new Session object and
associates it with the Authenticator object. Subsequent calls to the
getDefaultInstance method compare the Authenticator object passed in with the
Authenticator object saved in the default session. Access to the default session is allowed
if both objects have been loaded by the same class loader. Typically, this is the case when both
the default session creator and the program requesting default session access are in the same
"security domain." Also, if both objects are null, access is allowed. Using null to gain
access is discouraged, because this allows access to the default session from any security
domain.
A mail-enabled client uses the Session object to retrieve a Store or Transport object in
order to read or send mail. Typically, the client retrieves the default Store or Transport
object based on properties loaded for that session:
Store store = session.getStore();
The client can override the session defaults and access a Store or Transport object that
implements a particular protocol.
Store store = session.getStore("imap");
See “The Provider Registry” on page 26 for details.
Implementations of Store and Transport objects will be told the session to which they
have been assigned. They can then make the Session object available to other objects
contained within this Store or Transport objects using application-dependent logic.
Resource Files
The providers for JavaMail APIs are configured using the following files:
? javamail.providers and javamail.default.providers
? javamail.address.map and javamail.default.address.map
Each javamail.X resource file is searched in the following order:
1. java.home/lib/javamail.X
2. META-INF/javamail.X
3. META-INF/javamail.default.X
The first method allows the user to include their own version of the resource file by placing it
in the lib directory where the java.home property points. The second method allows an
application that uses the JavaMail APIs to include their own resource files in their
application’s or jar file’s META-INF directory. The javamail.default.X default files are
part of the JavaMail mail.jar file.
File location depends upon how the ClassLoader.getResource method is implemented.
Usually, the getResource method searches through CLASSPATH until it finds the requested
file and then stops. JDK 1.2 and newer allows all resources of a given name to be loaded from
all elements of the CLASSPATH. However, this only affects method two, above; method one
is loaded from a specific location (if allowed by the SecurityManager) and method three
uses a different name to ensure that the default resource file is always loaded successfully.
The ordering of entries in the resource files matters. If multiple entries exist, the first entries
take precedence over the latter entries as the initial defaults. For example, the first IMAP
provider found will be set as the default IMAP implementation until explicitly changed by the
application.
The user- or system-supplied resource files augment, they do not override, the default files
included with the JavaMail APIs. This means that all entries in all files loaded will be
available.
javamail.providers and
javamail.default.providers
These resource files specify the stores and transports that are available on the system, allowing
an application to "discover" what store and transport implementations are available. The
protocol implementations are listed one per line. The file format defines four attributes that
describe a protocol implementation. Each attribute is an "="-separated name-value pair with
the name in lowercase. Each name-value pair is semi-colon (";") separated.
Name Description
javamail.address.map and
javamail.default.address.map
These resource files map transport address types to the transport protocol. The
javax.mail.Address.getType() method returns the address type. The
javamail.address.map file maps the transport type to the protocol. The file format is a
series of name-value pairs. Each key name should correspond to an address type that is
currently installed on the system; there should also be an entry for each
javax.mail.Address implementation that is present if it is to be used. For example,
javax.mail.internet.InternetAddress.getType() returns rfc822. Each
referenced protocol should be installed on the system. For the case of news, below, the client
should install a Transport provider supporting the nntp protocol.
Here are the typical contents of a javamail.address.map file.
rfc822=smtp
news=nntp
Provider
Provider is a class that describes a protocol implementation. The values come from the
javamail.providers and javamail.default.providers resource files.
Example Scenarios
Scenario 1: The client application invokes the default protocols:
class Application1 {
init() {
// application properties include the JavaMail
// required properties: mail.store.protocol,
// mail.transport.protocol, mail.host, mail.user
Properties props = loadApplicationProps();
Session session = Session.getInstance(props, null);
props.put("mail.smtp.class", "com.acme.SMTPTRANSPORT");
Session session = Session.getInstance(props, null);
Managing Security
The Session class allows messaging system implementations to use the Authenticator
object that was registered when the session was created. The Authenticator object is
created by the application and allows interaction with the user to obtain a user name and
password. The user name and password is returned in a PasswordAuthentication
object. The messaging system implementation can ask the session to associate a user name and
password with a particular message store using the setPasswordAuthentication
method. This information is retrieved using the getPasswordAuthentication method.
This avoids the need to ask the user for a password when reconnecting to a Store that has
disconnected, or when a second application sharing the same session needs to create its own
connection to the same Store.
Messaging system implementations can register PasswordAuthentication objects with
the Session object for use later in the session or for use by other users of the same session.
Because PasswordAuthentication objects contain passwords, access to this information
must be carefully controlled. Applications that create Session objects must restrict access to
those objects appropriately. In addition, the Session class shares some responsibility for
controlling access to the default Session object.
The first call to getDefaultInstance creates a new Session object and associates the
Authenticator object with the Session object. Later calls to getDefaultInstance
compare the Authenticator object passed in, to the Authenticator object saved in the
default session. If both objects have been loaded by the same class loader, then
getDefaultInstance will allow access to the default session. Typically, this is the case
when both the creator of the default session and the code requesting access to the default
session are in the same "security domain." Also, if both objects are null, access is allowed.
This last case is discouraged because setting objects to null allows access to the default
session from any security domain.
In the future, JDK security Permissions could control access to the default session. Note that
the Authenticator and PasswordAuthentication classes and their use in JavaMail
is similar to the classes with the same names provided in the java.net package in the JDK.
As new authentication mechanisms are added to the system, new methods can be added to the
Authenticator class to request the needed information. The default implementations of
these new methods will fail, but new clients that understand these new authentication
mechanisms can provide implementations of these methods. New classes other than
PasswordAuthentication could be needed to contain the new authentication
information, and new methods could be needed in the Session class to store such
information. JavaMail design evolution will be patterned after the corresponding JDK classes.
Folder f = session.getFolder(URLName);
or
Store s = session.getStore(URLName);
Chapter 6:
The Store presents a default namespace to clients. Store implementations can also present
other namespaces. The getDefaultFolder method on Store returns the root folder for
the default namespace.
Clients terminate a session by calling the close method on the Store object. Once a Store
is closed (either explicitly using the close method; or externally, if the Mail server fails), all
Messaging components belonging to that Store become invalid. Typically, clients will try to
recover from an unexpected termination by calling connect to reconnect to the Store
object, and then fetching new Folder objects and new Message objects.
Store Events
Store sends the following events to interested listeners:
StoreEvent Communicates alerts and notification messages from the Store to the end
user. The getMessageType method returns the event type, which can be
one of: ALERT or NOTICE. The client must display ALERT events in some
fashion that calls the user’s attention to the message.
FolderEvent Communicates changes to any folder contained within the Store. These
changes include creation of a new Folder, deletion of an existing Folder,
and renaming of an existing Folder.
The messages within a Folder are sequentially numbered, from 1 through the total number
of messages. This ordering is referred to as the “mailbox order” and is usually based on the
arrival time of the messages in the folder. As each new message arrives into a folder, it is
assigned a sequence number that is one higher than the previous number of messages in that
folder. The getMessageNumber method on a Message object returns its sequence
number.
The sequence number assigned to a Message object is valid within a session, but only as long
as it retains its relative position within the Folder. Any change in message ordering can
change the Message object's sequence number. Currently this occurs when the client calls
expunge to remove deleted messages and renumber messages remaining in the folder.
A client can reference a message stored within a Folder either by its sequence number, or by
the corresponding Message object itself. Since a sequence number can change within a
session, it is preferable to use Message objects rather than sequence numbers as cached
references to messages. Clients extending JavaMail are expected to provide light-weight
Message objects that get filled ’on-demand’, so that calling the getMessages method on
a Folder object is an inexpensive operation, both in terms of CPU cycles and memory. For
instance, an IMAP implementation could return Message objects that contain only the
corresponding IMAP UIDs.
Folder Events
Folders generate events to notify listeners of any change in either the folder or in its Messages
list. The client can register listeners to a closed Folder, but generates a notification event
only after that folder is opened.
Folder supports the following events:
FolderEvent This event is generated when the client creates, deletes or renames this folder.
Note that the Store object containing this folder can also generate this
event.
MessageCountEvent This event notifies listeners that the message count has changed. The
following actions can cause this change:
? Addition of new Messages into the Folder, either by a delivery
agent or because of an append operation. The new Message
objects are included in the event.
? Removal of existing messages from this Folder. Removed
messages are referred to as expunged messages. The
isExpunged method returns true for removed Messages and the
getMessageNumber method returns the original sequence
number assigned to that message. All other Message methods
throw a MessageRemovedException. See “The Folder
Class” on page 34 for a discussion of removing deleted messages
in shared folders. The expunged Message objects are included
in the event. An expunged message is invalid and should be
pruned from the client's view as early as possible. See “The
Expunge Process” on page 37 for details on the expunge
method.
FIGURE 6-1
? The client should prune expunged messages from its internal storage as early as possible.
? The expunge process becomes complex when dealing with a shared folder that can be
edited. Consider the case where two clients are operating on the same folder. Each client
possesses its own Folder object, but each Folder object actually represents the same
physical folder.
If one client expunges the shared folder, any deleted messages are physically removed from
the folder. The primary client can probably deal with this appropriately since it initiated this
process and is ready to handle the consequences. However, secondary clients are not
guaranteed to be in a state where they can handle an unexpected Message removed event—
especially if the client is heavily multithreaded or if it uses sequence numbers.
To allow clients to handle such situations gracefully, the JavaMail API applies following
restrictions to Folder implementations:
? A Folder can remove and renumber its Messages only when it is explicitly expunged
using the expunge method. When the folder is implicitly expunged, it marks any
expunged messages as expunged, but it still maintains access to those Message objects.
This means that the following state is maintained when the Folder is implicitly expunged:
? getMessages returns expunged Message objects together with valid message
objects. However; an expunged message can throw the
MessageExpungedException if direct access is attempted.
? The messages in the Folder should not be renumbered.
? The implicit expunge operation can not change the total Folder message count.
A Folder can notify listeners of “implicit” expunges by generating appropriate
MessageEvents. However, the removed field in the event must be set to false to indicate
that the message is still in the folder. When this Folder is explicitly expunged, then the
Folder must remove all expunged messages, renumber it's internal Message cache, and
generate MessageEvents for all the expunged messages, with each removed flag set to true.
The recommended set of actions for a client under the above situation is as follows:
? Multithreaded clients that expect to handle shared folders are advised not to use sequence
numbers.
? If a client receives a MessageEvent indicating message removal, it should check the
removed flag. If the flag is false, this indicates that another client has removed the
message from this folder. This client might want to issue an expunge request on the
folder object to synchronize it with the physical folder (but note the caveats in the
previous section about using a shared folder). Alternatively, this client might want to close
the Folder object (without expunging) and reopen it to synchronize with the physical
folder (but note that all message objects would need to be refreshed in this case). The
client may also mark the expunged messages in order to notify the end user.
? If the removed flag was set to true, the client should follow earlier recommendations on
dealing with explicit expunges.
The search package also provides a set of standard logical operator terms that can be used to
compose complex search terms. These include AndTerm, OrTerm and NotTerm.
The Folder class supports searches on messages through these search method versions:
These methods return the Message objects matching the specified search term. The default
implementation applies the search term on each Message object in the specified range. Other
implementations may optimize this; for example, the IMAP Folder implementation maps the
search term into an IMAP SEARCH command that the server executes.
Chapter 7:
Note – Perform error checking to ensure that a valid Component was created.
DataHandler dh = bp.getDataHandler();
CommandInfo cinfo = dh.getCommand("view");
Component comp = (Component) dh.getBean(cinfo);
See “Setting Message Content” on page 47 for examples that construct a message for a send
operation.
Chapter 8:
Message Composition
This section describes the process used to instantiate a message object, add content to that
message, and send it to its intended list of recipients.
The JavaMail API allows a client program to create a message of arbitrary complexity.
Messages are instantiated from the Message subclass. The client program can manipulate any
message as if it had been retrieved from a Store.
Message Creation
javax.mail.Message is an abstract class that implements the Part interface. Therefore,
to create a message object, select a message subclass that implements the appropriate message
type.
For example, to create a Mime message, a JavaMail client instantiates an empty
javax.mail.internet.MimeMessage object passing the current Session object to
it:
The Part interface specifies the following method, that sets custom headers:
msg.setFrom(fromAddr);
msg.setRecipients(Message.RecipientType.TO, toAddrs);
msg.setSubject("Takeoff time.");
msg.setSentDate(new Date());
msg.setDataHandler(data);
Alternately, setContent implements a simpler technique that takes the data object and its
MIME type. setContent creates the DataHandler object automatically:
msg.setContent(content, "text/plain");
When the client calls Transport.send()to send this message, the recipient will receive
the message below, using either technique:
Date: Wed, 23 Apr 1997 22:38:07 -0700 (PDT)
From: [email protected]
Subject: Takeoff time
To: [email protected]
Leave at 300.
Note – The default subtype for a MimeMultipart object is mixed. It can be set to other
subtypes as required. MimeMultipart subclasses might already have their subtype set
appropriately.
The example below creates a Multipart object and then adds two message parts to it.
The first message part is a text string, “Spaceport Map,” and the second contains a
document of type “application/postscript.” Finally, this multipart object is added to a
MimeMessage object of the type described above.
After all message parts are created and inserted, call the saveChanges method to ensure that
the client writes appropriate message headers. This is identical to the process followed with a
single part message. Note that the JavaMail API calls the saveChanges method implicitly
during the send process, so invoking it is unnecessary and expensive if the message is to be
sent immediately.
Chapter 9:
Transport Methods
The Transport class provides the connect and protocolConnect methods, which
operate similarly to those on the Store class. See “The Store Class” on page 33 for details.
A Transport object generates a ConnectionEvent to notify its listeners of a successful
or a failed connection. A Transport object can throw an IOException if the connection
fails.
Transport implementations should ensure that the message specified is of a known type. If the
type is known, then the Transport object sends the message to its specified destinations. If
the type is not known, then the Transport object can attempt to reformat the Message
object into a suitable version using gatewaying techniques, or it can throw a
MessagingException, indicating failure. For example, the SMTP transport
implementation recognizes MimeMessages. It invokes the writeTo method on a
MimeMessage object to generate a RFC822 format byte stream that is sent to the SMTP
host.
The message is sent using the Transport.send static method or the sendMessage
instance method. The Transport.send method is a convenience method that instantiates
the transports necessary to send the message, depending on the recipients' addresses, and then
passes the message to each transport's sendMessage method. Alternatively, the client can
get the transport that implements a particular protocol itself and send the message using the
sendMessage method. This adds the benefit of being able to register as event listeners on
the individual transports.
Note that the Address[] argument passed to the send and sendMessage methods do not
need to match the addresses provided in the message headers. Although these arguments
usually will match, the end-user determines where the messages are actually sent. This is
useful for implementing the Bcc: header, and other similar functions.
Transport Events
Clients can register as listeners for events generated by transport implementations. (Note that
the abstract Transport class doesn't fire any events, only particular protocol
implementations generate events). There are two events generated: ConnectionEvent and
TransportEvent.
ConnectionEvent
If the transport connects successfully, it will fire the ConnectionEvent with the type set to
OPENED. If the connection times out or is closed, ConnectionEvent with type CLOSED is
generated.
TransportEvent
The sendMessage method generates a TransportEvent to its listeners. That event
contains information about the method’s success or failure. There are three types of
TransportEvent: MESSAGE_DELIVERED, MESSAGE_NOT_DELIVERED,
MESSAGE_PARTIALLY_DELIVERED. The event contains three arrays of addresses:
validSent[], validUnsent[], and invalid[] that list the valid and invalid
addresses for this message and protocol.
MESSAGE_DELIVERED When the message has been successfully sent to all recipients by
this transport. validSent[] contains all the addresses.
validUnsent[] and invalid[] are null.
MESSAGE_PARTIALLY_DELIVERED Message was successfully sent to some recipients but not to all.
ValidSent[] holds addresses of recipients to whom the
message was sent. validUnsent[] holds valid addresses but
the message wasn't sent to them. invalid[] holds invalid
addresses.
// Get a session
Session session = Session.getInstance(props, null);
Chapter 10:
Internet Mail
The JavaMail specification does not define any implementation. However, the API does
include a set of classes that implement Internet Mail standards. Although not part of the
specification, these classes can be considered part of the JavaMail package. They show how to
adapt an existing messaging architecture to the JavaMail framework.
These classes implement the Internet Mail Standards defined by the RFCs listed below:
? RFC822 (Standard for the Format of Internet Text Messages)
? RFC2045, RFC2046, RFC2047 (MIME)
RFC822 describes the structure of messages exchanged across the Internet. Messages are
viewed as having a header and contents. The header is composed of a set of standard and
optional header fields. The header is separated from the content by a blank line. The RFC
specifies the syntax for all header fields and the semantics of the standard header fields. It
does not however, impose any structure on the message contents.
The MIME RFCs 2045, 2046 and 2047 define message content structure by defining
structured body parts, a typing mechanism for identifying different media types, and a set of
encoding schemes to encode data into mail-safe characters.
The Internet Mail package allows clients to create, use and send messages conforming to the
standards listed above. It gives service providers a set of base classes and utilities they can use
to implement Stores and Transports that use the Internet mail protocols. See “MimeMessage
Object Hierarchy” on page 89 for a Mime class and interface hierarchy diagram.
The JavaMail MimePart interface models an entity as defined in RFC2045, Section 2.4.
MimePart extends the JavaMail Part interface to add MIME-specific methods and semantics.
The MimeMessage and MimeBodyPart classes implement the MimePart interface. The
following figure shows the class hierarchy of these classes.
FIGURE 10-1
Message MimePart
Legend
Extends
MimeMessage Implements
BodyPart MimePart
MimeBodyPart
headers. Also note that decodeText attempts decoding only if the header value was encoded
in RFC 2047 style. It is advised that you always run header values through the decoder to be
safe.
if (cType.match("application/x-foobar"))
iString color = cType.getParameter("color");
This code sample uses this class to construct a MIME Content-Type value:
ContentType cType = new ContentType();
cType.setPrimaryType("application");
cType.setSubType("x-foobar");
cType.setParameter("color", "red");
Appendix A:
Environment Properties
This section lists some of the environment properties that are used by the JavaMail APIs. The
JavaMail javadocs contain additional information on properties supported by JavaMail.
Note that Applets can not determine some defaults listed in this Appendix. When writing an
applet, you must specify the properties you require.
mail.store.protocol Specifies the default Message Access Protocol. The first appropriate
The Session.getStore() method returns protocol in the config
a Store object that implements this protocol. files
The client can override this property and
explicitly specify the protocol with the
Session.getStore(String
protocol) method.
mail.transport.protocol Specifies the default Transport Protocol. The The first appropriate
Session.getTransport() method protocol in the config
returns a Transport object that implements files
this protocol. The client can override this
property and explicitly specify the protocol by
using Session.getTransport(String
protocol) method.
mail.host Specifies the default Mail server. The Store The local machine
and Transport object’s connect methods
use this property, if the protocol-specific host
property is absent, to locate the target host.
Appendix B:
/*
* Demo app that exercises the Message interfaces.
* Show information about and contents of messages.
*
* @author John Mani
* @author Bill Shannon
*/
try {
if (optind < argv.length)
msgnum = Integer.parseInt(argv[optind]);
if (showMessage) {
MimeMessage msg;
if (mbox != null)
msg = new MimeMessage(session,
new BufferedInputStream(new FileInputStream(mbox)));
else
msg = new MimeMessage(session, msgStream);
dumpPart(msg);
System.exit(0);
}
// Connect
if (host != null || user != null || password != null)
store.connect(host, port, user, password);
else
store.connect();
}
if (mbox == null)
mbox = "INBOX";
folder = folder.getFolder(mbox);
if (folder == null) {
System.out.println("Invalid folder");
System.exit(1);
}
if (totalMessages == 0) {
System.out.println("Empty folder");
folder.close(false);
store.close();
System.exit(1);
}
if (verbose) {
int newMessages = folder.getNewMessageCount();
System.out.println("Total messages = " + totalMessages);
System.out.println("New messages = " + newMessages);
System.out.println("-------------------------------");
}
if (msgnum == -1) {
// Attributes & Flags for all messages ..
Message[] msgs = folder.getMessages();
try {
m = folder.getMessage(msgnum);
dumpPart(m);
folder.close(false);
store.close();
} catch (Exception ex) {
System.out.println("Oops, got exception! " + ex.getMessage());
ex.printStackTrace();
System.exit(1);
}
System.exit(0);
}
InputStream is = p.getInputStream();
// If "is" is not already buffered, wrap a BufferedInputStream
// around it.
if (!(is instanceof BufferedInputStream))
is = new BufferedInputStream(is);
int c;
while ((c = is.read()) != -1)
System.out.write(c);
**/
String ct = p.getContentType();
try {
pr("CONTENT-TYPE: " + (new ContentType(ct)).toString());
} catch (ParseException pex) {
pr("BAD CONTENT-TYPE: " + ct);
}
String filename = p.getFileName();
if (filename != null)
pr("FILENAME: " + filename);
/*
* Using isMimeType to determine the content type avoids
* fetching the actual content data until we need it.
*/
if (p.isMimeType("text/plain")) {
pr("This is plain text");
pr("---------------------------");
if (!showStructure && !saveAttachments)
System.out.println((String)p.getContent());
} else if (p.isMimeType("multipart/*")) {
pr("This is a Multipart");
pr("---------------------------");
Multipart mp = (Multipart)p.getContent();
level++;
int count = mp.getCount();
for (int i = 0; i < count; i++)
dumpPart(mp.getBodyPart(i));
level--;
} else if (p.isMimeType("message/rfc822")) {
pr("This is a Nested Message");
pr("---------------------------");
level++;
dumpPart((Part)p.getContent());
level--;
} else {
if (!showStructure && !saveAttachments) {
/*
* If we actually want to see the data, and it's not a
* MIME type we know, fetch it and check its Java type.
*/
Object o = p.getContent();
if (o instanceof String) {
pr("This is a string");
pr("---------------------------");
System.out.println((String)o);
} else if (o instanceof InputStream) {
pr("This is just an input stream");
pr("---------------------------");
InputStream is = (InputStream)o;
int c;
while ((c = is.read()) != -1)
System.out.write(c);
} else {
pr("This is an unknown type");
pr("---------------------------");
pr(o.toString());
}
} else {
// just a separator
pr("---------------------------");
}
}
/*
* If we're saving attachments, write out anything that
* looks like an attachment into an appropriately named
* file. Don't overwrite existing files to prevent
* mistakes.
*/
if (saveAttachments && level != 0 && !p.isMimeType("multipart/*")){
String disp = p.getDisposition();
// many mailers don't include a Content-Disposition
if (disp == null || disp.equalsIgnoreCase(Part.ATTACHMENT)) {
if (filename == null)
// TO
if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
for (int j = 0; j < a.length; j++) {
pr("TO: " + a[j].toString());
InternetAddress ia = (InternetAddress)a[j];
if (ia.isGroup()) {
InternetAddress[] aa = ia.getGroup(false);
for (int k = 0; k < aa.length; k++)
pr(" GROUP: " + aa[k].toString());
}
}
}
// SUBJECT
pr("SUBJECT: " + m.getSubject());
// DATE
Date d = m.getSentDate();
pr("SendDate: " +
(d != null ? d.toString() : "UNKNOWN"));
// FLAGS
Flags flags = m.getFlags();
StringBuffer sb = new StringBuffer();
Flags.Flag[] sf = flags.getSystemFlags(); // get the system flags
// X-MAILER
String[] hdrs = m.getHeader("X-Mailer");
if (hdrs != null)
pr("X-Mailer: " + hdrs[0]);
else
pr("X-Mailer NOT available");
}
/**
* Print a, possibly indented, string.
*/
public static void pr(String s) {
if (showStructure)
System.out.print(indentStr.substring(0, level * 2));
System.out.println(s);
}
import com.sun.mail.imap.*;
/**
* Demo app that exercises the Message interfaces.
* List information about folders.
*
* @author John Mani
* @author Bill Shannon
*/
} else if (argv[optind].equals("--")) {
optind++;
break;
} else if (argv[optind].startsWith("-")) {
System.out.println(
"Usage: folderlist [-T protocol] [-H host] [-U user] [-P password] [-L
url]");
System.out.println(
"\t[-R root] [-r] [-v] [-D] [pattern]");
System.exit(1);
} else {
break;
}
}
if (optind < argv.length)
pattern = argv[optind];
// Connect
if (host != null || user != null || password != null)
store.connect(host, user, password);
else
store.connect();
}
// List namespace
if (root != null)
rf = store.getFolder(root);
else
rf = store.getDefaultFolder();
store.close();
}
if (verbose) {
if (!folder.isSubscribed())
System.out.println(tab + "Not Subscribed");
/*
* Demonstrate use of IMAP folder attributes
* returned by the IMAP LIST response.
*/
if (folder instanceof IMAPFolder) {
IMAPFolder f = (IMAPFolder)folder;
String[] attrs = f.getAttributes();
if (attrs != null && attrs.length > 0) {
System.out.println(tab + "IMAP Attributes:");
for (int i = 0; i < attrs.length; i++)
System.out.println(tab + " " + attrs[i]);
}
}
}
System.out.println();
}
}
}
/*
* Search the given folder for messages matching the given
* criteria.
*
* @author John Mani
*/
debug = true;
} else if (argv[optind].equals("-f")) {
mbox = argv[++optind];
} else if (argv[optind].equals("-L")) {
url = argv[++optind];
} else if (argv[optind].equals("-subject")) {
subject = argv[++optind];
} else if (argv[optind].equals("-from")) {
from = argv[++optind];
} else if (argv[optind].equals("-today")) {
today = true;
} else if (argv[optind].equals("--")) {
optind++;
break;
} else if (argv[optind].startsWith("-")) {
System.out.println(
"Usage: search [-D] [-L url] [-T protocol] [-H host] " +
"[-U user] [-P password] [-f mailbox] " +
"[-subject subject] [-from from] [-or] [-today]");
System.exit(1);
} else {
break;
}
}
try {
// Connect
folder = folder.getFolder(mbox);
if (folder == null) {
System.out.println("Invalid folder");
System.exit(1);
}
folder.open(Folder.READ_ONLY);
SearchTerm term = null;
if (subject != null)
term = new SubjectTerm(subject);
if (from != null) {
FromStringTerm fromTerm = new FromStringTerm(from);
if (term != null) {
if (or)
term = new OrTerm(term, fromTerm);
else
term = new AndTerm(term, fromTerm);
}
else
term = fromTerm;
}
if (today) {
ReceivedDateTerm dateTerm =
new ReceivedDateTerm(ComparisonTerm.EQ, new Date());
if (term != null) {
if (or)
term = new OrTerm(term, dateTerm);
else
term = new AndTerm(term, dateTerm);
}
else
term = dateTerm;
}
System.exit(1);
folder.close(false);
store.close();
} catch (Exception ex) {
System.out.println("Oops, got exception! " + ex.getMessage());
ex.printStackTrace();
}
System.exit(1);
}
// TO
if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
for (int j = 0; j < a.length; j++)
System.out.println("TO: " + a[j].toString());
}
// SUBJECT
System.out.println("SUBJECT: " + m.getSubject());
// DATE
Date d = m.getSentDate();
System.out.println("SendDate: " +
(d != null ? d.toLocaleString() : "UNKNOWN"));
// FLAGS:
Flags flags = m.getFlags();
StringBuffer sb = new StringBuffer();
Flags.Flag[] sf = flags.getSystemFlags(); // get the sys flags
Object o = p.getContent();
if (o instanceof String) {
System.out.println("This is a String");
System.out.println((String)o);
} else if (o instanceof Multipart) {
System.out.println("This is a Multipart");
Multipart mp = (Multipart)o;
int count = mp.getCount();
for (int i = 0; i < count; i++)
dumpPart(mp.getBodyPart(i));
} else if (o instanceof InputStream) {
System.out.println("This is just an input stream");
InputStream is = (InputStream)o;
int c;
while ((c = is.read()) != -1)
System.out.write(c);
}
}
}
try {
Properties props = System.getProperties();
// Connect
store.connect(argv[0], argv[1], argv[2]);
// Open a Folder
Folder folder = store.getFolder(argv[3]);
if (folder == null || !folder.exists()) {
System.out.println("Invalid folder");
System.exit(1);
}
folder.open(Folder.READ_WRITE);
for (; ;) {
Thread.sleep(freq); // sleep for freq milliseconds
import javax.mail.internet.*;
import javax.activation.*;
/**
* msgmultisendsample creates a simple multipart/mixed message and sends
* it. Both body parts are text/plain.
* <p>
* usage: <code>java msgmultisendsample <i>to from smtp true|false</i></
code>
* where <i>to</i> and <i>from</i> are the destination and
* origin email addresses, respectively, and <i>smtp</i>
* is the hostname of the machine that has smtp server
* running. The last parameter either turns on or turns off
* debugging during sending.
*
* @author Max Spivak
*/
public class msgmultisendsample {
static String msgText1 = "This is a message body.\nHere's line two.";
static String msgText2 = "This is the text in the message attachment.";
String to = args[0];
String from = args[1];
String host = args[2];
boolean debug = Boolean.valueOf(args[3]).booleanValue();
try {
// create a message
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
InternetAddress[] address = {new InternetAddress(to)};
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject("JavaMail APIs Multipart Test");
msg.setSentDate(new Date());
Appendix C:
Message Security
Overview
This is not a full specification of how Message Security will be integrated into the JavaMail
system. This is a description of implementation strategy. The purpose of this section is to
declare that it is possible to integrate message security, not to define how it will be integrated.
The final design for Message Security will change based on feedback and finalization of the S/
MIME IETF specification.
This section discusses encrypting/decrypting messages, and signing/verifying signatures. It
will not discuss how Security Restrictions on untrusted or signed applets will work, nor will it
discuss a general authentication model for Stores (For example; a GSS API in the Java
platform.)
MultiPartEncrypted/Signed Classes
The JavaMail API will probably add two new content classes: MultiPartEncrypted and
MultiPartSigned. They subclass the MultiPart class and handle the MIME types
multipart/encrypted and multipart/signed. There are many possible "protocols" that specify
how a message has been encrypted and/or signed. The MPE/MPS classes will find all the
installed protocols. The ContentType’s protocol parameter determines which protocol class
to use. There needs to be a standard registration of protocol objects or a way to search for
valid packages and instantiate a particular class. The MultiPart classes will hand off the
control information, other parameters, and the data to be manipulated (either the signed or
encrypted block) through some defined Protocol interface.
Verifying Signatures
Applications/applets will need to verify the validity of a signature. The code sample below
shows how this might be done:
Creating a Message
There are two methods for creating an Encrypted/Signed message. Users will probably see an
editor bean for the content types multipart/signed and multipart/encrypted. These beans would
handle the UI components to allow the user to select how they want to encrypt/sign the
message. The beans could be integrated into an application’s Message Composition window.
Encrypted/Signed
The non-GUI method of creating the messages involves using the MultiPartEncrypted/Signed
classes. The classes can be created and used as the content for a message. The following code
shows how might work:
Appendix D:
FIGURE D-1
Appendix E:
FIGURE E-1
MimeMessage Object
NestedMultipart Message
Message
<address of message sender> Legend:
getFrom()
getContent() "text/plain"
"3"
BodyPart getContentType()
Multipart getCount()
(String)getContent() <message text>
<Text> getBodyPart(0)
"image/gif"
Multipart
(Multipart)getContent() repeat with Multipart
as before...
...
Appendix F:
New SearchTerms
The current address related search terms: AddressTerm, FromTerm and
RecipientTerm, are limited in that they operate on Address objects, not Strings.
These terms use the equals methd to compare the addresses, which is not useful for the
common case of substring comparisons.
Hence three new SearchTerms have been introduced:
? AddressStringTerm
? FromStringTerm
? RecipientStringTerm
These terms operate on Address Strings, rather than Address objects.
These new terms correspond to the capabilities provided by the IMAP protocol. The older
terms were not supported by IMAP and thus resulted in client-side searches.
Appendix G:
To provide this support, the following classes and all their subclasses now implement the
Serializable interface:
? javax.mail.search.SearchTerm
? javax.mail.Address
? javax.mail.Flags
? javax.mail.Message.RecipientType
In addition, to allow comparison between search terms, the equals and hashCode methods
on SearchTerm (and all subclasses) now implement "value" equivalence rather than identity
equivalence.
Appendix H:
/**
* Returns the value of the RFC 822 "Sender" header field.
* If the "Sender" header field is absent, <code>null</code>
* is returned.<p>
*
* This implementation uses the <code>getHeader</code> method
* to obtain the requisite header field.
*
* @return Address object
* @exception MessagingException
* @see #headers
* @since JavaMail 1.3
*/
public Address getSender() throws MessagingException
/**
* Set the RFC 822 "Sender" header field. Any existing values are
* replaced with the given address. If address is <code>null</code>,
* this header is removed.
*
* @param address the sender of this message
* @exception IllegalWriteException if the underlying
* implementation does not support modification
* of existing values
* @exception IllegalStateException if this message is
* obtained from a READ_ONLY folder.
* @exception MessagingException
* @since JavaMail 1.3
*/
/**
* Set the "Content-ID" header field of this body part.
* If the <code>cid</code> parameter is null, any existing
* "Content-ID" is removed.
*
* @exception IllegalWriteException if the underlying
* implementation does not support modification
* @exception IllegalStateException if this body part is
* obtained from a READ_ONLY folder.
* @exception MessagingException
* @since JavaMail 1.3
*/
public void setContentID(String cid) throws MessagingException
/**
* Get the number of deleted messages in this Folder. <p>
*
* This method can be invoked on a closed folder. However, note
* that for some folder implementations, getting the deleted message
* count can be an expensive operation involving actually opening
* the folder. In such cases, a provider can choose not to support
* this functionality in the closed state, in which case this method
* must return -1. <p>
*
* Clients invoking this method on a closed folder must be aware
* that this is a potentially expensive operation. Clients must
/**
* Parse the given sequence of addresses into InternetAddress
* objects. If <code>strict</code> is false, the full syntax rules for
* individual addresses are not enforced. If <code>strict</code> is
* true, many (but not all) of the RFC822 syntax rules are enforced.
*
* Non-strict parsing is typically used when parsing a list of
* mail addresses entered by a human. Strict parsing is typically
* used when parsing address headers in mail messages.
*
* @param addresslist comma separated address strings
* @param strict enforce RFC822 syntax
* @return array of InternetAddress objects
* @exception AddressException if the parse failed
* @since JavaMail 1.3
*/
public static InternetAddress[] parseHeader(String s, boolean strict)
throws AddressException
To allow applications to check the syntax of addresses that might’ve been parsed with the
strict flag set to false, we add a validate method.
/**
* Validate that this address conforms to the syntax rules
* of RFC 822. The current implementation checks many, not
* all, syntax rules. Note that, even though the syntax of
* the address may be correct, there’s no guarantee that a
* mailbox of that name exists.
*
* @exception AddressException if the address
* isn’t valid.
* @since JavaMail 1.3
*/
public void validate() throws AddressException
To control the strict flag when constructing a single InternetAddress object we add a new
constructor.
/**
* Parse the given string and create an InternetAddress.
* If <code>strict</code> is false, the detailed syntax of the
* address isn’t checked.
*
* @param address the address in RFC822 format
* @param strict enforce RFC822 syntax
* @exception AddressException if the parse failed
* @since JavaMail 1.3
*/
public InternetAddress(String address, boolean strict)
throws AddressException
/**
* Indicates whether this address is an RFC 822 group address.
* Note that a group address is different than the mailing
* list addresses supported by most mail servers. Group addresses
* are rarely used; see RFC 822 for details.
*
* @return true if this address represents a group
* @since JavaMail 1.3
*/
public boolean isGroup()
/**
* Return the members of a group address. A group may have zero,
* one, or more members. If this address is not a group, null
* is returned. The <code>strict</code> parameter controls whether
* the group list is parsed using strict RFC 822 rules or not.
* The parsing is done using the <code>parseHeader</code> method.
*
/**
* Set the stream to be used for debugging output for this session.
* If <code>out</code> is null, <code>System.out</code> will be used.
* Note that debugging output that occurs before any session is
created,
* as a result of setting the <code>mail.debug</code> system property,
* will always be sent to <code>System.out</code>.
*
* @param out the PrintStream to use for debugging output
* @since JavaMail 1.3
*/
public void setDebugOut(PrintStream out)
/**
* Returns the stream to be used for debugging output. If no stream
* has been set, <code>System.out</code> is returned.
*
* @return the PrintStream to use for debugging output
* @since JavaMail 1.3
*/
public PrintStream getDebugOut()
Appendix I:
/**
* Convenience method that sets the given String as this part’s
* content, with a primary MIME type of “text” and the specified
* MIME subtype. The given Unicode string will be charset-encoded
* using the specified charset. The charset is also used to set
* the “charset” parameter.
*
* @param text the text content to set
* @param charset the charset to use for the text
* @param subtype the MIME subtype to use (e.g., “html”)
* @exception MessagingException if an error occurs
* @since JavaMail 1.4
*/
public void setText(String text, String charset, String subtype)
throws MessagingException;
The MimeMessage and MimeBodyPart classes, which implement the MimePart interface,
will be updated to provide implementations of the new method.
/**
* Connect to the current host using the specified username
* and password. This method is equivalent to calling the
* <code>connect(host, user, password)</code> method with null
* for the host name.
*
* @param user the user name
* @param password this user’s password
* @exception AuthenticationFailedException for authentication failures
* @exception MessagingException for other failures
* @exception IllegalStateException if the service is already connected
* @see javax.mail.event.ConnectionEvent
* @see javax.mail.Session#setPasswordAuthentication
* @see #connect(java.lang.String, java.lang.String, java.lang.String)
* @since JavaMail 1.4
*/
public void connect(String user, String password)
throws MessagingException
Add mail.mime.multipart.ignoremissingendboundary
System property (4971381)
The current implementation of the MimeMultipart class will ignore a missing end
boundary line; if EOF is reached when parsing the content before seeing an end boundary line,
the last part of the multipart is terminated and no error is returned.
Some users have requested a way to force the multipart parsing to more strictly enforce the
MIME specification. To support this we we introduce a new System property:
mail.mime.multipart.ignoremissingendboundary
* The <code>mail.mime.multipart.ignoremissingendboundary</code>
* System property may be set to <code>false</code> to cause a
* <code>MessagingException</code> to be thrown if the multipart
* data does not end with the required end boundary line. If this
* property is set to <code>true</code> or not set, missing end
* boundaries are not considered an error and the final body part
* ends at the end of the data. <p>
/**
* Return true if the final boundary line for this
* multipart was seen. When parsing multipart content,
* this class will (by default) terminate parsing with
* no error if the end of input is reached before seeing
* the final multipart boundary line. In such a case,
* this method will return false. (If the System property
* “mail.mime.multipart.ignoremissingendboundary” is set to
* false, parsing such a message will instead throw a
* MessagingException.)
*
* @return true if the final boundary line was seen
* @since JavaMail 1.4
*/
public boolean isComplete() throws MessagingException
Add
mail.mime.multipart.ignoremissingboundaryparamet
er property (6300814)
The following property is already supported as part of the JavaMail implementation. This
change makes the property a part of the standard API.
* The <code>mail.mime.multipart.ignoremissingboundaryparameter</code>
* System property may be set to <code>false</code> to cause a
* <code>MessagingException</code> to be thrown if the Content-Type
* of the MimeMultipart does not include a <code>boundary</code> parameter.
* If this property is set to <code>true</code> or not set, the multipart
* parsing code will look for a line that looks like a bounary line and
* use that as the boundary separating the parts.
/**
* Get the preamble text, if any, that appears before the
* first body part of this multipart. Some protocols,
* such as IMAP, will not allow access to the preamble text.
*
* @return the preamble text, or null if no preamble
* @since JavaMail 1.4
*/
public String getPreamble() throws MessagingException
/**
* Set the preamble text to be included before the first
* body part. Applications should generally not include
* any preamble text. In some cases it may be helpful to
* include preamble text with instructions for users of
* pre-MIME software.
*
* @param preamble the preamble text
* @since JavaMail 1.4
*/
public void setPreamble(String preamble) throws MessagingException
/**
* Update the Message-ID header. This method is called
* by the <code>updateHeaders</code> and allows a subclass
* to override only the algorithm for choosing a Message-ID.
*
* @since JavaMail 1.4
*/
protected void updateMessageID() throws MessagingException
/**
* Create and return a MimeMessage object. The reply method
* uses this method to create the MimeMessage object that it
* will return. Subclasses can override this method to return
* a subclass of MimeMessage. This implementation simply constructs
* and returns a MimeMessage object using the supplied Session.
*
* @param session the Session to use for the new message
* @return the new MimeMessage object
* @since JavaMail 1.4
*/
protected MimeMessage createMimeMessage(Session session)
throws MessagingException
/**
* The MimePart that provides the data for this DataSource.
*
* @sinceJavaMail 1.4
*/
protected MimePart part;
/**
* Return the delimiter character that separates this Folder’s pathname
* from the names of immediate subfolders. This method can be invoked
* on a closed Folder.
*
* @exception FolderNotFoundException if the implementation
* requires the folder to exist, but it does not
* @return Hierarchy separator character
*/
public abstract char getSeparator() throws MessagingException;
/**
* A MimeBodyPart that handles data that has already been encoded.
* This class is useful when constructing a message and attaching
* data that has already been encoded (for example, using base64
* encoding). The data may have been encoded by the application,
* or may have been stored in a file or database in encoded form.
* The encoding is supplied when this object is created. The data
* is attached to this object in the usual fashion, by using the
* <code>setText</code>, <code>setContent</code>, or
* <code>setDataHandler</code> methods.
*
* @sinceJavaMail 1.4
*/
/**
* Use the specified file to provide the data for this part.
* The simple file name is used as the file name for this
* part and the data in the file is used as the data for this
* part. The encoding will be chosen appropriately for the
* file data.
*
* @param file the File object to attach
* @exception IOException errors related to accessing the file
* @exception MessagingException message related errors
* @since JavaMail 1.4
*/
public void attachFile(File file)
throws IOException, MessagingException
/**
* Use the specified file to provide the data for this part.
* The simple file name is used as the file name for this
* part and the data in the file is used as the data for this
* part. The encoding will be chosen appropriately for the
* file data.
*
* @param file the name of the file to attach
* @exception IOException errors related to accessing the file
* @exception MessagingException message related errors
* @since JavaMail 1.4
*/
public void attachFile(String file)
throws IOException, MessagingException
/**
* Save the contents of this part in the specified file. The content
* is decoded and saved, without any of the MIME headers.
*
* @param file the File object to write to
* @exception IOException errors related to accessing the file
* @exception MessagingException message related errors
* @since JavaMail 1.4
*/
/**
* Save the contents of this part in the specified file. The content
* is decoded and saved, without any of the MIME headers.
*
* @param file the name of the file to write to
* @exception IOException errors related to accessing the file
* @exception MessagingException message related errors
* @since JavaMail 1.4
*/
public void saveFile(String file)
throws IOException, MessagingException
/**
* Fold a string at linear whitespace so that each line is no longer
* than 76 characters, if possible. If there are more than 76
* non-whitespace characters consecutively, the string is folded at
* the first whitespace after that sequence. The parameter
* <code>used</code> indicates how many characters have been used in
* the current line; it is usually the length of the header name. <p>
*
* Note that line breaks in the string aren’t escaped; they probably
* should be.
*
* @param used characters used in line so far
* @param s the string to fold
* @return the folded string
*/
public static String fold(int used, String s)
/**
* Unfold a folded header. Any line breaks that aren’t escaped and
* are followed by whitespace are removed.
*
* @param s the string to unfold
* @return the unfolded string
*/
public static String unfold(String s)
The elements of the list are objects of a new protected final class
InternetHeaders.InternetHeader that extends the javax.mail.Header class.
To allow the InternetHeader class to make use of the Header class, we make the
following fields of Header protected:
/**
* The name of the header.
*
* @since JavaMail 1.4
*/
protected String name;
/**
* The value of the header.
*
* @since JavaMail 1.4
*/
protected String value;
/**
* Create a new provider of the specified type for the specified
* protocol. The specified class implements the provider.
*
* @param type Type.STORE or Type.TRANSPORT
* @param protocol valid protocol for the type
* @param classname class name that implements this protocol
/**
* Add a provider to the session.
*
* @param provider the provider to add
* @since JavaMail 1.4
*/
public void addProvider(Provider provider)
/**
* Set the default transport protocol to use for addresses of
* the specified type. Normally the default is set by the
* <code>javamail.default.address.map</code> or
* <code>javamail.address.map</code> files or resources.
*
* @param addresstype type of address
* @param protocol name of protocol
* @see #getTransport(Address)
* @since JavaMail 1.4
*/
public void setProtocolForAddress(String addresstype, String protocol)
/**
* Set a parameter. If this parameter already exists, it is
* replaced by this new value. If the
* <code>mail.mime.encodeparameters</code> System property
* is true, and the parameter value is non-ASCII, it will be
* encoded with the specified charset.
*
* @param name name of the parameter.
* @param value value of the parameter.
* @param charset charset of the parameter value.
* @since JavaMail 1.4
*/
public void set(String name, String value, String charset)
package javax.mail;
/**
* An interrface implemented by Stores that support quotas.
* The {@link #getQuota getQuota} and {@link #setQuota setQuota} methods
* support the quota model defined by the IMAP QUOTA extension.
* Refer to <A HREF=”http://www.ietf.org/rfc/rfc2087.txt”>RFC 2087</A>
* for more information. <p>
*
* @since JavaMail 1.4
*/
public interface QuotaAwareStore {
/**
* Get the quotas for the named quota root.
* Quotas are controlled on the basis of a quota root, not
* (necessarily) a folder. The relationship between folders
/**
* Set the quotas for the quota root specified in the quota argument.
* Typically this will be one of the quota roots obtained from the
* <code>getQuota</code> method, but it need not be.
*
* @param quota the quota to set
* @exception MessagingException if the server doesn’t support the
* QUOTA extension
*/
void setQuota(Quota quota) throws MessagingException;
}
package javax.mail;
/**
* This class represents a set of quotas for a given quota root.
* Each quota root has a set of resources, represented by the
* <code>Quota.Resource</code> class. Each resource has a name
* (for example, “STORAGE”), a current usage, and a usage limit.
* See RFC 2087.
*
* @since JavaMail 1.4
*/
/**
* An individual resource in a quota root.
*
* @since JavaMail 1.4
*/
public static class Resource {
/** The name of the resource. */
public String name;
/** The current usage of the resource. */
public long usage;
/** The usage limit for the resource. */
public long limit;
/**
* Construct a Resource object with the given name,
* usage, and limit.
*
* @param name the resource name
* @param usage the current usage of the resource
* @param limit the usage limit for the resource
*/
public Resource(String name, long usage, long limit)
}
/**
* The name of the quota root.
*/
public String quotaRoot;
/**
* The set of resources associated with this quota root.
*/
public Quota.Resource[] resources;
/**
* Create a Quota object for the named quotaroot with no associated
* resources.
*
* @param quotaRoot the name of the quota root
*/
public Quota(String quotaRoot)
/**
* Set a resource limit for this quota root.
*
* @param name the name of the resource
* @param limit the resource limit
*/
public void setResourceLimit(String name, long limit)
}
package javax.mail.util;
/**
* A DataSource backed by a byte array. The byte array may be
/**
* Create a ByteArrayDataSource with data from the
* specified InputStream and with the specified MIME type.
* The InputStream is read completely and the data is
* stored in a byte array.
*/
public ByteArrayDataSource(InputStream is, String type)
throws IOException
/**
* Create a ByteArrayDataSource with data from the
* specified String and with the specified MIME type.
* The MIME type should include a <code>charset</code>
* parameter specifying the charset to be used for the
* string. If the parameter is not included, the
* default charset is used.
*/
public ByteArrayDataSource(String data, String type) throws IOException
/**
* Return an InputStream for the data.
* Note that a new stream is returned each time
* this method is called.
*/
public InputStream getInputStream() throws IOException
/**
* Return an OutputStream for the data.
* Writing the data is not supported; an <code>IOException</code>
* is always thrown.
*/
public OutputStream getOutputStream() throws IOException
/**
* Get the MIME content type of the data.
*/
public String getContentType()
/**
* Get the name of the data.
* By default, an empty string (““) is returned.
*/
public String getName()
/**
* Set the name of the data.
*/
public void setName(String name)
}
package javax.mail.util;
/**
* A ByteArrayInputStream that implements the SharedInputStream interface,
* allowing the underlying byte array to be shared between multiple
* readers.
*
* @since JavaMail 1.4
*/
public class SharedByteArrayInputStream extends ByteArrayInputStream
implements SharedInputStream {
/**
* Position within shared buffer that this stream starts at.
*/
protected int start;
/**
* Create a SharedByteArrayInputStream representing the entire
* byte array.
*/
public SharedByteArrayInputStream(byte[] buf)
/**
* Create a SharedByteArrayInputStream representing the part
* of the byte array from <code>offset</code> for <code>length</code>
* bytes.
*/
public SharedByteArrayInputStream(byte[] buf, int offset, int length)
/**
* Return the current position in the InputStream, as an
* offset from the beginning of the InputStream.
*
/**
* Return a new InputStream representing a subset of the data
* from this InputStream, starting at <code>start</code> (inclusive)
* up to <code>end</code> (exclusive). <code>start</code> must be
* non-negative. If <code>end</code> is -1, the new stream ends
* at the same place as this stream. The returned InputStream
* will also implement the SharedInputStream interface.
*
* @paramstartthe starting position
* @paramendthe ending position + 1
* @returnthe new stream
*/
public InputStream newStream(long start, long end)
}
package javax.mail.util;
/**
* A <code>SharedFileInputStream</code> is a
* <code>BufferedInputStream</code> that buffers
* data from the file and supports the <code>mark</code>
* and <code>reset</code> methods. It also supports the
* <code>newStream</code> method that allows you to create
* other streams that represent subsets of the file.
* A <code>RandomAccessFile</code> object is used to
* access the file data.
*
* @since JavaMail 1.4
*/
public class SharedFileInputStream extends BufferedInputStream
implements SharedInputStream {
/**
* The file containing the data.
* Shared by all related SharedFileInputStream instances.
*/
protected RandomAccessFile in;
/**
* The normal size of the read buffer.
*/
protected int bufsize;
/**
* The file offset that corresponds to the first byte in
* the read buffer.
*/
protected long bufpos;
/**
* The file offset of the start of data in this subset of the file.
*/
protected long start = 0;
/**
* The amount of data in this subset of the file.
*/
protected long datalen;
/**
* Creates a <code>SharedFileInputStream</code>
* for the file.
*
* @param file the file
*/
public SharedFileInputStream(File file) throws IOException
/**
* Creates a <code>SharedFileInputStream</code>
* for the named file.
*
* @param file the file
*/
public SharedFileInputStream(String file) throws IOException
/**
* Creates a <code>SharedFileInputStream</code>
* with the specified buffer size.
*
* @param file the file
* @param size the buffer size.
* @exception IllegalArgumentException if size <= 0.
*/
public SharedFileInputStream(File file, int size) throws IOException
/**
* Creates a <code>SharedFileInputStream</code>
* with the specified buffer size.
*
* @param file the file
* @param size the buffer size.
* @exception IllegalArgumentException if size <= 0.
*/
/**
* See the general contract of the <code>read</code>
* method of <code>InputStream</code>.
*
* @return the next byte of data, or <code>-1</code> if the end of
* the stream is reached.
* @exception IOException if an I/O error occurs.
*/
public int read() throws IOException
/**
* Reads bytes from this stream into the specified byte array,
* starting at the given offset.
*
* <p> This method implements the general contract of the corresponding
* <code>{@link java.io.InputStream#read(byte[], int, int) read}</code>
* method of the <code>{@link java.io.InputStream}</code> class.
*
* @param b destination buffer.
* @param off offset at which to start storing bytes.
* @param len maximum number of bytes to read.
* @return the number of bytes read, or <code>-1</code> if the end
* of the stream has been reached.
* @exception IOException if an I/O error occurs.
*/
public int read(byte b[], int off, int len) throws IOException
/**
* See the general contract of the <code>skip</code>
* method of <code>InputStream</code>.
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
* @exception IOException if an I/O error occurs.
*/
public long skip(long n) throws IOException
/**
* Returns the number of bytes that can be read from this input
* stream without blocking.
*
* @return the number of bytes that can be read from this input
* stream without blocking.
* @exception IOException if an I/O error occurs.
*/
public int available() throws IOException
/**
* See the general contract of the <code>mark</code>
* method of <code>InputStream</code>.
*
/**
* See the general contract of the <code>reset</code>
* method of <code>InputStream</code>.
* <p>
* If <code>markpos</code> is <code>-1</code>
* (no mark has been set or the mark has been
* invalidated), an <code>IOException</code>
* is thrown. Otherwise, <code>pos</code> is
* set equal to <code>markpos</code>.
*
* @exception IOException if this stream has not been marked or
* if the mark has been invalidated.
* @see #mark(int)
*/
public void reset() throws IOException
/**
* Tests if this input stream supports the <code>mark</code>
* and <code>reset</code> methods. The <code>markSupported</code>
* method of <code>SharedFileInputStream</code> returns
* <code>true</code>.
*
* @return a <code>boolean</code> indicating if this stream type
* supports the <code>mark</code> and <code>reset</code>
* methods.
* @see java.io.InputStream#mark(int)
* @see java.io.InputStream#reset()
*/
public boolean markSupported()
/**
* Closes this input stream and releases any system resources
* associated with the stream.
*
* @exception IOException if an I/O error occurs.
*/
public void close() throws IOException
/**
* Return the current position in the InputStream, as an
* offset from the beginning of the InputStream.
*
* @return the current position
*/
public long getPosition()
/**
/**
* Force this stream to close.
*/
protected void finalize() throws Throwable
}
Appendix J:
/**
* SIZE is a fetch profile item that can be included in a
* <code>FetchProfile</code> during a fetch request to a Folder.
* This item indicates that the sizes of the messages in the specified
* range should be prefetched. <p>
*
* @sinceJavaMail 1.5
*/
public static final Item SIZE;
javax.mail.search.FlagTerm:
private boolean set;
private Flags flags;
javax.mail.search.HeaderTerm:
private String headerName;
javax.mail.search.NotTerm:
javax.mail.search.OrTerm:
private SearchTerm[] terms;
javax.mail.search.RecipientTerm:
private Message.RecipientType type;
/**
* Construct a MimeMultipart object of the default “mixed” subtype,
* and with the given body parts. More body parts may be added later.
*
* @since JavaMail 1.5
*/
public MimeMultipart(BodyPart... parts) throws MessagingException
/**
* Construct a MimeMultipart object of the given subtype
* and with the given body parts. More body parts may be added later.
*
* @since JavaMail 1.5
*/
public MimeMultipart(String subtype, BodyPart... parts)
throws MessagingException
javax.mail.AuthenticationFailedException:
/**
* Constructs an AuthenticationFailedException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param message The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
public AuthenticationFailedException(String message, Exception e)
javax.mail.FolderClosedException:
/**
* Constructs a FolderClosedException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param folder The Folder
* @param message The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
public FolderClosedException(Folder folder, String message, Exception e)
javax.mail.FolderNotFoundException:
/**
* Constructs a FolderNotFoundException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param folder The Folder
* @param s The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
public FolderNotFoundException(Folder folder, String s, Exception e)
javax.mail.IllegalWriteException:
/**
* Constructs an IllegalWriteException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param s The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
public IllegalWriteException(String s, Exception e)
javax.mail.MessageRemovedException:
/**
* Constructs a MessageRemovedException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param s The detailed error message
* @param e The embedded exception
javax.mail.MethodNotSupportedException:
/**
* Constructs a MethodNotSupportedException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param s The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
public MethodNotSupportedException(String s, Exception e)
javax.mail.NoSuchProviderException:
/**
* Constructs a NoSuchProviderException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param message The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
public NoSuchProviderException(String message, Exception e)
javax.mail.ReadOnlyFolderException:
/**
* Constructs a ReadOnlyFolderException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param folder The Folder
* @param message The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
public ReadOnlyFolderException(Folder folder, String message, Exception
e)
javax.mail.StoreClosedException:
/**
* Constructs a StoreClosedException with the specified
* detail message and embedded exception. The exception is chained
* to this exception.
*
* @param store The dead Store object
* @param message The detailed error message
* @param e The embedded exception
* @since JavaMail 1.5
*/
/**
* Normal users of this class will use simple parameter names.
* In some cases, for example, when processing IMAP protocol
* messages, individual segments of a multi-segment name
* (specified by RFC 2231) will be encountered and passed to
* the {@link #set} method. After all these segments are added
* to this ParameterList, they need to be combined to represent
* the logical parameter name and value. This method will combine
* all segments of multi-segment names. <p>
*
* Normal users should never need to call this method.
*
* @since JavaMail 1.5
*/
public void combineSegments()
javax.mail.internet.ContentType:
/**
* Retrieve a RFC2045 style string representation of
* this Content-Type. Returns an empty string if
* the conversion failed.
*
* @return RFC2045 style string
*/
public String toString()
javax.mail.internet.ContentDisposition:
/**
* Retrieve a RFC2045 style string representation of
* this ContentDisposition. Returns an empty string if
* the conversion failed.
*
* @return RFC2045 style string
* @since JavaMail 1.2
*/
public String toString()
/**
* Send a message. The message will be sent to all recipient
* addresses specified in the message (as returned from the
* <code>Message</code> method <code>getAllRecipients</code>).
* The <code>send</code> method calls the <code>saveChanges</code>
* method on the message before sending it. <p>
*
* Use the specified user name and password to authenticate to
* the mail server.
*
* @param msg the message to send
* @param user the user name
* @param password this user’s password
* @exception SendFailedException if the message could not
* be sent to some or any of the recipients.
* @exception MessagingException
* @see Message#saveChanges
* @see #send(Message)
* @see javax.mail.SendFailedException
* @since JavaMail 1.5
*/
public static void send(Message msg,
String user, String password) throws MessagingException
/**
* Send the message to the specified addresses, ignoring any
* recipients specified in the message itself. The
* <code>send</code> method calls the <code>saveChanges</code>
* method on the message before sending it. <p>
*
* Use the specified user name and password to authenticate to
/**
* Set the RFC 822 “From” header field. Any existing values are
* replaced with the given addresses. If address is <code>null</code>,
* this header is removed.
*
* @param address the sender(s) of this message
* @exception IllegalWriteException if the underlying
* implementation does not support modification
* of existing values
* @exception IllegalStateException if this message is
* obtained from a READ_ONLY folder.
* @exception MessagingException
* @since JvaMail 1.5
*/
public void setFrom(String address) throws MessagingException
/**
* Return the Session used when this message was created.
*
* @return the message’s Session
* @since JavaMail 1.5
*/
public Session getSession()
/**
* Use the specified file to provide the data for this part.
* The simple file name is used as the file name for this
* part and the data in the file is used as the data for this
* part. The encoding will be chosen appropriately for the
* file data. The disposition of this part is set to
* {@link Part#ATTACHMENT Part.ATTACHMENT}.
*
* @param file the File object to attach
* @exception IOException errors related to accessing the
file
* @exception MessagingException message related errors
* @since JavaMail 1.4
*/
public void attachFile(File file) throws IOException,
MessagingException
/**
* Use the specified file to provide the data for this part.
* The simple file name is used as the file name for this
* part and the data in the file is used as the data for this
* part. The encoding will be chosen appropriately for the
* file data.
*
* @param file the name of the file to attach
* @exception IOException errors related to accessing the
file
* @exception MessagingException message related errors
* @since JavaMail 1.4
*/
public void attachFile(String file) throws IOException,
MessagingException
/**
* Get a new Message suitable for a reply to this message.
* The new Message will have its attributes and headers
* set up appropriately. Note that this new message object
* will be empty, i.e., it will <strong>not</strong> have a “content”.
* These will have to be suitably filled in by the client. <p>
*
* If <code>replyToAll</code> is set, the new Message will be addressed
* to all recipients of this message. Otherwise, the reply will be
* addressed to only the sender of this message (using the value
* of the <code>getReplyTo</code> method). <p>
*
* If <code>setAnswered</code> is set, the
* {@link javax.mail.Flags.Flag#ANSWERED ANSWERED} flag is set
* in this message. <p>
*
* The “Subject” field is filled in with the original subject
* prefixed with “Re:” (unless it already starts with “Re:”).
* The “In-Reply-To” header is set in the new message if this
* message has a “Message-Id” header.
*
* The current implementation also sets the “References” header
* in the new message to include the contents of the “References”
* header (or, if missing, the “In-Reply-To” header) in this message,
* plus the contents of the “Message-Id” header of this message,
* as described in RFC 2822.
*
* @param replyToAll reply should be sent to all recipients
* of this message
* @param setAnswered set the ANSWERED flag in this message?
* @return the reply Message
* @exception MessagingException
* @since JavaMail 1.5
*/
public Message reply(boolean replyToAll, boolean setAnswered)
throws MessagingException
/**
* Parses the next token from this String.
* If endOfAtom is not NUL, the token extends until the
* endOfAtom character is seen, or to the end of the header.
* This method is useful when parsing headers that don’t
* obey the MIME specification, e.g., by failing to quote
* parameter values that contain spaces.
*
* @param endOfAtom if not NUL, character marking end of token
* @return the next Token
* @exception ParseException if the parse fails
* @since JavaMail 1.5
*/
public Token next(char endOfAtom) throws ParseException
/**
* Parses the next token from this String.
* endOfAtom is handled as above. If keepEscapes is true,
* any backslash escapes are preserved in the returned string.
* This method is useful when parsing headers that don’t
* obey the MIME specification, e.g., by failing to escape
* backslashes in the filename parameter.
*
* @param endOfAtom if not NUL, character marking end of token
* @param keepEscapes keep all backslashes in returned string?
* @return the next Token
* @exception ParseException if the parse fails
* @since JavaMail 1.5
*/
public Token next(char endOfAtom, boolean keepEscapes)
throws ParseException
javax.mail.MailSessionDefinition:
/**
* Annotation used by Java EE applications to define a <code>MailSession</
code>
* to be registered with JNDI. The <code>MailSession</code> may be
configured
* by setting the annotation elements for commonly used <code>Session</
code>
/**
* Description of this mail session.
*/
String description() default ““;
/**
* JNDI name by which the mail session will be registered.
*/
String name();
/**
* Store protocol name.
*/
String storeProtocol() default ““;
/**
* Transport protocol name.
*/
String transportProtocol() default ““;
/**
* Host name for the mail server.
*/
String host() default ““;
/**
* User name to use for authentication.
*/
String user() default ““;
/**
* Password to use for authentication.
*/
String password() default ““;
/**
* From address for the user.
*/
String from() default ““;
/**
* Properties to include in the Session.
* Properties are specified using the format:
* <i>propertyName=propertyValue</i> with one property per array
element.
*/
String[] properties() default {};
}
javax.mail.MailSessionDefinitions:
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
/**
* Declares one or more <code>MailSessionDefinition</code> annotations.
*
* @see MailSessionDefinition
* @since JavaMail 1.5
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MailSessionDefinitions {
MailSessionDefinition[] value();
}
/**
* If our content is a Multipart or Message object, we save it
* the first time it’s created by parsing a stream so that changes
* to the contained objects will not be lost. <p>
*
* If this field is not null, it’s return by the {@link #getContent}
* method. The {@link #getContent} method sets this field if it
* would return a Multipart or MimeMessage object. This field is
* is cleared by the {@link #setDataHandler} method.
*
* @since JavaMail 1.5
*/
protected Object cachedContent;
/**
* Have we seen the final bounary line?
*
* @since JavaMail 1.5
*/
protected boolean complete = true;
/**
* The MIME multipart preamble text, the text that
* occurs before the first boundary line.
*
* @since JavaMail 1.5
*/
protected String preamble = null;
/**
* Flag corresponding to the
“mail.mime.multipart.ignoremissingendboundary”
* property, set in the {@link #initializeProperties} method called
* from constructors and the parse method.
*
* @since JavaMail 1.5
*/
protected boolean ignoreMissingEndBoundary = true;
/**
* Flag corresponding to the
* “mail.mime.multipart.ignoremissingboundaryparameter”
* property, set in the {@link #initializeProperties} method called
* from constructors and the parse method.
*
* @since JavaMail 1.5
*/
protected boolean ignoreMissingBoundaryParameter = true;
/**
* Flag corresponding to the
* “mail.mime.multipart.ignoreexistingboundaryparameter”
* property, set in the {@link #initializeProperties} method called
* from constructors and the parse method.
*
* @since JavaMail 1.5
*/
protected boolean ignoreExistingBoundaryParameter = false;
/**
* Flag corresponding to the “mail.mime.multipart.allowempty”
* property, set in the {@link #initializeProperties} method called
* from constructors and the parse method.
*
* @since JavaMail 1.5
*/
protected boolean allowEmpty = false;
/**
* Initialize flags that control parsing behavior,
* based on System properties described above in
* the class documentation.
*
* @since JavaMail 1.5
*/
protected void initializeProperties()
The following additional System properties are defined corresponding to the last two fields
above:
mail.mime.multipart.ignoreexistingboundaryparameter:
Normally the boundary parameter in the Content-Type header of a multipart body part is
used to specify the separator between parts of the multipart body. This System property
may be set to ”true” to cause the parser to look for a line in the multipart body that
looks like a boundary line and use that value as the separator between subsequent parts.
This may be useful in cases where a broken anti-virus product has rewritten the message
incorrectly such that the boundary parameter and the actual boundary value no longer
match.
The default value of this property is false.
mail.mime.multipart.allowempty:
Normally, when writing out a MimeMultipart that contains no body parts, or when
trying to parse a multipart message with no body parts, a MessagingException is
thrown. The MIME spec does not allow multipart content with no body parts. This
System property may be set to ”true” to override this behavior. When writing out such
a MimeMultipart, a single empty part will be included. When reading such a
multipart, a MimeMultipart will be created with no body parts.
The default value of this property is false.
package javax.mail;
/**
* A {@link javax.activation.DataSource DataSource} that also implements
* <code>EncodingAware</code> may specify the Content-Transfer-Encoding
* to use for its data. Valid Content-Transfer-Encoding values specified
* by RFC 2045 are “7bit”, “8bit”, “quoted-printable”, “base64”, and
* “binary”.
* <p>
* For example, a {@link javax.activation.FileDataSource FileDataSource}
* could be created that forces all files to be base64 encoded: <p>
* <blockquote><pre>
* public class Base64FileDataSource extends FileDataSource
* implements EncodingAware {
* public Base64FileDataSource(File file) {
* super(file);
* }
*
* // implements EncodingAware.getEncoding()
* public String getEncoding() {
* return “base64”;
* }
* }
* </pre></blockquote><p>
*
* @since JavaMail 1.5
* @author Bill Shannon
*/
/**
* Return the MIME Content-Transfer-Encoding to use for this data,
* or null to indicate that an appropriate value should be chosen
* by the caller.
*
* @return the Content-Transfer-Encoding value, or null
*/
public String getEncoding();
}
/**
* Use the specified file with the specified Content-Type and
* Content-Transfer-Encoding to provide the data for this part.
* If contentType or encoding are null, appropriate values will
* be chosen.
* The simple file name is used as the file name for this
* part and the data in the file is used as the data for this
* part. The disposition of this part is set to
* {@link Part#ATTACHMENT Part.ATTACHMENT}.
*
* @param file the File object to attach
* @param contentType the Content-Type, or null
* @param encoding the Content-Transfer-Encoding, or
null
* @exception IOException errors related to accessing the
file
* @exception MessagingException message related errors
* @since JavaMail 1.5
*/
public void attachFile(File file, String contentType, String encoding)
throws IOException, MessagingException
/**
* Use the specified file with the specified Content-Type and
* Content-Transfer-Encoding to provide the data for this part.
* If contentType or encoding are null, appropriate values will
* be chosen.
* The simple file name is used as the file name for this
* part and the data in the file is used as the data for this
* part. The disposition of this part is set to
* {@link Part#ATTACHMENT Part.ATTACHMENT}.
*
* @param file the name of the file
* @param contentType the Content-Type, or null
* @param encoding the Content-Transfer-Encoding, or
null
* @exception IOException errors related to accessing the
file
* @exception MessagingException message related errors
* @since JavaMail 1.5
*/
public void attachFile(String file, String contentType, String
encoding)
throws IOException, MessagingException
Appendix K:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MailSessionDefinitions.class)
public @interface MailSessionDefinition {
...
}
The Repeatable annotation is not known to Java SE 7 and will be ignored (as expected)
when JavaMail 1.6 is used on Java SE 7.
/**
* Called by the <code>saveChanges</code> method to actually
* update the MIME headers. The implementation here sets the
* <code>Content-Transfer-Encoding</code> header (if needed
* and not already set), the <code>Date</code> header (if
* not already set), the <code>MIME-Version</code> header
* and the <code>Message-ID</code> header. Also, if the content
* of this message is a <code>MimeMultipart</code>, its
* <code>updateHeaders</code> method is called. <p>
*
* If the {@link #cachedContent} field is not null (that is,
javax.mail.Multipart
javax.mail.Part
javax.mail.Service
javax.mail.internet.InternetHeaders
javax.mail.internet.MimeBodyPart
javax.mail.internet.MimeMessage
javax.mail.internet.MimePart
javax.mail.internet.ParameterList
Details follow:
--- a/mail/src/main/java/javax/mail/internet/MimePart.java
+++ b/mail/src/main/java/javax/mail/internet/MimePart.java
@@ -111,2 +111,1 @@
- @SuppressWarnings("rawtypes")
- public Enumeration getAllHeaderLines() throws MessagingException;
+ public Enumeration<String> getAllHeaderLines() throws
MessagingException;
@@ -123,2 +122,1 @@
- @SuppressWarnings("rawtypes")
- public Enumeration getMatchingHeaderLines(String[] names)
+ public Enumeration<String> getMatchingHeaderLines(String[] names)
@@ -136,2 +134,1 @@
- @SuppressWarnings("rawtypes")
- public Enumeration getNonMatchingHeaderLines(String[] names)
+ public Enumeration<String> getNonMatchingHeaderLines(String[] names)
diff -r 1f6b2c17e291 mail/src/main/java/javax/mail/internet/
ParameterList.java
--- a/mail/src/main/java/javax/mail/internet/ParameterList.java
+++ b/mail/src/main/java/javax/mail/internet/ParameterList.java
@@ -627,2 +627,1 @@
- @SuppressWarnings("rawtypes")
- public Enumeration getNames() {
+ public Enumeration<String> getNames() {
/**
* This method always throws an UnsupportedOperationException and
* should not be used because RFC 2822 mandates a specific pattern.
*
* @throws UnsupportedOperationException if this method is invoked
* @since JavaMail 1.6
*/
@Override
public void applyLocalizedPattern(String pattern) {
throw new UnsupportedOperationException("Method "
+ "applyLocalizedPattern() shouldn't be called");
}
/**
* This method always throws an UnsupportedOperationException and
* should not be used because RFC 2822 mandates a specific pattern.
*
* @throws UnsupportedOperationException if this method is invoked
* @since JavaMail 1.6
*/
@Override
public void applyPattern(String pattern) {
throw new UnsupportedOperationException("Method "
+ "applyPattern() shouldn't be called");
}
/**
* This method always throws an UnsupportedOperationException and
* should not be used because RFC 2822 mandates another strategy
* for interpreting 2-digits years.
*
* @return the start of the 100-year period into which two digit
* years are parsed
* @throws UnsupportedOperationException if this method is invoked
* @since JavaMail 1.6
*/
@Override
public Date get2DigitYearStart() {
throw new UnsupportedOperationException("Method "
+ "get2DigitYearStart() shouldn't be called");
}
/**
* This method always throws an UnsupportedOperationException and
* should not be used because RFC 2822 mandates another strategy
* for interpreting 2-digits years.
*
* @throws UnsupportedOperationException if this method is invoked
* @since JavaMail 1.6
*/
@Override
public void set2DigitYearStart(Date startDate) {
throw new UnsupportedOperationException("Method "
+ "set2DigitYearStart() shouldn't be called");
}
/**
* This method always throws an UnsupportedOperationException and
* should not be used because RFC 2822 mandates specific date
* format symbols.
*
* @throws UnsupportedOperationException if this method is invoked
* @since JavaMail 1.6
*/
@Override
public void setDateFormatSymbols(
DateFormatSymbols newFormatSymbols) {
throw new UnsupportedOperationException("Method "
+ "setDateFormatSymbols() shouldn't be called");
/**
* Overrides Cloneable.
*
* @return a clone of this instance
* @since JavaMail 1.6
*/
@Override
public MailDateFormat clone() {
return (MailDateFormat) super.clone();
}
/**
* Close this Folder and expunge deleted messages. <p>
*
* A CLOSED ConnectionEvent is delivered to any ConnectionListeners
* registered on this Folder. Note that the folder is closed even
* if this method terminates abnormally by throwing a
* MessagingException. <p>
*
* This method supports the {@link java.lang.AutoCloseable AutoCloseable}
* interface. <p>
*
/**
* Returns the predicted UID that will be assigned to the
* next message that is appended to this folder.
* Messages might be appended to the folder after this value
* is retrieved, causing this value to be out of date.
* This value might only be updated when a folder is first opened.
* Note that messages may have been appended to the folder
* while it was open and thus this value may be out of
* date. <p>
*
* If the value is unknown, -1 is returned. <p>
*
* @return the UIDNEXT value, or -1 if unknown
* @exception MessagingException for failures
* @since JavaMail 1.6
*/
public long getUIDNext() throws MessagingException;
Ideally this new method added to the interface would include a default implementation to
provide compatibility with existing classes that implement this method. However, since the
JavaMail 1.6 reference implementation targets Java SE 7, this is not possible. It's very likely
that the only class implementing this interface is the IMAPFolder class in the JavaMail
reference implementation, thus this incompatibility is extremely unlikely to cause a problem in
practice.
/**
* The largest value possible for a UID, a 32-bit unsigned integer.
* This can be used to fetch all new messages by keeping track of the
* last UID that was seen and using:
* <blockquote><pre>
*
* Folder f = store.getFolder("whatever");
* UIDFolder uf = (UIDFolder)f;
* Message[] newMsgs =
* uf.getMessagesByUID(lastSeenUID + 1, UIDFolder.MAXUID);
*
* </pre></blockquote><p>
*
* @since JavaMail 1.6
*/
public static final long MAXUID = 0xffffffffL;
/**
* Constructs a MimeMultipart object and its bodyparts from the
* given DataSource. <p>
*
* This constructor handles as a special case the situation where the
* given DataSource is a MultipartDataSource object. In this case, this
* method just invokes the superclass (i.e., Multipart) constructor
* that takes a MultipartDataSource object. <p>
*
...
/**
* Parse the InputStream from our DataSource, constructing the
* appropriate MimeBodyParts. The <code>parsed</code> flag is
* set to true, and if true on entry nothing is done. This
* method is called by all other methods that need data for
* the body parts, to make sure the data has been parsed.
* The {@link #initializeProperties} method is called before
* parsing the data.
*
* @exception ParseException for failures parsing the message
* @exception MessagingException for other failures
* @since JavaMail 1.2
*/
protected synchronized void parse() throws MessagingException
/**
* Convert the given array of InternetAddress objects into
* a comma separated sequence of address strings. The
* resulting string contains Unicode characters. <p>
*
* @param addresses array of InternetAddress objects
* @exception ClassCastException if any address object in the
* given array is not an InternetAddress object.
* Note that this is a RuntimeException.
* @return comma separated string of addresses
* @since JavaMail 1.6
*/
public static String toUnicodeString(Address[] addresses)
/**
/**
* Read and parse the given RFC822 message stream till the
* blank line separating the header from the body. The input
* stream is left positioned at the start of the body. The
* header lines are stored internally. <p>
*
* For efficiency, wrap a BufferedInputStream around the actual
* input stream and pass it as the parameter. <p>
*
* No placeholder entries are inserted; the original order of
* the headers is preserved.
*
* @param is RFC822 input stream
* @param allowutf8 if UTF-8 encoded headers are allowed
* @exception MessagingException for any I/O error reading the stream
* @since JavaMail 1.6
*/
public InternetHeaders(InputStream is, boolean allowutf8)
throws MessagingException
/**
* Read and parse the given RFC822 message stream till the
* blank line separating the header from the body. Store the
* header lines inside this InternetHeaders object. The order
* of header lines is preserved. <p>
*
* Note that the header lines are added into this InternetHeaders
The following Session property can be set to enable implicit use of these new methods:
mail.mime.allowutf8:
/**
* The Session class represents a mail session and is not subclassed.
* It collects together properties and defaults used by the mail API's.
* A single default session can be shared by multiple applications on
* the desktop. Unshared sessions can also be created. <p>
*
* The Session class provides access to the protocol providers that
* implement the <code>Store</code>, <code>Transport</code>, and related
* classes. The protocol providers are configured using the following
* files:
* <ul>
* <li> <code>javamail.providers</code> and
* <code>javamail.default.providers</code> </li>
* <li> <code>javamail.address.map</code> and
* <code>javamail.default.address.map</code> </li>
* </ul>
* <p>
* Each <code>javamail.</code><i>X</i> resource file is searched for
* using three methods in the following order:
* <ol>
* <li> <code><i>java.home</i>/<i>conf</i>/javamail.</code><i>X</i> </li>
* <li> <code>META-INF/javamail.</code><i>X</i> </li>
* <li> <code>META-INF/javamail.default.</code><i>X</i> </li>
* </ol>
* <p>
* (Where <i>java.home</i> is the value of the "java.home" System
* property and <i>conf</i> is the directory named "conf" if it exists,
* otherwise the directory named "lib"; the "conf" directory was
* introduced in JDK 1.9.)
* <p>
* The first method allows the user to include their own version of the
* resource file by placing it in the <i>conf</i> directory where the
* <code>java.home</code> property points. The second method allows an
* application that uses the JavaMail APIs to include their own resource
* files in their application's or jar file's <code>META-INF</code>
* directory. The <code>javamail.default.</code><i>X</i> default files
* are part of the JavaMail <code>mail.jar</code> file and should not be
* supplied by users. <p>
/**
* Remove any flags <strong>not</strong> in the given Flags object.
* Useful for clearing flags not supported by a server. If the
* given Flags object includes the Flags.Flag.USER flag, all user
* flags in this Flags object are retained.
*
* @param f the flags to keep
* @return true if this Flags object changed
* @since JavaMail 1.6
*/
public boolean retainAll(Flags f)
/**
* Clear all of the system flags.
*
* @since JavaMail 1.6
*/
public void clearSystemFlags()
/**
* Clear all of the user flags.
*
* @since JavaMail 1.6
*/
public void clearUserFlags()