俊星的BLOG

JAVAMAIL之我的SMTP客户端实现

JAVAMAIL源代码中包含了对于SMTP发邮件的实现,下面是我的一个简单实现:
1、BASE64编码类:
package mymail;

public class MyBase64Encoder {
    
public static byte[] encode(byte[] inbuf) {
        
int size = inbuf.length;
        
byte[] outbuf = new byte[((size + 2/ 3* 4];
        
int inpos, outpos;
        
int val;
        
// 情况1:大于等于3
        for (inpos = 0, outpos = 0; size >= 3; size -= 3, outpos += 4{
            val 
= inbuf[inpos++& 0xff;
            val 
<<= 8;
            val 
|= inbuf[inpos++& 0xff;
            val 
<<= 8;
            val 
|= inbuf[inpos++& 0xff;
            
// 到此val中存储了3*8=24个二进制位,然后分4次,每次6个二进制位输出
            outbuf[outpos + 3= (byte) pem_array[val & 0x3f];
            val 
>>= 6;
            outbuf[outpos 
+ 2= (byte) pem_array[val & 0x3f];
            val 
>>= 6;
            outbuf[outpos 
+ 1= (byte) pem_array[val & 0x3f];
            val 
>>= 6;
            outbuf[outpos 
+ 0= (byte) pem_array[val & 0x3f];
        }

        
// 情况2:等于1或者等于2
        if (size == 1{
            val 
= inbuf[inpos++& 0xff;
            val 
<<= 4;
            
// 到此val中实际有效二进制位8+4=12个,并且后4个都为0
            outbuf[outpos + 3= (byte'='// pad character;
            outbuf[outpos + 2= (byte'='// pad character;
            outbuf[outpos + 1= (byte) pem_array[val & 0x3f];
            val 
>>= 6;
            outbuf[outpos 
+ 0= (byte) pem_array[val & 0x3f];
        }
 else if (size == 2{
            val 
= inbuf[inpos++& 0xff;
            val 
<<= 8;
            val 
|= inbuf[inpos++& 0xff;
            val 
<<= 2;
            
// 得到此val中实际有效二进制位为8+8+2=18个,并且后2个为0
            outbuf[outpos + 3= (byte'='// pad character;
            outbuf[outpos + 2= (byte) pem_array[val & 0x3f];
            val 
>>= 6;
            outbuf[outpos 
+ 1= (byte) pem_array[val & 0x3f];
            val 
>>= 6;
            outbuf[outpos 
+ 0= (byte) pem_array[val & 0x3f];
        }

        
return outbuf;
    }


    
private final static char pem_array[] = 'A''B''C''D''E''F''G''H'// 0
            'I''J''K''L''M''N''O''P'// 1
            'Q''R''S''T''U''V''W''X'// 2
            'Y''Z''a''b''c''d''e''f'// 3
            'g''h''i''j''k''l''m''n'// 4
            'o''p''q''r''s''t''u''v'// 5
            'w''x''y''z''0''1''2''3'// 6
            '4''5''6''7''8''9''+''/' // 7
    }
;
}


2、具体应用类:
package mymail;

import java.io.File;
import java.io.IOException;
import java.util.Date;

public class MyTest {
    
public static void main(String[] args) throws IOException {
        MyMsg msg 
= new MyMsg();
        msg.setSubject(
"suject 主题");
        msg.setFrom(
"from@test.com");
        msg.setRecipient(
"test@test.com");
        msg.setDate(
new Date());

        MyBodyPart body 
= new MyBodyPart();
        body.setText(
"text 邮件正文");
        MyBodyPart attach 
= new MyBodyPart();
        attach.attachFile(
new File("D:\\My Documents\\music.txt"));

        MyMultiPart content 
= new MyMultiPart();
        content.addPart(body);
        content.addPart(attach);
        msg.setContent(content);

        SMTPTrans trans 
= SMTPTrans.getInstance();
        trans.setDebug(
true);
        trans.connect(
"127.0.0.1");;
        trans.sendMsg(msg);
    }

}


输出:
C:EHLO 127.0.0.1
S:
220 kinkding-d1d01d SMTP Server (JAMES SMTP Server 2.3.1) ready Sun, 26 Apr 2009 01:05:20 +0800 (CST)

C:MAIL FROM:<from@test.com>
S:
250-kinkding-d1d01d Hello 127.0.0.1 (localhost [127.0.0.1])

C:MAIL FROM:<from@test.com>
S:
250-PIPELINING

C:RCPT TO:<test@test.com>
S:
250 ENHANCEDSTATUSCODES

C:DATA
S:
250 2.1.0 Sender <from@test.com> OK

C:.
S:
503 5.5.0 Sender already specified
250 2.1.5 Recipient <test@test.com> OK
354 Ok Send data ending with <CRLF>.<CRLF>

C:QUIT
S:
250 2.6.0 Message received

3、邮件类:
package mymail;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MyMsg {
    
private String subject;
    
private String from;
    
private String recipient;
    
private Date date;
    
private String newline = "\r\n";
    
private MyMultiPart content;

    
public Date getDate() {
        
return date;
    }


    
public void setDate(Date date) {
        
this.date = date;
    }


    
public void setSubject(String subject) {
        
this.subject = subject;
    }


    
public void setFrom(String from) {
        
this.from = from;
    }


    
public String getRecipient() {
        
return recipient;
    }


    
public void setRecipient(String recipient) {
        
this.recipient = recipient;
    }


    
public String getSubject() {
        
return subject;
    }


    
public String getFrom() {
        
return from;
    }

    
    
public void setContent(MyMultiPart content) {
        
this.content = content;
    }


    
public void writeTo(OutputStream out) throws IOException {
        
// 发送日期
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss '+0800' (z)", Locale.US);
        out.write((
"Date: " + sdf.format(date) + newline).getBytes());
        out.write((
"From: " + this.from + newline).getBytes());
        out.write((
"To: " + this.recipient + newline).getBytes());
        
// 发送主题
        out.write("Subject: =?gb2312?B?".getBytes());
        out.write(MyBase64Encoder.encode(
this.subject.getBytes()));
        out.write((
"?=" + newline).getBytes());
        
// 发送内容
        this.content.writeTo(out);

    }


}


4、MyMultiPart:
package mymail;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class MyMultiPart {
    
private String boundary;
    
private String contentType;
    
private List<MyBodyPart> parts = new ArrayList<MyBodyPart>();
    
private String newLine = "\r\n";

    
public MyMultiPart() {
        boundary 
= "----=_Part_0" + this.hashCode() + "_" + System.currentTimeMillis();
        contentType 
= "Content-Type: multipart/mixed;";
    }


    
public void addPart(MyBodyPart part) {
        parts.add(part);
    }


    
public void writeTo(OutputStream out) throws IOException {
        out.write((
this.contentType + "boundary=\"" + this.boundary+ "\"" + newLine).getBytes());
        
for (MyBodyPart body : parts) {
            out.write((newLine
+"--" + this.boundary + newLine).getBytes());
            body.writeTo(out);
            out.write(newLine.getBytes());
            out.flush();
        }

        out.write((newLine
+"--" + this.boundary + newLine).getBytes());
    }

}


5、MyBodyPart:
package mymail;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

public class MyBodyPart {
    
private String contentType = "Content-Type: ";
    
private String transferEncoding = "Content-Transfer-Encoding: base64";
    
private String contentDisp;
    
private String newLine = "\r\n";
    
private String text;
    
private File file;

    
public void setText(String str) {
        contentType 
+= "text/plain";
        text 
= str;
    }


    
public void attachFile(File f) {
        contentType 
+= "application/octet-stream; name=" + f.getName();
        contentDisp 
= "Content-Disposition: attachment; filename=" + f.getName();
        file 
= f;
    }


    
public void writeTo(OutputStream out) throws IOException {
        out.write((
this.contentType + newLine).getBytes());
        out.write((
this.transferEncoding + newLine).getBytes());
        
if (this.text != null{
            
// 字符形式
            out.write(newLine.getBytes());
            
this.byteWrite(out, text.getBytes());
        }
 else {
            
// 文件形式
            out.write((this.contentDisp + newLine + newLine).getBytes());
            FileInputStream input 
= new FileInputStream(file);
            
byte[] content = new byte[0];
            
byte[] buf = new byte[256];
            
int len;
            
while ((len = input.read(buf)) > -1{
                
byte[] temp = new byte[content.length];
                System.arraycopy(content, 
0, temp, 0, content.length);
                content 
= new byte[content.length + len];
                System.arraycopy(temp, 
0, content, 0, temp.length);
                System.arraycopy(buf, 
0, content, temp.length, len);
            }

            
this.byteWrite(out, content);

        }

    }


    
private void byteWrite(OutputStream out, byte[] bytes) throws IOException {
        
byte[] encoded = MyBase64Encoder.encode(bytes);
        
// 每行最多76个字符输出
        int maxChar = 76;
        
int idx = 0;
        
for (int size = encoded.length / maxChar; idx < size; idx++{
            out.write(encoded, idx 
* maxChar, maxChar);
            out.write(newLine.getBytes());
        }

        
if (encoded.length % maxChar > 0{
            out.write(encoded, idx 
* maxChar, encoded.length % maxChar);
            out.write(newLine.getBytes());
        }

    }

}


6、查看生成的邮件:
Return-Path: <from@test.com>
Message
-ID: <2737550.71240679122296.JavaMail.kinkding@kinkding-d1d01d>
MIME
-Version: 1.0
Delivered
-To: test@test.com
Received: from localhost ([
127.0.0.1])
          by kinkding
-d1d01d (JAMES SMTP Server 2.3.1) with SMTP ID 4
          
for <test@test.com>;
          Sun, 
26 Apr 2009 01:05:20 +0800 (CST)
Date: Sun, 
26 Apr 2009 01:05:20 +0800 (CST)
From: from@test.com
To: test@test.com
Subject: 
=?B?c3VqZWN0INb3zOI=?=
Content
-Type: multipart/mixed;boundary="----=_Part_010267414_1240679120062"

------=_Part_010267414_1240679120062
Content
-Type: text/plain
Content
-Transfer-Encoding: base64

dGV4dCDTyrz
+1f3OxA==


------=_Part_010267414_1240679120062
Content
-Type: application/octet-stream; name=music.txt
Content
-Transfer-Encoding: base64
Content
-Disposition: attachment; filename=music.txt

MjAwOMTqtsi
/4c7STtfaobDX7qGxDQoNCrCuyOfJ2cTqDQoNCg0KKy0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0rDQpNWVNRTDoNCrbLv9qjujMzMDYNClNlcnZlck5hbWU6TXlTUUwN
CnJvb3Qvcm9vdA0KDQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsNCmRvbWFp
bjoxMjcuMC4wLjENCnNlcnZlciBuYW1lOjEyNy4wLjAuMQ0KZW1haWw6dGVzdEB0ZXN0LmNvbQ0K
DQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsNClVDZW50ZXI6dWNlbnRlcg0K
ZGlzY3V6OmRpc2N1eg0KaHR0cDovL2xvY2FsaG9zdDo4MDcwL2Rpc2N1ei9pbmRleC5waHANCmh0
dHA6Ly8xOTIuMTY4LjE4LjI6ODA3MC9kaXNjdXovaW5kZXgucGhw


------=_Part_010267414_1240679120062

在FOXMAIL中查看邮件的截图:


7、点击下载代码

posted on 2009-04-26 01:19 俊星 阅读(1003) 评论(0)  编辑  收藏 所属分类: 代码库


只有注册用户登录后才能发表评论。


网站导航: