001 /* 002 * Copyright 2010 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package com.hs.mail.smtp.message; 017 018 import java.io.BufferedInputStream; 019 import java.io.BufferedOutputStream; 020 import java.io.File; 021 import java.io.FileInputStream; 022 import java.io.FileNotFoundException; 023 import java.io.FileOutputStream; 024 import java.io.IOException; 025 import java.io.InputStream; 026 import java.io.ObjectInputStream; 027 import java.io.ObjectOutputStream; 028 import java.io.OutputStream; 029 import java.io.Serializable; 030 import java.text.DateFormat; 031 import java.util.Date; 032 import java.util.Set; 033 import java.util.TreeSet; 034 035 import javax.mail.MessagingException; 036 import javax.mail.Session; 037 import javax.mail.internet.MailDateFormat; 038 import javax.mail.internet.MimeMessage; 039 040 import org.apache.commons.io.IOUtils; 041 042 import com.hs.mail.container.config.Config; 043 import com.hs.mail.imap.message.MailMessage; 044 import com.hs.mail.smtp.SmtpException; 045 046 /** 047 * 048 * @author Won Chul Doh 049 * @since May 31, 2010 050 * 051 */ 052 public class SmtpMessage implements Serializable { 053 054 private static final long serialVersionUID = 7983042396136261548L; 055 private static final DateFormat SMTP_DATE_FORMAT = new MailDateFormat(); 056 057 public static final int LOCAL = 1; 058 public static final int REMOTE = 2; 059 public static final int ALL = 3; 060 061 /** 062 * The number of mails generated. Access needs to be synchronized for 063 * thread safety and to ensure that all threads see the latest value. 064 */ 065 private static long count; 066 067 private String name; 068 069 private int node; 070 /** 071 * The sender of this message. 072 */ 073 private MailAddress from; 074 /** 075 * The remained recipients of this message. 076 */ 077 private Set<Recipient> recipients; 078 /** 079 * The retry count. 080 */ 081 private int retryCount = 0; 082 /** 083 * The last time this message was updated. 084 */ 085 private Date lastUpdate = new Date(); 086 /** 087 * The error message, if any, associated with this mail. 088 */ 089 private transient String errorMessage = ""; 090 /** 091 * The MailMessage that holds the mail data. 092 */ 093 private transient MailMessage mailMessage = null; 094 /** 095 * The time this message was created. 096 */ 097 private transient long time; 098 099 public SmtpMessage(MailAddress from, int node) { 100 this.time = System.currentTimeMillis(); 101 this.from = from; 102 this.recipients = new TreeSet<Recipient>(); 103 this.name = getId(); 104 this.node = node; 105 this.errorMessage = ""; 106 } 107 108 public SmtpMessage(MailAddress from) { 109 this(from, ALL); 110 } 111 112 public String getName() { 113 return name; 114 } 115 116 public int getNode() { 117 return node; 118 } 119 120 public void setNode(int node) { 121 this.node = node; 122 } 123 124 public MailAddress getFrom() { 125 return from; 126 } 127 128 public Set<Recipient> getRecipients() { 129 return recipients; 130 } 131 132 public void addRecipient(Recipient recipient) { 133 recipients.add(recipient); 134 } 135 136 public int getRecipientsSize() { 137 return recipients.size(); 138 } 139 140 public long getTime() { 141 return time; 142 } 143 144 public int getRetryCount() { 145 return retryCount; 146 } 147 148 public void setRetryCount(int retryCount) { 149 this.retryCount = retryCount; 150 } 151 152 public String getDate() { 153 return SMTP_DATE_FORMAT.format(new Date(time)); 154 } 155 156 public Date getLastUpdate() { 157 return lastUpdate; 158 } 159 160 public void setLastUpdate(Date lastUpdate) { 161 this.lastUpdate = lastUpdate; 162 } 163 164 public String getErrorMessage() { 165 return errorMessage; 166 } 167 168 public boolean isNotificationMessage() { 169 return "".equals(getFrom().getMailbox()); 170 } 171 172 public void appendErrorMessage(String errorMessage) { 173 if (this.errorMessage == null) 174 this.errorMessage = errorMessage; 175 else 176 this.errorMessage += errorMessage; 177 } 178 179 public File getDataFile() { 180 return new File(Config.getSpoolDirectory(), getName()); 181 } 182 183 private File getControlFile() { 184 return new File(Config.getSpoolDirectory(), getName() + ".control"); 185 } 186 187 public void setContent(InputStream is) throws IOException { 188 OutputStream os = null; 189 try { 190 os = new FileOutputStream(getDataFile()); 191 IOUtils.copyLarge(is, os); 192 } finally { 193 IOUtils.closeQuietly(os); 194 } 195 } 196 197 public void setContent(MimeMessage msg) throws IOException, 198 MessagingException { 199 OutputStream os = null; 200 try { 201 os = new BufferedOutputStream(new FileOutputStream(getDataFile())); 202 msg.writeTo(os); 203 } finally { 204 IOUtils.closeQuietly(os); 205 } 206 } 207 208 public void store() throws IOException { 209 File file = getControlFile(); 210 ObjectOutputStream os = null; 211 try { 212 OutputStream out = new BufferedOutputStream(new FileOutputStream( 213 file), 1024 * 4); 214 os = new ObjectOutputStream(out); 215 os.writeObject(this); 216 os.flush(); 217 } finally { 218 IOUtils.closeQuietly(os); 219 } 220 } 221 222 public void createTrigger() throws IOException { 223 File file = new File(Config.getSnapshotDirectory(), getName()); 224 file.createNewFile(); 225 } 226 227 public MailMessage getMailMessage() throws IOException { 228 if (mailMessage == null) { 229 mailMessage = MailMessage.createMailMessage(getDataFile()); 230 } 231 return mailMessage; 232 } 233 234 public MimeMessage getMimeMessage() throws MessagingException { 235 Session session = Session.getInstance(System.getProperties(), null); 236 InputStream is = null; 237 try { 238 is = new FileInputStream(getDataFile()); 239 return new MimeMessage(session, is); 240 } catch (FileNotFoundException e) { 241 throw new MessagingException(e.getMessage(), e); 242 } finally { 243 IOUtils.closeQuietly(is); 244 } 245 } 246 247 public void dispose() { 248 File file = getDataFile(); 249 if (file.exists()) { 250 if (file.delete()) { 251 file = getControlFile(); 252 if (file.exists()) { 253 file.delete(); 254 } 255 } 256 } 257 } 258 259 private String getId() { 260 File d = Config.getSpoolDirectory(); 261 File f; 262 String id; 263 do { 264 f = new File(d, (id = _getId())); 265 } while (f.exists()); 266 return id; 267 } 268 269 private String _getId() { 270 long localCount = -1; 271 synchronized (SmtpMessage.class) { 272 localCount = count++; 273 } 274 return new StringBuffer(64) 275 .append(time) 276 .append("-") 277 .append(localCount) 278 .toString(); 279 } 280 281 public static SmtpMessage readMessage(String name) throws SmtpException { 282 File dir = Config.getSpoolDirectory(); 283 File file = new File(dir, name + ".control"); 284 ObjectInputStream is = null; 285 try { 286 InputStream in = new BufferedInputStream(new FileInputStream(file), 287 1024); 288 is = new ObjectInputStream(in); 289 SmtpMessage message = (SmtpMessage) is.readObject(); 290 return message; 291 } catch (Exception e) { 292 throw new SmtpException("Error while reading message file: " + file); 293 } finally { 294 IOUtils.closeQuietly(is); 295 } 296 } 297 298 }