source: trunk/src/org/expeditee/agents/mail/MailSession.java@ 282

Last change on this file since 282 was 282, checked in by ra33, 16 years ago
File size: 15.1 KB
Line 
1package org.expeditee.agents.mail;
2
3import java.awt.Color;
4import java.awt.Point;
5import java.io.BufferedReader;
6import java.io.InputStream;
7import java.io.InputStreamReader;
8import java.util.Collection;
9import java.util.Date;
10import java.util.LinkedList;
11import java.util.Properties;
12
13import javax.mail.Authenticator;
14import javax.mail.Folder;
15import javax.mail.Message;
16import javax.mail.MessagingException;
17import javax.mail.Multipart;
18import javax.mail.Part;
19import javax.mail.PasswordAuthentication;
20import javax.mail.Session;
21import javax.mail.Store;
22import javax.mail.Transport;
23import javax.mail.Flags.Flag;
24import javax.mail.event.MessageCountAdapter;
25import javax.mail.event.MessageCountEvent;
26import javax.mail.internet.InternetAddress;
27import javax.mail.internet.MimeMessage;
28
29import org.expeditee.importer.FrameDNDTransferHandler;
30import org.expeditee.gui.AttributeValuePair;
31import org.expeditee.gui.Frame;
32import org.expeditee.gui.FrameCreator;
33import org.expeditee.gui.MessageBay;
34import org.expeditee.items.Item;
35import org.expeditee.items.Text;
36
37public class MailSession {
38 public static boolean _autoConnect = false;
39
40 private static MailSession _theMailSession = null;
41
42 private Session _session;
43
44 private Transport _transport;
45
46 private Store _store;
47
48 private Folder _folder;
49
50 private String _address;
51
52 private String _username;
53
54 private String _password;
55
56 private String _mailServer;
57
58 private String _serverType;
59
60 private Boolean _bConnecting;
61
62 private MailSession(Frame settingsFrame) {
63 _bConnecting = false;
64
65 Properties props = System.getProperties();
66
67 _username = null;
68 _password = "";
69 _mailServer = null;
70 _serverType = null;
71
72 // Set the settings
73 for (Text item : settingsFrame.getBodyTextItems(false)) {
74 if (item.getText().toLowerCase().trim().equals("autoconnect")) {
75 _autoConnect = true;
76 }
77 AttributeValuePair avp = new AttributeValuePair(item.getText());
78 if (!avp.hasPair())
79 continue;
80 String attributeFullCase = avp.getAttribute();
81 String attribute = attributeFullCase.toLowerCase();
82
83 if (attribute.equals("user")) {
84 _username = avp.getValue();
85 props.setProperty("mail.user", _username);
86 } else if (attribute.equals("password")) {
87 _password = avp.getValue();
88 props.setProperty("mail.password", _password);
89 } else if (attribute.equals("address")) {
90 _address = avp.getValue();
91 } else if (attribute.equals("smtpserver")) {
92 props.setProperty("mail.transport.protocol", "smtp");
93 props.setProperty("mail.host", avp.getValue());
94 props.setProperty("mail.smtp.starttls.enable", "true");
95 props.setProperty("mail.smtp.host", avp.getValue());
96 props.setProperty("mail.smtp.auth", "true");
97 } else if (attribute.equals("popserver")) {
98 _mailServer = avp.getValue();
99 _serverType = "pop3s";
100 props.setProperty("mail.pop3.host", _mailServer);
101 } else if (attribute.equals("imapserver")) {
102 _mailServer = avp.getValue();
103 _serverType = "imaps";
104 props.setProperty("mail.imap.host", _mailServer);
105 }
106 }
107
108 // Create the authenticator
109 Authenticator auth = null;
110 if (_username != null) {
111 auth = new SMTPAuthenticator(_username, _password);
112 }
113 java.security.Security
114 .addProvider(new com.sun.net.ssl.internal.ssl.Provider());
115
116 // -- Attaching to default Session, or we could start a new one --
117 _session = Session.getDefaultInstance(props, auth);
118 try {
119 // Set up the mail receiver
120 _store = _session.getStore(_serverType);
121
122 // Connect the mail sender
123 _transport = _session.getTransport();
124 if (_autoConnect) {
125 connectThreaded();
126 }
127 } catch (Exception e) {
128 MessageBay.errorMessage("Error in ExpMail setup");
129 }
130 }
131
132 /**
133 * Attempts to connect the mail transporter to the mail server.
134 *
135 */
136 public static void connect() {
137 if (_theMailSession._bConnecting) {
138 MessageBay.errorMessage("Already connecting to mail server");
139 return;
140 } else if (_theMailSession != null) {
141 _theMailSession.connectThreaded();
142 }
143 }
144
145 private void connectThreaded() {
146 Thread t = new ConnectThread(this);
147 t.start();
148 }
149
150 public synchronized void connectServers() {
151 try {
152 if (!_transport.isConnected()) {
153 MessageBay.displayMessage("Connecting to SMTP server...");
154 _bConnecting = true;
155 _transport.connect();
156 MessageBay.overwriteMessage("SMTP server connected",
157 Color.green);
158 } else {
159 MessageBay.warningMessage("SMTP server already connected");
160 }
161 } catch (MessagingException e) {
162 MessageBay.errorMessage("Error connecting to SMTP server");
163 }
164
165 if (_mailServer != null && !_store.isConnected()) {
166 try {
167 MessageBay.displayMessage("Connecting to " + _mailServer
168 + "...");
169 _store.connect(_mailServer, _username, _password);
170
171 // -- Try to get hold of the default folder --
172 _folder = _store.getDefaultFolder();
173 if (_folder == null)
174 throw new Exception("No default folder");
175 // -- ...and its INBOX --
176 _folder = _folder.getFolder("INBOX");
177 if (_folder == null)
178 throw new Exception("No INBOX");
179 // -- Open the folder for read only --
180 _folder.open(Folder.READ_WRITE);
181 _folder.addMessageCountListener(new MessageCountAdapter() {
182 @Override
183 public void messagesAdded(MessageCountEvent e) {
184 MessageBay.displayMessage("New mail message!",
185 Color.green);
186 displayUnreadMailCount();
187 }
188 });
189
190 new Thread() {
191 public void run() {
192 for (;;) {
193 try {
194 Thread.sleep(1000); // sleep for freq
195 // milliseconds
196 // This is to force the IMAP server to send us
197 // EXISTS notifications
198 // TODO: Is synchronisation needed?
199 _folder.getMessageCount();
200 } catch (Exception e) {
201 }
202 }
203 }
204 }.start();
205
206 MessageBay.overwriteMessage("Connection complete", Color.GREEN);
207
208 displayUnreadMailCount();
209
210 } catch (Exception e) {
211 // e.printStackTrace();
212 MessageBay.errorMessage("Error connecting to " + _mailServer);
213 }
214 }
215 _bConnecting = false;
216 }
217
218 private void displayUnreadMailCount() {
219 Text text = new Text(-1, getUnreadCount() + " unread message"
220 + (getUnreadCount() == 1 ? "" : "s"), Color.BLUE, null);
221 text.addAction("getUnreadMail");
222 MessageBay.displayMessage(text);
223 }
224
225 public static boolean sendTextMessage(String to, String cc, String bcc,
226 String subject, String body, Object attachments) {
227
228 if (_theMailSession == null) {
229 MessageBay.errorMessage("Add mail settings to profile frame");
230 return false;
231 }
232
233 if (_theMailSession._bConnecting) {
234 MessageBay.errorMessage("Busy connecting to mail server...");
235 return false;
236 }
237
238 return _theMailSession.sendText(to, cc, bcc, subject, body, attachments);
239 }
240
241 private synchronized boolean sendText(String to, String cc, String bcc,
242 String subject, String body, Object attachments) {
243 if (!_transport.isConnected()) {
244 MessageBay
245 .warningMessage("Not connected to server, attempting to reconnect...");
246 try {
247 _bConnecting = true;
248 _transport.connect();
249 _bConnecting = false;
250 } catch (Exception e) {
251 MessageBay.errorMessage("Could not connect to mail server");
252 _bConnecting = false;
253 return false;
254 }
255 }
256
257 if (to == null) {
258 MessageBay.errorMessage("Add tag @to:<sendToEmailAddress>");
259 return false;
260 }
261
262 try {
263 // -- Create a new message --
264 Message msg = new MimeMessage(_session);
265
266 // -- Set the FROM and TO fields --
267 msg.setFrom(new InternetAddress(_address));
268 msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(
269 to, false));
270
271 // -- We could include CC recipients too --
272 if (cc != null) {
273 msg.setRecipients(Message.RecipientType.CC, InternetAddress
274 .parse(cc, false));
275 }
276
277 if (bcc != null) {
278 msg.setRecipients(Message.RecipientType.BCC, InternetAddress
279 .parse(bcc, false));
280 }
281
282 // -- Set the subject and body text --
283 msg.setSubject(subject);
284 msg.setContent(body.toString(), "text/plain");
285
286 // -- Set some other header information --
287 msg.setHeader("ExpMail", "Expeditee");
288 msg.setSentDate(new Date());
289
290 Transport.send(msg, msg.getRecipients(Message.RecipientType.TO));
291 } catch (Exception e) {
292 MessageBay.errorMessage("Error sending mail: " + e.getMessage());
293 return false;
294 }
295 MessageBay.displayMessage("Message sent OK.");
296 return true;
297 }
298
299 public static void init(Frame settingsFrame) {
300
301 if (settingsFrame == null)
302 return;
303
304 if (_theMailSession == null)
305 _theMailSession = new MailSession(settingsFrame);
306 }
307
308 private class SMTPAuthenticator extends javax.mail.Authenticator {
309 private String _username;
310
311 private String _password;
312
313 public SMTPAuthenticator(String username, String password) {
314 _username = username;
315 _password = password;
316 }
317
318 @Override
319 public PasswordAuthentication getPasswordAuthentication() {
320 return new PasswordAuthentication(_username, _password);
321 }
322 }
323
324 public static MailSession getInstance() {
325 return _theMailSession;
326 }
327
328 public synchronized void finalise() {
329 try {
330 if (_transport != null && _transport.isConnected()) {
331 _transport.close();
332 }
333
334 if (_folder != null && _folder.isOpen()) {
335 _folder.close(false);
336 }
337
338 if (_store != null && _store.isConnected()) {
339 _store.close();
340 }
341 } catch (Exception e) {
342
343 }
344 }
345
346 public int getUnreadCount() {
347 try {
348 return _folder.getUnreadMessageCount();
349 } catch (MessagingException e) {
350 // TODO Auto-generated catch block
351 e.printStackTrace();
352 }
353 return 0;
354 }
355
356 /**
357 * Gets mail and puts a list of mail items with links to the messages
358 * content. TODO: Put reply and forward button on the frame...
359 *
360 * @param flag
361 * @param isPresent
362 * @param frame
363 * @param point
364 * @return
365 */
366 public String getMailString(Flag flag, Boolean isPresent) {
367 StringBuffer sb = new StringBuffer();
368 // -- Get the message wrappers and process them --
369 Message[] msgs;
370 try {
371 msgs = _folder.getMessages();
372 for (int msgNum = 0; msgNum < msgs.length; msgNum++) {
373
374 if (flag == null
375 || msgs[msgNum].getFlags().contains(flag) == isPresent) {
376 if (sb.length() > 0) {
377 sb.append('\n').append('\n').append(
378 "-----------------------------").append('\n')
379 .append('\n');
380 }
381 // Only get messages that have not been read
382 sb.append(getTextMessage(msgs[msgNum]));
383 }
384 }
385 } catch (MessagingException e) {
386 e.printStackTrace();
387 }
388 return sb.toString();
389 }
390
391 /**
392 * Gets mail and puts a list of mail items with links to the messages
393 * content. TODO: Put reply and forward button on the frame...
394 *
395 * @param flag
396 * @param isPresent
397 * @param frame
398 * @param point
399 * @return
400 */
401 public Collection<Item> getMail(Flag flag, Boolean isPresent, Frame frame,
402 Point point) {
403 Collection<Item> mailItems = new LinkedList<Item>();
404 // -- Get the message wrappers and process them --
405 Message[] msgs;
406 try {
407 msgs = _folder.getMessages();
408 for (int msgNum = 0; msgNum < msgs.length; msgNum++) {
409 if (flag == null
410 || msgs[msgNum].getFlags().contains(flag) == isPresent) {
411 Item newItem = readMessage(msgs[msgNum], msgNum, frame,
412 point);
413 if (newItem != null) {
414 mailItems.add(newItem);
415 point.y += newItem.getBoundsHeight();
416 }
417 }
418
419 }
420 } catch (MessagingException e) {
421 e.printStackTrace();
422 }
423 return mailItems;
424 }
425
426 private Item readMessage(final Message message, final int messageNo,
427 final Frame frame, final Point point) {
428
429 final Text source = FrameDNDTransferHandler.importString(
430 "Loading message " + messageNo, point);
431
432 new Thread() {
433 public void run() {
434 try {
435 String subject = message.getSubject();
436 source.setText(messageNo + ". " + subject);
437 // Create a frameCreator
438 final FrameCreator frames = new FrameCreator(frame
439 .getFramesetName(), frame.path, subject, false);
440
441 // Get the header information
442 String from = ((InternetAddress) message.getFrom()[0])
443 .getPersonal();
444 if (from != null) {
445 frames.addText("@fromName: " + from, null, null, null,
446 false);
447 }
448 from = ((InternetAddress) message.getFrom()[0])
449 .getAddress();
450 Text fromAddressItem = frames.addText("@from: " + from,
451 null, null, null, false);
452
453 Text reply = frames.addText("@reply" + from, null, null,
454 null, false);
455 reply.setPosition(10 + fromAddressItem.getX()
456 + fromAddressItem.getBoundsWidth(), fromAddressItem
457 .getY());
458
459 // -- Get the message part (i.e. the message itself) --
460 Part messagePart = message;
461 Object content = messagePart.getContent();
462 // -- or its first body part if it is a multipart
463 // message --
464 if (content instanceof Multipart) {
465 messagePart = ((Multipart) content).getBodyPart(0);
466 // System.out.println("[ Multipart Message ]");
467 }
468 // -- Get the content type --
469 String contentType = messagePart.getContentType()
470 .toLowerCase();
471 // -- If the content is plain text, we can print it --
472 // System.out.println("CONTENT:" + contentType);
473 if (contentType.startsWith("text/plain")
474 || contentType.startsWith("text/html")) {
475 InputStream is = messagePart.getInputStream();
476 BufferedReader reader = new BufferedReader(
477 new InputStreamReader(is));
478 String thisLine = reader.readLine();
479 while (thisLine != null) {
480 frames.addText(thisLine, null, null, null, false);
481 thisLine = reader.readLine();
482 }
483 }
484 message.setFlag(Flag.SEEN, true);
485
486 frames.save();
487 source.setLink(frames.getName());
488 } catch (MessagingException e) {
489 MessageBay.errorMessage("GetMail error: " + e.getMessage());
490 } catch (Exception e) {
491 MessageBay.errorMessage("Error reading mail: "
492 + e.getMessage());
493 }
494 }
495 }.start();
496 return source;
497 }
498
499 /**
500 * "getTextMessage()" method to print a message.
501 */
502 public String getTextMessage(Message message) {
503 StringBuffer sb = new StringBuffer();
504
505 try {
506 // Get the header information
507 String from = ((InternetAddress) message.getFrom()[0])
508 .getPersonal();
509 if (from == null)
510 from = ((InternetAddress) message.getFrom()[0]).getAddress();
511 sb.append("FROM: " + from).append('\n');
512 String subject = message.getSubject();
513 sb.append("SUBJECT: " + subject).append('\n').append('\n');
514 // -- Get the message part (i.e. the message itself) --
515 Part messagePart = message;
516 Object content = messagePart.getContent();
517 // -- or its first body part if it is a multipart message --
518 if (content instanceof Multipart) {
519 messagePart = ((Multipart) content).getBodyPart(0);
520 System.out.println("[ Multipart Message ]");
521 }
522 // -- Get the content type --
523 String contentType = messagePart.getContentType();
524 // -- If the content is plain text, we can print it --
525 // System.out.println("CONTENT:" + contentType);
526 if (contentType.startsWith("text/plain")
527 || contentType.startsWith("text/html")) {
528 InputStream is = messagePart.getInputStream();
529 BufferedReader reader = new BufferedReader(
530 new InputStreamReader(is));
531 String thisLine = reader.readLine();
532 while (thisLine != null) {
533 sb.append(thisLine).append('\n');
534 thisLine = reader.readLine();
535 }
536 }
537 message.setFlag(Flag.SEEN, true);
538 } catch (Exception ex) {
539 ex.printStackTrace();
540 }
541 sb.deleteCharAt(sb.length() - 1);
542 return sb.toString();
543 }
544
545 public Folder getFolder() {
546 return _folder;
547 }
548}
Note: See TracBrowser for help on using the repository browser.