Jakarta Mail FAQ
General
Installation and Configuration
Programming
- Where can I learn the basics about Internet email that
I'll need to know to program Jakarta Mail effectively?
- Where can I find some example programs that show how to use Jakarta Mail?
- What are some of the most common mistakes people make
when using Jakarta Mail?
- How do I send a message with an attachment?
- How do I tell if a message has attachments?
- How do I read a message with an attachment and save the
attachment?
- How do I find the main message body in a message that has
attachments?
- How do I find the attachments in a message?
- How do I get all the unread messages in a folder?
- Should I use the
isMimeType
method,
or should I use instanceof
on the object returned by the
getContent
method, when deciding how to process a message
part?
- When reading a multipart message, why is the getContent
method returning an IMAPInputStream (or SharedByteArrayInputStream) instead
of a MimeMultipart object?
- When I attach a file it gets a MIME type of
application/octet-stream
instead of the correct MIME type.
- How do I manually set the MIME type for an attached file,
for example in the case where the filename doesn't have an obvious extension?
- How do I create a multipart message with a part of any
MIME type I choose?
- Can I read or send a Microsoft Office document using
Jakarta Mail?
- How do I create or process calendar appointments?
- When should I use
Session.getDefaultInstance
and when should I use Session.getInstance
?
- What is "disconnected support"?
- How do I support disconnected operation using the
Jakarta Mail APIs?
- How do I send secure email using the Jakarta Mail APIs?
- The
writeTo()
method generates message text
with lines that are neither the canonical MIME representation of the data
(i.e., using CRLF to terminate lines), nor using the canonical line
separator of my platform (e.g., "\n" on UNIX). How do I get either
of these representations if I need them?
- Can I use the Jakarta Mail APIs to implement a
mail server?
- Can I use the Jakarta Mail APIs to add new user accounts to my
mail server, remove user accounts from my mail server, or change the passwords
for user accounts on my mail server?
- Can I use the Jakarta Mail APIs to access my address book
on my mail server?
- Why doesn't the MimeMessage class implement Serializable
so that I can serialize a message to disk and read it back later?
- How do I write a Service Provider?
- I'm having trouble logging into my Microsoft Exchange server,
even though I'm sure I'm using the correct username and password, what
could I be doing wrong?
- How do I encode a binary file before sending it and how do I
decode it when I receive it?
- If I don't need to encode and decode attachments myself,
when should I use the
MimeUtility
methods?
- I have data that's already encoded in (e.g.) base64, how do I
tell Jakarta Mail to send this data without re-encoding it?
- Even though Jakarta Mail does all the encoding and decoding for me,
I need to manually control the encoding for some body parts.
- Why doesn't Jakarta Mail properly encode and decode filenames in
non-ASCII character sets?
- Why do I get an error such as
java.net.SocketException: Permission denied: connect
when connecting to my mail server using JDK7?
Debugging
Reading mail, IMAP
Sending mail, SMTP
- How do I reply to a message?
- How do I forward a message?
- How do I send HTML mail?
- How do I send mail with formatted text using different fonts
and colors?
- How do I send mail with both plain text as well as HTML text
so that each mail reader can choose the format appropriate for it?
- How do I send HTML mail that includes images?
- What's the difference between the Transport methods
send
and sendMessage
?
- When I try to send a message I get an error like
SMTPSendFailedException: 530, Address requires authentication
.
- How do I use SSL or TLS when connecting to my mail server?
- I need to authenticate to my SMTP server so I call
trans.connect(host, user, password)
and then
trans.send(msg)
to send the message, but it's not working.
- I modified this message, but the headers do not reflect the changes.
- I set a particular value for the Message-ID header of my
new message, but when I send this message that header is rewritten.
- Why do I get an UnsupportedDataTypeException when sending this
new message that I created?
- How can I explicitly set the SMTP FROM: attribute when sending a
message?
- I want to repeatedly send messages, to a different set of
recipients each time. But invoking
Transport.send(Message)
causes
a new Transport session to be established each time. This is
suboptimal in this case, so how do I get around this?
- I get "MessagingException: 501 HELO requires domain address"
when trying to send a message.
- I get "Must issue a STARTTLS command first"
when trying to send a message.
- If I send a message to a bad address, why don't I get a
SendFailedException or TransportEvent indicating that the address is
bad?
- When a message can't be delivered, a failure message is returned.
How can I detect these "bounced" messages?
- When I construct an InternetAddress object, why don't I get an
exception if the address is illegal?
- When I try to send a message, why do I get
javax.mail.SendFailedException: 550 Unable to relay for
my-address
?
- When I try to send a message to (for example) Yahoo,
why do I get an error that says "connection refused"?
- When sending mail, why does it fail with an exception that includes a
message something like
553 To send mail, first check your mail with a valid POP account
?
POP3
Jakarta Mail in servlets
Jakarta Mail in applets
General
Q: What is the Jakarta Mail API?
A: The Jakarta Mail API is a set of
abstract APIs that model a mail system.
(Jakarta Mail was previously known as JavaMail.)
The API provides a platform independent and protocol independent framework
to build Java technology based email client applications.
The Jakarta Mail API provides facilities for reading and sending email.
Service providers implement particular protocols.
Several service providers are included with the Jakarta Mail API package;
others are available separately.
The Jakarta Mail API is implemented as a Java optional package that can be
used on JDK 1.4 and later on any operating system.
The Jakarta Mail API is also a required part of the
Jakarta EE Platform and the
Java Platform,
Enterprise Edition (Java EE).
Q: How do I get an implementation of the Jakarta Mail API?
A: Eclipse provides an open source
implementation that developers may use and ship.
The implementation
includes the core Jakarta Mail packages and IMAP, POP3, and SMTP service providers.
The implementation may be downloaded
here.
Q: How do I send feedback or comments?
A: Send email to
mail-dev@eclipse.org.
Q: Where is javax.activation
?
A: javax.activation
is part of the
JavaBeans Activation Framework (JAF)
and is included in Java SE 6 through Java SE 10.
The Jakarta Mail API uses JAF for data content handling.
Q: What JDK does the Jakarta Mail API need?
A: The Jakarta Mail API requires JDK/JRE 1.7 or higher.
The Jakarta Mail API is a Java
optional package, it is not part of the core
Java SE
but is included in
Java EE
and
Jakarta EE.
Q: Where can I find a version of Jakarta Mail for my favorite
operating system?
A: Jakarta Mail is completely written in Java and will run on
any operating system that supports the required version of the JDK.
No special version is needed for different operating systems.
Q: Do the Jakarta Mail APIs work in web browsers?
A: Jakarta Mail will work in any browser that supports the
required JDK version.
The
Java Plug-in may be required to provide such support.
Q: Can I use Jakarta Mail to read mail from my web mail account
(such as Yahoo or Hotmail)?
A: It depends. Many web-based email services provide access only
using a browser with HTTP. These services cannot be accessed using Jakarta Mail.
If the service also provides POP3 or IMAP access, Jakarta Mail can probably
be used to access it.
Contact your web email service provider for details.
Another helpful tool is MrPostman, a proxy server that provides POP3 access
to Hotmail and Yahoo! Mail, available at
http://sourceforge.net/projects/mrpostman/
Q: What is IMAP?
A: IMAP stands for Internet Message Access Protocol. It is a
method of accessing electronic mail messages stored on a (possibly shared)
mail server. In other words, it permits a "client" email program to
access remote message stores as if they were local. IMAP is defined
by RFC2060.
Q: What is SMTP?
A: SMTP stands for Simple Mail Transfer Protocol. It is used
to transfer RFC822-style messages between different mail hosts as
well as to submit new messages to a host for delivery. SMTP is in
very wide use (it originated in 1982) and is defined by
RFC821.
Q: What is MIME?
A: MIME and
RFC822
are the standards for describing email
messages that are sent across the Internet. The javax.mail.internet
subpackage (which is part of the Jakarta Mail APIs) provides a complete
implementation of these two packages. MIME is specified by the
following RFCs: RFC2045,
RFC2046,
RFC2047.
Q: What is POP3?
A: POP3 stands for Post Office Protocol version 3.
POP3 is a very limited protocol for accessing a single mailbox.
It is much less capable than IMAP.
POP3 is very widely used and is defined by
RFC1939.
Q: What about support for MAPI, NNTP, Lotus Notes,
and other service providers?
A: We have no current plans to implement any of these
providers. However, the architecture of the Jakarta Mail APIs provides
for being able to easily plug-in third-party service providers. It is
our hope that third-parties will embrace the Jakarta Mail APIs by writing
providers for other standard and proprietary protocols.
See our Third Party Products page
for the latest list of such providers.
Q: How do I store mail messages on my local disk?
A: A "local store provider" can be used to store mail messages
on a local disk. The Jakarta Mail API download does not include such a provider
but a provider that supports the Unix mbox format is available in the Jakarta Mail
source repository that you can build yourself. See
this page
for details.
In addition, several local store providers are available from third parties
for different local store formats such as MH and Mbox.
See our Third Party Products page
for the latest list of such providers.
Q: Where do I find documentation on the protocol providers?
A: The protocol providers for IMAP, POP3, and SMTP support
many features that are not part of the Jakarta Mail API specification. The
documentation for these protocol providers is included in the Jakarta Mail
javadocs. The package level documentation for each protocol provider
package describes the properties that are supported by the protocol
proivder. In addition, the protocol providers include some classes and
methods that applications can use to take advantage of
provider-specific features. Note that use of these properties,
classes, and methods renders a program non-portable; it may
only work with Oracle's implementation of the Jakarta Mail API.
See the
IMAP,
POP3, and
SMTP package
javadocs for details.
Q: Is the Jakarta Mail API implementation completely free?
Can I ship it along with my product?
A: Yes. The Jakarta Mail API implementation
is completely free and open source and you can include it in your product.
This release includes IMAP, POP3, and SMTP providers as well. Please do
read the license and ensure that you understand it.
The Jakarta Mail license is described
here.
Q: Can I get the source code for the Jakarta Mail API
implementation?
A: Starting with Jakarta Mail 1.4.2, the source code for the
Jakarta Mail API
Reference Implementation is available under the CDDL or GPL open source licenses
in the Jakarta Mail project.
Q: Is Jakarta Mail Y2K compliant?
A: Yes. Oracle's Jakarta Mail implementation is Option-3 Y2K compliant. Please
see the NOTES.txt
file in the Jakarta Mail package for more information.
Q: The answer to my question isn't here, where else should I look?
A: In addition to the Jakarta Mail API spec and javadocs
(available from
our main web page),
don't forget to check the
README.txt and
NOTES.txt files
for additional important information.
You can reach the Jakarta Mail team directly at
mail-dev@eclipse.org.
You can use this address to report bugs.
Bugs can also be reported using the Issue Tracker at the
Jakarta Mail project.
The Oracle Technology Network maintains a Jakarta Mail forum, see the
Jakarta Mail Forum.
jGuru also maintains a Jakarta Mail FAQ, which you'll find at
http://www.jguru.com/faq/Jakarta Mail,
although it hasn't been updated in several years.
Installation and Configuration
Q: How do I install the Jakarta Mail API implementation?
A: Download the
[Jakarta Mail jar file](https://github.com/eclipse-ee4j/mail/releases/download/1.6.4/jakarta.mail.jar)
and edit your CLASSPATH environment variable to include the jakarta.mail.jar file.
You will also need an implementation of the
JavaBeans Activation Framework (see below) unless you're using JDK 1.6
through JDK 10 (which includes JAF).
See the README.txt file
for additional details and examples,
as well as the following FAQ entry.
Q: I get a ClassNotFoundException when I run my program.
A: You haven't set CLASSPATH properly. See
Setting the class path (Windows) or
Setting the class path (Solaris/Linux) in the JDK documentation.
Note that if you're running your program using "java -jar", the CLASSPATH
environment variable setting is ignored. In that case you'll need to
add the "-classpath" argument to the java command, or add the
Class-Path
header to the manifest file of your jar file.
See the
Java Tutorial
and this
Wikipedia article
for more information.
Q: I get a ClassNotFoundException for a javax.activation class
when I run my program on JDK 9 or 10.
A: JDK 9 and 10 hide many of the javax.* classes by default.
You need to use the java command line option
--add-modules java.activation
to enable access the the javax.activation (JAF) classes.
(Note that there's no "x" in the module name.)
Or, you need to include the
jakarta.activation.jar
file in your CLASSPATH.
Q: How do I set my CLASSPATH on Windows?
A: Detailed instructions are available
here
Q: How do I add the Jakarta Mail library to my NetBeans Java Project?
A:
Use the Library Manager to create a library and add a reference to that library
to your project.
- Inside Netbeans, open the Library Manager (Tools > Libraries from the
main menu bar).
- Select <New Library...>
- Enter a library name, e.g., "Jakarta Mail", and hit <OK>. Do not
check server library.
- Make sure the new library is selected under "Libraries" on the left.
- Select the "Classpath" tab on the right and choose
<Add Jar/Folder...>
- Using the file browser, select the jakarta.mail.jar that you downloaded,
and hit <Add Jar/Folder> to accept.
- Select the "Javadoc" tab and choose <Add ZIP/Folder...>
- Using the file browser, select the folder where the Jakarta Mail javadoc
index files are, and hit <Add ZIP/Folder> to accept.
- If you downloaded the Jakarta Mail source code, you
can set the source code reference on the "Sources" tab. This can be helpful
for debugging. Using the file browser, select the source root for the
Jakarta Mail sources and hit <Add Jar/Folder> to accept.
Note: If you are using JDK 1.5.0 or earlier you will need to add the
JavaBeans Activation Framework
library as well. You can create a separate library in a manner similar to
the above, or just add activation.jar (and javadoc/source references
if desired) to this library definition.
Now add a reference to this library to your project.
- Open your project in NetBeans and make sure the "Projects" tab is
visible.
- Right click your project in the project explorer and select
"Properties"
- In the Properties dialog, select "Libraries" in the tree on the left
and make sure the "Compile" tab is selected.
- Click <Add Library...>
- Locate and select the library you created above and
click "Add Library". It should be added to the list of compile-time
libraries.
- Click "OK" and you're done.
Q: How do I add the Jakarta Mail library to my Eclipse Java Project?
A:
Create a "user library" for Jakarta Mail and add a reference to that library to
your project.
- From the Eclipse main menu, open Window > Preferences
- Open the tree to Java > Build Path > User Libraries and select
the <User Libraries> node.
- Choose <New...> from the panel on the right
- In the new library dialog, enter a user library name, e.g. "Jakarta Mail",
and hit <OK>. Do not check system library.
- Make sure the new library is selected and choose <Add Jars...>
- Browse to where Jakarta Mail is installed and select jakarta.mail.jar
- Select <Javadoc location: (None)> and hit <Edit...> to
add a reference to the javadoc location. This can be found at docs/javadocs
under the same folder where you installed Jakarta Mail.
- You can also set the source code reference here if you downloaded the
Jakarta Mail source code. Use
".../jakartamail-1.6.4/mail/src/main/java" as the source root for 1.6.4.
- Choose <OK> to close the Preferences dialog. Jakarta Mail is now
installed as a Library in Eclipse.
Note: If you are using JDK 1.5.0 or earlier you will need to add the
JavaBeans Activation Framework
library as well. You can create a separate library in a manner similar to
the above, or just add activation.jar (and javadoc/source references
if desired) to this library definition.
Now use the Jakarta Mail library in your Eclipse Java Project (Eclipse 3.4)
- Open your project in Eclipse and be in the Java Perspective
- Right click your project in the project explorer and select
"Build Path > Configure Build Path..."
- In the Properties dialog that opens, ensure Java Build Path is selected
in the tree on the left and select the Libraries tab on the right
- Click <Add Library...>
- Select "User Library", then click <Next>
- Locate and select the Jakarta Mail library added in the previous step,
click "Finish", and you're done.
This article
explains how to make the Jakarta Mail source code available to your Eclipse project.
Q: Does Jakarta Mail include all the necessary mail servers?
A: No, the Jakarta Mail API package does not include any mail servers.
To use the Jakarta Mail API package, you'll need to have access to an IMAP
or POP3 mail server (for reading mail) and/or an SMTP mail server (for
sending mail).
These mail servers are usually provided by your Internet Service Provider
or are a part of your organization's networking infrastructure.
If you don't have access to such a mail server, see below.
Q: Where can I get the necessary mail servers?
A:
The University of Washington IMAP server supports multiple platforms
(UNIX, Windows 32bit, etc).
Get the source code from
http://www.washington.edu/imap/.
There are several free, all Java mail servers available, including
Apache James and
Java Email Server.
Sendmail is a popular (non-Java) SMTP server.
SubEthaSMTP
is a Java library for implementing SMTP server functionality;
their web page also references other mail servers.
Many other vendors provide mail servers supporting Internet standards.
There are also many free, public mail servers that support the required
mail protocols such as Gmail, Yahoo! Mail, Hotmail, etc.
Q: What host name, user name, or password should I use?
A: We do not provide a mail server for you to use. You must use your
own mail server, or one provided by your Internet Service Provider
or the company you work for. Your network administrator can give you
the information necessary to configure Jakarta Mail to work with your mail server.
Q: How do I configure Jakarta Mail to work through my proxy server?
A: Starting with Jakarta Mail 1.6.0, Jakarta Mail supports accessing
mail servers through a web proxy server.
Set the "mail.protocol.proxy.host" and "mail.protocol.proxy.port"
properties for the proxy server.
Proxy server BASIC authentication is supported by setting the
"mail.protocol.proxy.user" and "mail.protocol.proxy.password"
properties.
In addition, if your proxy server supports the SOCKS V4 or V5 protocol
(http://www.socks.nec.com/aboutsocks.html,
RFC1928)
and allows anonymous connections, and
you're using JDK 1.5 or newer and Jakarta Mail 1.4.5 or newer, you can
configure a SOCKS proxy on a per-session, per-protocol basis by setting the
"mail.smtp.socks.host" property as described in the javadocs for the
com.sun.mail.smtp package.
Similar properties exist for the "imap" and "pop3" protocols.
Authentication for SOCKS servers is supported by the JDK by setting the
"java.net.socks.username" and "java.net.socks.password" System properties
(and thus apply to all SOCKS connections) as describe in the
JDK Networking
Properties documentation.
If you're using older versions of the JDK or Jakarta Mail, you can tell the Java
runtime to direct all TCP socket connections to the SOCKS server.
See the
Networking Properties guide
for the latest documentation of the socksProxyHost
and
socksProxyPort
properties. These are system-level properties,
not Jakarta Mail session properties. They can be set from the command line
when the application is invoked, for example:
java -DsocksProxyHost=myproxy ...
.
This facility can be used to direct the SMTP, IMAP, and POP3
communication from Jakarta Mail to the SOCKS proxy server. Note that
setting these properties directs all TCP sockets to the SOCKS
proxy, which may have negative impact on other aspects of your
application.
When using older versions of Jakarta Mail, and without such a SOCKS server,
if you want to use Jakarta Mail to access mail servers
outside the firewall indirectly, you might be able to use a program such as
connect
to tunnel TCP connections through an HTTP proxy server.
Configure Jakarta Mail to use the connect instance as the SOCKS server.
Q: When connecting to my mail server over SSL I get an exception like
"unable to find valid certification path to requested target".
A:
The full exception might look like:
javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
.
Your server is probably using a test certificate or self-signed
certificate instead of a certificate signed by a commercial Certificate
Authority.
You'll need to install the server's certificate into your trust store.
The
InstallCert program will help.
A
newer version of InstallCert is available here.
Alternatively, you can set the "mail.protocol.ssl.trust" property
to the host name of your mail server. See the javadocs for the protocol
provider packages for details.
Other common causes of this problem are:
- There's a firewall or anti-virus program intercepting your request.
- There's something wrong in your JDK installation preventing it from finding
the certificates for the trusted certificate authorities.
- You're running in an application server that has overridden the JDK's list
of trusted certificate authorities.
Q: While trying to run my program on Linux I get a very strange
error message and the program fails. What did I do wrong?
A: The error message often looks something like this:
Exception in thread "main"
java.lang.VerifyError:(Class:com/sun/mail/pop3/POP3Store,
method: finalize Signature :()V)
Illegal use of nonvirtual function call
The problem is due to a buggy version of the unzip command used to unzip
the Jakarta Mail download package on Linux. The unzip command corrupts the
jakarta.mail.jar file. Get a newer version of the unzip command, or use the
JDK's jar command to unzip the package.
Q: How do I use Jakarta Mail in an application run under a SecurityManager;
what permissions must I grant to the application and to Jakarta Mail?
A: When using Jakarta Mail in an environment with a
SecurityManager, Jakarta Mail will sometimes fail to read the configuration
files in the jakarta.mail.jar file. The JavaBeans Activation Framework may
have the same problem reading configuration files from the jakarta.activation.jar
file. These default configuration files are stored as "resource" files
in the META-INF directory in the jar file.
There are a number of debugging techniques that can be used to determine
if this is the problem. Setting the Session property "mail.debug" to
true (or calling session.setDebug(true)
) will cause Jakarta Mail
to print debugging messages as it attempts to load each configuration
file. A message of the form "DEBUG: can't load default providers file"
indicates that this problem might exist. Similarly, setting the System
property "javax.activation.debug" to "true" (e.g., by running the
program using "java -Djavax.activation.debug=true ...") will cause JAF
to print debugging messages as it attempts to load each resource file.
Finally, the JDK can produce helpful debugging output by setting the
system property "java.security.debug" to "access:failure" (e.g., by
running the program using "java -Djava.security.debug=access:failure ...").
The command java -Djava.security.debug=help
will display
other security debugging options.
In addition to the permissions necessary to read the configuration files,
the application (and Jakarta Mail) will also need permission to connect to the
mail servers it uses. If the application uses System properties to
configure Jakarta Mail (e.g., by passing the Properties object returned from
System.getProperties()
to the Session constructor, as many
of the Jakarta Mail demo programs do), it will also need permission to use
the System Properties object. Alternatively, the application can use
its own Properties object and be sure to set the "mail.from" property
or the "mail.user" and "mail.host" properties (see the
InternetAddress.getLocalAddress() method).
To allow an application to use Jakarta Mail under a SecurityManager,
the application, Jakarta Mail, and JAF will need permissions such as the
following (be sure to replace the host and path names with appropriate
values); add these to the security policy file used by the application:
grant {
// following two permissions allow
// access to default config files
permission java.io.FilePermission
"/path/to/jakarta.mail.jar", "read";
permission java.io.FilePermission
"/path/to/activation.jar", "read";
// following to use SMTP
permission java.net.SocketPermission
"SMTPHOST:25", "connect,resolve";
// following to use IMAP
permission java.net.SocketPermission
"IMAPHOST:143", "connect,resolve";
// following to use POP3
permission java.net.SocketPermission
"POP3HOST:110", "connect,resolve";
// following needed if System.getProperties() is used
permission java.util.PropertyPermission
"*", "read,write";
};
If you don't want to give the application read/write permission to
System properties, but you still want to be able to use System properties
to configure the application, you can give the application only "read"
permission to System properties and use the following approach:
Properties props = (Properties)System.getProperties().clone();
props.put("mail.smtp.host", "whatever");
// set as properties as needed
Session session = Session.getInstance(props, null);
Q: How do I configure Tomcat to allow me to use Jakarta Mail in my
web application?
A:
To run a web application using Jakarta Mail, you can add the Jakarta Mail
jakarta.mail.jar file and, if you're not using JDK 1.6 or newer, the JavaBeans
Activation Framework
jakarta.activation.jar
file to the lib directory under the
directory in which you installed Tomcat. This will cause Tomcat to
include these jar files in its classpath automatically.
For details, see
JNDI Resources HOW-TO in the Tomcat documentation.
Alternatively, you can package the jakarta.mail.jar file and jakarta.activation.jar
files in the lib directory of your web application package (war file).
Q: When using Jakarta Mail in my servlet, it is unable to find any of
the Jakarta Mail classes. I've added jakarta.mail.jar to the server's CLASSPATH.
A: It is often necessary to completely restart the web server
when changing the CLASSPATH.
Q: I'm sure I've set my CLASSPATH correctly, but I'm still getting
complaints about classes that can't be found, such as com.sun.mail
classes.
A: The most common cause of problems like this is having more than
one copy of jakarta.mail.jar in your CLASSPATH or available to your application.
In addition to checking your CLASSPATH setting, also look for copies in
the jre/lib/ext
directory of your JDK installation.
If you're running in a web server or application server, it may be
providing its own version of jakarta.mail.jar in one of its directories.
You should only have one version of jakarta.mail.jar available to your
application.
Q: My servlet can find the Jakarta Mail classes, but Jakarta Mail complains
that it can't find a service provider for "smtp" or "imap" or address
type "rfc822".
A: Usually this is because Jakarta Mail can't access the configuration
files in jakarta.mail.jar, possibly because of a security permission problem;
see this item for more details.
Also, make sure that you haven't extracted the jakarta.mail.jar contents;
you should include the unmodified jakarta.mail.jar file in the server's CLASSPATH.
Q: How do I access Gmail with Jakarta Mail?
A:
Jakarta Mail is capable of sending and reading messages using Gmail.
All that's required is to properly configure Jakarta Mail. I'll
illustrate the proper configuration using the
demo programs that come with Jakarta Mail -
msgshow.java
and smtpsend.java
.
You can use these programs for basic testing to ensure that
your networking is working properly, that you can connect to
the servers, that your username and password are correct, etc.
This is important when debugging problems to determine whether
the bug is in your code or is elsewhere.
Note that you'll need to configure your Gmail account to
enable less secure apps, or you'll need to use
OAuth2 authentication
(which is somewhat more complex).
Let's assume your Gmail username is "user@gmail.com" and your
password is "passwd".
To read mail from your Gmail Inbox, invoke msgshow as follows:
java msgshow -D -T imaps -H imap.gmail.com -U user -P passwd
By reading the msgshow.java
source code, you can see how these
command line arguments are used in the Jakarta Mail API. You should
first try using msgshow as shown above, and once that's working
move on to writing and configuring your own program to use Gmail.
The following code fragment shows a simple way to incorporate the
needed configuration in your application:
String host = "imap.gmail.com";
String username = "user";
String password = "passwd";
Properties props = new Properties();
props.setProperty("mail.imap.ssl.enable", "true");
// set any other needed mail.imap.* properties here
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
store.connect(host, username, password);
To connect to Gmail using the POP3 protocol instead of the IMAP protocol,
simply change the host name "imap.gmail.com" to "pop.gmail.com" and change
"imap" to "pop3" in the property name and protocol name in the above
instructions.
To send a message through Gmail, invoke smtpsend as follows:
java smtpsend -d -S -A -M smtp.gmail.com -U user -P passwd someone@example.com
The smtpsend program will prompt for a subject and message body text.
End the message body with ^D on UNIX or ^Z on Windows.
Again, you can read the smtpsend.java
source code to see how the
command line arguments are used in the Jakarta Mail API.
The following code fragment shows a simple way to incorporate the
needed configuration in your application:
String host = "smtp.gmail.com";
String username = "user";
String password = "passwd";
Properties props = new Properties();
props.setProperty("mail.smtp.host", host);
props.setProperty("mail.smtp.ssl.enable", "true");
// set any other needed mail.smtp.* properties here
Session session = Session.getInstance(props);
MimeMessage msg = new MimeMessage(session);
// set the message content here
Transport.send(msg, username, password);
There is, of course, more than one way to use the Jakarta Mail API to accomplish
the same goal. This should help you understand the essential
configuration parameters necessary to use Gmail.
Q: Why do I get AuthenticationFailedException when
accessing Gmail?
A:
Most likely you failed to
enable less secure apps.
Q: Why don't I see all my messages when accessing Gmail with POP3?
A:
Gmail has settings that control which of your messages are available via
the POP3 protocol. See the
Gmail settings page to change the configuration of your Gmail account.
Q: Why doesn't search find all the messages I expect when accessing
Gmail with IMAP?
A:
Gmail does not fully support all IMAP features. For details see
this Gmail Help page.
Q: How do I delete a message in Gmail?
A:
Gmail does not follow the normal IMAP conventions for deleting messages.
Marking a message as deleted and then expunging the folder simply removes
the current folder's "label" from the message. The message will still
appear in the "[Gmail]/All Mail" folder.
To delete a message, copy the message to the "[Gmail]/Trash" folder,
which will immediately remove the message from the current folder.
To permanently remove a message, open the "[Gmail]/Trash" folder,
mark the message deleted (msg.setFlag(Flags.Flag.DELETED, true);
),
and expunge the folder (folder.close(true);
).
Q: How do I access Yahoo! Mail with Jakarta Mail?
A:
Jakarta Mail is capable of sending and reading messages using Yahoo! Mail.
All that's required is to properly configure Jakarta Mail. I'll
illustrate the proper configuration using the
demo programs that come with Jakarta Mail -
msgshow.java
and smtpsend.java
.
Let's assume your Yahoo! Mail username is "user@yahoo.com" and your
password is "passwd".
To read mail from your Yahoo! Mail Inbox, invoke msgshow as follows:
java msgshow -D -T imaps -H imap.mail.yahoo.com -U user@yahoo.com -P passwd
By reading the msgshow.java
source code, you can see how these
command line arguments are used in the Jakarta Mail API. You should
first try using msgshow as shown above, and once that's working
move on to writing and configuring your own program to use Yahoo! Mail.
The code fragment shown above for connecting to Gmail will also work for
connecting to Yahoo! Mail by simply changing the host name.
To send a message through Yahoo! Mail, invoke smtpsend as follows:
java smtpsend -d -S -A -M smtp.mail.yahoo.com -U user@yahoo.com -P passwd someone@example.com
The smtpsend program will prompt for a subject and message body text.
End the message body with ^D on UNIX or ^Z on Windows.
Again, you can read the smtpsend.java
source code to see how the
command line arguments are used in the Jakarta Mail API. The code fragment shown
above for connecting to Gmail will also work for connecting to Yahoo! Mail
by simply changing the host name.
There is, of course, more than one way to use the Jakarta Mail API to accomplish
the same goal. This should help you understand the essential
configuration parameters necessary to use Yahoo! Mail.
Also see the Yahoo! Mail help page
POP server settings for Yahoo Mail
Q: How do I access Hotmail (Windows Live mail) with Jakarta Mail?
A:
Jakarta Mail is capable of sending and reading messages using Hotmail.
All that's required is to properly configure Jakarta Mail. I'll
illustrate the proper configuration using the
demo programs that come with Jakarta Mail -
msgshow.java
and smtpsend.java
.
Let's assume your Hotmail username is "user@hotmail.com" and your
password is "passwd".
To read mail from your Hotmail Inbox, invoke msgshow as follows:
java msgshow -D -T pop3s -H pop3.live.com -U user@hotmail.com -P passwd
By reading the msgshow.java
source code, you can see how these
command line arguments are used in the Jakarta Mail API. You should
first try using msgshow as shown above, and once that's working
move on to writing and configuring your own program to use Hotmail.
The code fragment shown above for connecting to Gmail will also work for
connecting to Hotmail by simply changing the host name.
To send a message through Hotmail, invoke smtpsend as follows:
java -Dmail.smtp.starttls.enable=true -Dmail.smtp.port=587
smtpsend -d -A -M smtp.live.com
-U user@hotmail.com -P passwd someone@example.com
(Note that I split the command over three lines for display, but you
should type it on one line.)
The smtpsend program uses the System properties
when creating the Jakarta Mail Session, so the properties set on the
command line will be available to the Jakarta Mail Session.
The smtpsend program will prompt for a subject and message body text.
End the message body with ^D on UNIX or ^Z on Windows.
Again, you can read the smtpsend.java
source code to see how the
command line arguments are used in the Jakarta Mail API. The code fragment shown
above for connecting to Gmail will also work for connecting to Hotmail
by simply changing the host name and changing the connect call to
t.connect(host, 587, username, password)
.
There is, of course, more than one way to use the Jakarta Mail API to accomplish
the same goal. This should help you understand the essential
configuration parameters necessary to use Hotmail.
For more details, search
Windows Live Hotmail help for "POP3".
Q: How do I access Outlook.com with Jakarta Mail?
A:
Jakarta Mail is capable of sending and reading messages using Outlook.com.
All that's required is to properly configure Jakarta Mail. I'll
illustrate the proper configuration using the
demo programs that come with Jakarta Mail -
msgshow.java
and smtpsend.java
.
Let's assume your Outlook.com username is "user@outlook.com" and your
password is "passwd".
To read mail from your Outlook.com Inbox, invoke msgshow as follows:
java msgshow -D -T imaps -H imap-mail.outlook.com -U user@outlook.com -P passwd
By reading the msgshow.java
source code, you can see how these
command line arguments are used in the Jakarta Mail API. You should
first try using msgshow as shown above, and once that's working
move on to writing and configuring your own program to use Outlook.com.
The code fragment shown above for connecting to Gmail will also work for
connecting to Outlook.com by simply changing the host name.
To connect to Outlook.com using the POP3 protocol instead of the IMAP protocol,
simply change the host name "imap-mail.outlook.com" to "pop-mail.outlook.com"
and change the protocol name "imaps" to "pop3s" in the above instructions.
To send a message through Outlook.com, invoke smtpsend as follows:
java -Dmail.smtp.starttls.enable=true
smtpsend -d -A -M smtp-mail.outlook.com
-U user@outlook.com -P passwd someone@example.com
(Note that I split the command over three lines for display, but you
should type it on one line.)
The smtpsend program uses the System properties
when creating the Jakarta Mail Session, so the properties set on the
command line will be available to the Jakarta Mail Session.
The smtpsend program will prompt for a subject and message body text.
End the message body with ^D on UNIX or ^Z on Windows.
Again, you can read the smtpsend.java
source code to see how the
command line arguments are used in the Jakarta Mail API.
The following code fragment shows a simple way to incorporate the
needed configuration in your application:
String host = "smtp-mail.outlook.com";
String username = "user@outlook.com";
String password = "passwd";
Properties props = new Properties();
props.setProperty("mail.smtp.host", host);
props.setProperty("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(props);
MimeMessage msg = new MimeMessage(session);
// set the message content here
Transport.send(msg, username, password);
There is, of course, more than one way to use the Jakarta Mail API to accomplish
the same goal. This should help you understand the essential
configuration parameters necessary to use Outlook.com.
For more details, see the
Outlook Blog.
Programming
Q: Where can I learn the basics about Internet email that
I'll need to know to program Jakarta Mail effectively?
A: See one of the
books
referenced on our web page for a good background on Internet email, MIME,
SMTP, IMAP, POP3, etc.
Q: Where can I find some example programs that show how to use Jakarta Mail?
A: There are many example programs available for download
on the
Jakarta Mail project page,
including simple command line programs illustrating various aspects of
the Jakarta Mail API, a Swing-based GUI application, a simple servlet-based
application, and a complete web application using JSP pages and a tag
library.
Q: What are some of the most common mistakes people make
when using Jakarta Mail?
A: Unfortunately, the internet is full of copy and paste
programmers who don't understand the code they're using, which has resulted
in a lot of unnecessarily complex and often incorrect examples.
The most common mistakes are:
-
Use of
Session.getDefaultInstance
.
Almost all code should use Session.getInstance
instead,
as described below
-
Calling the
send
method on a Transport instance variable.
As described below, send
is a static
method and ignores the Transport instance you use to call it.
-
Setting various
socketFactory
properties.
Long, long ago Jakarta Mail didn't have built in support for SSL connections,
so it was necessary to set these properties to use SSL.
This hasn't been the case for years; remove these properties and simplify
your code.
The easiest way to enable SSL support in current versions of Jakarta Mail is
to set the property "mail.smtp.ssl.enable" to "true".
(Replace "smtp" with "imap" or "pop3" as appropriate.)
-
Using an Authenticator just to supply a username and password.
There's really nothing wrong with using an Authenticator, it's just
unnecessarily complex.
A more straightforward approach is to call the
connect
method that takes a username and password when connecting to a Store.
When sending a message, use the static Transport.send
method
that takes a username and password.
Q: How do I send a message with an attachment?
A: A message with attachments is represented as a
MIME multipart message where the first part is the main body of the
message and the other parts are the attachments.
There are numerous examples showing how to construct such a message
in the demo programs included in the Jakarta Mail download package.
To attach a file use the
attachFile
method of MimeBodyPart
.
Q: How do I tell if a message has attachments?
A: In the simplest case, a message of MIME type
multipart/mixed
with more than one body part is likely
a message with attachments. As described above, there are more complex
cases to consider as well. In particular, messages may have arbitrary
nesting of multipart/mixed
and multipart/alternative
parts and may include multipart/related
parts for embedded
HTML and multipart/signed
and/or multipart/encrypted
parts for secure messages. It's up to you to decide how many of these
cases you want to handle in your application before deciding that a
message has an attachment. Most applications take a very simple approach
to this and handle only a few of the most commonly seen cases.
Note that while it's recommended that attachments have a Content-Disposition
of "ATTACHMENT", and will usually have a file name, these are not requirements.
Some messages with attachments will have only one or none of these. Looking
for attachments by looking for a body part with these set will fail in some
cases.
In the simplest case, here's how to tell if a message has attachments:
boolean hasAttachments(Message msg) throws MessagingException {
if (msg.isMimeType("multipart/mixed")) {
Multipart mp = (Multipart)msg.getContent();
if (mp.getCount() > 1)
return true;
}
return false;
}
Q: How do I read a message with an attachment and save the
attachment?
A: As described above, a message with an attachment is
represented in
MIME as a multipart message. In the simple case, the results of the
Message
object's getContent
method will be a
MimeMultipart
object. The first body part of the multipart
object wil be the main text of the message. The other body parts will
be attachments. The msgshow.java
demo program shows how
to traverse all the multipart objects in a message and extract the data
of each of the body parts. The getDisposition
method will
give you a hint as to whether the body part should be displayed inline
or should be considered an attachment (but note that not all mailers
provide this information). So to save the contents of a body part in a file,
use the saveFile
method of MimeBodyPart
.
To save the data in a body part into a file (for example), use the
getInputStream
method to access the attachment content and
copy the data to a FileOutputStream
.
Note that when copying the data you can not use the
available
method to determine how much data is in the
attachment. Instead, you must read the data until EOF.
The saveFile
method of MimeBodyPart
will
do this for you.
However, you should not use the results of the getFileName
method directly to name the file to be saved; doing so could cause you
to overwrite files unintentionally, including system files.
Note that there are also more complicated cases to be handled as well.
For example, some mailers send the main body as both plain text and
html. This will typically appear as a multipart/alternative
content (and a MimeMultipart
object) in place of a simple
text body part. Also, messages that are digitally signed or encrypted
are even more complex. Handling all these cases can be challenging.
Please refer to the various MIME specifications and other
resources listed on our main page.
Q: How do I find the main message body in a message that has
attachments?
A: The following approach will handle the most common cases.
Handling improperly formatted messages, messages with unknown charsets,
and signed or encrypted messages, can make this much more complex.
private boolean textIsHtml = false;
/**
* Return the primary text content of the message.
*/
private String getText(Part p) throws
MessagingException, IOException {
if (p.isMimeType("text/*")) {
String s = (String)p.getContent();
textIsHtml = p.isMimeType("text/html");
return s;
}
if (p.isMimeType("multipart/alternative")) {
// prefer html text over plain text
Multipart mp = (Multipart)p.getContent();
String text = null;
for (int i = 0; i < mp.getCount(); i++) {
Part bp = mp.getBodyPart(i);
if (bp.isMimeType("text/plain")) {
if (text == null)
text = getText(bp);
continue;
} else if (bp.isMimeType("text/html")) {
String s = getText(bp);
if (s != null)
return s;
} else {
return getText(bp);
}
}
return text;
} else if (p.isMimeType("multipart/*")) {
Multipart mp = (Multipart)p.getContent();
for (int i = 0; i < mp.getCount(); i++) {
String s = getText(mp.getBodyPart(i));
if (s != null)
return s;
}
}
return null;
}
You can call the getText
method with a Message
object (which is a Part
).
Q: How do I find the attachments in a message?
A:
There's a wide variety of possible MIME structures for email. A general
solution can be quite complex since it would need to take into account
signed and encrypted messages, among other issues. Different mailers
will use different MIME structure, and of course some mailers will have
bugs in how they use MIME. You need to decide which cases you need to
support.
In general, multipart/alternative is used to contain different versions
of the main message body, and so can be skipped because it doesn't
contain any attachments. Typically, a message with attachments will
have a top level multipart/mixed content with the first body part
containing the main message body. The first part may be a simple text
part, a multipart/alternative with text/plain and text/html parts, or a
multipart/related with a text/html part and associated images.
Attachments will usually, but not always, have a Content-Disposition of
attachment. Attachments will usually, but not always, have a file
name.
So, a good approach to start with is to only consider messages with a
top level multipart/mixed content and then consider the parts after the
first part to be attachments whether they say so or not. And as I said
above, signed and encrypted messages will make this more complex.
Q: How do I get all the unread messages in a folder?
A: Search for all messages with the SEEN flag not set:
Message[] unreadMessages = folder.search(
new FlagTerm(new Flags(Flags.Flag.SEEN), false));
Q: Should I use the isMimeType
method,
or should I use instanceof
on the object returned by the
getContent
method, when deciding how to process a message
part?
A: It is almost always more efficient to use the
isMimeType
method.
The msgshow.java
demo program shows how to use the
isMimeType
method when traversing the parts of a message.
Q: When reading a multipart message, why is the getContent
method returning an IMAPInputStream (or SharedByteArrayInputStream) instead
of a MimeMultipart object?
A: This usually happens because the JavaBeans Activation
Framework (JAF) can't find the mailcap configuration file included in the
jakarta.mail.jar file.
JAF uses the thread's context class loader to look for the configuration file.
If the context class loader is not set properly, this can fail.
Most application servers should set the context class loader properly, but
at least some versions of Tomcat do not.
One workaround is to put the jakarta.mail.jar file in Tomcat's lib directory
instead of including it in the war file.
Another workaround is to add code such as the following to the beginning of
your application:
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
And of course you should always make sure the message you're dealing with is
a multipart message before calling the getContent method, using something like
if (msg.isMimeType("multipart/*"))
, as described
above and in this example.
Q: When I attach a file it gets a MIME type of
application/octet-stream
instead of the correct MIME type.
A: The FileDataSource
class uses the JavaBeans Activation
Framework (JAF) class MimetypesFileTypeMap
to determine the
MIME type of a file based on the extension of the filename.
The default mapping knows about only a few extensions.
You can add support for more extensions either programmatically
or by adding a META-INF/mime.types
configuration file
to your application.
For example, to map the .doc
extension to the MIME type
application/msword
, create a META-INF/mime.types
file with the single line:
application/msword doc
See the javadocs for the MimetypesFileTypeMap
class for details.
Q: How do I manually set the MIME type for an attached file,
for example in the case where the filename doesn't have an obvious extension?
A: Subclass the FileDataSource
class and override
the getContentType
method.
(Note that with this approach you can't use the attachFile
method.)
File file = new File("filename");
DataSource ds = new FileDataSource(file) {
public String getContentType() {
return "mytype/mysubtype";
}
};
MimeBodyPart mbp = new MimeBodyPart();
mbp.setDataHandler(new DataHandler(ds));
mbp.setFileName(file.getName());
mbp.setDisposition(Part.ATTACHMENT);
Q: How do I create a multipart message with a part of any
MIME type I choose?
A: The Jakarta Mail API includes builtin support for the most
common MIME types, but to create a message that includes data in
a MIME type that Jakarta Mail does not already understand, you'll
need to supply that data to Jakarta Mail in a byte stream format.
The ByteArrayDataSource
class in the javax.mail.util
pacakge in Jakarta Mail 1.4 and later, or included in source code in the demo
directory of older versions of the Jakarta Mail download package, can help.
This class
will take a String
, byte array, or InputStream
and create a DataSource
object that you can use as follows:
MimeBodyPart mbp = new MimeBodyPart();
String data = "any ASCII data";
DataSource ds = new ByteArrayDataSource(data, "application/x-any");
mbp.setDataHandler(new DataHandler(ds));
You can specify any MIME type that you want. The MimeBodyPart
object can then be added to a MimeMultipart
object in the
usual way.
Note that if you create a ByteArrayDataSource
with an
InputStream
, it first copies all of the data in the stream
into memory. This is necessary because a DataSource
needs
to be able to supply multiple InputStream
objects so that
Jakarta Mail can read the data once to determine what
Content-Transfer-Encoding is appropriate, and then read the data again
to include the data in the message.
Q: Can I read or send a Microsoft Office document using
Jakarta Mail?
A: Jakarta Mail can read a Microsoft Office document as an
attachment and save that document in a file. Likewise, Jakarta Mail can attach a
Microsoft Office document to a message and send it as an attachment.
Use the MimeBodyPart
saveFile and
attachFile methods.
To process the content of a Microsoft Office document you'll need a
separate library such as
Apache POI.
Q: How do I create or process calendar appointments?
A: The iCal4j project
provides an API that might be useful.
More information about how different products, such as Microsoft Outlook,
support calendar appointments is available
here.
This blog entry
might also be helpful.
Q: When should I use Session.getDefaultInstance
and when should I use Session.getInstance
?
A: Almost all code should use Session.getInstance
.
The Session.getDefaultInstance
method creates a new Session the
first time it's called, using the Properties that are passed.
Subsequent calls will return that original Session and ignore any
Properties you pass in.
If you want to create different Sessions with different properties,
Session.getDefaultInstance
won't do that.
If some other code in the same JVM (e.g., in the same app server) has already
created the default Session with their properties, you may end up using their
Session and your properties will be ignored.
This often explains why your property settings seem to be ignored.
Always use Session.getInstance
to avoid this problem.
Q: What is "disconnected support"?
A: A mail client supporting disconnected operation will allow
the user to access messages in a remote message store (e.g.,
IMAP), cache (parts of) some of those messages locally, and
break the connection to the server. While in this disconnected
state, the mail client can access the messages that have been
cached, possibly deleting them or saving them to other folders.
When the mail client next connects to the remote message store,
the changes made locally will be synchronized with the remote
store. Similarly, disconnected support may allow the client
to "send" messages when there is no connection to the server, with
the messages being queued until a connection to the server is
available. See also
RFC 1733 and
RFC 4549.
Q: How do I support disconnected operation using the
Jakarta Mail APIs?
A: The Jakarta Mail API specification defines interfaces that can
be used by a mail client to support disconnected operation.
Our IMAP provider implements these interfaces (the UIDFolder interfaces).
Q: How do I send secure email using the Jakarta Mail APIs?
A: The Jakarta Mail APIs currently have no support for sending
or receiving secure email. The architecture of the
Jakarta Mail APIs allows such support to be easily added later,
by us or by third parties.
Please browse our
Third Party Products
page for solutions from other vendors.
The most popular third party solution is the
Bouncy Castle library.
Q: The writeTo()
method generates message text
with lines that are neither the canonical MIME representation of the data
(i.e., using CRLF to terminate lines), nor using the canonical line
separator of my platform (e.g., "\n" on UNIX). How do I get either
of these representations if I need them?
A: In either case you'll need to create an appropriate
FilterOutputStream to hand to writeTo()
. The
FilterOutputStream will need to accept lines with any of the common
line terminators and write out lines with only the desired line
terminator. The following are examples of such filters.
NewlineOutputStream
converts to the local platform's line terminator and is useful when
writing a message to a file.
CRLFOutputStream
converts to the MIME canonical CRLF line terminator and is useful
when the canonical MIME format is needed (e.g., to compute a digital
signature).
Q: Can I use the Jakarta Mail APIs to implement a
mail server?
A: The Jakarta Mail APIs were not intended to help you implement a
mail server.
Nonetheless, some of the utility classes, such as the MIME
message parsing classes, might be of use to you.
In general you'll find that the Jakarta Mail API errs on the side
of "simple" instead of "robust". That's appropriate for a mail
client, but a mail server would likely make different tradeoffs.
Q: Can I use the Jakarta Mail APIs to add new user accounts to my
mail server, remove user accounts from my mail server, or change the passwords
for user accounts on my mail server?
A: The Jakarta Mail API does not include any facilities for adding,
removing, or changing user accounts. There are no standards in this area;
every mail server handles this differently.
Q: Can I use the Jakarta Mail APIs to access my address book
on my mail server?
A: The Jakarta Mail API does not include any facilities for accessing
an address book. There are no standards in this area;
every mail server handles this differently.
If you can figure out how your server does it, you might be able
to find a Java API to access it. For example, if your server stores
address books in LDAP, you could use the JNDI API to access it.
Q: Why doesn't the MimeMessage class implement Serializable
so that I can serialize a message to disk and read it back later?
A:
The Jakarta Mail API was designed to layer on top of existing email systems,
using existing message formats. The ability to use Java serialization
was neither essential nor useful for such implementations, and thus was
not considered a goal of the Jakarta Mail API.
The hard part about serializing a Message is retaining the pointers to
the Folder, Store, and Session. If you only want to save the content
of the message, and not the object itself, the writeTo
method of a message gives you everything you need.
If you want to create an entire email system based on serialized messages,
you should be able to subclass Message et. al. and implement Serializable
in your subclass.
If you want to serialize other objects of your own that reference
MimeMessages, the writeObject
method of your object can use the
writeTo
method of MimeMessage, and the readObject
method of your object can use the MimeMessage constructor that takes an
InputStream. Your class will need to provide a Session when constructing
the MimeMessage.
Q: How do I write a Service Provider?
A: Please read the Service Provider documentation for details.
In general, if you want to write a Store provider, you subclass
javax.mail.Store
, javax.mail.Folder
, possibly
javax.mail.Message
and a few others. For a Transport
provider, you subclass javax.mail.Transport
, possibly
javax.mail.Message
and a few others. Then you add
the entry describing your provider to the javamail.providers
registry. If you're interested in writing a service provider for a protocol
or messaging system not currently supported by the Jakarta Mail API
implementation, please contact us at
mail-dev@eclipse.org.
Q: I'm having trouble logging into my Microsoft Exchange server,
even though I'm sure I'm using the correct username and password, what
could I be doing wrong?
A: When logging in to Exchange you need to use a username that's
more than your simple login name. For example, if your email address
is "J.User@server.com", your Windows NT login name is "juser", your
NT domain name is "dom", and your Exchange mailbox name is "Joe User",
then you would need to use a username of "dom\juser\J.User" when logging
in using Jakarta Mail.
Note also that there's a bug in Exchange 2007. The Exchange server
advertises that it supports AUTH=PLAIN, even though
this Exchange documentation claims that it's not supported.
This causes Jakarta Mail to choose PLAIN authentication, which will always fail.
To work around this Exchange bug, set the session property
"mail.imap.auth.plain.disable" to "true". (Change "imap" to "imaps" if
you're using the "imaps" protocol.)
Q: How do I encode a binary file before sending it and how do I
decode it when I receive it?
A: You don't need to! Jakarta Mail will automatically determine an
appropriate encoding to use for your message parts before sending the
message, and will automatically decode message parts when reading them.
The getInputStream
method will return the decoded
data.
Q: If I don't need to encode and decode attachments myself,
when should I use the MimeUtility
methods?
A: The MimeUtility
methods are useful in cases that
Jakarta Mail doesn't handle automatically for you. One such case that
occurs frequently is encoding of filenames. The base MIME spec does not
allow header parameter values (such as the filename parameter) to be
encoded in the same way that (e.g.) the Subject header may be encoded.
This restricts parameter values, and thus filenames, to ASCII. However,
some mailers actually do encode non-ASCII filenames using the MIME text
encoding. Applications that wish to interoperate with such non-standard
mailers can use the encodeText
method to encode filenames
before calling the MimeBodyPart
setFileName
method,
and can use the decodeText
method to decode returned filenames.
See also this entry below if you need to
encode filenames.
Q: I have data that's already encoded in (e.g.) base64, how do I
tell Jakarta Mail to send this data without re-encoding it?
A: Use the PreencodedMimeBodyPart
class,
new in Jakarta Mail 1.4.
Q: Even though Jakarta Mail does all the encoding and decoding for me,
I need to manually control the encoding for some body parts.
A: In the rare case that you need to control the encoding, there
are several ways to override Jakarta Mail's default behavior. A simple
approach is as follows. After creating the entire message, call
msg.saveChanges()
and then use something like
mbp.setHeader("Content-Transfer-Encoding", "base64")
to force base64 encoding for the given body part.
Another approach is to subclass MimeBodyPart
and override
the updateHeaders
method so that it first calls
super.updateHeaders()
and then sets the
Content-Transfer-Encoding
header as above.
Q: Why doesn't Jakarta Mail properly encode and decode filenames in
non-ASCII character sets?
A: The filename is stored as a parameter in MIME headers.
Encoded filenames of the form =?ISO-8859-15?B?5OTkLUluZm8ucGRm?=
are not part of the MIME spec. A filename of
the form =?A?B?C?=
is a perfectly valid filename,
not an incorrectly encoded filename. Jakarta Mail does
not encode and decode filenames by default because doing so
would violate the MIME spec.
The base MIME spec does not allow for encoding parameters.
RFC 2231 defines a new way to include encoded paramters,
including filenames, in MIME headers. It is not
compatible with the de facto way that many older applications
illegally encode filenames. Even though Jakarta Mail supports RFC 2231, that
alone does not allow Jakarta Mail to interoperate with these older
programs. Most recent email programs support RFC 2231 and Jakarta Mail
enables support for it by default starting in Jakarta Mail 1.5.
To enable RFC 2231 support in older Jakarta Mail releases for encoded parameters,
set the System properties "mail.mime.encodeparameters" and
"mail.mime.decodeparameters" to "true".
If you choose to violate the MIME spec, in order to
interoperate with other programs that also violate the
MIME spec, Jakarta Mail gives you all the tools you need to
do so. Starting with Jakarta Mail 1.4, setting the System properties
"mail.mime.encodefilename" and "mail.mime.decodefilename" to "true"
will cause Jakarta Mail to encode and decode the filename parameter
using the non-RFC 2231 MIME encoding.
Applications using earlier versions of Jakarta Mail can use the following
workaround to encode a filename:
mbp.setFileName(MimeUtility.encodeText(filename));
The workaround for decoding a filename is equally simple:
String filename = MimeUtility.decodeText(part.getFileName());
Again, this is primarily for applications using old versions of Jakarta Mail.
Most applications should never need to use these methods.
Q: Why do I get an error such as
java.net.SocketException: Permission denied: connect
when connecting to my mail server using JDK7?
A: You may be running into an issue with support for IPv6.
You can work around this problem by setting the System property
"java.net.preferIPv4Stack" to "true".
You can do this when starting your program using
"java -Djava.net.preferIPv4Stack=true ..."
Debugging
Q: How do I debug my application that uses Jakarta Mail APIs?
A: Turn on session debugging by invoking the method
setDebug(true)
on the Session object in your code. That will cause debug information to
be printed to the console, including a protocol trace.
If you passed the System properties to the Session when you created it,
you can simply run your program with java -Dmail.debug=true ...
If you think that you found a bug in Jakarta Mail,
send us this trace along with a test case that reproduces the problem,
the platform you are using, the version of the JDK you are using, and
the name and version of the mail servers (IMAP, SMTP) that you are using.
Q: How do I debug problems connecting to my mail server?
A: The first thing to do when debugging such problems is to
determine whether it's a Java problem or a networking problem.
Use telnet to try to connect to the remote system. For
example, if you're having trouble connecting to the POP3 server named
mail.example.com
, you would use:
telnet mail.example.com 110
If you're trying to connect to an SMTP server, use 25 instead of 110
for the port number. If you're trying to connect to an IMAP server
use 143 for the port number.
If you get a greeting banner you can simply disconnect.
If this works, your
networking, name service, firewall, etc. are all set up
correctly and your problem is most likely in your Java
program.
If it doesn't work, you'll need to check your networking
configuration or talk to your network administrator for help.
Sometimes a firewall installed on your local machine or on
your network will prevent you from connecting to the server.
If telnet complains that it doesn't know the host name that
you're using, most likely your name service (e.g., DNS) isn't
properly configured to resolve internet host names.
None of these problems are Jakarta Mail or Java problems.
Usually, when you get a low level SocketException
when connecting, the problem is due to your networking
configuration. Usually it's not a Java problem.
If you've succeeded in connecting with telnet, the next thing
to do is to turn on Session debugging and get the protocol
trace when Jakarta Mail tries to connect to the remote machine,
as described above.
This will often include more detailed error messages from the
server that will indicate the real source of the problem.
Q: How do I debug problems connecting to my mail server using SSL?
A: Debugging SSL problems, and in particular certificate problems,
can be difficult. The file
SSLNOTES.txt
includes some useful information. Angus Mail uses the JDK's JSSE
API to provide SSL support. You can find information about debugging
JSSE problems in the
JSSE Reference Guide.
Q: How do I debug problems with Java security permissions?
A: You can set the java.security.debug
System property
to debug problems with Java security permissions.
To get the possible values for setting that property, the following command
will print a help message: java -Djava.security.debug=help MyClass
Reading mail, IMAP
Q: I tried running your demos against my IMAP server,
but I get an error.
A: First verify that you indeed have an email account on the IMAP
server. Check with your system administrator about it.
Turn debug mode on, by invoking the method setDebug(true) on
the session object in your code. This will cause the IMAP
protocol trace to be dumped on your screen. Send us this trace.
The trace will be very useful to us for identifying the problem.
If you can, please send us vendor information about your IMAP
server.
Q: I can read messages from my IMAP server with other mail clients,
but even though I can connect to the server using Jakarta Mail, when I use
Jakarta Mail to read some messages it fails. Doesn't that mean there's a bug
in Jakarta Mail?
A: No, not usually. Most other mail clients make very little
use of the rich IMAP protocol. They use the IMAP protocol as little
more than a variant of the POP3 protocol, typically downloading the
entire message to the client and parsing it in the client. This allows
them to avoid all sorts of parsing and protocol bugs in many IMAP
servers, but of course it comes at the cost of being less efficient
because they don't take advantage of the IMAP protocol's ability to
fetch only the parts of the message that are needed. These server bugs
often manifest themselves as the following exception on the client:
javax.mail.MessagingException: Unable to load BODYSTRUCTURE
The best approach when running into server bugs of this sort is to contact
the vendor of the server and get them to fix their product. Contact
mail-dev@eclipse.org and we'll help you
pinpoint the problem so that you can report it to the server vendor.
If you can't get a fix from the server vendor, the following technique
will often allow you to work around these server bugs:
// Get the message object from the folder in the
// usual way, for example:
MimeMessage msg = (MimeMessage)folder.getMessage(n);
// Use the MimeMessage copy constructor to make a copy
// of the entire message, which will fetch the entire
// message from the server and parse it on the client:
MimeMessage cmsg = new MimeMessage(msg);
// The cmsg object is disconnected from the server so
// setFlags will have no effect (for example). Use
// the original msg object for such operations. Use
// the cmsg object to access the content of the message.
In some cases, the server may be so badly broken that loading the envelope
data is not possible, which can cause the above workaround to fail because
internally it first fetches the message flags and message size from the server.
In that case, the following approach will usually work:
// Get the message object from the folder in the
// usual way, for example:
MimeMessage msg = (MimeMessage)folder.getMessage(n);
// Copy the message by writing into a byte array and
// creating a new MimeMessage object based on the contents
// of the byte array:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
msg.writeTo(bos);
bos.close();
SharedByteArrayInputStream bis =
new SharedByteArrayInputStream(bos.toByteArray());
MimeMessage cmsg = new MimeMessage(session, bis);
bis.close();
// The cmsg object is disconnected from the server so
// setFlags will have no effect (for example). Use
// the original msg object for such operations. Use
// the cmsg object to access the content of the message.
Q: The IMAP provider seems to lose data when I fetch messages with large
attachments.
A: This is due to bugs in the partial fetch implementation of your
IMAP server. To workaround this server bug, set the
"mail.imap.partialfetch" property to "false".
Refer to NOTES.txt from
the Jakarta Mail package for more information.
Q: Does the IMAP provider cache the retrieved data?
A: The IMAP provider fetches the data for a message from the server only
when necessary. (The javax.mail.FetchProfile
can be used
to optimize this).
The header and bodystructure information, once fetched, is always
cached within the Message object. However, the content of a bodypart
is not cached. So each time the content is
requested by the client (either using getContent()
or
using getInputStream()
), a new FETCH request is issued
to the server.
The reason for this is that the content of a message could be
potentially large, and if we cache this content for a large number
of messages, there is the possibility that the system may
run out of memory soon since the garbage collector cannot free
the referenced objects.
Clients should be aware of this and must hold on to the retrieved
content themselves if needed.
Q: I want to move messages between folders. Should I use
appendMessages()
or copyMessages()
?
A: Use copyMessages()
if the messages to be copied/moved
belong to the folder on which this method is being invoked. This is because
some implementations can optimize this operation if the source
and destination folder belong to the same backend Store.
Otherwise, use appendMessages()
.
Q: Retrieving large message bodies seems inefficient at times.
A: If you are using the IMAP provider, you could try increasing
the mail.imap.fetchsize
property (the current default is 16k).
This will cause data to be fetched from the server in larger chunks.
Note that you risk the possibility of the JVM running out of memory
when you do this.
Q: I get OutOfMemory errors when loading this large binary attachement.
A: Increase the maximum JVM heapsize at startup. Use the "-mx" option
if using the standard JVM from Oracle.
Don't keep references to the "content" of messages not being used.
In certain cases, you could try streaming the message content
(using getInputStream()
) as raw bytes, use and then discard the
used data chunks.
Q: Why do I get the UnsupportedDataTypeException when I invoke
getContent()
on a bodypart?
A: The getContent()
method returns a Java object that
represents
the bodypart content. For this to work, a JAF DataContentHandler
corresponding to the content's MIME type must be registered. Otherwise, the
UnsupportedDataTypeException will be thrown. In this case, you
can use the getInputStream()
method to retrieve the content as
a stream of bytes. See the JAF docs for details on how to create
and register your own DataContentHandlers.
Q: Why do I get the UnsupportedEncodingException when I invoke
getContent()
on a bodypart that contains text data?
A: Textual bodyparts (i.e., bodyparts whose type is "text/plain",
"text/html", or "text/xml")
return Unicode String objects when getContent()
is used.
Typically,
such bodyparts internally hold their textual data in some non Unicode
charset. Jakarta Mail (through the corresponding DataContentHandler)
attempts to convert that data into a Unicode string.
The underlying JDK's charset converters are used to do this.
If the JDK does not support a particular charset, then the
UnsupportedEncodingException is thrown.
In this case, you can use the getInputStream()
method to retrieve
the content as a stream of bytes.
For example:
String s;
if (part.isMimeType("text/plain")) {
try {
s = part.getContent();
} catch (UnsupportedEncodingException uex) {
InputStream is = part.getInputStream();
/*
* Read the input stream into a byte array.
* Choose a charset in some heuristic manner, use
* that charset in the java.lang.String constructor
* to convert the byte array into a String.
*/
s = convert_to_string(is);
} catch (Exception ex) {
// Handle other exceptions appropriately
}
}
There are some commonly used charsets that the JDK does not yet support.
You can find support for some of these additional charsets in the JCharset
package at
http://www.freeutils.net/source/jcharset/.
You can also add an alias for an existing charset already supported
by the JDK so that it will be known by an additional name.
You can create
a charset provider for the "bad" charset name that simply redirects to
an existing charset provider; see the following code.
Create an appropriate CharsetProvider subclass and include it along with the
META-INF/services file and the JDK will find it.
Obviously you could get significantly more clever and redirect all
unknown charsets to "us-ascii", for instance.
==> UnknownCharsetProvider.java <==
import java.nio.charset.*;
import java.nio.charset.spi.*;
import java.util.*;
public class UnknownCharsetProvider extends CharsetProvider {
private static final String badCharset = "x-unknown";
private static final String goodCharset = "iso-8859-1";
public Charset charsetForName(String charset) {
if (charset.equalsIgnoreCase(badCharset))
return Charset.forName(goodCharset);
return null;
}
public Iterator<Charset> charsets() {
return Collections.emptyIterator();
}
}
==> META-INF/services/java.nio.charset.spi.CharsetProvider <==
UnknownCharsetProvider
Q: How do I process all the messages in an IMAP folder
and add a listener to wait for the arrival of new messages?
A:
Open the folder, process all the messages in the folder, and check
whether new messages have arrived (the message count has increased).
If so, loop. If not, add the listener, then wait for new messages
(e.g., by calling the idle method).
Part of the key to understanding how this works is understanding when
the server is allowed to notify the client of new messages, and when
Jakarta Mail will see those notifications. Between getting the number of
messages and adding the listener, Jakarta Mail won't see any notifications
of new messages. By the time you do an operation that will allow
Jakarta Mail to see the notification, the listener will be in place.
The following code illustrates the general approach. Many details have
been omitted.
folder.open(Folder.READ_WRITE); // or READ_ONLY
// first batch of messages
int start = 1;
int end = folder.getMessageCount();
while (start <= end) {
Message[] msgs = folder.getMessages(start, end);
for (Message msg : msgs)
processMessage(msg);
// new messages that have arrived
start = end + 1;
end = folder.getMessageCount();
}
// processed all messages
// add MessageCountListener to listen for new messages
folder.addMessageCountListener(new MessageCountAdapter() {
public void messagesAdded(MessageCountEvent ev) {
Message[] msgs = ev.getMessages();
for (Message msg : msgs)
processMessage(msg);
}
});
// wait for new messages
for (;;)
((IMAPFolder)folder).idle();
Sending mail, SMTP
Q: How do I reply to a message?
A: To reply to a message, use the reply
method
on the Message object. This method will return a new object with the
headers set appropriately for a reply. You'll need to supply the content
of the message yourself.
If you have the content of the original message as a String, you can use
a simple method such as the following to create the prototypical reply
text, which inserts "> " in front of each line:
String text = (String)msg.getContent();
Message reply = msg.reply();
String replyText = text.replaceAll("(?m)^", "> ");
// allow user to edit replyText,
// e.g., using a Swing GUI or a web form
reply.setText(replyText);
Q: How do I forward a message?
A: The approach used to forward a message depends on how you want
to present the forwarded message.
It's straightforward to create a new MimeMessage, address it appropriately,
and attach an existing message as an attachment to the new message.
To attach the original message to the new message, use code such as:
MimeMessage msg = new MimeMessage(session);
// set To, From, Subject, Date, etc.
MimeMultipart mp = new MimeMultipart();
// create a body part to contain whatever text you want to include
MimeBodyPart mbp = new MimeBodyPart();
mbp.setText("Here's the forwarded message\n");
mp.addPart(mbp);
// create another body part to contain the message to be forwarded
MimeBodyPart fmbp = new MimeBodyPart();
// forwardedMsg is the MimeMessage object you want to forward
// as an attachment
fmbp.setContent(forwardedMsg, "message/rfc822");
fmbp.setDisposition(Part.ATTACHMENT);
mp.addPart(fmbp);
msg.setContent(mp);
If instead you want to create the new message with the text of the
original message included in the new message, to forward the message
"inline", you can use an approach such as the following:
String text = (String)forwardedMsg.getContent();
String forwardedText = String.format(
"\n\n-------- Original Message --------\n" +
"Subject: %s\nDate: %s\nFrom: %s\nTo: %s\n",
forwardedMsg.getSubject(),
forwardedMsg.getSentDate(),
forwardedMsg.getFrom()[0],
formatAddressList(
forwardedMsg.getRecipients(Message.RecipientType.TO)));
// allow user to edit forwardedText,
// e.g., using a Swing GUI or a web form
msg.setText(forwardedText);
(You'll have to write the formatAddressList
method using
the toUnicodeString
method of InternetAddress
.
You'll also want to include appropriate error checking and test for null
values.)
Q: How do I send HTML mail?
A: There are a number of demo programs included with the
distribution that show how to send HTML mail. If you want to
send a simple message that has HTML instead of plain text, see
the sendhtml.java
program in the demo directory.
If you want to send an HTML file as an attachment, see the
sendfile.java
example that shows how to send any file
as an attachment.
Q: How do I send mail with formatted text using different fonts
and colors?
A: The simplest approach is to send a message using HTML text.
See above.
Q: How do I send mail with both plain text as well as HTML text
so that each mail reader can choose the format appropriate for it?
A: You'll want to send a MIME multipart/alternative
message. You construct such a message essentially the same way you
construct a multipart/mixed
message, using a MimeMultipart
object constructed using new MimeMultipart("alternative")
.
You then insert the text/plain
body part as the first part
in the multpart and insert the text/html
body part as the
second part in the multipart.
You'll need to construct the plain and html parts yourself to have
appropriate content.
See RFC2046
for details of the structure of such a message.
Q: How do I send HTML mail that includes images?
A: The simplest approach is to send HTML text with image tags
that reference images on a public web site. In this approach the
images aren't actually included in the message, and so won't be visible
if the user is not connected to the Internet when they read the message.
Note also that some mailers will refuse to display images that are on
remote sites.
Another approach is to include the image data inline in the html content
of the message, for example:
<img src="data:image/jpeg;base64,base64-encoded-data-here" />
This works best for relatively small images.
Alternatively, you can construct a MIME multipart/related
message. See RFC2387
for details of the structure of such a message.
A simple example follows:
Multipart multipart = new MimeMultipart("related");
MimeBodyPart htmlPart = new MimeBodyPart();
// messageBody contains html that references image
// using something like <img src="cid:XXX"> where
// "XXX" is an identifier that you make up to refer
// to the image
htmlPart.setText(messageBody, "utf-8", "html");
multipart.addBodyPart(htmlPart);
MimeBodyPart imgPart = new MimeBodyPart();
// imageFile is the file containing the image
imgPart.attachFile(imageFile);
// or, if the image is in a byte array in memory, use
// imgPart.setDataHandler(new DataHandler(
// new ByteArrayDataSource(bytes, "image/whatever")));
// "XXX" below matches "XXX" above in html code
imgPart.setContentID("<XXX>");
multipart.addBodyPart(imgPart);
message.setContent(multipart);
For more advice, see
How to Embed Images in Your Emails: The Facts
Q: What's the difference between the Transport methods
send
and sendMessage
?
A: The send()
method is a static method and can be
used without needing an instance of a Transport object. It is intended
for the common, simple case of sending a single message using the
default transport. Internally, the send()
method will
first call the saveChanges()
method on the message.
It will then create an appropriate new Transport object, call the Transport's
connect()
method, call the Transport's sendMessage()
method to actually send the message, call the Transport's close()
method, and finally abandon the new instance of the Transport object to be
collected by the garbage collector.
(Actually, it's rather more complicated than that, but that's the general
idea.)
As you can see, the static send()
convenience method is
built on the more general per-instance sendMessage()
method. There are a number of reasons for an application to use the
sendMessage()
method directly. The most common reasons are
to improve performance by sending more than one message during a single
connection, or to manually manage the connection so as to provide
authentication information.
Q: When I try to send a message I get an error like
SMTPSendFailedException: 530, Address requires authentication
.
A: You need to authenticate to your SMTP server. The package
javadocs for the
com.sun.mail.smtp package describe several methods to do this.
The easiest is to replace the call Transport.send(msg);
with
Transport.send(msg, username, password);
.
You'll have to supply the appropriate username and password
needed by your mail server.
Q: How do I use SSL or TLS when connecting to my mail server?
A:
To use SMTP over SSL, set the mail.smtp.ssl.enable
property
in the Session properties.
To use the STARTTLS command set the mail.smtp.starttls.enable
property in the Session properties.
For example:
Properties props = new Properties();
props.setProperty("mail.smtp.host", host);
props.setProperty("mail.smtp.ssl.enable", "true");
// or: props.put("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(props);
MimeMessage msg = new MimeMessage(session);
// set message content here
Transport.send(msg, username, password);
Q: I need to authenticate to my SMTP server so I call
trans.connect(host, user, password)
and then
trans.send(msg)
to send the message, but it's not working.
A: You should call
trans.sendMessage(msg, addrs)
to send the message. As described
above, the send
method is a static
convenience method that acquires its own Transport object and creates
its own connection to use for sending; it does not use the connection
associated with any Transport object through which it is invoked.
Q: I modified this message, but the headers do not reflect the changes.
A: You should call saveChanges()
after you create a
new message or modify an existing message. This will cause the headers to be
reset and reflect your changes.
Note that the Transport.send(Message)
method calls this implicitly.
So if all you are doing is sending the modified message, you can
skip calling saveChanges()
yourself.
saveChanges()
is a potentially expensive operation (especially for
large or deeply nested messages), so call it only when needed.
Q: I set a particular value for the Message-ID header of my
new message, but when I send this message that header is rewritten.
A:
A new value for the Message-ID field is set when the saveChanges
method is called (usually implicitly when a message is sent),
overwriting any value you set yourself. If you need
to set your own Message-ID and have it retained, you will have to create
your own MimeMessage subclass, override the updateMessageID
method
and use an instance of this subclass.
class MyMessage extends MimeMessage {
...
protected void updateMessageID() throws MessagingException {
setHeader("Message-ID", "my-message-id");
}
...
}
Q: Why do I get an UnsupportedDataTypeException when sending this
new message that I created?
A: You probably set some content for your message using the
setContent(Object o, String type)
method. For this to work, there
must be a JAF DataContentHandler
registered for the given "type".
If not, you will get the UnsupportedDataTypeException. See the
JAF documents
for more information.
In most cases the simplest workaround is to use a
ByteArrayDataSource
as described
above.
Q: How can I explicitly set the SMTP FROM: attribute when sending a
message?
A: The mail.smtp.from
property can be used to set the
SMTP FROM: attribute. If this property if absent, the message's From
attribute is used.
If multiple threads need to send mail simultaneously, and each needs
to set the From attribute, each thread should use its own Session object
with its own Properties object. The mail.smtp.from
property
can then be set on each Properties object for each Session (and thus
each thread) independently.
Alternatively, each thread can use the com.sun.mail.SMTPMessage
class. The setEnvelopeFrom
method on that class can be used
to set this value. With this approach, all threads can use the same Session.
Q: I want to repeatedly send messages, to a different set of
recipients each time. But invoking Transport.send(Message)
causes
a new Transport session to be established each time. This is
suboptimal in this case, so how do I get around this?
A: Create an instance of the appropriate Transport object, connect
to it and invoke the sendMessage()
method repeatedly. For example:
MimeMessage msg = ...;
// construct message
msg.saveChanges();
Transport t = session.getTransport("smtp");
t.connect();
for (int i = 0; .....) {
t.sendMessage(msg, new Address[] { recipients[i] });
}
t.close();
Q: I get "MessagingException: 501 HELO requires domain address"
when trying to send a message.
A: The SMTP provider uses the results of
InetAddress.getLocalHost().getHostName()
in the SMTP HELO command. If that call fails to return any data, no
name is sent in the HELO command. Check your JDK and name server
configuration to ensure that that call returns the correct data.
You may also set the "mail.smtp.localhost"
property to the name you want to use for the HELO command.
Q: I get "Must issue a STARTTLS command first"
when trying to send a message.
A: Your SMTP server wants you to switch from a plain text connection
to a secure connection using the STARTTLS command.
You can enable use of this command by setting the Session property
"mail.smtp.starttls.enable" to "true".
This will cause the SMTP protocol provider to issue the STARTTLS
command after connecting to the server.
See the file
SSLNOTES.txt
for additional information.
Also, the javadocs for the
com.sun.mail.smtp
package has more information on the properties that can be set.
Note that your server is most likely also going to want you to authenticate,
as described in this entry.
Q: If I send a message to a bad address, why don't I get a
SendFailedException or TransportEvent indicating that the address is
bad?
A: There is no end-to-end address verification on the Internet.
Often a message will need to be forwarded to several mail servers before
reaching one that can determine whether or not it can deliver the message.
If a failure occurs in one of these later steps, the message will
typically be returned to the sender as undeliverable. A successful
"send" indicates only that the mail server has accepted the message
and will try to deliver it.
Q: When a message can't be delivered, a failure message is returned.
How can I detect these "bounced" messages?
A: While there is an Internet standard for reporting such errors
(the multipart/report MIME type, see
RFC1892),
it is not widely implemented yet.
RFC1211
discusses this problem in depth, including numerous examples.
In Internet email, the existence of a particular mailbox or user
name can only be determined by the ultimate server that would deliver the
message. The message may pass through several relay servers (that are not
able to detect the error) before reaching the end server. Typically, when
the end server detects such an error, it will return a message indicating
the reason for the failure to the sender of the original message. There
are many Internet standards covering such Delivery Status Notifications
but a large number of servers don't support these new standards, instead
using ad hoc techniques for returning such failure messages. This makes
it very difficult to correlate a "bounced" message with the original message
that caused the problem. (Note that this problem is completely independent
of Jakarta Mail.)
Jakarta Mail now includes support for parsing Delivery Status Notifications;
see the NOTES.txt
file in the Jakarta Mail package for details.
There are a number of techniques and heuristics for dealing with this
problem - none of them perfect. One technique is Variable Envelope
Return Paths, described at
http://cr.yp.to/proto/verp.txt.
The use of VERP with Jakarta Mail and Apache James is described
here.
Q: When I construct an InternetAddress object, why don't I get an
exception if the address is illegal?
A: The InternetAddress class only checks the syntax of the address.
As discussed above, the InternetAddress class is not
able to determine whether the address actually exists as a legal address.
It is not even possible to verify the host name if the application is
running behind a firewall or isn't currently connected to the Internet.
Q: When I try to send a message, why do I get
javax.mail.SendFailedException: 550 Unable to relay for
my-address
?
A: This is not a Jakarta Mail problem. This is an error reply from
your SMTP mail server. It indicates that your mail server is not
configured to allow you to send mail through it. Typically, mail servers
for an organization will be configured to allow mail from within the
organization to be sent to other addresses within the organization,
or to addresses external to the organization. It will also typically allow
mail coming from an address external to an organization to be sent to
addresses within the orgnaization. What it will typically not
allow is mail coming from an address external to the organization to be
sent (relayed) to another address also external to the organization.
The configuration of the mail server determines whether such relaying is
allowed, and which addresses are considered internal vs. external.
Often mail servers will require you to
authenticate before they will
relay messages.
Q: When I try to send a message to (for example) Yahoo,
why do I get an error that says "connection refused"?
A: The host you're trying to connect to is most likely not
running a mail server. If you're trying to connect to a web mail
service such as Yahoo, you can't usually use the web host name
(e.g., "yahoo.com") since this host doesn't run the required
mail server. Instead, you'll need to learn the name of the host
running the required mail server; contact your web mail provider for
this information. You can find this information for Yahoo at
http://help.yahoo.com/help/us/mail/pop/pop-02.html.
Note that some web mail providers don't offer this service, instead
allowing you to access your mail only through a browser.
If you're not trying to connect to a web mail account, but instead are
trying to connect to a host on your local network, then most likely the
host you're trying to connect to is not running a mail server. Sometimes
this will occur if you forget to set (for example) the "mail.smtp.host"
property, which will cause you to try to connect to "localhost". Most
Windows machines do not run a mail server, although many UNIX (Solaris,
Linux, etc.) machines do. Thus, attempts to connect to "localhost" on
Windows machines will usually fail with a "connection refused" error.
Q: When sending mail, why does it fail with an exception that includes a
message something like
553 To send mail, first check your mail with a valid POP account
?
A: In order to prevent their use to send spam, some mail servers
will require you to have a valid POP3 account and require you to login
to that account before they'll let you send mail through that mail server.
This is simple to handle in Jakarta Mail. When you know that you're dealing
with such a mail server, make sure you connect to your POP3 Store on that
mail server before sending mail.
POP3
Q: I want to delete messages on a POP3 server. I set the
DELETED
flag
on those messages. Then I call the expunge()
method, but I get a
MethodNotSupportedException.
How do I delete messages when I use the POP3 provider?
A: The expunge()
method is not supported by the
POP3 provider. Instead, after marking the messages to be deleted
by setting the DELETED flag on those messages, close the folder with
the expunge flag set to true. That is, invoke folder.close(true)
.
Q: How can I retrieve POP3 UIDLs in messages obtained from the POP3
provider?
A: This is possible with the POP3 provider. See
the com.sun.mail.pop3
package documentation for details.
Q: How can I tell which messages are new with POP3?
A: The POP3 protocol doesn't provide support for any permanent flags
so the RECENT flag is of no use. The com.sun.mail.pop3
package
documentation discusses several strategies for dealing with this problem.
Q: Why does hasNewMessages()
always return false when using
POP3?
A: The POP3 protocol provides no way to determine whether a folder
has new messages.
Q: I set up a MessageCountListener
(as demonstrated in the
monitor
program) but I'm never notified
of new mail in my POP3 INBOX.
A: The POP3 protocol does not allow the client to see new messages
delivered to the INBOX while the INBOX is open.
The application must close the INBOX and reopen it in order to see any
new messages. You will never be notified of new mail using the
MessageCountListener
interface with POP3. See the
com.sun.mail.pop3
package documentation
for more information.
Q: Why does getReceivedDate()
return null when using
POP3?
A: The POP3 protocol does not provide information about when a
message was received. It may be possible to guess at the received date
by looking at some message headers such as the Received
header, but this is not very reliable.
Q: When using POP3 I get complaints about the SocketFetcher class.
A: Most likely you
have more than one version of pop3.jar or jakarta.mail.jar in your CLASSPATH.
Check the setting of CLASSPATH and
check the "jre/lib/ext" directory in the JDK.
Q: When using POP3 I get complaints about the contentStream field.
A: The error usually looks like:
java.lang.NoSuchFieldError: contentStream at
com.sun.mail.pop3.POP3Message.getContentStream(POP3Message.java:115)
As above, you've mixed versions of the POP3
provider and jakarta.mail.jar. You probably have an older version of
jakarta.mail.jar in your CLASSPATH before the newer version that includes
the POP3 provider.
Q: How do I access or create folders other than INBOX on my POP3 server?
A: You can't. POP3 servers only support a single mailbox per user.
Most mail readers that use POP3 also maintain a local message store into
which they copy incoming messages (from the POP3 INBOX) and allow you to
file messages in other folders. See this item
for more information about local store providers.
Q: Why does the getSize
method return a negative number
when using POP3?
A: Your POP3 server is broken. The POP3 provider uses the
TOP
command to fetch the headers for the message
and the LIST
command to determine the size of the
entire message. It then subtracts the two values to determine
the size of the message body. If the server reports the size of
the entire message incorrectly, you may get a negative number.
You can set the property "mail.pop3.disabletop" to "true" to
disable the use of the TOP
command, but note that
this will cause any access to the message headers to fetch the
entire message.
Q: I'm having problems using POP3 with Microsoft Exchange.
A: Some versions of Microsoft Exchange do not implement the
POP3 protocol properly. They return different headers from the
TOP
command than they do from the RETR
command. This can cause all sorts of strange failures in Jakarta Mail.
One solution is to disable use of the TOP
command,
as described above. Another approach
that works in some cases os to tell Jakarta Mail to forget about the
headers it retrieved using the TOP
command after
retrieving the entire message using the RETR
command.
To do this, set the property "mail.pop3.forgettopheaders" to "true".
Jakarta Mail in servlets
Q: Can I use Jakarta Mail in servlets?
A:
Yes, see the Installation and Configuration section above for more details.
The Jakarta Mail API is also a required part of the
Java Platform, Enterprise Edition (Java EE).
No installation or configuration is necessary when using Jakarta Mail
in a Java EE product, it's just there!
Q: My web application uses Jakarta Mail to attach and send a file that
the user specifies, but my application can't find the file.
A: If the user species the filename in an HTML form in the browser,
the filename is normally the name of a file on the user's machine, not on
the server. The file will need to be uploaded to the server before
Jakarta Mail can access it.
The
Apache Jakarta Commons FileUpload package can help.
Jakarta Mail in applets
Q: Can I use Jakarta Mail in applets?
A:
Yes, Jakarta Mail will work in applets in browsers that support the
required JDK version.
The
Java Plug-in may be required to provide such support.
Q: What are the security implications of using Jakarta Mail in an applet?
A: One of the biggest
issues with using Jakarta Mail in applets is the default applet security
restrictions. These restrictions only allow applets to connect to the
host from which they were loaded. Thus, for such applets to use Jakarta Mail,
the mail server will need to be located on the same machine as the web
server from which the applet is loaded. You can find more information
on the applet security model
here.
Q: Ok, maybe I really don't want to use an applet, what should I
do instead?
A: In general, we recommend use of a web application to collect
a mail message and send it using Jakarta Mail. The demo servlet included in
the Jakarta Mail download package illustrates this approach. The
Email Web Application demo program on the Oracle Technology Network
illustrates another approach using JavaServer Pages.