In this example, Elvis is sending a GIF of his old Gumby friend. The attachment is encoded using the BASE64 algorithm.
In this example, we are sending as an attachment this image :

import java.io.*;
import java.net.*;
public class TestMailMIME {
static int SMTPport = 25;
static Socket socket;
static DataInputStream in;
static DataOutputStream out;
static PrintStream prout;
/* Name of file to be sent. */
String FileName = "gumby.gif";
public static void main(String s[]) {
/*
** TestMailMIME [server] [recipient]
*/
TestMailMIME t = new TestMailMIME();
t.sendMail(s[0], s[1]);
}
public void sendMail(String mailServer, String recipient) {
System.out.println("Send mail with attached file ");
try {
Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader
(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream(), "8859_1"));
String boundary = "DataSeparatorString";
// here you are supposed to send your username
sendln(in, out, "HELO theWorld");
// warning : some mail server validate the sender address
// in the MAIL FROM command, put your real address here
sendln(in, out, "MAIL FROM: ");
sendln(in, out, "RCPT TO: <" + recipient + ">" );
// to have more than one recipient, repeat
// sendln(in, out, "RCPT TO: <" + recipient2 + ">" );
// sendln(in, out, "RCPT TO: <" + recipient3 + ">" );
// etc...
// thanks to P-Y Colle for the tip!
sendln(in, out, "DATA");
sendln(out, "MIME-Version: 1.0");
sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <Elvis.Presley@jailhouse.rock>");
sendln
(out, "Content-Type: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n--" + boundary);
// Send the body
sendln(out, "Content-Type: text/plain; charset=\"us-ascii\"\r\n");
sendln(out, "I'm alive. Help me!\r\n\r\n");
sendln(out, "\r\n--" + boundary );
// send the GIF
sendln(out, "Content-Type:image/gif; name="+FileName);
sendln
(out, "Content-Disposition: attachment;filename=\""+FileName+"\"");
sendln(out, "Content-transfer-encoding: base64\r\n");
MIMEBase64.encode(FileName, out);
sendln(out, "\r\n--" + boundary);
sendln(out, "\r\n\r\n--" + boundary + "--\r\n");
sendln(in, out,".");
sendln(in, out, "QUIT");
s.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
public void sendln(BufferedReader in, BufferedWriter out, String s) {
try {
out.write(s + "\r\n");
out.flush();
// System.out.println(s);
s = in.readLine();
// System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
public void sendln(BufferedWriter out, String s) {
try {
out.write(s + "\r\n");
out.flush();
System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
And the MIMEBase64 class
import java.io.*;
public class MIMEBase64 {
/*
Base64 uses a 65 character subset of US-ASCII,
allowing 6 bits for each character so the character
"m" with a Base64 value of 38, when represented
in binary form, is 100110.
With a text string, let's say "men" is encoded this
is what happens :
The text string is converted into its US-ASCII value.
The character "m" has the decimal value of 109
The character "e" has the decimal value of 101
The character "n" has the decimal value of 110
When converted to binary the string looks like this :
m 01101101
e 01100101
n 01101110
These three "8-bits" are concatenated to make a
24 bit stream
011011010110010101101110
This 24 bit stream is then split up into 4 6-bit
sections
011011 010110 010101 101110
We now have 4 values. These binary values are
converted to decimal form
27 22 21 46
And the corresponding Base64 character are :
b W V u
The encoding is always on a three characters basis
(to have a set of 4 Base64 characters). To encode one
or two then, we use the special character "=" to pad
until 4 base64 characters is reached.
ex. encode "me"
01101101 01100101
0110110101100101
011011 010110 0101
111111 (AND to fill the missing bits)
011011 010110 010100
b W U
b W U = ("=" is the padding character)
so "bWU=" is the base64 equivalent.
encode "m"
01101101
011011 01
111111 (AND to fill the missing bits)
011011 010000
b Q = = (two paddings are added)
Finally, MIME specifies that lines are 76 characters wide maximum.
*/
static String BaseTable[] = {
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
"Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
"g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
"w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"
};
public static void encode(String filename, BufferedWriter out) {
try {
File f = new File(filename);
FileInputStream fin = new FileInputStream(filename);
// read the entire file into the byte array
byte bytes[] = new byte[(int)(f.length())];
int n = fin.read(bytes);
if (n < 1) return; // no bytes to encode!?!
byte buf[] = new byte[4]; // array of base64 characters
int n3byt = n / 3; // how 3 bytes groups?
int nrest = n % 3; // the remaining bytes from the grouping
int k = n3byt * 3; // we are doing 3 bytes at a time
int linelength = 0; // current linelength
int i = 0; // index
// do the 3-bytes groups ...
while ( i < k ) {
buf[0] = (byte)(( bytes[i] & 0xFC) >> 2);
buf[1] = (byte)(((bytes[i] & 0x03) << 4) |
((bytes[i+1] & 0xF0) >> 4));
buf[2] = (byte)(((bytes[i+1] & 0x0F) << 2) |
((bytes[i+2] & 0xC0) >> 6));
buf[3] = (byte)( bytes[i+2] & 0x3F);
send(out, BaseTable[buf[0]]);
send(out, BaseTable[buf[1]]);
send(out, BaseTable[buf[2]]);
send(out, BaseTable[buf[3]]);
/*
The above code can be written in more "optimized"
way. Harder to understand but more compact.
Thanks to J. Tordera for the tip!
buf[0]= (byte)(b[i] >> 2);
buf[1]= (byte)(((b[i] & 0x03) << 4)|(b[i+1]>> 4));
buf[2]= (byte)(((b[i+1] & 0x0F)<< 2)|(b[i+2]>> 6));
buf[3]= (byte)(b[i+2] & 0x3F);
send(out,BaseTable[buf[0]]+BaseTable[buf[1]]+
BaseTable[buf[2]]+BaseTable[buf[3]]);
*/
if ((linelength += 4) >= 76) {
send(out, "\r\n");
linelength = 0;
}
i += 3;
}
// deals with with the padding ...
if (nrest==2) {
// 2 bytes left
buf[0] = (byte)(( bytes[k] & 0xFC) >> 2);
buf[1] = (byte)(((bytes[k] & 0x03) << 4) |
((bytes[k+1] & 0xF0) >> 4));
buf[2] = (byte)(( bytes[k+1] & 0x0F) << 2);
}
else if (nrest==1) {
// 1 byte left
buf[0] = (byte)((bytes[k] & 0xFC) >> 2);
buf[1] = (byte)((bytes[k] & 0x03) << 4);
}
if (nrest > 0) {
// send the padding
if ((linelength += 4) >= 76) send(out, "\r\n");
send(out, BaseTable[buf[0]]);
send(out, BaseTable[buf[1]]);
// Thanks to R. Claerman for the bug fix here!
if (nrest==2) {
send(out, BaseTable[buf[2]]);
}
else {
send(out, "=");
}
send(out, "=");
}
out.flush();
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void send(BufferedWriter out, String s) {
try {
out.write(s);
System.out.print(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
If Elvis want to send a GIF and a text file about his Gumby old friend then he would change his sendMail() for something like this
...
/* Name of files to be sent. */
String FileName1 = "gumby.gif";
String FileName2 = "gumby.txt";
...
public void sendMail(String mailServer, String recipient) {
System.out.println("Send mail with attached file");
try {
Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader
(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream(), "8859_1"));
String boundary = "DataSeparatorString";
// here you are supposed to send your username
sendln(in, out, "HELO world");
sendln(in, out, "MAIL FROM: <real@gagnon.com>");
sendln(in, out, "RCPT TO: <" + recipient + ">" );
sendln(in, out, "DATA");
sendln(out, "MIME-Version: 1.0");
sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <Elvis.Presley@jailhouse.rock<");
sendln
(out,"Content-Type: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n--" + boundary);
// send the GIF
sendln(out, "Content-Type: text/plain; charset=\"us-ascii\"\r\n");
sendln(out, "I'm alive. Help me!\n\n");
sendln(out, "\r\n" + "--" + boundary );
sendln(out, "Content-Type:image/gif; name="+FileName1);
sendln
(out, "Content-Disposition: attachment;filename=\""+FileName1+"\"");
sendln(out, "Content-transfer-encoding: base64\r\n");
MIMEBase64.encode(FileName1, out);
sendln(out, "\r\n--" + boundary);
// the text file
sendln(out, "Content-Type: text/plain; name="+FileName2);
sendln(out, "Content-Disposition: inline;filename=\""+FileName2+"\"");
// to send the file as an attachment instead of "inline" use :
// sendln
// (out, "Content-Type: text/plain; name="+FileName2);
// sendln
// (out,"Content-Disposition: attachment;filename=\""+FileName2+"\"");
sendln(out, "Content-Transfer-Encoding: base64\r\n");
MIMEBase64.encode(FileName2, out);
sendln(out, "\r\n\r\n--" + boundary + "--\r\n");
// done
sendln(in, out,".");
sendln(in, out, "QUIT");
s.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
...
Done! Haapy Coding!
Related posts:
Java Program to Implement Fermat Factorization Algorithm
Java Program to find the maximum subarray sum O(n^2) time(naive method)
Java Program to Implement LinkedBlockingDeque API
Java Program to Find the Shortest Path Between Two Vertices Using Dijkstra’s Algorithm
A Guide to LinkedHashMap in Java
Object cloning trong java
@Lookup Annotation in Spring
Using the Not Operator in If Conditions in Java
Java Program to Implement Gift Wrapping Algorithm in Two Dimensions
Uploading MultipartFile with Spring RestTemplate
Java Program to Create a Balanced Binary Tree of the Incoming Data
Notify User of Login From New Device or Location
Java String Conversions
Java Program to Perform Addition Operation Using Bitwise Operators
Java Program to Implement Multi-Threaded Version of Binary Search Tree
Java Program to Perform Insertion in a 2 Dimension K-D Tree
Java Program to Implement Heap Sort Using Library Functions
Java Program to Implement Segment Tree
Java Program to Implement Efficient O(log n) Fibonacci generator
Java Program to find the peak element of an array using Binary Search approach
Changing Annotation Parameters At Runtime
Object Type Casting in Java
Java Program to do a Breadth First Search/Traversal on a graph non-recursively
Spring MVC Content Negotiation
Java Program to Implement ArrayDeque API
How to Read a Large File Efficiently with Java
Chuyển đổi từ HashMap sang ArrayList
Java Program for Douglas-Peucker Algorithm Implementation
The Spring @Controller and @RestController Annotations
Hướng dẫn Java Design Pattern – Abstract Factory
Java Program to Implement Johnson’s Algorithm
Java Program to Implement Selection Sort