| Home: www.vipan.com | Vipan Singla | e-mail: vipan@vipan.com |
|
mail.jar (from the JavaMail download) and activation.jar (from the JavaBeans Activation Framework download) in Java classpath.
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
// Send a simple, single part, text/plain e-mail
public class TestEmail {
public static void main(String[] args) {
// SUBSTITUTE YOUR EMAIL ADDRESSES HERE!!!
String to = "vipan@vipan.com";
String from = "vipan@vipan.com";
// SUBSTITUTE YOUR ISP'S MAIL SERVER HERE!!!
String host = "smtp.yourisp.net";
// Create properties, get Session
Properties props = new Properties();
// If using static Transport.send(),
// need to specify which host to send it to
props.put("mail.smtp.host", host);
// To see what is going on behind the scene
props.put("mail.debug", "true");
Session session = Session.getInstance(props);
try {
// Instantiatee a message
Message msg = new MimeMessage(session);
//Set message attributes
msg.setFrom(new InternetAddress(from));
InternetAddress[] address = {new InternetAddress(to)};
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject("Test E-Mail through Java");
msg.setSentDate(new Date());
// Set message content
msg.setText("This is a test of sending a " +
"plain text e-mail through Java.\n" +
"Here is line 2.");
//Send the message
Transport.send(msg);
}
catch (MessagingException mex) {
// Prints all nested (chained) exceptions as well
mex.printStackTrace();
}
}
}//End of class
mail.jar (from the JavaMail download) and activation.jar (from the JavaBeans Activation Framework download) in Java classpath.
import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
public class SendMailUsage {
public static void main(String[] args) {
// SUBSTITUTE YOUR EMAIL ADDRESSES HERE!!!
String to = "you@yourisp.net";
String from = "you@yourisp.net";
// SUBSTITUTE YOUR ISP'S MAIL SERVER HERE!!!
String host = "smtpserver.yourisp.net";
// Create properties for the Session
Properties props = new Properties();
// If using static Transport.send(),
// need to specify the mail server here
props.put("mail.smtp.host", host);
// To see what is going on behind the scene
props.put("mail.debug", "true");
// Get a session
Session session = Session.getInstance(props);
try {
// Get a Transport object to send e-mail
Transport bus = session.getTransport("smtp");
// Connect only once here
// Transport.send() disconnects after each send
// Usually, no username and password is required for SMTP
bus.connect();
//bus.connect("smtpserver.yourisp.net", "username", "password");
// Instantiate a message
Message msg = new MimeMessage(session);
// Set message attributes
msg.setFrom(new InternetAddress(from));
InternetAddress[] address = {new InternetAddress(to)};
msg.setRecipients(Message.RecipientType.TO, address);
// Parse a comma-separated list of email addresses. Be strict.
msg.setRecipients(Message.RecipientType.CC,
InternetAddress.parse(to, true));
// Parse comma/space-separated list. Cut some slack.
msg.setRecipients(Message.RecipientType.BCC,
InternetAddress.parse(to, false));
msg.setSubject("Test E-Mail through Java");
msg.setSentDate(new Date());
// Set message content and send
setTextContent(msg);
msg.saveChanges();
bus.sendMessage(msg, address);
setMultipartContent(msg);
msg.saveChanges();
bus.sendMessage(msg, address);
setFileAsAttachment(msg, "C:/WINDOWS/CLOUD.GIF");
msg.saveChanges();
bus.sendMessage(msg, address);
setHTMLContent(msg);
msg.saveChanges();
bus.sendMessage(msg, address);
bus.close();
}
catch (MessagingException mex) {
// Prints all nested (chained) exceptions as well
mex.printStackTrace();
// How to access nested exceptions
while (mex.getNextException() != null) {
// Get next exception in chain
Exception ex = mex.getNextException();
ex.printStackTrace();
if (!(ex instanceof MessagingException)) break;
else mex = (MessagingException)ex;
}
}
}
// A simple, single-part text/plain e-mail.
public static void setTextContent(Message msg) throws MessagingException {
// Set message content
String mytxt = "This is a test of sending a " +
"plain text e-mail through Java.\n" +
"Here is line 2.";
msg.setText(mytxt);
// Alternate form
msg.setContent(mytxt, "text/plain");
}
// A simple multipart/mixed e-mail. Both body parts are text/plain.
public static void setMultipartContent(Message msg) throws MessagingException {
// Create and fill first part
MimeBodyPart p1 = new MimeBodyPart();
p1.setText("This is part one of a test multipart e-mail.");
// Create and fill second part
MimeBodyPart p2 = new MimeBodyPart();
// Here is how to set a charset on textual content
p2.setText("This is the second part", "us-ascii");
// Create the Multipart. Add BodyParts to it.
Multipart mp = new MimeMultipart();
mp.addBodyPart(p1);
mp.addBodyPart(p2);
// Set Multipart as the message's content
msg.setContent(mp);
}
// Set a file as an attachment. Uses JAF FileDataSource.
public static void setFileAsAttachment(Message msg, String filename)
throws MessagingException {
// Create and fill first part
MimeBodyPart p1 = new MimeBodyPart();
p1.setText("This is part one of a test multipart e-mail." +
"The second part is file as an attachment");
// Create second part
MimeBodyPart p2 = new MimeBodyPart();
// Put a file in the second part
FileDataSource fds = new FileDataSource(filename);
p2.setDataHandler(new DataHandler(fds));
p2.setFileName(fds.getName());
// Create the Multipart. Add BodyParts to it.
Multipart mp = new MimeMultipart();
mp.addBodyPart(p1);
mp.addBodyPart(p2);
// Set Multipart as the message's content
msg.setContent(mp);
}
// Set a single part html content.
// Sending data of any type is similar.
public static void setHTMLContent(Message msg) throws MessagingException {
String html = "<html><head><title>" +
msg.getSubject() +
"</title></head><body><h1>" +
msg.getSubject() +
"</h1><p>This is a test of sending an HTML e-mail" +
" through Java.</body></html>";
// HTMLDataSource is an inner class
msg.setDataHandler(new DataHandler(new HTMLDataSource(html)));
}
/*
* Inner class to act as a JAF datasource to send HTML e-mail content
*/
static class HTMLDataSource implements DataSource {
private String html;
public HTMLDataSource(String htmlString) {
html = htmlString;
}
// Return html string in an InputStream.
// A new stream must be returned each time.
public InputStream getInputStream() throws IOException {
if (html == null) throw new IOException("Null HTML");
return new ByteArrayInputStream(html.getBytes());
}
public OutputStream getOutputStream() throws IOException {
throw new IOException("This DataHandler cannot write HTML");
}
public String getContentType() {
return "text/html";
}
public String getName() {
return "JAF text/html dataSource to send e-mail only";
}
}
} //End of class
mail.jar (from the JavaMail download) and activation.jar (from the JavaBeans Activation Framework download) in Java classpath.
import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.search.*;
import javax.activation.*;
public class FetchMailUsage {
public static void main(String[] args) {
// SUBSTITUTE YOUR ISP's POP3 SERVER HERE!!!
String host = "pop.yourisp.net";
// SUBSTITUTE YOUR USERNAME AND PASSWORD TO ACCESS E-MAIL HERE!!!
String user = "your_username";
String password = "your_password";
// SUBSTITUTE YOUR SUBJECT SUBSTRING TO SEARCH HERE!!!
String subjectSubstringToSearch = "Test E-Mail through Java";
// Get a session. Use a blank Properties object.
Session session = Session.getInstance(new Properties());
try {
// Get a Store object
Store store = session.getStore("pop3");
store.connect(host, user, password);
// Get "INBOX"
Folder fldr = store.getFolder("INBOX");
fldr.open(Folder.READ_WRITE);
int count = fldr.getMessageCount();
System.out.println(count + " total messages");
// Message numebers start at 1
for(int i = 1; i <= count; i++) {
// Get a message by its sequence number
Message m = fldr.getMessage(i);
// Get some headers
Date date = m.getSentDate();
Address [] from = m.getFrom();
String subj = m.getSubject();
String mimeType = m.getContentType();
System.out.println(date + "\t" + from[0] + "\t" +
subj + "\t" + mimeType);
}
// Search for e-mails by some subject substring
String pattern = subjectSubstringToSearch;
SubjectTerm st = new SubjectTerm(pattern);
// Get some message references
Message [] found = fldr.search(st);
System.out.println(found.length +
" messages matched Subject pattern \"" +
pattern + "\"");
for (int i = 0; i < found.length; i++) {
Message m = found[i];
// Get some headers
Date date = m.getSentDate();
Address [] from = m.getFrom();
String subj = m.getSubject();
String mimeType = m.getContentType();
System.out.println(date + "\t" + from[0] + "\t" +
subj + "\t" + mimeType);
Object o = m.getContent();
if (o instanceof String) {
System.out.println("**This is a String Message**");
System.out.println((String)o);
}
else if (o instanceof Multipart) {
System.out.print("**This is a Multipart Message. ");
Multipart mp = (Multipart)o;
int count3 = mp.getCount();
System.out.println("It has " + count3 +
" BodyParts in it**");
for (int j = 0; j < count3; j++) {
// Part are numbered starting at 0
BodyPart b = mp.getBodyPart(j);
String mimeType2 = b.getContentType();
System.out.println( "BodyPart " + (j + 1) +
" is of MimeType " + mimeType);
Object o2 = b.getContent();
if (o2 instanceof String) {
System.out.println("**This is a String BodyPart**");
System.out.println((String)o2);
}
else if (o2 instanceof Multipart) {
System.out.print(
"**This BodyPart is a nested Multipart. ");
Multipart mp2 = (Multipart)o2;
int count2 = mp2.getCount();
System.out.println("It has " + count2 +
"further BodyParts in it**");
}
else if (o2 instanceof InputStream) {
System.out.println(
"**This is an InputStream BodyPart**");
}
} //End of for
}
else if (o instanceof InputStream) {
System.out.println("**This is an InputStream message**");
InputStream is = (InputStream)o;
// Assumes character content (not binary images)
int c;
while ((c = is.read()) != -1) {
System.out.write(c);
}
}
// Uncomment to set "delete" flag on the message
//m.setFlag(Flags.Flag.DELETED,true);
} //End of for
// "true" actually deletes flagged messages from folder
fldr.close(true);
store.close();
}
catch (MessagingException mex) {
// Prints all nested (chained) exceptions as well
mex.printStackTrace();
}
catch (IOException ioex) {
ioex.printStackTrace();
}
}
} //End of class
Session object authenticates the user and controls access to the mail servers. The Session class is a final concrete class. It cannot be subclassed. By calling the appropriate factory method on a Session object, you can obtain Transport and Store objects which support specific protocols to send or fetch e-mail respectively.
InternetAddress object to use it with JavaMail. The InternetAddress class extends the abstract Address class to come up with an "rfc822" type address.public class InternetAddress extends Address implements Cloneable where: public abstract class Address extends Object implements Serializable
MimeMessage class.public class MimeMessage extends Message implements MimePart where public abstract class Message extends Object implements Part public interface MimePart extends Part public interface Part
All Java e-mails are of Message type.
msg.setText(textString).
MimeMultipart class handles multipart content which adheres to the MIME specifications.
public class MimeMultipart extends Multipart
where:
public abstract class Multipart extends Object
You create a new MimeMultipart object by invoking its default constructor.
When you get content of an multipart e-mail, it always returns an object of this type.
MimeBodyPart.
public class MimeBodyPart extends BodyPart implements MimePart
where:
public abstract class BodyPart extends Object implements Part
public interface Part
MimeMultipart's getBodyPart(int index) method returns the MimeBodyPart object at the given index. Index starts at 0. The addBodyPart(...) method adds a new MimeBodyPart object to it as a step towards constructing a new multipart MimeMessage.
Each Bodypart type object can contain either a JAF DataHandler object or another (nested) Multipart type object. So, check the content-type of each BodyPart before using it in your code.
To extract a nested Multipart type object from a MimePart containing a ContentType attribute set to "multipart/*", use the MimePart's getContent() method. Its getSubType method returns the multipart message MIME subtype. The subtype
defines the relationship among the individual body parts of a multipart message.
Folder objects which may also contain subfolders. All mail servers have the folder named "INBOX". The Folder class declares methods that fetch, append, copy and delete messages. A Folder object can also send events to components registered as event listeners.
Store class which requires username, and password to connect to the database. As a user, you will first connect to the mail server by calling one of the three connect(...) methods on a Store class, specifying the server to access, username and password.
msg.getMessageNumber() returns its sequence number. You can reference a message either by its sequence number or by the corresponding Message object itself.
When messages marked as deleted are actually purged, the remaining messages are renumbered. So there is no guarantee that a message will always have the same message number in a folder. Since a sequence number can change within a session, use references to Message objects rather than sequence numbers as cached references to messages.
FetchProfile to selectively retrieve message attributes/content for efficiency:Message[] msgs = folder.getMessages(); FetchProfile fp = new FetchProfile(); // ENVELOPE, CONTENT_INFO and/or FLAGS // ENVELOPE: From, To, Cc, Bcc, ReplyTo, Subject and Date // CONTENT_INFO: Type, Disposition, Description, Size and LineCount // FLAGS: Flags set on this message fp.add(FetchProfile.Item.ENVELOPE); // Add a specific header field to the list of attributes to be prefetched fp.add("X-mailer"); folder.fetch(msgs, fp); for (int i = 0; i < folder.getMessageCount(); i++) { display(msgs[i].getFrom()); display(msgs[i].getSubject()); display(msgs[i].getHeader("X-mailer")); }
Properties props = new Properties(); // From system properties //Properties props = System.getProperties(); // Get the shared Session object Session session = Session.getDefaultInstance(props); // Get an unshared Session object Session session = Session.getInstance(props);
The "props" Properties file contains mail protocols to use, mail host and port to connect to, username etc. which will be used later to connect to the mail server. It can be blank although you may want to set mail.store.protocol, mail.transport.protocol, mail.host, mail.user and mail.from properties. Passwords can not be specified using properties. Here are the various properties that can be in the Properties object and what they do:
mail.smtp.host=smtp2.yourisp.com. Defaults to what's in "mail.host" property (see next).
user.name. The Store and Transport objects' connect() method uses this property to send the username to the mail server, if the protocol-specific username property is absent (see next).
InternetAddress.getLocalAddress method to specify the current user’s email address. Defaults to username@host.
Message msg = new MimeMessage(session);
InternetAddress[] toAddrs = new InternetAddress[1];
toAddrs[0] = new InternetAddress("your@buddy.com");
Address fromAddr = new InternetAddress("you@home.com");
msg.setFrom(fromAddr);
msg.setRecipients(Message.RecipientType.TO, toAddrs);
msg.setSubject("Test Email");
msg.setSentDate(new Date());
// Custom header other than pre-defined ones
msg.setHeader("content-type", "text/plain");
msg.setText("This is a test message");
// Or, for other content types, e.g.
msg.setContent("This is a test message", "text/plain");
MimeMultipart object. The default subtype of a multipart content is "mixed". You can specify other subtypes such as "alternative", "related", "parallel" and "signed".
Multipart mp = new MimeMultipart();
// Some other subtype
//Multipart mp = new MimeMultipart("alternative");
MimeBodyPart objects
BodyPart b1 = new MimeBodyPart();
b1.setContent("Spaceport Map","text/plain");
BodyPart b2 = new MimeBodyPart();
// Map is some binary postscript file
b2.setContent(map,"application/postscript");
BodyPart objects to Multipart object
mp.addBodyPart(b1);
mp.addBodyPart(b2);
Multipart object as the message's content
msg.setContent(mp); // This form takes a Multipart object
Transport.send(msg);
// Ignore recipient addresses in the Message object, specify your own
Transport.send(msg, recipientAddressesArray);
This is a convenience static method. It does not allow registering event listeners with the Transport object. Depending on each recipient's address type, it instantiates the appropriate Transport subclass, calls msg.saveChanges() and calls transportObject.sendMessage(msg).
msg.saveChanges();
// Use provider configuration file
Transport bus = session.getTransport("smtp");
// Use address type to protocol mapping file
//Transport bus = session.getTransport(address);
// Use session properties to get default protocol
//Transport bus = session.getTransport();
// Add a class implementing the appropriate listener interface
bus.addConnectionListener(this); // this implements ConnectionListener
bus.addTransportListener(this); // this implements TransportListener
Address [] addresses = msg.getAllRecipients();
// Or, Make your own
Address [] addresses = {
new InternetAddress("you@me.com"),
new InternetAddress("me@you.com"),
};
bus.sendMessage(msg, addresses);
msg.writeTo(someOutputStream);
// Gets protocol from session properties
Store store = session.getStore();
// Store for a non-default protocol
Store store = session.getStore("pop3");
//Uses session properties
store.connect();
//uses default port, hostString is like "mail.yourisp.com"
store.connect(hostString, username, password);
//uses specific port, -1 means default
store.connect(hostString, portNumberInteger username, password);
// get the INBOX folder (All stores usually have this one)
Folder inbox = store.getFolder("INBOX");
// open the INBOX folder
inbox.open(Folder.READ_WRITE);
Message m = inbox.getMessage(1); // get Message #1
// Get the subject attribute String subject = m.getSubject();
String mimeType = m.getContentType();
Object o = m.getContent();
Multipart object or its subclass.
InputStream object is returned.
if (o instanceof String) {
System.out.println("This is a String");
System.out.println((String)o);
}
else if (o instanceof Multipart) {
System.out.println("This is a Multipart");
Multipart mp = (Multipart)o;
int count = mp.getCount();
for (int i = 0; i < count; i++) {
BodyPart b = mp.getBodyPart(i);
mp.removeBodyPart(b);
// Or, simply
//mp.removeBodyPart(i);
mp.addBodyPart(b);
}
}
else if (o instanceof InputStream) {
System.out.println("This is just an input stream");
InputStream is = (InputStream)o;
int c;
while ((c = is.read()) != -1) {
System.out.write(c);
}
}
inbox.close(); // Close the INBOX store.close(); // Close the Store
MimeUtility class to convert non-US-ASCII headers and content to mail-safe format. Remember to do it before calling setHeader(), addHeader() and addHeaderLine() methods. In addition, these header fields must be folded (wrapped) before being sent if they exceed the line length limitation for the transport (1000 bytes for SMTP). Received headers may have been folded. Your application is responsible for folding and unfolding headers as appropriate.
MimeUtility utility class are static methods.
getEncoding() takes a JAF DataSource object and returns the Content-Transfer-Encoding that should be applied to the data in that DataSource object to make it mail-safe.
encode() wraps an encoder around the given output stream based on the specified Content-Transfer-Encoding.
decode() decodes the given input stream, based on the specified Content-Transfer-Encoding.
MimeUtility.encodeText() method on the header names and values, and then call setHeader(), addHeader() or addHeaderLine() methods on the encoded strings. It encodes header values only if they contain non US-ASCII characters.
MimePart part = ...
String rawvalue = "FooBar Mailer, Japanese version 1.1"
part.setHeader("X-mailer", MimeUtility.encodeText(rawvalue));
MimeUtility.decodeText method on header values obtained from a MimeMessage or MimeBodyPart using the "getHeader" set of methods. This method takes a header value, applies RFC 2047 decoding standards, and returns the decoded value as a Unicode String. You should always run header values through the decoder to be safe.
MimePart part = ...
String rawvalue = part.getHeader("X-mailer")[0]);
String value = null;
if ((rawvalue != null) {
value = MimeUtility.decodeText(rawvalue);
}
ContentType class is a utility class that can parse received MIME content-type headers and also generate new MIME content-type headers.
Multipart part = ...;
String type = part.getContentType();
ContentType cType = new ContentType(type);
if (cType.match("application/x-foobar")) {
// Extract a MIME parameter
iString color = cType.getParameter("color");
}
ContentType cType2 = new ContentType();
cType2.setPrimaryType("application");
cType2.setSubType("x-foobar");
cType2.setParameter("color", "red");
// Construct a MIME Content-Type value
String contentType = cType2.toString();
USER flag, you can set arbitrary user-definable flags on any message belonging to this folder. Other flags are:
// Get current flags set on a message Flags msgFlags = msg.getFlags(); // Get all supported flags by this folder Flags allowedFlags = fldr.getPermanentFlags(); // Check if a Flags object contains a flag allowedFlags.contains(flagToCheck); // Add a flag to a set of flags using a Flags.Flag object msgFlags.add(flagToAdd); // Set the flags on a message msg.setFlags(msgFlags, isToBeSet);
MailEvent class. The Transport, Store and Folder classes generate such events.
ConnectionEvent and TransportEvent. If the transport object connects successfully, it will fire the ConnectionEvent with the type set to OPENED. If the connection times out or is closed, ConnectionEvent with type CLOSED is generated. The sendMessage method of a Transport object generates a TransportEvent which contains information about the method’s success or failure. The event object contains three arrays of address arrays: validSent[], validUnsent[] and invalid[]:
MESSAGE_DELIVERED: Message sent to all recipients successfully. validSent[] contains all the addresses. validUnsent[] and invalid[] are null.
MESSAGE_NOT_DELIVERED: When ValidSent[] is null, the message was not successfully sent to any recipients. validUnsent[] may have addresses that are valid. invalid[] may contain invalid addresses.
MESSAGE_PARTIALLY_DELIVERED: Message was successfully sent to some recipients but not to all. ValidSent[] holds addresses of recipients to whom the message was sent. validUnsent[] holds valid addresses but the message wasn't sent to them. invalid[] holds invalid addresses.ConnectionEvent (generated on a successful connection or close), StoreEvent (event.getMessageType method returns either ALERT or NOTICE), FolderEvent (upon creation, deletion or renaming of a Folder).
ConnectionEvent (a Folder is opened or closed), FolderEvent (this folder creates, deletes or renames) and MessageCountEvent (message count has changed, expunged Message objects are in the event).
getInstance(...), getDefaultInstance(...), getStore(...) and getTransport(...) methods look for your configured javaMail implementations in two text files named javamail.providers and javamail.default.providers.
Usually, you don't need to do anything because the default providers in mail.jar file are sufficient.
protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=SunMicrosystems,Inc;
protocol=smtp; type=transport;class=com.sun.mail.smtp.SMTPTransport;
java.home/lib/javamail.providers file. There can be one such file per JVM.
META-INF/javamail.providers file in your application's directory or JAR file. There can be one such file per application.
META-INF/javamail.default.providers file in JavaMail's mail.jar file. There can be one such file per JavaMail installation.
mail.protocol.class property to the class name you want when you create the Session object.
props.put("mail.smtp.class", "com.acme.SMTPTRANSPORT");
Session session = Session.getInstance(props, null);
Or, you can change it later using Session's getProviders(), getProvider() and setProvider() methods.
// Find out which implementations are available Provider[] providers = session.getProviders(); // Pick a provider Provider yourPick = providers[5]; // For example // Then, set a provider session.setProvider(yourPick);
A Provider object cannot be explicitly created; it must be retrieved using the session.getProviders() method and it must be one of those configured in the resource files.
The providers in your files are added before the ones that come in mail.jar's default files. All are available from your code via the session.getProviders() method.
javamail.address.map and javamail.default.address.map.
Usually, you don't need to do anything because the default mappings in mail.jar file are sufficient.
javax.mail.Address.getType() method to get the address type. For example,
Address a = new InternetAddress("your@buddy.com");
String addrType = a.getType(); // Returns "rfc822"
Two common address types are "rfc822" (InternetAddress class) and "news" (NewsAddress class).
rfc822=smtp news=nntp
java.home/lib/javamail.address.map file. There can be one such file per JVM.
META-INF/javamail.address.map file in your application's directory or JAR file. There can be one such file per application.
META-INF/javamail.default.address.map file in JavaMail's mail.jar file. There can be one such file per JavaMail installation.
URLNames which may be constructed from strings specifying protocol, host, port, file, username, password. RFC 1738 specifies the URL syntax for IP-based protocols such as IMAP4 and POP3. Specify -1 as port number to use the default port.// Get a Store using the "scheme" part of the URL string Store s = session.getStore(URLName); // Or, directly // First gets a Store which uses the rest of URLName // to locate and instantiate Folder Folder f = session.getFolder(URLName);
SearchTerm class represents search terms. It has a single method: public boolean match(Message msg); There are concrete subclasses of this class to search on subject, from, to etc. and to specify AND and OR criteria.
The Folder class supports searches on messages:
public Message[] search(SearchTerm term) public Message[] search(SearchTerm term, Message[] msgs)
Your e-mail program:helo test
Mail server:250 mx1.mindspring.com Hello abc.sample.com
[220.57.69.37], pleased to meet you
Your e-mail program:mail from: test@sample.com
Mail server:250 2.1.0 test@sample.com... Sender ok
Your e-mail program:rcpt to: jsmith@mindspring.com
Mail server:250 2.1.5 jsmith... Recipient ok
Your e-mail program:data
Mail server:354 Enter mail, end with "." on a line by itself
Your e-mail program:from: test@sample.com
to:jsmith@mindspring.com
subject: testing
John, I am testing...
.
Mail server:250 2.0.0 e1NMajH24604 Message accepted
for delivery
Your e-mail program:quit
Mail server:221 2.0.0 mx1.mindspring.com closing connection
Connection closed by foreign host.
It is that simple! Really! All e-mail programs do this behind the scenes. If you have "mail.debug" property set to "true", you can see the commands being issued by the Sun JavaMail implementation as they print out on your console.
Fetching email from a POP3 server works the same way. See How E-mail Works for details.
Notice that the sender and recipients e-mail addresses during interaction with the SMTP server are specified before the "body" of the message. They can be different from what's in the body of the message.
base64 and quoted-printable schemes. The MIME RFCs 2045, 2046 and 2047 specify how to do this. Each MIME content will have a content type, structured body parts and a set of encoding schemes to encode data into mail-safe characters.