今天看到一个朋友的Blog, 就忍不住把以前写的这个代码拿出来了, 不然这代码闲着也是闲着. 当然没有必要照搬全部, 只要中间的那个 zoomImage() 方法即可. 当然还有设置图片部分透明的方法.
/** @(#)BlogMailHandler.java 1.00 2004-10-4** Copyright 2004 . All rights reserved.* PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*/import java.awt.Color;import java.awt.Graphics2D;import java.awt.RenderingHints;import java.awt.image.BufferedImage;import java.io.BufferedInputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.sql.Timestamp;import java.util.Properties;
import javax.imageio.ImageIO;import javax.mail.Address;import javax.mail.FetchProfile;import javax.mail.Flags;import javax.mail.Folder;import javax.mail.Message;import javax.mail.MessagingException;import javax.mail.Multipart;import javax.mail.Part;import javax.mail.Session;import javax.mail.Store;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeUtility;
import studio.beansoft.jsp.StringUtil;import com.keypoint.PngEncoder;import com.keypoint.PngEncoderB;
import moblog.*;
/*** BlogMailHandler, 彩E博客邮件的处理程序.* 每 15 分钟更新一次邮件, 发布博客并更新用户产量.* 邮件 POP3 帐户信息位于 /blogmail.properties 文件中.* * @author 刘长炯* @version 1.00 2004-10-4*/public class BlogMailHandler extends Thread {/*** @alias 文件根目录 : String*/private String rootDirectory;
// 邮件帐户配置属性private static Properties props = new Properties();
static {try {InputStream in = BlogMailHandler.class.getResourceAsStream("/blogmail.properties");props.load(in);in.close();} catch (Exception ex) {System.err.println("无法加载配置文件 blogmail.properties:"+ ex.getMessage());ex.printStackTrace();}}
// 图像加载的共享实例, 在 Linux 平台上有可能无法生成图形对象// private static Frame sharedFrame = new Frame();private boolean shouldExit = false;
public BlogMailHandler() {}/** 定时开始读取邮件信息 */public void startMailProcessCycle() {start();}public void run() {while(!shouldExit) {doProcess();try {// 每15分钟读取一次Thread.currentThread().sleep(60 * 15 * 1000);} catch (Exception e) {e.printStackTrace();}} }/** 处理进程 */private void doProcess() {try {Store store = openStore();Folder inbox = openInbox(store);
processAllMessages(inbox);inbox.close(true);store.close();} catch (Exception e) {e.printStackTrace();} }protected void finalize() throws Throwable {shouldExit = true;}/*** 缩放原始图片到合适大小.* * @param srcImage - 原始图片* @return BufferedImage - 处理结果*/private BufferedImage zoomImage(BufferedImage srcImage) {int MAX_WIDTH = 100;// TODO: 缩放后的图片最大宽度int MAX_HEIGHT = 160;// TODO: 缩放后的图片最大高度int imageWidth = srcImage.getWidth(null);int imageHeight = srcImage.getHeight(null);
// determine thumbnail size from MAX_WIDTH and MAX_HEIGHTint thumbWidth = MAX_WIDTH;int thumbHeight = MAX_HEIGHT;double thumbRatio = (double)thumbWidth / (double)thumbHeight;double imageRatio = (double)imageWidth / (double)imageHeight;if (thumbRatio < imageRatio) {thumbHeight = (int)(thumbWidth / imageRatio);} else {thumbWidth = (int)(thumbHeight * imageRatio);}// 如果图片小于所略图大小, 不作处理if(imageWidth < MAX_WIDTH && imageHeight < MAX_HEIGHT) {thumbWidth = imageWidth;thumbHeight = imageHeight;}
// draw original image to thumbnail image object and// scale it to the new size on-the-fly (drawImage is quite powerful)BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);//thumbImage.getscGraphics2D graphics2D = thumbImage.createGraphics();graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);graphics2D.drawImage(srcImage, 0, 0, thumbWidth, thumbHeight, null);System.out.println("thumbWidth=" + thumbWidth);System.out.println("thumbHeight=" + thumbHeight);return thumbImage;}
// Open mail Storeprivate Store openStore() throws Exception {Store store;//--[ Set up the default parametersprops.put("mail.transport.protocol", "pop");props.put("mail.pop.port", "110");// props.put("mail.debug", "true");
Session session = Session.getInstance(props);store = session.getStore("pop3");// void javax.mail.Service.connect(String host, String user, String// password) throws// MessagingExceptionstore.connect(props.getProperty("mail.pop3.host"), props.getProperty("username"), props.getProperty("password"));return store;}
// Open Inboxprivate Folder openInbox(Store store) throws Exception {Folder folder = store.getDefaultFolder();if (folder == null) {System.out.println("Problem occurred");System.exit(1);}
Folder popFolder = folder.getFolder("INBOX");popFolder.open(Folder.READ_WRITE);return popFolder;}
/** Close mail store. */private void closeStore(Store store) {try {store.close();} catch (MessagingException e) {e.printStackTrace();}}
/*** 处理账号中的所有邮件并删除这些邮件.* * @param folder - Folder, 收件箱* @throws Exception*/private void processAllMessages(Folder folder) throws Exception {
Message[] listOfMessages = folder.getMessages();FetchProfile fProfile = new FetchProfile();fProfile.add(FetchProfile.Item.ENVELOPE);folder.fetch(listOfMessages, fProfile);
for (int i = 0; i < listOfMessages.length; i++) {try {processSingleMail(listOfMessages[i]);} catch (Exception e) {e.printStackTrace();}
// Delete maillistOfMessages[i].setFlag(Flags.Flag.DELETED, true);}}
/*** 处理单个 Email, 将文章发表, 并将附件图片转换为 PNG 后存入用户目录.** @param message -* Message, email 消息*/private void processSingleMail(Message message) throws Exception {BlogContent content = new BlogContent();BlogUser user = new BlogUser();BlogPicture picture = new BlogPicture();
// 1. 假定发件人为手机号, 并尝试根据手机号查找用户Address[] addList = message.getFrom();if (addList.length > 0) {String userMail = ((InternetAddress) addList[0]).getAddress();// 取出 彩E 邮件用户手机号, 格式: 手机号@someone.comString mobileNumber = userMail.substring(0, userMail.indexOf("@"));System.out.println("用户手机号为:" + mobileNumber);if (!user.findByMDN(mobileNumber)) {// Not found user, then returnSystem.err.println("user " + ((InternetAddress) addList[0]).getAddress() + " not found.");return;}}
// 2. 尝试读取邮件正文// 复合邮件if (message.isMimeType("multipart/*")) {// 标记是否处理过图片boolean imageHasProcessed = false;Multipart multipart = (Multipart) message.getContent();for (int i = 0, n = multipart.getCount(); i < n; i++) {// System.err.println("Reading multipart " + i);Part part = multipart.getBodyPart(i);// System.err.println("ContentType = " + part.getContentType());
// 3. 处理附件图片, 只处理第一个图片String disposition = part.getDisposition();// System.err.println("disposition = " + disposition);if (disposition != null&& (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE)) && !imageHasProcessed) {// 需要反编码邮件文件名, 有的邮件的附件的文件名是经过编码的, // 但是 JavaMail 并不能处理出来(BeanSoft, 2004-10-13)String fileName = MimeUtility.decodeText(part.getFileName());String ext = StringUtil.getExtension(fileName).toLowerCase();System.err.println("part.getFileName() = " + fileName);
if ("gif".equals(ext) || "jpg".equals(ext)|| "png".equals(ext)) {BufferedInputStream dataIn = null;// 转换非 PNG 格式图片为 PNG 格式 -- 取消// if (!"png".equals(ext)) {ByteArrayOutputStream pngOut = new ByteArrayOutputStream();try {// Convert image file to PNG fileBufferedImage buffImg = ImageIO.read(part.getInputStream());// Read image file from attachment// 缩放图片buffImg = zoomImage(buffImg);
int imageWidth = buffImg.getWidth(null);int imageHeight = buffImg.getHeight(null);BufferedImage outImg = new BufferedImage(imageWidth, imageHeight,// BufferedImage.TYPE_4BYTE_ABGR 是 24 位色深, TYPE_BYTE_INDEXED 是 8 位BufferedImage.TYPE_INT_RGB);// 使图片透明// embossImage(buffImg, outImg);outImg.getGraphics().drawImage(buffImg, 0, 0, imageWidth, imageHeight, null);// Save image to PNG output stream// ImageIO.write(outImg, "png", pngOut);// Save using keypoint PNG encoderPngEncoderB pngb = new PngEncoderB(outImg,PngEncoder.NO_ALPHA, 0, 9);pngOut.write(pngb.pngEncode());dataIn = new BufferedInputStream(new ByteArrayInputStream(pngOut.toByteArray()));} catch (Exception e) {}// } else {// dataIn = new BufferedInputStream(part// .getInputStream());// }// All pictures change to png formatext = "png"// Insert picture info into databasepicture.setBlogID(user.getId());picture.setCreationTime(new Timestamp(System.currentTimeMillis()));picture.setFileEXName(ext);picture.setTitle(fileName);picture.create();// Save png file to user directory, /users/userId/pictureId.pngFileOutputStream outFile = new FileOutputStream(rootDirectory + File.separatorChar + user.getId() + File.separatorChar+ picture.getId() + "." + ext);int c;while ((c = dataIn.read()) != -1) {outFile.write(c);}
outFile.close();imageHasProcessed = true;}}// 纯文本邮件, 带附件else if (part.isMimeType("text/plain")) {String body = part.getContent().toString();String title = message.getSubject();
content.setBlogID(user.getId());content.setCreationTime(new Timestamp(System.currentTimeMillis()));content.setTitle(title);content.setNote(body);}
// 典型的 HTML 和 文本邮件可选形式, 进一步分析if (part.getContent() instanceof Multipart) {Multipart subPart = (Multipart) part.getContent();
for (int j = 0, m = subPart.getCount(); j < m; j++) {Part mailText = subPart.getBodyPart(j);
if (mailText.isMimeType("text/plain")) {String body = mailText.getContent().toString();String title = message.getSubject();
content.setBlogID(user.getId());content.setCreationTime(new Timestamp(System.currentTimeMillis()));content.setTitle(title);content.setNote(body);break;}}}
}// End of multipart parse
// 4. 创建博客记录content.setPictureId(picture.getId());if(content.create() > 0) {// 更新用户产量user.setPostTimes(user.getPostTimes() + 1);user.update();}}// 纯文本邮件, 无附件else if (message.isMimeType("text/plain")) {String body = message.getContent().toString();String title = message.getSubject();
content.setBlogID(user.getId());content.setCreationTime(new Timestamp(System.currentTimeMillis()));content.setTitle(title);content.setNote(body);
if(content.create() > 0) {// 更新用户产量user.setPostTimes(user.getPostTimes() + 1);user.update();}}}
// 测试, 尝试连接一次到邮件服务器public static void main(String[] args) {BlogMailHandler handler = new BlogMailHandler();
// TODO: debug, 请在 JSP 里面设置图片目录的根路径handler.rootDirectory = "F:/Moblog/users/"handler.doProcess();}
/*** @return Returns the rootDirectory.*/public String getRootDirectory() {return rootDirectory;}
/*** @param rootDirectory* The rootDirectory to set.*/public void setRootDirectory(String property1) {this.rootDirectory = property1;}
/** Make image transparent */private void embossImage(BufferedImage srcImage, BufferedImage destImage) {int width = srcImage.getWidth();int height = srcImage.getHeight();
for (int i = 0; i < height; i++) {for (int j = 0; j < width; j++) {int newColor = handlesinglepixel(j, i, srcImage.getRGB(j, i));destImage.setRGB(j, i, newColor);}}}
// Handle picture single pixel, change 0xff00ff color to transparentprivate int handlesinglepixel(int x, int y, int pixel) {int alpha = (pixel >> 24) & 0xff;int red = (pixel >> 16) & 0xff;int green = (pixel >> 8) & 0xff;int blue = (pixel) & 0xff;// Deal with the pixel as necessary...// alpha 为 0 时完全透明, 为 255 时不透明Color back = new Color(0xFF00FF);// 将与背景色相同(此处PNG图片为紫色)的像素点的透明度设为透明if (isDeltaInRange(back.getRed(), red, 2)&& isDeltaInRange(back.getGreen(), green, 2)&& isDeltaInRange(back.getBlue(), blue, 2)) {// System.out.println("x=" + x + "y=" + y + " is transparent.");alpha = 0;}// red = red / 2;// //green = green / 2 + 68;// blue = blue / 2;
return alpha << 24 | red << 16 | green << 8 | blue;}
// 判断两个整数的差是否在一定范围之内private boolean isDeltaInRange(int first, int second, int range) {if (first - second <= range && second - first <= range)return true;return false;}} |