我的意思不是给多个人发送件,这个比较好实现。比如我如果给A和B同时发邮件,A打开邮件在邮件头处的收件人可以看到A,B。同理B也一样。这个要怎么做呀?实在没分了,会的帮帮吧!
5条回答
- qq1988627 2011-08-17 12:00关注
package com.byd.core;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import sun.misc.BASE64Encoder;
/**
- 该类使用Socket连接到邮件服务器, 并实现了向指定邮箱发送邮件及附件的功能。
-
@author Kou Hongtao
*/
public class Email {/**
- 换行符 */ private static final String LINE_END = "\r\n";
/**
- 值为“true”输出高度信息(包括服务器响应信息),值为“ false”则不输出调试信息。 */ private boolean isDebug = true;
/**
- 值为“true”则在发送邮件{@link Mail#send()} 过程中会读取服务器端返回的消息,
- 并在邮件发送完毕后将这些消息返回给用户。 */ private boolean isAllowReadSocketInfo = true;
/**
- 邮件服务器地址 */ private String host;
/**
- 发件人邮箱地址 */ private String from;
/**
- 收件人邮箱地址 */ private List to;
/**
- 抄送地址 */ private List cc;
/**
- 暗送地址 */ private List bcc;
/**
- 邮件主题 */ private String subject;
/**
- 用户名 */ private String user;
/**
- 密码 */ private String password;
/**
- MIME邮件类型 */ private String contentType;
/**
- 用来绑定多个邮件单元{@link #partSet}
- 的分隔标识,我们可以将邮件的正文及每一个附件都看作是一个邮件单元 。 */ private String boundary;
/**
- 邮件单元分隔标识符,该属性将用来在邮件中作为分割各个邮件单元的标识 。 */ private String boundaryNextPart;
/**
- 传输邮件所采用的编码 */ private String contentTransferEncoding;
/**
- 设置邮件正文所用的字符集 */ private String charset;
/**
- 内容描述 */ private String contentDisposition;
/**
- 邮件正文 */ private String content;
/**
- 发送邮件日期的显示格式 */ private String simpleDatePattern;
/**
- 附件的默认MIME类型 */ private String defaultAttachmentContentType;
/**
- 邮件单元的集合,用来存放正文单元和所有的附件单元。 */ private List partSet;
private List alternativeList;
private String mixedBoundary;
private String mixedBoundaryNextPart;
/**
- 不同类型文件对应的{@link MIME} 类型映射。在添加附件
- {@link #addAttachment(String)} 时,程序会在这个映射中查找对应文件的
- {@link MIME} 类型,如果没有, 则使用
- {@link #defaultAttachmentContentType} 所定义的类型。 */ private static Map contentTypeMap;
private static enum TextType {
PLAIN("plain"), HTML("html");private String v; private TextType(String v) { this.v = v; } public String getValue() { return this.v; }
}
static {
// MIME Media Types
contentTypeMap = new HashMap();
contentTypeMap.put("xls", "application/vnd.ms-excel");
contentTypeMap.put("xlsx", "application/vnd.ms-excel");
contentTypeMap.put("xlsm", "application/vnd.ms-excel");
contentTypeMap.put("xlsb", "application/vnd.ms-excel");
contentTypeMap.put("doc", "application/msword");
contentTypeMap.put("dot", "application/msword");
contentTypeMap.put("docx", "application/msword");
contentTypeMap.put("docm", "application/msword");
contentTypeMap.put("dotm", "application/msword");
}/**
- 该类用来实例化一个正文单元或附件单元对象,他继承了 {@link Mail}
- ,在这里制作这个子类主要是为了区别邮件单元对象和邮件服务对象 ,使程序易读一些。
- 这些邮件单元全部会放到partSet 中,在发送邮件 {@link #send()}时, 程序会调用
- {@link #getAllParts()} 方法将所有的单元合并成一个符合MIME格式的字符串。
- @author Kou Hongtao */ private class MailPart extends Email { public MailPart() { } }
/**
- 默认构造函数 */ public Email() { defaultAttachmentContentType = "application/octet-stream"; simpleDatePattern = "yyyy-MM-dd HH:mm:ss"; boundary = "--=_NextPart_zlz_3907_" + System.currentTimeMillis(); boundaryNextPart = "--" + boundary; contentTransferEncoding = "base64"; contentType = "multipart/mixed"; charset = Charset.defaultCharset().name(); partSet = new ArrayList(); alternativeList = new ArrayList(); to = new ArrayList(); cc = new ArrayList(); bcc = new ArrayList(); mixedBoundary = "=NextAttachment_zlz_" + System.currentTimeMillis(); mixedBoundaryNextPart = "--" + mixedBoundary; }
/**
- 根据指定的完整文件名在 {@link #contentTypeMap} 中查找其相应的MIME类型,
- 如果没找到,则返回 {@link #defaultAttachmentContentType}
- 所指定的默认类型。
- @param fileName
- 文件名
-
@return 返回文件对应的MIME类型。
*/
private String getPartContentType(String fileName) {
String ret = null;
if (null != fileName) {
int flag = fileName.lastIndexOf(".");
if (0 <= flag && flag < fileName.length() - 1) {
fileName = fileName.substring(flag + 1);
}
ret = contentTypeMap.get(fileName);
}if (null == ret) {
ret = defaultAttachmentContentType;
}
return ret;
}
/**
- 将给定字符串转换为base64编码的字符串
- @param str
- 需要转码的字符串
- @param charset
- 原字符串的编码格式
- @return base64编码格式的字符 */ private String toBase64(String str, String charset) { if (null != str) { try { return toBase64(str.getBytes(charset)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return ""; }
/**
- 将指定的字节数组转换为base64格式的字符串
- @param bs
- 需要转码的字节数组
- @return base64编码格式的字符 */ private String toBase64(byte[] bs) { return new BASE64Encoder().encode(bs); }
/**
- 将给定字符串转换为base64编码的字符串
- @param str
- 需要转码的字符串
- @return base64编码格式的字符 */ private String toBase64(String str) { return toBase64(str, Charset.defaultCharset().name()); }
/**
- 将所有的邮件单元按照标准的MIME格式要求合并。
-
@return 返回一个所有单元合并后的字符串。
*/
private String getAllParts() {StringBuilder sbd = new StringBuilder(LINE_END);
sbd.append(mixedBoundaryNextPart);
sbd.append(LINE_END);
sbd.append("Content-Type: ");
sbd.append("multipart/alternative");
sbd.append(";");
sbd.append("boundary=\"");
sbd.append(boundary).append("\""); // 邮件类型设置
sbd.append(LINE_END);
sbd.append(LINE_END);
sbd.append(LINE_END);
addPartsToString(alternativeList, sbd, getBoundaryNextPart());
sbd.append(getBoundaryNextPart()).append("--");
sbd.append(LINE_END);addPartsToString(partSet, sbd, mixedBoundaryNextPart);
sbd.append(LINE_END);
sbd.append(mixedBoundaryNextPart).append("--");
sbd.append(LINE_END);
// sbd.append(boundaryNextPart).
// append(LINE_END);
alternativeList.clear();
partSet.clear();
return sbd.toString();
}
private void addPartsToString(List list, StringBuilder sbd,
String nextPartString) {
int partCount = list.size();
for (int i = 0; i < partCount; i++) {
Email attachment = list.get(i);
String attachmentContent = attachment.getContent();
if (null != attachmentContent && 0 < attachmentContent.length()) {
sbd.append(nextPartString).append(LINE_END);
sbd.append("Content-Type: ");
sbd.append(attachment.getContentType());
sbd.append(LINE_END);
sbd.append("Content-Transfer-Encoding: ");
sbd.append(attachment.getContentTransferEncoding());
sbd.append(LINE_END);
String cd = attachment.getContentDisposition();
if (null != cd) {
sbd.append("Content-Disposition: ");
sbd.append(cd);
sbd.append(LINE_END);
}sbd.append(LINE_END); sbd.append(attachmentContent); sbd.append(LINE_END); } }
}
/**
- 添加邮件正文单元 */ private void addContent() { if (null != content) { MailPart part = new MailPart(); part.setContent(toBase64(content)); part.setContentType("text/plain;charset=\"" + charset + "\""); alternativeList.add(part); } }
private String listToMailString(List mailAddressList) {
StringBuilder sbd = new StringBuilder();
if (null != mailAddressList) {
int listSize = mailAddressList.size();
for (int i = 0; i < listSize; i++) {
if (0 != i) {
sbd.append(";");
}
sbd.append("<").append(mailAddressList.get(i)).append(">");
}
}
return sbd.toString();
}private List getrecipient() {
List list = new ArrayList();
list.addAll(to);
list.addAll(cc);
list.addAll(bcc);
return list;
}/**
- 添加超文本内容
- @param text */ public void addHtmlContent(String text) { addContent(text, TextType.HTML); }
/**
- 添加纯文本内容
- @param text */ public void addTextContent(String text) { addContent(text, TextType.PLAIN); }
private void addContent(String text, TextType type) {
if (null != text) {
MailPart part = new MailPart();
part.setContent(toBase64(text));
part.setContentType("text/" + type.getValue() + ";charset=\""
+ charset + "\"");
alternativeList.add(part);
}
}/**
- 添加一个附件单元
- @param filePath
- 文件路径 */ public void addAttachment(String filePath) { addAttachment(filePath, null); }
public void addTo(String mailAddress) {
this.to.add(mailAddress);
}public void addCc(String mailAddress) {
this.cc.add(mailAddress);
}public void addBcc(String mailAddress) {
this.bcc.add(mailAddress);
}/**
- 添加一个附件单元
- @param filePath
- 文件路径
- @param charset
- 文件编码格式 */ public void addAttachment(String filePath, String charset) { if (null != filePath && filePath.length() > 0) { File file = new File(filePath); try { addAttachment(file.getName(), new FileInputStream(file), charset); } catch (FileNotFoundException e) { System.out.println("错误:" + e.getMessage()); System.exit(1); } } }
/**
- 添加一个附件单元
- @param fileName
- 文件名
- @param attachmentStream
- 文件流
- @param charset
-
文件编码格式
*/
public void addAttachment(String fileName, InputStream attachmentStream,
String charset) {
try {byte[] bs = null; if (null != attachmentStream) { int buffSize = 1024; byte[] buff = new byte[buffSize]; byte[] temp; bs = new byte[0]; int readTotal = 0; while (-1 != (readTotal = attachmentStream.read(buff))) { temp = new byte[bs.length]; System.arraycopy(bs, 0, temp, 0, bs.length); bs = new byte[temp.length + readTotal]; System.arraycopy(temp, 0, bs, 0, temp.length); System.arraycopy(buff, 0, bs, temp.length, readTotal); } } if (null != bs) { MailPart attachmentPart = new MailPart(); charset = null != charset ? charset : Charset.defaultCharset() .name(); String contentType = getPartContentType(fileName) + ";name=\"=?" + charset + "?B?" + toBase64(fileName) + "?=\""; attachmentPart.setCharset(charset); attachmentPart.setContentType(contentType); attachmentPart.setContentDisposition("attachment;filename=\"=?" + charset + "?B?" + toBase64(fileName) + "?=\""); attachmentPart.setContent(toBase64(bs)); partSet.add(attachmentPart); }
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != attachmentStream) {
try {
attachmentStream.close();
attachmentStream = null;
} catch (IOException e) {
e.printStackTrace();
}
}Runtime.getRuntime().gc(); Runtime.getRuntime().runFinalization();
}
}
/**
- 发送邮件
-
@return 邮件服务器反回的信息
*/
public String send() {// 对象申明
// 当邮件发送完毕后,以下三个对象(Socket、
// PrintWriter,
// BufferedReader)需要关闭。
Socket socket = null;
PrintWriter pw = null;
BufferedReader br = null;try {
socket = new Socket(host, 25);
pw = new PrintWriter(socket.getOutputStream());
br = new BufferedReader(new InputStreamReader(socket
.getInputStream()));StringBuilder infoBuilder = new StringBuilder( "\nServer info: \n------------\n"); // 与服务器建立连接 pw.write("HELO ".concat(host).concat(LINE_END)); // 连接到邮件服务 if (!readResponse(pw, br, infoBuilder, "220")) return infoBuilder.toString(); pw.write("AUTH LOGIN".concat(LINE_END)); // 登录 if (!readResponse(pw, br, infoBuilder, "250")) return infoBuilder.toString(); pw.write(toBase64(user).concat(LINE_END)); // 输入用户名 if (!readResponse(pw, br, infoBuilder, "334")) return infoBuilder.toString(); pw.write(toBase64(password).concat(LINE_END)); // 输入密码 if (!readResponse(pw, br, infoBuilder, "334")) return infoBuilder.toString(); pw.write("MAIL FROM:<" + from + ">" + LINE_END); // 发件人邮箱地址 if (!readResponse(pw, br, infoBuilder, "235")) return infoBuilder.toString(); List<String> recipientList = getrecipient(); // 收件邮箱地址 for (int i = 0; i < recipientList.size(); i++) { pw.write("RCPT TO:<" + recipientList.get(i) + ">" + LINE_END); if (!readResponse(pw, br, infoBuilder, "250")) return infoBuilder.toString(); } // System.out.println( // getAllSendAddress()); pw.write("DATA" + LINE_END); // 开始输入邮件 if (!readResponse(pw, br, infoBuilder, "250")) return infoBuilder.toString(); flush(pw); // 设置邮件头信息 StringBuffer sbf = new StringBuffer("From: <" + from + ">" + LINE_END); // 发件人 sbf.append("To: " + listToMailString(to) + LINE_END);// 收件人 sbf.append("Cc: " + listToMailString(cc) + LINE_END);// 收件人 sbf.append("Bcc: " + listToMailString(bcc) + LINE_END);// 收件人 sbf.append("Subject: " + subject + LINE_END);// 邮件主题 SimpleDateFormat sdf = new SimpleDateFormat(simpleDatePattern); sbf.append("Date: ").append(sdf.format(new Date())); sbf.append(LINE_END); // 发送时间 sbf.append("Content-Type: "); sbf.append(contentType); sbf.append(";"); sbf.append("boundary=\""); sbf.append(mixedBoundary).append("\""); // 邮件类型设置 sbf.append(LINE_END); // sbf.append( // "This is a multi-part message in MIME format." // ); // sbf.append(LINE_END); // 添加邮件正文单元 addContent(); // 合并所有单元,正文和附件。 sbf.append(getAllParts()); // System.out.println( // "///////////\n" + // sbf.toString() + // "///////////////\n"); // 发送 sbf.append(LINE_END).append(".").append(LINE_END); pw.write(sbf.toString()); readResponse(pw, br, infoBuilder, "354"); flush(pw); // QUIT退出 pw.write("QUIT" + LINE_END); if (!readResponse(pw, br, infoBuilder, "250")) return infoBuilder.toString(); flush(pw); return infoBuilder.toString();
} catch (Exception e) {
e.printStackTrace();
return "Exception:>" + e.getMessage();
} finally {
// 释放资源
try {
if (null != socket)
socket.close();
if (null != pw)
pw.close();
if (null != br)
br.close();
} catch (IOException e) {
e.printStackTrace();
}// this.to.clear(); // this.cc.clear(); // this.bcc.clear(); this.partSet.clear();
}
}
/**
- 将SMTP命令发送到邮件服务器
- @param pw
- 邮件服务器输入流 */ private void flush(PrintWriter pw) { if (!isAllowReadSocketInfo) { pw.flush(); } }
/**
- 读取邮件服务器的响应信息
- @param pw
- 邮件服务器输入流
- @param br
- 邮件服务器输出流
- @param infoBuilder
- 用来存放服务器响应信息的字符串缓冲
- @param msgCode
- @return
- @throws IOException */ private boolean readResponse(PrintWriter pw, BufferedReader br, StringBuilder infoBuilder, String msgCode) throws IOException { if (isAllowReadSocketInfo) { pw.flush(); String message = br.readLine(); infoBuilder.append("SERVER:/>"); infoBuilder.append(message).append(LINE_END); if (null == message || 0 > message.indexOf(msgCode)) { System.out.println("ERROR: " + message); pw.write("QUIT".concat(LINE_END)); pw.flush(); return false; } if (isDebug) { System.out.println("DEBUG:/>" + msgCode + "/" + message); } } return true; }
public String getBoundaryNextPart() {
return boundaryNextPart;
}public void setBoundaryNextPart(String boundaryNextPart) {
this.boundaryNextPart = boundaryNextPart;
}public String getDefaultAttachmentContentType() {
return defaultAttachmentContentType;
}public void setDefaultAttachmentContentType(
String defaultAttachmentContentType) {
this.defaultAttachmentContentType = defaultAttachmentContentType;
}public String getHost() {
return host;
}public void setHost(String host) {
this.host = host;
}public String getFrom() {
return from;
}public void setFrom(String from) {
this.from = from;
}public List getTo() {
return to;
}public void setTo(List to) {
this.to = to;
}public String getSubject() {
return subject;
}public void setSubject(String subject) {
this.subject = subject;
}public String getUser() {
return user;
}public void setUser(String user) {
this.user = user;
}public String getPassword() {
return password;
}public void setPassword(String password) {
this.password = password;
}public String getContentType() {
return contentType;
}public void setContentType(String contentType) {
this.contentType = contentType;
}public String getBoundary() {
return boundary;
}public void setBoundary(String boundary) {
this.boundary = boundary;
}public String getContentTransferEncoding() {
return contentTransferEncoding;
}public void setContentTransferEncoding(String contentTransferEncoding) {
this.contentTransferEncoding = contentTransferEncoding;
}public String getCharset() {
return charset;
}public void setCharset(String charset) {
this.charset = charset;
}public String getContentDisposition() {
return contentDisposition;
}public void setContentDisposition(String contentDisposition) {
this.contentDisposition = contentDisposition;
}public String getSimpleDatePattern() {
return simpleDatePattern;
}public void setSimpleDatePattern(String simpleDatePattern) {
this.simpleDatePattern = simpleDatePattern;
}public String getContent() {
return content;
}/**
- @param content
- @deprecated 请参见 {@link #addTextContent(String)} 和
- {@link #addHtmlContent(String)} */ public void setContent(String content) { this.content = content; }
public boolean isAllowReadSocketInfo() {
return isAllowReadSocketInfo;
}public void setAllowReadSocketInfo(boolean isAllowReadSocketInfo) {
this.isAllowReadSocketInfo = isAllowReadSocketInfo;
}/**
-
@param args
*/
public static void main(String[] args) {
// 应用示例:线程化发送邮件
new Thread() {
@Override
public void run() {
System.out.println("SENDER-" + this.getId() + ":/>"
+ "开始发送邮件...");// 创建邮件对象 Email mail = new Email(); mail.setHost("smtp.byd.com"); // 邮件服务器地址 mail.setFrom("kou.hongtao@byd.com"); // 发件人邮箱 mail.addTo("zhang.peng24@byd.com"); // 收件人邮箱 mail.addCc("zhao.xiaowei@byd.com"); mail.addBcc(""); mail.setSubject("研发物料邮件发送测试"); // 邮件主题 mail.setUser("kou.hongtao"); // 用户名 mail.setPassword("byd@user"); // 密码 // 邮件正文 mail.addHtmlContent("<h3>研发物料邮件测试,请不要回复!</h3>"); // mail.addAttachment("add.js"); // 添加附件 System.out.println(mail.send()); // 发送 System.out.println("SENDER-" + this.getId() + ":/>" + "邮件已发送完毕!"); }
}.start();
}
}
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报
悬赏问题
- ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
- ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
- ¥15 绘制多分类任务的roc曲线时只画出了一类的roc,其它的auc显示为nan
- ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
- ¥20 腾讯企业邮箱邮件可以恢复么
- ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
- ¥15 错误 LNK2001 无法解析的外部符号
- ¥50 安装pyaudiokits失败
- ¥15 计组这些题应该咋做呀
- ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?