KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jsmtpd > core > mail > Email


1 /*
2  *
3  * Jsmtpd, Java SMTP daemon
4  * Copyright (C) 2005 Jean-Francois POUX, jf.poux@laposte.net
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  */

21
22 package org.jsmtpd.core.mail;
23
24 import java.io.ByteArrayInputStream JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.ObjectInputStream JavaDoc;
28 import java.io.ObjectOutput JavaDoc;
29 import java.io.ObjectOutputStream JavaDoc;
30 import java.io.RandomAccessFile JavaDoc;
31 import java.io.Serializable JavaDoc;
32 import java.util.Date JavaDoc;
33 import java.util.LinkedList JavaDoc;
34 import java.util.List JavaDoc;
35
36 import javax.mail.internet.MimeBodyPart JavaDoc;
37 import javax.mail.internet.MimeMessage JavaDoc;
38 import javax.mail.internet.MimeMultipart JavaDoc;
39
40 import org.jsmtpd.core.common.io.InvalidStreamParserInitialisation;
41 import org.jsmtpd.core.common.io.dataStream.DataStreamParser;
42 import org.jsmtpd.tools.DateUtil;
43
44 /**
45  * Info class for pending E-Mail<br>
46  * Any received mail is put in an instance of this class.<br>
47
48  * 7/03/2005<br>
49  * changed linkedlist of strings to a byte array (no errors of charset, efficient to store)
50  * @author Jean-Francois POUX
51  */

52 public class Email implements Serializable JavaDoc {
53     /**
54      * If there was someone identified by the server while emting the mail.
55      */

56     private String JavaDoc authContext = null;
57     /**
58      * Set by the receiver upon reception
59      */

60     private Date JavaDoc arrival;
61     /**
62      * Number of delivery attemps
63      */

64     private int attemps=0;
65
66     /**
67      * Recipients of the message
68      */

69     private List JavaDoc<Rcpt> rcpt = new LinkedList JavaDoc<Rcpt>();
70     /**
71      * Senders adress
72      */

73     private EmailAddress from;
74     /**
75      * Sender ip
76      */

77     private String JavaDoc receivedFrom;
78
79     /**
80      * Instance name on disk upon serialisation/writing
81      */

82     private String JavaDoc diskName = "default.mls";
83     /**
84      * Internal mails should not be filtered, and an already filtered mail should not be filtered again.
85      */

86     private boolean filtered = false;
87     /**
88      * Holding the DATA sent by the client, after eventual cleanings.
89      */

90     private byte[] dataBuffer = null;
91
92     public Email() {
93         generateDiskName();
94     }
95
96     /**
97      * Adds a recipient
98      */

99     public void addRcpt(EmailAddress in) {
100         rcpt.add(new Rcpt(in));
101     }
102
103     /**
104      * get the reception date
105      * @return reception data
106      */

107     public Date JavaDoc getArrival() {
108         return arrival;
109     }
110
111     public void setArrival(Date JavaDoc arrival) {
112         this.arrival = arrival;
113     }
114
115     public int getAttemps() {
116         return attemps;
117     }
118
119     public void setAttemps(int attemps) {
120         this.attemps = attemps;
121     }
122
123     public void increaseAttempts () {
124         attemps++;
125     }
126     
127     public String JavaDoc getReceivedFrom() {
128         return receivedFrom;
129     }
130
131     public void setReceivedFrom(String JavaDoc receivedFrom) {
132         this.receivedFrom = receivedFrom;
133     }
134
135     public List JavaDoc<Rcpt> getRcpt() {
136         return rcpt;
137     }
138
139     /**
140      * usefull for debugging, error mails. puts all the recipient into a String
141      * @return the string of RCPT
142      */

143     public String JavaDoc getRcptAsString() {
144         String JavaDoc rcp = "";
145         for (Rcpt elm : rcpt) {
146             rcp += elm.getEmailAddress().toString() + ";";
147         }
148         return rcp;
149     }
150
151     /**
152      * Dump for debugging
153      */

154     public String JavaDoc toString() {
155         String JavaDoc out = "Message Dump\n";
156
157         out += "Received on " + arrival + " From " + receivedFrom + "\n";
158         out += "Attempts :" + attemps + "\n";
159         out += "FROM :" + from + "\n";
160         Rcpt re;
161         for (int i = 0; i < rcpt.size(); i++) {
162             re = (Rcpt) rcpt.get(i);
163             out += "RCPT: " + re.getEmailAddress().toString() + "\n";
164         }
165
166         return out;
167     }
168
169     public EmailAddress getFrom() {
170         return from;
171     }
172
173     public void setFrom(EmailAddress from) {
174         this.from = from;
175     }
176
177     public long getSize() {
178         if (dataBuffer == null)
179             return 0;
180         return dataBuffer.length;
181     }
182
183     /**
184      * Saves the mail on disk
185      * @param fileName filename to use
186      * @param e the mail instance to save
187      * @throws IOException
188      */

189     public static void save(String JavaDoc fileName, Email e) throws IOException JavaDoc {
190         ObjectOutput JavaDoc out = new ObjectOutputStream JavaDoc(new FileOutputStream JavaDoc(fileName));
191         out.writeObject(e);
192         out.close();
193     }
194
195     /**
196      * Creates an instance from a file on disk
197      * @param fileName the name of the serialized email
198      * @return the instance
199      * @throws IOException
200      */

201     public static Email load(String JavaDoc fileName) throws IOException JavaDoc {
202         RandomAccessFile JavaDoc fp = new RandomAccessFile JavaDoc(fileName, "r");
203         byte[] data = new byte[(int) fp.length()];
204         fp.read(data);
205         fp.close();
206         ObjectInputStream JavaDoc in = new ObjectInputStream JavaDoc(new ByteArrayInputStream JavaDoc(data));
207         Email e = null;
208         try {
209             e = (Email) in.readObject();
210         } catch (ClassNotFoundException JavaDoc cnfe) {
211             cnfe.printStackTrace();
212         }
213         in.close();
214         return e;
215     }
216
217     /**
218      * If all recipients got the mail or permanent error, this should return true
219      * @return true if the mail is delivered
220      */

221     public boolean isDelivered() {
222         for (Rcpt elm : rcpt) {
223             if (!elm.isDelivered())
224                 return false;
225         }
226         return true; }
227
228     /**
229      * acces to the data buffer
230      * @return the buffer containing the mail
231      */

232     public byte[] getDataAsByte() {
233         return dataBuffer;
234     }
235
236     /**
237      * Convenient method to create an error message, as long as message parsing/processing tools are not thoughts yet ;)
238      * @param to recipient
239      * @param subject
240      * @param mailMessages a linkedlist of strings of the error message
241      * @param attach not implemented, but will attach a copy of the mail generating the error
242      * @return the error Email instance
243      */

244     public static Email createInternalMail(EmailAddress to, String JavaDoc subject, LinkedList JavaDoc<String JavaDoc> mailMessages, Email attach) {
245         Email e = new Email();
246         e.generateDiskName();
247         EmailAddress from = new EmailAddress();
248         e.setFiltered(true);
249         from.setUser("<>");
250         e.setFrom(from);
251         e.addRcpt(to);
252         e.setArrival(new Date JavaDoc());
253         e.setReceivedFrom("jsmtpd mailer daemon");
254
255         try {
256             DataStreamParser dsp = new DataStreamParser(512, 1024 * 1024 * 10);
257             dsp.appendString("Message-ID: <" + e.getDiskName() + ">");
258             dsp.appendString("From: \"Jsmtpd Mailer-Daemon\" <>");
259             dsp.appendString("To: <" + to.toString() + ">");
260             dsp.appendString("Subject: " + subject);
261             dsp.appendString("Date: " + DateUtil.currentRFCDate());
262             dsp.appendString("Content-Type: text/plain; charset=\"ISO-8859-1\"");
263             dsp.appendString("Content-Transfer-Encoding: 7bit");
264             dsp.appendString("");
265             for (String JavaDoc string : mailMessages) {
266                 dsp.appendString(string);
267             }
268             e.setDataBuffer(dsp.getData());
269         } catch (InvalidStreamParserInitialisation e1) {
270         }
271
272         return e;
273     }
274
275     public String JavaDoc generateDiskName() {
276         return diskName = Thread.currentThread().getId() + "-" + System.currentTimeMillis() + ".eml";
277     }
278
279     public String JavaDoc getDiskName() {
280         return diskName;
281     }
282
283     public void setDiskName(String JavaDoc diskName) {
284         this.diskName = diskName;
285     }
286
287     public boolean isFiltered() {
288         return filtered;
289     }
290
291     public void setFiltered(boolean filtered) {
292         this.filtered = filtered;
293     }
294
295     public void setDataBuffer(byte[] dataBuffer) {
296         this.dataBuffer = dataBuffer;
297     }
298
299     public String JavaDoc getAuthContext() {
300         return authContext;
301     }
302
303     public void setAuthContext(String JavaDoc authContext) {
304         this.authContext = authContext;
305     }
306     
307     public boolean hasRecipient (String JavaDoc in) {
308         for (Rcpt rc : rcpt) {
309             if (rc.getEmailAddress().toString().equals(in))
310                 return true;
311         }
312         return false;
313     }
314     
315     public boolean contains (String JavaDoc in) throws Exception JavaDoc {
316         if (dataBuffer==null)
317             return false;
318         MimeMessage JavaDoc msg = new MimeMessage JavaDoc(null,new ByteArrayInputStream JavaDoc(getDataAsByte()));
319         if (msg.isMimeType("text/plain"))
320             return msg.getContent().toString().contains(in) || msg.getContent().equals("");
321         if (msg.isMimeType("text/html"))
322             return msg.getContent().toString().contains(in)|| msg.getContent().equals("");
323         if (msg.isMimeType("multipart/alternative")) {
324              MimeMultipart JavaDoc mpart = (MimeMultipart JavaDoc) msg.getContent();
325              String JavaDoc all = "";
326                 for (int i= 0; i < mpart.getCount(); i++) {
327                     MimeBodyPart JavaDoc bodyPart = (MimeBodyPart JavaDoc) mpart.getBodyPart(i);
328                     if (bodyPart.isMimeType("text/html") || bodyPart.isMimeType("text/plain"))
329                         all+=bodyPart.getContent().toString();
330                 }
331                 return all.contains(in)|| all.equals("");
332         }
333         return false;
334     }
335     
336     public Email(Email original) {
337         setFrom(new EmailAddress(original.getFrom()));
338         byte[] newData = new byte[original.getDataAsByte().length];
339         System.arraycopy(original.dataBuffer,0,newData,0,newData.length);
340         setDataBuffer(newData);
341         generateDiskName();
342         if (original.authContext!=null)
343             setAuthContext(new String JavaDoc (original.authContext));
344         setFiltered(false);
345         if (original.getReceivedFrom()!=null)
346             setReceivedFrom(new String JavaDoc (original.receivedFrom));
347         List JavaDoc<Rcpt> rcpts = original.getRcpt();
348         for (Rcpt rcpt : rcpts) {
349             addRcpt(rcpt.getEmailAddress());
350         }
351     }
352     public Email copy () {
353         return new Email(this);
354     }
355 }
Popular Tags